pax_global_header00006660000000000000000000000064141700023070014504gustar00rootroot0000000000000052 comment=3775f3c46c5b5dbb3c238c274bec88f574c6fe6c centreon-plugins-20220113/000077500000000000000000000000001417000230700152345ustar00rootroot00000000000000centreon-plugins-20220113/.github/000077500000000000000000000000001417000230700165745ustar00rootroot00000000000000centreon-plugins-20220113/.github/issue_template.md000066400000000000000000000024571417000230700221510ustar00rootroot00000000000000Thanks for using centreon-plugins! Please follow the indications shown below according to your issue and describe it in English. ## New Plugins and modes To develop a Plugin/mode, we need the following: * SNMP: MIBs files and full snmpwalk of entreprise branch (snmpwalk -ObentU -v 2c -c public address .1.3.6.1.4.1 > equipment.snmpwalk) * HTTP API (SOAP, Rest/Json, XML-RPC): the documentation and some curls examples * CLI: command line examples * SQL: requests * JMX: mbean names and attributes If some parts of information are confidentials, please send them directly by email to qgarnier@centreon.com and sbomm@centreon.com. Please note that all the developments are open-source. We can't give a date for the development, achievement or release. If it's a priority for you, send us an email about it (qgarnier@centreon.com and sbomm@centreon.com) and we'll put you in touch with our company. ## Bug/Question If you are reporting a bug/question, make sure that there aren't any similar/duplicates issues already open. You can ensure this by searching the issue list for this repository. If so, please close your issue and add a comment to the existing one instead. Otherwise, open a new issue and provide all parts of information you can (full command line used, actual output, expected output, error message...). centreon-plugins-20220113/Jenkinsfile000066400000000000000000000031201417000230700174140ustar00rootroot00000000000000 env.REF_BRANCH = 'master' if ((env.BRANCH_NAME == env.REF_BRANCH)) { env.BUILD = 'REFERENCE' } else { env.BUILD = 'CI' } stage('Source') { node { sh 'setup_centreon_build.sh' dir('centreon-plugins') { checkout scm } sh './centreon-build/jobs/plugins/plugins-source.sh' source = readProperties file: 'source.properties' env.VERSION = "${source.VERSION}" env.RELEASE = "${source.RELEASE}" // Run sonarQube analysis withSonarQubeEnv('SonarQubeDev') { sh './centreon-build/jobs/plugins/plugins-analysis.sh' } timeout(time: 10, unit: 'MINUTES') { def qualityGate = waitForQualityGate() if (qualityGate.status != 'OK') { currentBuild.result = 'FAIL' } } } } stage('RPM Packaging') { parallel 'all': { node { sh 'setup_centreon_build.sh' sh './centreon-build/jobs/plugins/plugins-package.sh' archiveArtifacts artifacts: 'rpms-centos7.tar.gz' archiveArtifacts artifacts: 'rpms-centos8.tar.gz' stash name: "rpms-centos7", includes: 'output-centos7/noarch/*.rpm' stash name: "rpms-centos8", includes: 'output-centos8/noarch/*.rpm' sh 'rm -rf output' } } if ((currentBuild.result ?: 'SUCCESS') != 'SUCCESS') { error('Package stage failure.'); } } stage('RPM Delivery') { parallel 'all': { node { sh 'setup_centreon_build.sh' unstash 'rpms-centos7' unstash 'rpms-centos8' sh './centreon-build/jobs/plugins/plugins-delivery.sh' } } if ((currentBuild.result ?: 'SUCCESS') != 'SUCCESS') { error('Package stage failure.'); } } centreon-plugins-20220113/LICENSE.txt000066400000000000000000000261351417000230700170660ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] 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. centreon-plugins-20220113/README.md000066400000000000000000000104771417000230700165240ustar00rootroot00000000000000# centreon-plugins [![License](https://img.shields.io/badge/License-APACHE2-brightgreen.svg)](https://github.com/centreon/centreon-plugins/blob/master/LICENSE.txt) [![Contributors][contributors-shield]][contributors-url] [![Stars][stars-shield]][stars-url] [![Forks][forks-shield]][forks-url] [![Issues][issues-shield]][issues-url] “centreon-plugins” is a free and open source project to monitor systems. The project can be used with Centreon and all monitoring softwares compatible with Nagios plugins. You can monitor many systems: * application: Apache, Asterisk, Elasticsearch, Github, Jenkins, Kafka, Nginx, Pfsense, Redis, Tomcat, Varnish,... * cloud: AWS, Azure, Docker, Office365, Nutanix, Prometheus,... * database: Firebird, Informix, MS SQL, MySQL, Oracle, Postgres, Cassandra * hardware: printers (rfc3805), UPS (Powerware, Mge, Standard), Sun Hardware, Cisco UCS, SensorIP, HP Proliant, HP Bladechassis, Dell Openmanage, Dell CMC, Raritan,... * network: Aruba, Brocade, Bluecoat, Brocade, Checkpoint, Cisco AP/IronPort/ASA/Standard, Extreme, Fortigate, H3C, Hirschmann, HP Procurve, F5 BIG-IP, Juniper, PaloAlto, Redback, Riverbed, Ruggedcom, Stonesoft,... * os: Linux (SNMP, NRPE), Freebsd (SNMP), AIX (SNMP), Solaris (SNMP)... * storage: EMC Clariion, Netapp, Nimble, HP MSA p2000, Dell EqualLogic, Qnap, Panzura, Synology... ## Basic Usage We'll use a basic example to show you how to monitor a system. I have finished the install section and I want to monitor a Linux in SNMP. First, I need to find the plugin to use in the list: $ perl centreon_plugins.pl --list-plugin | grep -i linux | grep 'PLUGIN' PLUGIN: os::linux::local::plugin PLUGIN: os::linux::snmp::plugin It seems that 'os::linux::snmp::plugin' is the good one. So I verify with the option ``--help`` to be sure: $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --help ... Plugin Description: Check Linux operating systems in SNMP. It's exactly what I need. Now I'll add the option ``--list-mode`` to know what can I do with it: $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --list-mode ... Modes Available: processcount time list-storages disk-usage diskio uptime swap cpu-detailed load traffic cpu inodes list-diskspath list-interfaces packet-errors memory tcpcon storage I would like to test the 'load' mode: $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --mode=load UNKNOWN: Missing parameter --hostname. It's not working because some options are missing. I can have a description of the mode and options with the option ``--help``: $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --mode=load --help Eventually, I have to configure some SNMP options: $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --mode=load --hostname=127.0.0.1 --snmp-version=2c --snmp-community=public OK: Load average: 0.00, 0.00, 0.00 | 'load1'=0.00;;;0; 'load5'=0.00;;;0; 'load15'=0.00;;;0; I can set threshold with options ``--warning`` and ``--critical``: $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --mode=load --hostname=127.0.0.1 --snmp-version=2c --snmp-community=public --warning=1,2,3 --critical=2,3,4 OK: Load average: 0.00, 0.00, 0.00 | 'load1'=0.00;0:1;0:2;0; 'load5'=0.00;0:2;0:3;0; 'load15'=0.00;0:3;0:4;0; For more information or help, please read ['doc/en/user/guide.rst'](./doc/en/user/guide.rst). [contributors-shield]: https://img.shields.io/github/contributors/centreon/centreon-plugins?color=%2384BD00&label=CONTRIBUTORS&style=for-the-badge [stars-shield]: https://img.shields.io/github/stars/centreon/centreon-plugins?color=%23433b02a&label=STARS&style=for-the-badge [forks-shield]: https://img.shields.io/github/forks/centreon/centreon-plugins?color=%23009fdf&label=FORKS&style=for-the-badge [issues-shield]: https://img.shields.io/github/issues/centreon/centreon-plugins?color=%230072ce&label=ISSUES&style=for-the-badge [contributors-url]: https://github.com/centreon/centreon-plugins/graphs/contributors [forks-url]: https://github.com/centreon/centreon-plugins/network/members [stars-url]: https://github.com/centreon/centreon-plugins/stargazers [issues-url]: https://github.com/centreon/centreon-plugins/issues centreon-plugins-20220113/apps/000077500000000000000000000000001417000230700161775ustar00rootroot00000000000000centreon-plugins-20220113/apps/antivirus/000077500000000000000000000000001417000230700202235ustar00rootroot00000000000000centreon-plugins-20220113/apps/antivirus/clamav/000077500000000000000000000000001417000230700214665ustar00rootroot00000000000000centreon-plugins-20220113/apps/antivirus/clamav/local/000077500000000000000000000000001417000230700225605ustar00rootroot00000000000000centreon-plugins-20220113/apps/antivirus/clamav/local/mode/000077500000000000000000000000001417000230700235045ustar00rootroot00000000000000centreon-plugins-20220113/apps/antivirus/clamav/local/mode/updatestatus.pm000066400000000000000000000300221417000230700265650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::antivirus::clamav::local::mode::updatestatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use Net::DNS; use DateTime; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_engine_status_output { my ($self, %options) = @_; return sprintf( "clamav engine version '%s/%s'", $self->{result_values}->{current_engine_version}, $self->{result_values}->{last_engine_version} ); } sub custom_maindb_status_output { my ($self, %options) = @_; return sprintf( "main.cvd version '%s/%s', last update %s", $self->{result_values}->{current_maindb_version}, $self->{result_values}->{last_maindb_version}, centreon::plugins::misc::change_seconds( value => $self->{result_values}->{current_maindb_timediff} ) ); } sub custom_dailydb_status_output { my ($self, %options) = @_; return sprintf( "daily.cvd version '%s/%s', last update %s", $self->{result_values}->{current_dailydb_version}, $self->{result_values}->{last_dailydb_version}, centreon::plugins::misc::change_seconds( value => $self->{result_values}->{current_dailydb_timediff} ) ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'update', type => 0, message_separator => ' - ' }, ]; $self->{maps_counters}->{update} = [ { label => 'engine-status', type => 2, critical_default => '%{last_engine_version} ne %{current_engine_version}', set => { key_values => [ { name => 'last_engine_version' }, { name => 'current_engine_version' } ], closure_custom_output => $self->can('custom_engine_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'maindb-status', type => 2, critical_default => '%{last_maindb_version} ne %{current_maindb_version}', set => { key_values => [ { name => 'last_maindb_version' }, { name => 'current_maindb_version' }, { name => 'current_maindb_timediff' } ], closure_custom_output => $self->can('custom_maindb_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'dailydb-status', type => 2, critical_default => '%{last_dailydb_version} ne %{current_dailydb_version} || %{current_dailydb_timediff} > 432000', set => { key_values => [ { name => 'last_dailydb_version' }, { name => 'current_dailydb_version' }, { name => 'current_dailydb_timediff' } ], closure_custom_output => $self->can('custom_dailydb_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $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' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options' }, 'nameservers:s@' => { name => 'nameservers' }, 'maindb-file:s' => { name => 'maindb_file', default => '/var/lib/clamav/main.cvd' }, 'dailydb-file:s' => { name => 'dailydb_file', default => '/var/lib/clamav/daily.cvd' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{clamav_command} = 'echo "==== CLAMD ===" ; clamd -V ; echo "==== DAILY ===="; sigtool --info ' . $self->{option_results}->{dailydb_file} . '; echo "==== MAIN ====" ; sigtool --info ' . $self->{option_results}->{maindb_file}; } sub get_clamav_last_update { my ($self, %options) = @_; #0.99.2:57:23114:1487851834:1:63:45614:290 # field 2 = main.cvd version number # field 3 = daily.cvd version number my $nameservers = []; if (defined($self->{option_results}->{nameservers})) { $nameservers = [@{$self->{option_results}->{nameservers}}]; } my $handle = Net::DNS::Resolver->new( nameservers => $nameservers ); my $txt_query = $handle->query("current.cvd.clamav.net", "TXT"); if (!$txt_query) { $self->{output}->add_option_msg(short_msg => "Unable to get TXT Record : " . $handle->errorstring . "."); $self->{output}->option_exit(); } my @fields = split /:/, ($txt_query->answer)[0]->txtdata; ($self->{last_engine_version}, $self->{last_maindb_version}, $self->{last_dailydb_version}) = ($fields[0], $fields[1], $fields[2]); } sub get_clamav_current_signature_info { my ($self, %options) = @_; if ($options{content} !~ /====\s+$options{label}.*?Build\s+time:\s+(.*?)\n.*?Version:\s+(\d+)/msi) { return ; } $self->{'current_' . $options{label} . 'db_version'} = $2; #13 Jun 2016 09:53 -0400 my $time = $1; if ($time =~ /^\s*(\d+)\s+(\S+)\s+(\d+)\s+(\d+):(\d+)\s+(\S+)/) { my %months = ("Jan" => 1, "Feb" => 2, "Mar" => 3, "Apr" => 4, "May" => 5, "Jun" => 6, "Jul" => 7, "Aug" => 8, "Sep" => 9, "Oct" => 10, "Nov" => 11, "Dec" => 12); my $dt = DateTime->new( year => $3, month => $months{$2}, day => $1, hour => $4, minute => $5, second => 0, time_zone => $6, ); $self->{'current_' . $options{label} . 'db_timediff'} = time() - $dt->epoch; } } sub manage_selection { my ($self, %options) = @_; $self->get_clamav_last_update(); my ($stdout) = centreon::plugins::misc::execute( output => $self->{output}, options => $self->{option_results}, sudo => $self->{option_results}->{sudo}, command => defined($self->{option_results}->{command}) && $self->{option_results}->{command} ne '' ? $self->{option_results}->{command} : $self->{clamav_command}, command_path => $self->{option_results}->{command_path}, command_options => defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne '' ? $self->{option_results}->{command_options} : undef ); #==== CLAMD === #ClamAV 0.99.2/21723/Mon Jun 13 14:53:00 2016 #==== DAILY ==== #File: /var/lib/clamav/daily.cvd #Build time: 13 Jun 2016 09:53 -0400 #Version: 21723 #Signatures: 276682 #Functionality level: 63 #Builder: neo #MD5: 280928f25d175359e6e6a0270d9d4fb2 #Digital signature: yLfcgb9dbgKO2rWpXGa238252jqH7VDsAjnqQsHc+9cbIwiM9wnz3fqyl33G15S4YsMbRR6CYbSTxccKXBJvvxRhgZQJmpCYiThslUKBPo5QhIFcI1QBMfoHKCpf8riB2/xAgI401UkZVJip+6eWFpUJ9aeaFai+Mvinif5BRzi #LibClamAV Warning: ************************************************** #LibClamAV Warning: *** The virus database is older than 7 days! *** #LibClamAV Warning: *** Please update it as soon as possible. *** #LibClamAV Warning: ************************************************** #Verification OK. #==== MAIN ==== #File: /var/lib/clamav/main.cvd #Build time: 16 Mar 2016 23:17 +0000 #Version: 57 #Signatures: 4218790 #Functionality level: 60 #Builder: amishhammer #MD5: 06386f34a16ebeea2733ab037f0536be #Digital signature: AIzk/LYbX8K9OEbR5GMyJ6LWTqSu9ffa5bONcA0FN3+onMlZ2BMRzuyvVURBvAZvOaGPdtMBcgDJSl7fGxDfcxRWhIrQ98f8FPdAQaFPgWu3EX46ufw+IRZnM4irKKYuh1GdCIbsGs6jejWo9iNErsbDqkFSobVBkUJYxBgvqfd #Verification OK. $self->get_clamav_current_signature_info(label => 'daily', content => $stdout); $self->get_clamav_current_signature_info(label => 'main', content => $stdout); if ($stdout =~ /==== CLAMD.*?ClamAV (.*?)\//msi) { $self->{current_engine_version} = $1; } $self->{update} = { last_engine_version => $self->{last_engine_version}, last_maindb_version => $self->{last_maindb_version}, last_dailydb_version => $self->{last_dailydb_version}, current_engine_version => $self->{current_engine_version}, current_maindb_version => $self->{current_maindb_version}, current_maindb_timediff => $self->{current_maindb_timediff}, current_dailydb_version => $self->{current_dailydb_version}, current_dailydb_timediff => $self->{current_dailydb_timediff}, }; } 1; __END__ =head1 MODE Check antivirus update status. =over 8 =item B<--nameservers> Set nameserver to query (can be multiple). The system configuration is used by default. =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. Used it you have output in a file. =item B<--command-path> Command path. =item B<--command-options> Command options (Default: '-report -most_columns'). =item B<--maindb-file> Antivirus main.cvd file (Default: '/var/lib/clamav/main.cvd'). =item B<--dailydb-file> Antivirus daily.cvd file (Default: '/var/lib/clamav/daily.cvd'). =item B<--warning-engine-status> Set warning threshold for status (Default: '') Can used special variables like: %{last_engine_version}, %{current_engine_version} =item B<--critical-engine-status> Set critical threshold for status (Default: '%{last_engine_version} ne %{current_engine_version}'). Can used special variables like: %{last_engine_version}, %{current_engine_version} =item B<--warning-maindb-status> Set warning threshold for status (Default: '') Can used special variables like: %{last_maindb_version}, %{current_maindb_version}, %{current_maindb_timediff} =item B<--critical-maindb-status> Set critical threshold for status (Default: '%{last_maindb_version} ne %{current_maindb_version}'). Can used special variables like: %{last_maindb_version}, %{current_maindb_version}, %{current_maindb_timediff} =item B<--warning-dailydb-status> Set warning threshold for status (Default: '') Can used special variables like: %{last_dailydb_version}, %{current_dailydb_version}, %{current_dailydb_timediff} =item B<--critical-dailydb-status> Set critical threshold for status (Default: '%{last_dailydb_version} ne %{current_dailydb_version} || %{current_dailydb_timediff} > 432000'). Can used special variables like: %{last_dailydb_version}, %{current_dailydb_version}, %{current_dailydb_timediff} =back =cut centreon-plugins-20220113/apps/antivirus/clamav/local/plugin.pm000066400000000000000000000024251417000230700244170ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::antivirus::clamav::local::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} = '0.1'; $self->{modes} = { 'update-status' => 'apps::antivirus::clamav::local::mode::updatestatus', }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check ClamAV Antivirus through local commands (the plugin can use SSH). =cut centreon-plugins-20220113/apps/antivirus/kaspersky/000077500000000000000000000000001417000230700222375ustar00rootroot00000000000000centreon-plugins-20220113/apps/antivirus/kaspersky/snmp/000077500000000000000000000000001417000230700232145ustar00rootroot00000000000000centreon-plugins-20220113/apps/antivirus/kaspersky/snmp/mode/000077500000000000000000000000001417000230700241405ustar00rootroot00000000000000centreon-plugins-20220113/apps/antivirus/kaspersky/snmp/mode/deployment.pm000066400000000000000000000263751417000230700266730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::antivirus::kaspersky::snmp::mode::deployment; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf("Deployment status is '%s'", $self->{result_values}->{status}); } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_deploymentStatus'}; return 0; } sub custom_progress_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => 'progress', nlabel => $self->{nlabel}, value => $self->{result_values}->{installed}, min => 0, max => $self->{result_values}->{total} ); } sub custom_progress_threshold { my ($self, %options) = @_; my ($exit, $threshold_value); $threshold_value = defined($self->{instance_mode}->{option_results}->{percent}) ? $self->{result_values}->{prct_installed} : $self->{result_values}->{installed} ; $exit = $self->{perfdata}->threshold_check( value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_progress_output { my ($self, %options) = @_; return sprintf( "Deployment progress: %d/%d (%.2f%%)", $self->{result_values}->{installed}, $self->{result_values}->{total}, $self->{result_values}->{prct_installed} ); } sub custom_progress_calc { my ($self, %options) = @_; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_hostsInGroups'}; $self->{result_values}->{installed} = $options{new_datas}->{$self->{instance} . '_hostsWithAntivirus'}; $self->{result_values}->{prct_installed} = ($self->{result_values}->{total} != 0) ? $self->{result_values}->{installed} * 100 / $self->{result_values}->{total} : 0; return 0; } sub custom_expiring_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => 'expiring', nlabel => $self->{nlabel}, value => $self->{result_values}->{expiring}, 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_expiring_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check( value => $self->{result_values}->{expiring}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_expiring_output { my ($self, %options) = @_; my $msg = sprintf("%d host(s) with expiring licence", $self->{result_values}->{expiring}); $msg .= sprintf(" [serial: %s] [days: %d]", $self->{result_values}->{serial}, $self->{result_values}->{days}) if ($self->{result_values}->{serial} ne ''); return $msg; } sub custom_expiring_calc { my ($self, %options) = @_; $self->{result_values}->{serial} = $options{new_datas}->{$self->{instance} . '_licenceExpiringSerial'}; $self->{result_values}->{days} = $options{new_datas}->{$self->{instance} . '_licenceExpiringDays'}; $self->{result_values}->{expiring} = $options{new_datas}->{$self->{instance} . '_hostsLicenceExpiring'}; return 0; } sub custom_expired_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => 'expired', nlabel => $self->{nlabel}, value => $self->{result_values}->{expired}, 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_expired_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check( value => $self->{result_values}->{expired}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_expired_output { my ($self, %options) = @_; my $msg = sprintf("%d host(s) with expired licence", $self->{result_values}->{expired}); $msg .= sprintf(" [serial: %s]", $self->{result_values}->{serial}) if ($self->{result_values}->{serial} ne ''); return $msg; } sub custom_expired_calc { my ($self, %options) = @_; $self->{result_values}->{serial} = $options{new_datas}->{$self->{instance} . '_licenceExpiredSerial'}; $self->{result_values}->{expired} = $options{new_datas}->{$self->{instance} . '_hostsLicenceExpired'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, message_separator => ' - ' }, ]; $self->{maps_counters}->{global} = [ { label => 'status', type => 2, warning_default => '%{status} =~ /Warning/i', critical_default => '%{status} =~ /Critical/i', set => { key_values => [ { name => 'deploymentStatus' } ], 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 => \&catalog_status_threshold_ng, } }, { label => 'progress', nlabel => 'hosts.antivirus.installed.count', set => { key_values => [ { name => 'hostsInGroups' }, { name => 'hostsWithAntivirus' } ], closure_custom_calc => $self->can('custom_progress_calc'), closure_custom_output => $self->can('custom_progress_output'), closure_custom_threshold_check => $self->can('custom_progress_threshold'), closure_custom_perfdata => $self->can('custom_progress_perfdata'), } }, { label => 'failed', nlabel => 'hosts.antivirus.install.failed.count', set => { key_values => [ { name => 'hostsRemoteInstallFailed' } ], output_template => '%d failed remote installation(s)', perfdatas => [ { label => 'failed', template => '%d', min => 0 }, ] } }, { label => 'expiring', nlabel => 'hosts.expiring.licence.count', set => { key_values => [ { name => 'licenceExpiringSerial' }, { name => 'licenceExpiringDays' }, { name => 'hostsLicenceExpiring' } ], closure_custom_calc => $self->can('custom_expiring_calc'), closure_custom_output => $self->can('custom_expiring_output'), closure_custom_threshold_check => $self->can('custom_expiring_threshold'), closure_custom_perfdata => $self->can('custom_expiring_perfdata'), } }, { label => 'expired', nlabel => 'hosts.expired.licence.count', set => { key_values => [ { name => 'licenceExpiredSerial' }, { name => 'hostsLicenceExpired' } ], closure_custom_calc => $self->can('custom_expired_calc'), closure_custom_output => $self->can('custom_expired_output'), closure_custom_threshold_check => $self->can('custom_expired_threshold'), closure_custom_perfdata => $self->can('custom_expired_perfdata'), } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'percent' => { name => 'percent' } }); return $self; } my %map_status = ( 0 => 'OK', 1 => 'Info', 2 => 'Warning', 3 => 'Critical' ); my $oid_deploymentStatus = '.1.3.6.1.4.1.23668.1093.1.1.1'; my $oid_hostsInGroups = '.1.3.6.1.4.1.23668.1093.1.1.3'; my $oid_hostsWithAntivirus = '.1.3.6.1.4.1.23668.1093.1.1.4'; my $oid_hostsRemoteInstallFailed = '.1.3.6.1.4.1.23668.1093.1.1.5'; my $oid_licenceExpiringSerial = '.1.3.6.1.4.1.23668.1093.1.1.6'; my $oid_licenceExpiredSerial = '.1.3.6.1.4.1.23668.1093.1.1.7'; my $oid_licenceExpiringDays = '.1.3.6.1.4.1.23668.1093.1.1.8'; my $oid_hostsLicenceExpiring = '.1.3.6.1.4.1.23668.1093.1.1.9'; my $oid_hostsLicenceExpired = '.1.3.6.1.4.1.23668.1093.1.1.10'; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_leef( oids => [ $oid_deploymentStatus, $oid_hostsInGroups, $oid_hostsWithAntivirus, $oid_hostsRemoteInstallFailed, $oid_licenceExpiringSerial, $oid_licenceExpiredSerial, $oid_licenceExpiringDays, $oid_hostsLicenceExpiring, $oid_hostsLicenceExpired ], nothing_quit => 1 ); $self->{global} = { deploymentStatus => $map_status{$snmp_result->{$oid_deploymentStatus}}, hostsInGroups => $snmp_result->{$oid_hostsInGroups}, hostsWithAntivirus => $snmp_result->{$oid_hostsWithAntivirus}, hostsRemoteInstallFailed => $snmp_result->{$oid_hostsRemoteInstallFailed}, licenceExpiringSerial => $snmp_result->{$oid_licenceExpiringSerial}, licenceExpiredSerial => $snmp_result->{$oid_licenceExpiredSerial}, licenceExpiringDays => $snmp_result->{$oid_licenceExpiringDays}, hostsLicenceExpiring => $snmp_result->{$oid_hostsLicenceExpiring}, hostsLicenceExpired => $snmp_result->{$oid_hostsLicenceExpired}, }; } 1; __END__ =head1 MODE Check antivirus software deployment status. =over 8 =item B<--warning-status> Set warning threshold for status. (Default: '%{status} =~ /Warning/i'). Can use special variables like: %{status} =item B<--critical-status> Set critical threshold for status. (Default: '%{status} =~ /Critical/i'). Can use special variables like: %{status} =item B<--warning-*> Threshold warning. Can be: 'progress' (counter or %), 'failed', 'expiring', 'expired'. =item B<--critical-*> Threshold critical. Can be: 'progress' (counter or %), 'failed', 'expiring', 'expired'. =item B<--percent> Set this option if you want to use percent on progress thresholds. =back =cut centreon-plugins-20220113/apps/antivirus/kaspersky/snmp/mode/events.pm000066400000000000000000000072451417000230700260120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::antivirus::kaspersky::snmp::mode::events; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf("Events status is '%s'", $self->{result_values}->{status}); } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_eventsStatus'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, message_separator => ' - ' }, ]; $self->{maps_counters}->{global} = [ { label => 'status', type => 2, warning_default => '%{status} =~ /Warning/i', critical_default => '%{status} =~ /Critical/i', set => { key_values => [ { name => 'eventsStatus' } ], 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 => \&catalog_status_threshold_ng } }, { label => 'events', nlabel => 'events.critical.count', set => { key_values => [ { name => 'criticalEventsCount' } ], output_template => '%d critical event(s)', perfdatas => [ { label => 'events', template => '%d', min => 0 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my %map_status = ( 0 => 'OK', 1 => 'Info', 2 => 'Warning', 3 => 'Critical' ); my $oid_eventsStatus = '.1.3.6.1.4.1.23668.1093.1.6.1'; my $oid_criticalEventsCount = '.1.3.6.1.4.1.23668.1093.1.6.3'; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_leef( oids => [ $oid_eventsStatus, $oid_criticalEventsCount ], nothing_quit => 1 ); $self->{global} = { eventsStatus => $map_status{$snmp_result->{$oid_eventsStatus}}, criticalEventsCount => $snmp_result->{$oid_criticalEventsCount} }; } 1; __END__ =head1 MODE Check events status. =over 8 =item B<--warning-status> Set warning threshold for status. (Default: '%{status} =~ /Warning/i'). Can use special variables like: %{status} =item B<--critical-status> Set critical threshold for status. (Default: '%{status} =~ /Critical/i'). Can use special variables like: %{status} =item B<--warning-*> Threshold warning. Can be: 'events'. =item B<--critical-*> Threshold critical. Can be: 'events'. =back =cut centreon-plugins-20220113/apps/antivirus/kaspersky/snmp/mode/fullscan.pm000066400000000000000000000073271417000230700263160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::antivirus::kaspersky::snmp::mode::fullscan; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf("Full scan status is '%s'", $self->{result_values}->{status}); } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_fullscanStatus'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, message_separator => ' - ' }, ]; $self->{maps_counters}->{global} = [ { label => 'status', type => 2, warning_default => '%{status} =~ /Warning/i', critical_default => '%{status} =~ /Critical/i', set => { key_values => [ { name => 'fullscanStatus' } ], 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 => \&catalog_status_threshold_ng } }, { label => 'not-scanned', nlabel => 'hosts.unscanned.count', set => { key_values => [ { name => 'hostsNotScannedLately' } ], output_template => '%d hosts(s) has not been scanned lately', perfdatas => [ { label => 'not_scanned', template => '%d', min => 0 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my %map_status = ( 0 => 'OK', 1 => 'Info', 2 => 'Warning', 3 => 'Critical' ); my $oid_fullscanStatus = '.1.3.6.1.4.1.23668.1093.1.4.1'; my $oid_hostsNotScannedLately = '.1.3.6.1.4.1.23668.1093.1.4.3'; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_leef( oids => [ $oid_fullscanStatus, $oid_hostsNotScannedLately ], nothing_quit => 1 ); $self->{global} = { fullscanStatus => $map_status{$snmp_result->{$oid_fullscanStatus}}, hostsNotScannedLately => $snmp_result->{$oid_hostsNotScannedLately} }; } 1; __END__ =head1 MODE Check full scan status. =over 8 =item B<--warning-status> Set warning threshold for status. (Default: '%{status} =~ /Warning/i'). Can use special variables like: %{status} =item B<--critical-status> Set critical threshold for status. (Default: '%{status} =~ /Critical/i'). Can use special variables like: %{status} =item B<--warning-*> Threshold warning. Can be: 'not-scanned'. =item B<--critical-*> Threshold critical. Can be: 'not-scanned'. =back =cut centreon-plugins-20220113/apps/antivirus/kaspersky/snmp/mode/logicalnetwork.pm000066400000000000000000000126011417000230700275220ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::antivirus::kaspersky::snmp::mode::logicalnetwork; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf("Logical network status is '%s'", $self->{result_values}->{status}); } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_logicalNetworkStatus'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, message_separator => ' - ' }, ]; $self->{maps_counters}->{global} = [ { label => 'status', type => 2, warning_default => '%{status} =~ /Warning/i', critical_default => '%{status} =~ /Critical/i', set => { key_values => [ { name => 'logicalNetworkStatus' } ], 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 => \&catalog_status_threshold_ng } }, { label => 'new-hosts', nlabel => 'hosts.new.count', set => { key_values => [ { name => 'hostsFound' } ], output_template => '%d new host(s) found', perfdatas => [ { label => 'new_hosts', template => '%d', min => 0 } ] } }, { label => 'groups', nlabel => 'groups.total.count', set => { key_values => [ { name => 'groupsCount' } ], output_template => '%d group(s) on the server', perfdatas => [ { label => 'groups', template => '%d', min => 0 } ] } }, { label => 'not-connected-long-time', nlabel => 'hosts.notconnected.count', set => { key_values => [ { name => 'hostsNotConnectedLongTime' } ], output_template => '%d host(s) has not connected for a long time', perfdatas => [ { label => 'not_connected_long_time', template => '%d', min => 0 } ] } }, { label => 'not-controlled', nlabel => 'hosts.uncontrolled.count', set => { key_values => [ { name => 'hostsControlLost' } ], output_template => '%d host(s) are not controlled', perfdatas => [ { label => 'not_controlled', template => '%d', min => 0 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my %map_status = ( 0 => 'OK', 1 => 'Info', 2 => 'Warning', 3 => 'Critical' ); my $oid_logicalNetworkStatus = '.1.3.6.1.4.1.23668.1093.1.5.1'; my $oid_hostsFound = '.1.3.6.1.4.1.23668.1093.1.5.3'; my $oid_groupsCount = '.1.3.6.1.4.1.23668.1093.1.5.4'; my $oid_hostsNotConnectedLongTime = '.1.3.6.1.4.1.23668.1093.1.5.5'; my $oid_hostsControlLost = '.1.3.6.1.4.1.23668.1093.1.5.6'; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_leef( oids => [ $oid_logicalNetworkStatus, $oid_hostsFound, $oid_groupsCount, $oid_hostsNotConnectedLongTime, $oid_hostsControlLost ], nothing_quit => 1 ); $self->{global} = { logicalNetworkStatus => $map_status{$snmp_result->{$oid_logicalNetworkStatus}}, hostsFound => $snmp_result->{$oid_hostsFound}, groupsCount => $snmp_result->{$oid_groupsCount}, hostsNotConnectedLongTime => $snmp_result->{$oid_hostsNotConnectedLongTime}, hostsControlLost => $snmp_result->{$oid_hostsControlLost} }; } 1; __END__ =head1 MODE Check logical network status. =over 8 =item B<--warning-status> Set warning threshold for status. (Default: '%{status} =~ /Warning/i'). Can use special variables like: %{status} =item B<--critical-status> Set critical threshold for status. (Default: '%{status} =~ /Critical/i'). Can use special variables like: %{status} =item B<--warning-*> Threshold warning. Can be: 'new-hosts', 'groups', 'not-connected-long-time', 'not-controlled'. =item B<--critical-*> Threshold critical. Can be: 'new-hosts', 'groups', 'not-connected-long-time', 'not-controlled'. =back =cut centreon-plugins-20220113/apps/antivirus/kaspersky/snmp/mode/protection.pm000066400000000000000000000145001417000230700266640ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::antivirus::kaspersky::snmp::mode::protection; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf("Protection status is '%s'", $self->{result_values}->{status}); } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_protectionStatus'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, message_separator => ' - ' }, ]; $self->{maps_counters}->{global} = [ { label => 'status', type => 2, warning_default => '%{status} =~ /Warning/i', critical_default => '%{status} =~ /Critical/i', set => { key_values => [ { name => 'protectionStatus' } ], 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 => \&catalog_status_threshold_ng } }, { label => 'no-antivirus', nlabel => 'protection.hosts.antivirus.notrunning.count', set => { key_values => [ { name => 'hostsAntivirusNotRunning' } ], output_template => '%d host(s) without running antivirus', perfdatas => [ { label => 'no_antivirus', template => '%d', min => 0 } ] } }, { label => 'no-real-time', nlabel => 'protection.hosts.realtime.notrunning.count', set => { key_values => [ { name => 'hostsRealtimeNotRunning' } ], output_template => '%d hosts(s) without running real time protection', perfdatas => [ { label => 'no_real_time', template => '%d', min => 0 } ] } }, { label => 'not-acceptable-level', nlabel => 'protection.hosts.realtime.unacceptable.level.count', set => { key_values => [ { name => 'hostsRealtimeLevelChanged' } ], output_template => '%d host(s) with not acceptable level of real time protection', perfdatas => [ { label => 'not_acceptable_level', value => 'hostsRealtimeLevelChanged', template => '%d', min => 0 } ] } }, { label => 'not-cured-objects', nlabel => 'protection.hosts.uncured.objects.count', set => { key_values => [ { name => 'hostsNotCuredObject' } ], output_template => '%d host(s) with not cured objects', perfdatas => [ { label => 'not_cured_objects', value => 'hostsNotCuredObject', template => '%d', min => 0 } ] } }, { label => 'too-many-threats', nlabel => 'protection.hosts.toomanythreats.count', set => { key_values => [ { name => 'hostsTooManyThreats' } ], output_template => '%d host(s) with too many threats', perfdatas => [ { label => 'too_many_threats', template => '%d', min => 0 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my %map_status = ( 0 => 'OK', 1 => 'Info', 2 => 'Warning', 3 => 'Critical' ); my $oid_protectionStatus = '.1.3.6.1.4.1.23668.1093.1.3.1'; my $oid_hostsAntivirusNotRunning = '.1.3.6.1.4.1.23668.1093.1.3.3'; my $oid_hostsRealtimeNotRunning = '.1.3.6.1.4.1.23668.1093.1.3.4'; my $oid_hostsRealtimeLevelChanged = '.1.3.6.1.4.1.23668.1093.1.3.5'; my $oid_hostsNotCuredObject = '.1.3.6.1.4.1.23668.1093.1.3.6'; my $oid_hostsTooManyThreats = '.1.3.6.1.4.1.23668.1093.1.3.7'; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_leef( oids => [ $oid_protectionStatus, $oid_hostsAntivirusNotRunning, $oid_hostsRealtimeNotRunning, $oid_hostsRealtimeLevelChanged, $oid_hostsNotCuredObject, $oid_hostsTooManyThreats ], nothing_quit => 1 ); $self->{global} = { protectionStatus => $map_status{$snmp_result->{$oid_protectionStatus}}, hostsAntivirusNotRunning => $snmp_result->{$oid_hostsAntivirusNotRunning}, hostsRealtimeNotRunning => $snmp_result->{$oid_hostsRealtimeNotRunning}, hostsRealtimeLevelChanged => $snmp_result->{$oid_hostsRealtimeLevelChanged}, hostsNotCuredObject => $snmp_result->{$oid_hostsNotCuredObject}, hostsTooManyThreats => $snmp_result->{$oid_hostsTooManyThreats} }; } 1; __END__ =head1 MODE Check protection status. =over 8 =item B<--warning-status> Set warning threshold for status. (Default: '%{status} =~ /Warning/i'). Can use special variables like: %{status} =item B<--critical-status> Set critical threshold for status. (Default: '%{status} =~ /Critical/i'). Can use special variables like: %{status} =item B<--warning-*> Threshold warning. Can be: 'no-antivirus', 'no-real-time', 'not-acceptable-level', 'not-cured-objects', 'too-many-threats'. =item B<--critical-*> Threshold critical. Can be: 'no-antivirus', 'no-real-time', 'not-acceptable-level', 'not-cured-objects', 'too-many-threats'. =back =cut centreon-plugins-20220113/apps/antivirus/kaspersky/snmp/mode/updates.pm000066400000000000000000000144301417000230700261450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::antivirus::kaspersky::snmp::mode::updates; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use DateTime; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf("Updates status is '%s'", $self->{result_values}->{status}); } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_updatesStatus'}; return 0; } sub custom_last_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => 'last_server_update', nlabel => $self->{nlabel}, value => $self->{result_values}->{diff}, unit => 's', min => 0 ); } sub custom_last_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check( value => $self->{result_values}->{diff}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_last_output { my ($self, %options) = @_; return sprintf( 'Last server update: %s [%s]', centreon::plugins::misc::change_seconds(value => $self->{result_values}->{diff}), $self->{result_values}->{date_time} ); } sub custom_last_calc { my ($self, %options) = @_; my $time = $options{new_datas}->{$self->{instance} . '_lastServerUpdateTime'}; #2018-3-30,7:43:58.0 if ($time =~ /^\s*(\d+)-(\d+)-(\d+),(\d+):(\d+):(\d+)\.(\d+)/) { my $dt = DateTime->new( year => $1, month => $2, day => $3, hour => $4, minute => $5, second => $6, %{$self->{instance_mode}->{tz}} ); $self->{result_values}->{diff} = time() - $dt->epoch; $self->{result_values}->{date_time} = $dt->datetime(); } return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, message_separator => ' - ' } ]; $self->{maps_counters}->{global} = [ { label => 'status', type => 2, warning_default => '%{status} =~ /Warning/i', critical_default => '%{status} =~ /Critical/i', set => { key_values => [ { name => 'updatesStatus' } ], 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 => \&catalog_status_threshold_ng } }, { label => 'last-server-update', nlabel => 'update.server.freshness.seconds', set => { key_values => [ { name => 'lastServerUpdateTime' } ], closure_custom_calc => $self->can('custom_last_calc'), closure_custom_output => $self->can('custom_last_output'), closure_custom_threshold_check => $self->can('custom_last_threshold'), closure_custom_perfdata => $self->can('custom_last_perfdata') } }, { label => 'not-updated', nlabel => 'update.hosts.outdated.count', set => { key_values => [ { name => 'hostsNotUpdated' } ], output_template => '%d host(s) not up to date', perfdatas => [ { label => 'not_updated', template => '%d', min => 0 } ] } } ]; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{tz} = centreon::plugins::misc::set_timezone(name => $self->{option_results}->{timezone}); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'timezone:s' => { name => 'timezone', default => 'GMT' } }); return $self; } my $map_status = { 0 => 'OK', 1 => 'Info', 2 => 'Warning', 3 => 'Critical' }; my $oid_updatesStatus = '.1.3.6.1.4.1.23668.1093.1.2.1'; my $oid_lastServerUpdateTime = '.1.3.6.1.4.1.23668.1093.1.2.3'; my $oid_hostsNotUpdated = '.1.3.6.1.4.1.23668.1093.1.2.4'; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_leef( oids => [ $oid_updatesStatus, $oid_lastServerUpdateTime, $oid_hostsNotUpdated ], nothing_quit => 1 ); $self->{global} = { updatesStatus => $map_status->{$snmp_result->{$oid_updatesStatus}}, lastServerUpdateTime => $snmp_result->{$oid_lastServerUpdateTime}, hostsNotUpdated => $snmp_result->{$oid_hostsNotUpdated}, }; } 1; __END__ =head1 MODE Check updates status. =over 8 =item B<--warning-status> Set warning threshold for status. (Default: '%{status} =~ /Warning/i'). Can use special variables like: %{status} =item B<--critical-status> Set critical threshold for status. (Default: '%{status} =~ /Critical/i'). Can use special variables like: %{status} =item B<--warning-*> Threshold warning. Can be: 'last-server-update', 'not-updated'. =item B<--critical-*> Threshold critical. Can be: 'last-server-update', 'not-updated'. =item B<--timezone> Timezone options. Default is 'GMT'. =back =cut centreon-plugins-20220113/apps/antivirus/kaspersky/snmp/plugin.pm000066400000000000000000000032271417000230700250540ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::antivirus::kaspersky::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} = { 'deployment' => 'apps::antivirus::kaspersky::snmp::mode::deployment', 'events' => 'apps::antivirus::kaspersky::snmp::mode::events', 'full-scan' => 'apps::antivirus::kaspersky::snmp::mode::fullscan', 'logical-network' => 'apps::antivirus::kaspersky::snmp::mode::logicalnetwork', 'protection' => 'apps::antivirus::kaspersky::snmp::mode::protection', 'updates' => 'apps::antivirus::kaspersky::snmp::mode::updates', }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Kaspersky Security Center through SNMP =cut centreon-plugins-20220113/apps/antivirus/mcafee/000077500000000000000000000000001417000230700214435ustar00rootroot00000000000000centreon-plugins-20220113/apps/antivirus/mcafee/webgateway/000077500000000000000000000000001417000230700236025ustar00rootroot00000000000000centreon-plugins-20220113/apps/antivirus/mcafee/webgateway/snmp/000077500000000000000000000000001417000230700245575ustar00rootroot00000000000000centreon-plugins-20220113/apps/antivirus/mcafee/webgateway/snmp/mode/000077500000000000000000000000001417000230700255035ustar00rootroot00000000000000centreon-plugins-20220113/apps/antivirus/mcafee/webgateway/snmp/mode/clients.pm000066400000000000000000000055731417000230700275140ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::antivirus::mcafee::webgateway::snmp::mode::clients; 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 } ]; $self->{maps_counters}->{global} = [ { label => 'clients', nlabel => 'clients.connected.count', set => { key_values => [ { name => 'stClientCount' } ], output_template => 'Connected clients: %d', perfdatas => [ { label => 'connected_clients', template => '%d', min => 0, unit => 'clients' } ] } }, { label => 'sockets', nlabel => 'sockets.connected.count', set => { key_values => [ { name => 'stConnectedSockets' } ], output_template => 'Open network sockets: %d', perfdatas => [ { label => 'open_sockets', template => '%d', min => 0, unit => 'sockets' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my $oid_stClientCount = '.1.3.6.1.4.1.1230.2.7.2.5.2.0'; my $oid_stConnectedSockets = '.1.3.6.1.4.1.1230.2.7.2.5.3.0'; sub manage_selection { my ($self, %options) = @_; my $results = $options{snmp}->get_leef( oids => [ $oid_stClientCount, $oid_stConnectedSockets ], nothing_quit => 1 ); $self->{global} = { stClientCount => $results->{$oid_stClientCount}, stConnectedSockets => $results->{$oid_stConnectedSockets}, }; } 1; __END__ =head1 MODE Check connected clients and open network sockets. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). (Example: --filter-counters='clients') =item B<--warning-*> Threshold warning. Can be: 'clients', 'sockets'. =item B<--critical-*> Threshold critical. Can be: 'clients', 'sockets'. =back =cut centreon-plugins-20220113/apps/antivirus/mcafee/webgateway/snmp/mode/connections.pm000066400000000000000000000126411417000230700303670ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::antivirus::mcafee::webgateway::snmp::mode::connections; 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 => 'global', type => 0, cb_prefix_output => 'prefix_connection_output' } ]; $self->{maps_counters}->{global} = [ { label => 'legitimate', nlabel => 'connections.legitimate.persecond', set => { key_values => [ { name => 'stConnectionsLegitimate', per_second => 1 } ], output_template => 'Legitimate: %d', perfdatas => [ { label => 'legitimate_connections', template => '%d', min => 0, unit => 'connections/s' } ] } }, { label => 'blocked', nlabel => 'connections.blocked.persecond', set => { key_values => [ { name => 'stConnectionsBlocked', per_second => 1 } ], output_template => 'Blocked: %d', perfdatas => [ { label => 'blocked_connections', template => '%d', min => 0, unit => 'connections/s' } ] } }, { label => 'blocked-by-am', nlabel => 'connections.antimalware.blocked.persecond', set => { key_values => [ { name => 'stBlockedByAntiMalware', per_second => 1 } ], output_template => 'Blocked by Anti Malware: %d', perfdatas => [ { label => 'blocked_by_am', template => '%d', min => 0, unit => 'connections/s' } ] } }, { label => 'blocked-by-mf', nlabel => 'connections.mediafilter.blocked.persecond', set => { key_values => [ { name => 'stBlockedByMediaFilter', per_second => 1 } ], output_template => 'Blocked by Media Filter: %d', perfdatas => [ { label => 'blocked_by_mf', template => '%d', min => 0, unit => 'connections/s' } ] } }, { label => 'blocked-by-uf', nlabel => 'connections.urlfilter.blocked.persecond', set => { key_values => [ { name => 'stBlockedByURLFilter', per_second => 1 } ], output_template => 'Blocked by URL Filter: %d', perfdatas => [ { label => 'blocked_by_uf', template => '%d', min => 0, unit => 'connections/s' } ] } } ]; } sub prefix_connection_output { my ($self, %options) = @_; return 'Connections (per sec) '; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my $oid_stConnectionsLegitimate = '.1.3.6.1.4.1.1230.2.7.2.1.3.0'; my $oid_stBlockedByAntiMalware = '.1.3.6.1.4.1.1230.2.7.2.1.4.0'; my $oid_stConnectionsBlocked = '.1.3.6.1.4.1.1230.2.7.2.1.5.0'; my $oid_stBlockedByMediaFilter = '.1.3.6.1.4.1.1230.2.7.2.1.6.0'; my $oid_stBlockedByURLFilter = '.1.3.6.1.4.1.1230.2.7.2.1.7.0'; sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = 'mcafee_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); my $results = $options{snmp}->get_leef( oids => [ $oid_stConnectionsLegitimate, $oid_stBlockedByAntiMalware, $oid_stConnectionsBlocked, $oid_stBlockedByMediaFilter, $oid_stBlockedByURLFilter ], nothing_quit => 1 ); $self->{global} = { stConnectionsLegitimate => $results->{$oid_stConnectionsLegitimate}, stBlockedByAntiMalware => $results->{$oid_stBlockedByAntiMalware}, stConnectionsBlocked => $results->{$oid_stConnectionsBlocked}, stBlockedByMediaFilter => $results->{$oid_stBlockedByMediaFilter}, stBlockedByURLFilter => $results->{$oid_stBlockedByURLFilter}, }; } 1; __END__ =head1 MODE Check connections statistics. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). (Example: --filter-counters='blocked') =item B<--warning-*> Threshold warning. Can be: 'legitimate', 'blocked', 'blocked-by-am', 'blocked-by-mf', 'blocked-by-uf'. =item B<--critical-*> Threshold critical. Can be: 'legitimate', 'blocked', 'blocked-by-am', 'blocked-by-mf', 'blocked-by-uf'. =back =cut centreon-plugins-20220113/apps/antivirus/mcafee/webgateway/snmp/mode/detections.pm000066400000000000000000000121241417000230700302020ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::antivirus::mcafee::webgateway::snmp::mode::detections; 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 => 'global', type => 0 }, { name => 'categories', type => 1, cb_prefix_output => 'prefix_categories_output', message_multiple => 'All categories are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'malware-detected', nlabel => 'malwares.detected.persecond', set => { key_values => [ { name => 'stMalwareDetected', per_second => 1 } ], output_template => 'Malware detected (per sec): %d', perfdatas => [ { label => 'malware_detected', template => '%d', min => 0, unit => 'detections/s' } ] } } ]; $self->{maps_counters}->{categories} = [ { label => 'category', nlabel => 'category.malwares.detected.persecond', set => { key_values => [ { name => 'stCategoryCount', per_second => 1 }, { name => 'stCategoryName' } ], output_template => 'detections (per sec): %d', perfdatas => [ { label => 'category', template => '%d', min => 0, unit => 'detections/s', label_extra_instance => 1, instance_use => 'stCategoryName' } ] } } ]; } sub prefix_categories_output { my ($self, %options) = @_; return "Category '" . $options{instance_value}->{stCategoryName} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } my $oid_stMalwareDetected = '.1.3.6.1.4.1.1230.2.7.2.1.2.0'; my $mapping = { stCategoryName => { oid => '.1.3.6.1.4.1.1230.2.7.2.1.10.1.1' }, stCategoryCount => { oid => '.1.3.6.1.4.1.1230.2.7.2.1.10.1.2' }, }; my $oid_stCategoriesEntry = '.1.3.6.1.4.1.1230.2.7.2.1.10.1'; sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = 'mcafee_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); my $results = $options{snmp}->get_leef(oids => [ $oid_stMalwareDetected ], nothing_quit => 1); my $results2 = $options{snmp}->get_table(oid => $oid_stCategoriesEntry, nothing_quit => 1); $self->{global} = { stMalwareDetected => $results->{$oid_stMalwareDetected}, }; $self->{categories} = {}; foreach my $oid (keys %{$results2}) { next if ($oid !~ /^$mapping->{stCategoryName}->{oid}\.(\d+)/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $results2, instance => $instance); if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $result->{stCategoryName} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{stCategoryName} . "': no matching filter name.", debug => 1); next; } $self->{categories}->{ $result->{stCategoryName} } = { stCategoryName => $result->{stCategoryName}, stCategoryCount => $result->{stCategoryCount} } } if (scalar(keys %{$self->{categories}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No categories found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check detections statistics. =over 8 =item B<--filter-name> Filter category name (can be a regexp). =item B<--filter-counters> Only display some counters (regexp can be used). (Example: --filter-counters='^(?!(category)$)') =item B<--warning-*> Threshold warning. Can be: 'malware-detected', 'category' =item B<--critical-*> Threshold critical. Can be: 'malware-detected', 'category' =back =cut centreon-plugins-20220113/apps/antivirus/mcafee/webgateway/snmp/mode/ftpstatistics.pm000066400000000000000000000117711417000230700307540ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::antivirus::mcafee::webgateway::snmp::mode::ftpstatistics; 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 => 'traffics', type => 0, cb_prefix_output => 'prefix_traffic_output' } ]; $self->{maps_counters}->{traffics} = [ { label => 'client-to-proxy', nlabel => 'ftp.traffic.client2proxy.bitspersecond', set => { key_values => [ { name => 'stFtpBytesFromClient', per_second => 1 } ], output_template => 'from client to proxy: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'ftp_traffic_client_to_proxy', template => '%d', min => 0, unit => 'b/s' } ] } }, { label => 'server-to-proxy', nlabel => 'ftp.traffic.server2proxy.bitspersecond', set => { key_values => [ { name => 'stFtpBytesFromServer', per_second => 1 } ], output_template => 'from server to proxy: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'ftp_traffic_server_to_proxy', template => '%d', min => 0, unit => 'b/s' } ] } }, { label => 'proxy-to-client', nlabel => 'ftp.traffic.proxy2client.bitspersecond', set => { key_values => [ { name => 'stFtpBytesToClient', per_second => 1 } ], output_template => 'from proxy to client: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'ftp_traffic_proxy_to_client', template => '%d', min => 0, unit => 'b/s' } ] } }, { label => 'proxy-to-server', nlabel => 'ftp.traffic.proxy2server.bitspersecond', set => { key_values => [ { name => 'stFtpBytesToServer', per_second => 1 } ], output_template => 'from proxy to server: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'ftp_traffic_proxy_to_server', template => '%d', min => 0, unit => 'b/s' } ] } } ]; } sub prefix_traffic_output { my ($self, %options) = @_; return "FTP Traffic "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my $oid_stFtpBytesFromClient = '.1.3.6.1.4.1.1230.2.7.2.4.2.0'; my $oid_stFtpBytesFromServer = '.1.3.6.1.4.1.1230.2.7.2.4.3.0'; my $oid_stFtpBytesToClient = '.1.3.6.1.4.1.1230.2.7.2.4.4.0'; my $oid_stFtpBytesToServer = '.1.3.6.1.4.1.1230.2.7.2.4.5.0'; sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = 'mcafee_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); my $results = $options{snmp}->get_leef( oids => [ $oid_stFtpBytesFromClient, $oid_stFtpBytesFromServer, $oid_stFtpBytesToClient, $oid_stFtpBytesToServer ], nothing_quit => 1 ); $self->{traffics} = { stFtpBytesFromClient => $results->{$oid_stFtpBytesFromClient} * 8, stFtpBytesFromServer => $results->{$oid_stFtpBytesFromServer} * 8, stFtpBytesToClient => $results->{$oid_stFtpBytesToClient} * 8, stFtpBytesToServer => $results->{$oid_stFtpBytesToServer} * 8, }; } 1; __END__ =head1 MODE Check FTP statistics. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). (Example: --filter-counters='^proxy') =item B<--warning-*> Threshold warning. Can be: 'client-to-proxy', 'server-to-proxy', 'proxy-to-client', 'proxy-to-server'. =item B<--critical-*> Threshold critical. Can be: 'client-to-proxy', 'server-to-proxy', 'proxy-to-client', 'proxy-to-server'. =back =cut centreon-plugins-20220113/apps/antivirus/mcafee/webgateway/snmp/mode/httpsstatistics.pm000066400000000000000000000133551417000230700313250ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::antivirus::mcafee::webgateway::snmp::mode::httpsstatistics; 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 => 'global', type => 0 }, { name => 'traffics', type => 0, cb_prefix_output => 'prefix_traffic_output' } ]; $self->{maps_counters}->{global} = [ { label => 'requests', nlabel => 'https.requests.persecond', set => { key_values => [ { name => 'stHttpsRequests', per_second => 1 } ], output_template => 'HTTPS Requests (per sec): %d', perfdatas => [ { label => 'https_requests', template => '%d', min => 0, unit => 'requests/s' } ] } } ]; $self->{maps_counters}->{traffics} = [ { label => 'client-to-proxy', nlabel => 'https.traffic.client2proxy.bitspersecond', set => { key_values => [ { name => 'stHttpsBytesFromClient', per_second => 1 } ], output_template => 'from client to proxy: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'https_traffic_client_to_proxy', template => '%d', min => 0, unit => 'b/s' } ] } }, { label => 'server-to-proxy', nlabel => 'https.traffic.server2proxy.bitspersecond', set => { key_values => [ { name => 'stHttpsBytesFromServer', per_second => 1 } ], output_template => 'from server to proxy: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'https_traffic_server_to_proxy', template => '%d', min => 0, unit => 'b/s' } ] } }, { label => 'proxy-to-client', nlabel => 'https.traffic.proxy2client.bitspersecond', set => { key_values => [ { name => 'stHttpsBytesToClient', per_second => 1 } ], output_template => 'from proxy to client: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'https_traffic_proxy_to_client', template => '%d', min => 0, unit => 'b/s' } ] } }, { label => 'proxy-to-server', nlabel => 'https.traffic.proxy2server.bitspersecond', set => { key_values => [ { name => 'stHttpsBytesToServer', per_second => 1 } ], output_template => 'from proxy to server: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'https_traffic_proxy_to_server', template => '%d', min => 0, unit => 'b/s' } ] } } ]; } sub prefix_traffic_output { my ($self, %options) = @_; return "HTTPS Traffic "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my $oid_stHttpsRequests = '.1.3.6.1.4.1.1230.2.7.2.3.1.0'; my $oid_stHttpsBytesFromClient = '.1.3.6.1.4.1.1230.2.7.2.3.3.0'; my $oid_stHttpsBytesFromServer = '.1.3.6.1.4.1.1230.2.7.2.3.4.0'; my $oid_stHttpsBytesToClient = '.1.3.6.1.4.1.1230.2.7.2.3.5.0'; my $oid_stHttpsBytesToServer = '.1.3.6.1.4.1.1230.2.7.2.3.6.0'; sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = 'mcafee_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); my $results = $options{snmp}->get_leef( oids => [ $oid_stHttpsRequests, $oid_stHttpsBytesFromClient, $oid_stHttpsBytesFromServer, $oid_stHttpsBytesToClient, $oid_stHttpsBytesToServer ], nothing_quit => 1 ); $self->{global} = { stHttpsRequests => $results->{$oid_stHttpsRequests} }; $self->{traffics} = { stHttpsBytesFromClient => $results->{$oid_stHttpsBytesFromClient} * 8, stHttpsBytesFromServer => $results->{$oid_stHttpsBytesFromServer} * 8, stHttpsBytesToClient => $results->{$oid_stHttpsBytesToClient} * 8, stHttpsBytesToServer => $results->{$oid_stHttpsBytesToServer} * 8 }; } 1; __END__ =head1 MODE Check HTTPS statistics. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). (Example: --filter-counters='^proxy') =item B<--warning-*> Threshold warning. Can be: 'request', 'client-to-proxy', 'server-to-proxy', 'proxy-to-client', 'proxy-to-server'. =item B<--critical-*> Threshold critical. Can be: 'request', 'client-to-proxy', 'server-to-proxy', 'proxy-to-client', 'proxy-to-server'. =back =cut centreon-plugins-20220113/apps/antivirus/mcafee/webgateway/snmp/mode/httpstatistics.pm000066400000000000000000000133071417000230700311370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::antivirus::mcafee::webgateway::snmp::mode::httpstatistics; 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 => 'global', type => 0 }, { name => 'traffics', type => 0, cb_prefix_output => 'prefix_traffic_output' } ]; $self->{maps_counters}->{global} = [ { label => 'requests', nlabel => 'http.requests.persecond', set => { key_values => [ { name => 'stHttpRequests', per_second => 1 } ], output_template => 'HTTP Requests (per sec): %d', perfdatas => [ { label => 'http_requests', template => '%d', min => 0, unit => 'requests/s' } ] } } ]; $self->{maps_counters}->{traffics} = [ { label => 'client-to-proxy', nlabel => 'http.traffic.client2proxy.bitspersecond', set => { key_values => [ { name => 'stHttpBytesFromClient', per_second => 1 } ], output_template => 'from client to proxy: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'http_traffic_client_to_proxy', template => '%d', min => 0, unit => 'b/s' } ] } }, { label => 'server-to-proxy', nlabel => 'http.traffic.server2proxy.bitspersecond', set => { key_values => [ { name => 'stHttpBytesFromServer', per_second => 1 } ], output_template => 'from server to proxy: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'http_traffic_server_to_proxy', template => '%d', min => 0, unit => 'b/s' } ] } }, { label => 'proxy-to-client', nlabel => 'http.traffic.proxy2client.bitspersecond', set => { key_values => [ { name => 'stHttpBytesToClient', per_second => 1 } ], output_template => 'from proxy to client: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'http_traffic_proxy_to_client', template => '%d', min => 0, unit => 'b/s' } ] } }, { label => 'proxy-to-server', nlabel => 'http.traffic.proxy2server.bitspersecond', set => { key_values => [ { name => 'stHttpBytesToServer', per_second => 1 } ], output_template => 'from proxy to server: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'http_traffic_proxy_to_server', template => '%d', min => 0, unit => 'b/s' } ] } } ]; } sub prefix_traffic_output { my ($self, %options) = @_; return "HTTP Traffic "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my $oid_stHttpRequests = '.1.3.6.1.4.1.1230.2.7.2.2.1.0'; my $oid_stHttpBytesFromClient = '.1.3.6.1.4.1.1230.2.7.2.2.3.0'; my $oid_stHttpBytesFromServer = '.1.3.6.1.4.1.1230.2.7.2.2.4.0'; my $oid_stHttpBytesToClient = '.1.3.6.1.4.1.1230.2.7.2.2.5.0'; my $oid_stHttpBytesToServer = '.1.3.6.1.4.1.1230.2.7.2.2.6.0'; sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = 'mcafee_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); my $results = $options{snmp}->get_leef( oids => [ $oid_stHttpRequests, $oid_stHttpBytesFromClient, $oid_stHttpBytesFromServer, $oid_stHttpBytesToClient, $oid_stHttpBytesToServer ], nothing_quit => 1 ); $self->{global} = { stHttpRequests => $results->{$oid_stHttpRequests} }; $self->{traffics} = { stHttpBytesFromClient => $results->{$oid_stHttpBytesFromClient} * 8, stHttpBytesFromServer => $results->{$oid_stHttpBytesFromServer} * 8, stHttpBytesToClient => $results->{$oid_stHttpBytesToClient} * 8, stHttpBytesToServer => $results->{$oid_stHttpBytesToServer} * 8 }; } 1; __END__ =head1 MODE Check HTTP statistics. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). (Example: --filter-counters='^proxy') =item B<--warning-*> Threshold warning. Can be: 'request', 'client-to-proxy', 'server-to-proxy', 'proxy-to-client', 'proxy-to-server'. =item B<--critical-*> Threshold critical. Can be: 'request', 'client-to-proxy', 'server-to-proxy', 'proxy-to-client', 'proxy-to-server'. =back =cut centreon-plugins-20220113/apps/antivirus/mcafee/webgateway/snmp/mode/system.pm000066400000000000000000000053301417000230700273660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::antivirus::mcafee::webgateway::snmp::mode::system; 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 } ]; $self->{maps_counters}->{global} = [ { label => 'cpu-utilization', nlabel => 'system.cpu.utilization.percentage', set => { key_values => [ { name => 'cpu_util' } ], output_template => 'cpu usage: %.2f%%', perfdatas => [ { template => '%.2f', unit => '%', min => 0, max => 100 } ] } }, { label => 'dns-resolve-time', nlabel => 'system.dns.resolve.time.milliseconds', set => { key_values => [ { name => 'dns_time' } ], output_template => 'time to resolve dns: %sms', perfdatas => [ { template => '%s', unit => 'ms', min => 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 => { }); return $self; } my $oid_stCPULoad = '.1.3.6.1.4.1.1230.2.7.2.5.1.0'; my $oid_stResolveHostViaDNS = '.1.3.6.1.4.1.1230.2.7.2.5.6.0'; sub manage_selection { my ($self, %options) = @_; my $results = $options{snmp}->get_leef( oids => [ $oid_stCPULoad, $oid_stResolveHostViaDNS ], nothing_quit => 1 ); $self->{global} = { cpu_util => $results->{$oid_stCPULoad}, dns_time => $results->{$oid_stResolveHostViaDNS} }; } 1; __END__ =head1 MODE Check system. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). (Example: --filter-counters='cpu') =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'cpu-utilization', 'dns-resolve-time'. =back =cut centreon-plugins-20220113/apps/antivirus/mcafee/webgateway/snmp/mode/versions.pm000066400000000000000000000150031417000230700277100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::antivirus::mcafee::webgateway::snmp::mode::versions; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::statefile; use Digest::MD5 qw(md5_hex); sub custom_version_calc { my ($self, %options) = @_; $self->{result_values}->{output} = $options{extra_options}->{output_ref}; $self->{result_values}->{version} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{label_ref}}; $self->{result_values}->{timestamp} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{label_ref} . '_timestamp'}; $self->{result_values}->{since} = time() - $self->{result_values}->{timestamp}; return 0; } sub custom_version_threshold { my ($self, %options) = @_; return $self->{perfdata}->threshold_check( value => $self->{result_values}->{since}, threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{label}, exit_litteral => 'warning' } ] ); } sub custom_version_output { my ($self, %options) = @_; return sprintf( "%s: %s [Last update: %s]", $self->{result_values}->{output}, $self->{result_values}->{version}, centreon::plugins::misc::change_seconds(value => $self->{result_values}->{since}) ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'dat-version', set => { key_values => [ { name => 'pMFEDATVersion' }, { name => 'pMFEDATVersion_timestamp' } ], closure_custom_calc => $self->can('custom_version_calc'), closure_custom_calc_extra_options => { label_ref => 'pMFEDATVersion', output_ref => 'DAT Version' }, closure_custom_output => $self->can('custom_version_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => $self->can('custom_version_threshold') } }, { label => 'tsdb-version', set => { key_values => [ { name => 'pTSDBVersion' }, { name => 'pTSDBVersion_timestamp' } ], closure_custom_calc => $self->can('custom_version_calc'), closure_custom_calc_extra_options => { label_ref => 'pTSDBVersion', output_ref => 'TrustedSource Database Version' }, closure_custom_output => $self->can('custom_version_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => $self->can('custom_version_threshold') } }, { label => 'proactive-version', set => { key_values => [ { name => 'pAMProactiveVersion' }, { name => 'pAMProactiveVersion_timestamp' } ], closure_custom_calc => $self->can('custom_version_calc'), closure_custom_calc_extra_options => { label_ref => 'pAMProactiveVersion', output_ref => 'ProActive Database Version' }, closure_custom_output => $self->can('custom_version_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => $self->can('custom_version_threshold') } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); $self->{cache} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{cache}->check_options(%options); } my $oid_pMFEDATVersion = '.1.3.6.1.4.1.1230.2.7.1.20.4.0'; my $oid_pAMProactiveVersion = '.1.3.6.1.4.1.1230.2.7.1.20.5.0'; my $oid_pTSDBVersion = '.1.3.6.1.4.1.1230.2.7.1.20.6.0'; sub manage_selection { my ($self, %options) = @_; $self->{cache}->read(statefile => 'mcafee_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all'))); my $results = $options{snmp}->get_leef( oids => [ $oid_pMFEDATVersion, $oid_pAMProactiveVersion, $oid_pTSDBVersion ], nothing_quit => 1 ); $self->{new_datas} = { pMFEDATVersion => $results->{$oid_pMFEDATVersion}, pAMProactiveVersion => $results->{$oid_pAMProactiveVersion}, pTSDBVersion => $results->{$oid_pTSDBVersion} }; foreach my $version (('pMFEDATVersion', 'pAMProactiveVersion', 'pTSDBVersion')) { next if (!defined($self->{new_datas}->{$version}) || $self->{new_datas}->{$version} eq ''); $self->{new_datas}->{$version . '_timestamp'} = ($self->{new_datas}->{$version} > $self->{cache}->{datas}->{$version}) ? time() : $self->{cache}->{datas}->{$version . '_timestamp'}; $self->{new_datas}->{$version . '_timestamp'} = time() if (!defined($self->{new_datas}->{$version . '_timestamp'})); } $self->{global} = { %{$self->{new_datas}} }; $self->{cache}->write(data => $self->{new_datas}); } 1; __END__ =head1 MODE Check signature databases versions (last update is only guessed by version's changement, it does not appear clearly in the MIB). =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). (Example: --filter-counters='dat') =item B<--warning-*> Threshold warning on last update. Can be: 'dat-version', 'tsdb-version', 'proactive-version'. =item B<--critical-*> Threshold critical on last update. Can be: 'dat-version', 'tsdb-version', 'proactive-version'. =back =cut centreon-plugins-20220113/apps/antivirus/mcafee/webgateway/snmp/plugin.pm000066400000000000000000000036311417000230700264160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::antivirus::mcafee::webgateway::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} = { 'clients' => 'apps::antivirus::mcafee::webgateway::snmp::mode::clients', 'connections' => 'apps::antivirus::mcafee::webgateway::snmp::mode::connections', 'detections' => 'apps::antivirus::mcafee::webgateway::snmp::mode::detections', 'ftp-statistics' => 'apps::antivirus::mcafee::webgateway::snmp::mode::ftpstatistics', 'http-statistics' => 'apps::antivirus::mcafee::webgateway::snmp::mode::httpstatistics', 'https-statistics' => 'apps::antivirus::mcafee::webgateway::snmp::mode::httpsstatistics', 'system' => 'apps::antivirus::mcafee::webgateway::snmp::mode::system', 'versions' => 'apps::antivirus::mcafee::webgateway::snmp::mode::versions', }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check McAfee Web Gateway through SNMP. =cut centreon-plugins-20220113/apps/apache/000077500000000000000000000000001417000230700174205ustar00rootroot00000000000000centreon-plugins-20220113/apps/apache/serverstatus/000077500000000000000000000000001417000230700221725ustar00rootroot00000000000000centreon-plugins-20220113/apps/apache/serverstatus/mode/000077500000000000000000000000001417000230700231165ustar00rootroot00000000000000centreon-plugins-20220113/apps/apache/serverstatus/mode/cpuload.pm000066400000000000000000000117401417000230700251060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::apache::serverstatus::mode::cpuload; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::http; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "hostname:s" => { name => 'hostname' }, "port:s" => { name => 'port', }, "proto:s" => { name => 'proto' }, "urlpath:s" => { name => 'url_path', default => "/server-status/?auto" }, "credentials" => { name => 'credentials' }, "basic" => { name => 'basic' }, "username:s" => { name => 'username' }, "password:s" => { name => 'password' }, "header:s@" => { name => 'header' }, "warning:s" => { name => 'warning' }, "critical:s" => { name => 'critical' }, "timeout:s" => { name => 'timeout' }, }); $self->{http} = centreon::plugins::http->new(%options); 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(); } $self->{http}->set_options(%{$self->{option_results}}); } sub run { my ($self, %options) = @_; my $webcontent = $self->{http}->request(); # If not present: cpuload is 0 my ($cpuload) = 0; if ($webcontent !~ /^ReqPerSec:\s+([^\s]+)/mi) { $self->{output}->add_option_msg(short_msg => "Apache 'ExtendedStatus' option is off."); $self->{output}->option_exit(); } if ($webcontent =~ /^CPULoad:\s+([^\s]+)/mi) { $cpuload = $1; $cpuload = '0' . $cpuload if ($cpuload =~ /^\./); } my $exit = $self->{perfdata}->threshold_check(value => $cpuload, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit, short_msg => sprintf("CPU Load: %.2f %%", $cpuload)); $self->{output}->perfdata_add(label => "cpuload", unit => '%', value => sprintf("%.2f", $cpuload), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0 ); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check Apache WebServer CpuLoad =over 8 =item B<--hostname> IP Addr/FQDN of the webserver host =item B<--port> Port used by Apache =item B<--proto> Specify https if needed =item B<--urlpath> Set path to get server-status page in auto mode (Default: '/server-status/?auto') =item B<--credentials> Specify this option if you access server-status page with authentication =item B<--username> Specify username for authentication (Mandatory if --credentials is specified) =item B<--password> Specify password for authentication (Mandatory if --credentials is specified) =item B<--basic> Specify this option if you access server-status page over basic authentication and don't want a '401 UNAUTHORIZED' error to be logged on your webserver. Specify this option if you access server-status page over hidden basic authentication or you'll get a '404 NOT FOUND' error. (Use with --credentials) =item B<--timeout> Threshold for HTTP timeout =item B<--header> Set HTTP headers (Multiple option) =item B<--warning> Warning Threshold for CpuLoad =item B<--critical> Critical Threshold for CpuLoad =back =cut centreon-plugins-20220113/apps/apache/serverstatus/mode/requests.pm000066400000000000000000000274661417000230700253460ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::apache::serverstatus::mode::requests; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::http; use centreon::plugins::statefile; use centreon::plugins::misc; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port', }, 'proto:s' => { name => 'proto' }, 'urlpath:s' => { name => 'url_path', default => "/server-status/?auto" }, 'credentials' => { name => 'credentials' }, 'basic' => { name => 'basic' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'header:s@' => { name => 'header' }, 'warning:s' => { name => 'warning' }, 'critical:s' => { name => 'critical' }, 'warning-bytes:s' => { name => 'warning_bytes' }, 'critical-bytes:s' => { name => 'critical_bytes' }, 'warning-access:s' => { name => 'warning_access' }, 'critical-access:s' => { name => 'critical_access' }, 'timeout:s' => { name => 'timeout' }, }); $self->{http} = centreon::plugins::http->new(%options); $self->{statefile_value} = centreon::plugins::statefile->new(%options); 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 (($self->{perfdata}->threshold_validate(label => 'warning-bytes', value => $self->{option_results}->{warning_bytes})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning-bytes threshold '" . $self->{option_results}->{warning_bytes} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'critical-bytes', value => $self->{option_results}->{critical_bytes})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical-bytes threshold '" . $self->{option_results}->{critical_bytes} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'warning-access', value => $self->{option_results}->{warning_access})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning-access threshold '" . $self->{option_results}->{warning_access} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'critical-access', value => $self->{option_results}->{critical_access})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical-access threshold '" . $self->{option_results}->{critical_access} . "'."); $self->{output}->option_exit(); } $self->{http}->set_options(%{$self->{option_results}}); $self->{statefile_value}->check_options(%options); } sub run { my ($self, %options) = @_; my $webcontent = $self->{http}->request(); #Total accesses: 7323 - Total Traffic: 243.7 MB - Total Duration: 7175675 #CPU Usage: u1489.98 s1118.39 cu0 cs0 - .568% CPU load #.0159 requests/sec - 555 B/second - 34.1 kB/request - 979.882 ms/request my ($rPerSec, $bPerReq, $total_access, $total_bytes, $avg_bPerSec); $total_access = $1 if ($webcontent =~ /^Total Accesses:\s+([^\s]+)/mi); $total_bytes = $1 * 1024 if ($webcontent =~ /^Total kBytes:\s+([^\s]+)/mi); if ($webcontent =~ /Total\s+Traffic:\s+(\S+)\s+(.|)B\s+/mi) { $total_bytes = centreon::plugins::misc::convert_bytes(value => $1, unit => $2 . 'B'); } $rPerSec = $1 if ($webcontent =~ /^ReqPerSec:\s+([^\s]+)/mi); if ($webcontent =~ /^(\S+)\s+requests\/sec/mi) { $rPerSec = $1; $rPerSec = '0' . $rPerSec if ($rPerSec =~ /^\./); } # Need a little time to init $bPerReq = $1 if ($webcontent =~ /^BytesPerReq:\s+([^\s]+)/mi); if ($webcontent =~ /(\S+)\s+(.|)B\/request/mi) { $bPerReq = centreon::plugins::misc::convert_bytes(value => $1, unit => $2 . 'B'); } $avg_bPerSec = $1 if ($webcontent =~ /^BytesPerSec:\s+([^\s]+)/mi); if ($webcontent =~ /(\S+)\s+(.|)B\/second/mi) { $avg_bPerSec = centreon::plugins::misc::convert_bytes(value => $1, unit => $2 . 'B'); } if (!defined($avg_bPerSec)) { $self->{output}->add_option_msg(short_msg => "Apache 'ExtendedStatus' option is off."); $self->{output}->option_exit(); } $rPerSec = '0' . $rPerSec if ($rPerSec =~ /^\./); $avg_bPerSec = '0' . $avg_bPerSec if ($avg_bPerSec =~ /^\./); $bPerReq = '0' . $bPerReq if ($bPerReq =~ /^\./); $self->{statefile_value}->read(statefile => 'apache_' . $self->{option_results}->{hostname} . '_' . $self->{http}->get_port() . '_' . $self->{mode}); my $old_timestamp = $self->{statefile_value}->get(name => 'last_timestamp'); my $old_total_access = $self->{statefile_value}->get(name => 'total_access'); my $old_total_bytes = $self->{statefile_value}->get(name => 'total_bytes'); my $new_datas = {}; $new_datas->{last_timestamp} = time(); $new_datas->{total_bytes} = $total_bytes; $new_datas->{total_access} = $total_access; $self->{statefile_value}->write(data => $new_datas); if (!defined($old_timestamp) || !defined($old_total_access)) { $self->{output}->output_add(severity => 'OK', short_msg => "Buffer creation..."); $self->{output}->display(); $self->{output}->exit(); } $old_total_access = 0 if ($old_total_access > $new_datas->{total_access}); $old_total_bytes = 0 if ($old_total_bytes > $new_datas->{total_bytes}); my $delta_time = $new_datas->{last_timestamp} - $old_timestamp; $delta_time = 1 if ($delta_time == 0); # One seconds ;) my $bPerSec = ($new_datas->{total_bytes} - $old_total_bytes) / $delta_time; my $aPerSec = ($new_datas->{total_access} - $old_total_access) / $delta_time; my $exit1 = $self->{perfdata}->threshold_check(value => $rPerSec, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); my $exit2 = $self->{perfdata}->threshold_check(value => $bPerSec, threshold => [ { label => 'critical-bytes', 'exit_litteral' => 'critical' }, { label => 'warning-bytes', exit_litteral => 'warning' } ]); my $exit3 = $self->{perfdata}->threshold_check(value => $aPerSec, threshold => [ { label => 'critical-access', 'exit_litteral' => 'critical' }, { label => 'warning-access', exit_litteral => 'warning' } ]); my $exit = $self->{output}->get_most_critical(status => [ $exit1, $exit2, $exit3 ]); my ($bPerSec_value, $bPerSec_unit) = $self->{perfdata}->change_bytes(value => $bPerSec); my ($bPerReq_value, $bPerReq_unit) = $self->{perfdata}->change_bytes(value => $bPerReq); $self->{output}->output_add(severity => $exit, short_msg => sprintf("BytesPerSec: %s AccessPerSec: %.2f RequestPerSec: %.2f BytesPerRequest: %s ", $bPerSec_value . ' ' . $bPerSec_unit, $aPerSec, $rPerSec, $bPerReq_value . ' ' . $bPerReq_unit )); $self->{output}->perfdata_add(label => "avg_RequestPerSec", value => sprintf("%.2f", $rPerSec), 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 => "bytesPerSec", unit => 'B', value => sprintf("%.2f", $bPerSec), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-bytes'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-bytes'), min => 0); $self->{output}->perfdata_add(label => "avg_bytesPerRequest", unit => 'B', value => $bPerReq, min => 0 ); $self->{output}->perfdata_add(label => "avg_bytesPerSec", unit => 'B', value => $avg_bPerSec, min => 0 ); $self->{output}->perfdata_add(label => "accessPerSec", value => sprintf("%.2f", $aPerSec), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-access'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-access'), min => 0); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check Apache WebServer Request statistics =over 8 =item B<--hostname> IP Addr/FQDN of the webserver host =item B<--port> Port used by Apache =item B<--proto> Specify https if needed =item B<--urlpath> Set path to get server-status page in auto mode (Default: '/server-status/?auto') =item B<--credentials> Specify this option if you access server-status page with authentication =item B<--username> Specify username for authentication (Mandatory if --credentials is specified) =item B<--password> Specify password for authentication (Mandatory if --credentials is specified) =item B<--basic> Specify this option if you access server-status page over basic authentication and don't want a '401 UNAUTHORIZED' error to be logged on your webserver. Specify this option if you access server-status page over hidden basic authentication or you'll get a '404 NOT FOUND' error. (Use with --credentials) =item B<--timeout> Threshold for HTTP timeout =item B<--header> Set HTTP headers (Multiple option) =item B<--warning> Warning Threshold for Request per seconds =item B<--critical> Critical Threshold for Request per seconds =item B<--warning-bytes> Warning Threshold for Bytes per seconds =item B<--critical-bytes> Critical Threshold for Bytes per seconds =item B<--warning-access> Warning Threshold for Access per seconds =item B<--critical-access> Critical Threshold for Access per seconds =back =cut centreon-plugins-20220113/apps/apache/serverstatus/mode/responsetime.pm000066400000000000000000000124421417000230700261740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::apache::serverstatus::mode::responsetime; use base qw(centreon::plugins::mode); use strict; use warnings; use Time::HiRes qw(gettimeofday tv_interval); use centreon::plugins::http; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "hostname:s" => { name => 'hostname' }, "port:s" => { name => 'port', }, "proto:s" => { name => 'proto' }, "urlpath:s" => { name => 'url_path', default => "/server-status/?auto" }, "credentials" => { name => 'credentials' }, "basic" => { name => 'basic' }, "username:s" => { name => 'username' }, "password:s" => { name => 'password' }, "header:s@" => { name => 'header' }, "warning:s" => { name => 'warning' }, "critical:s" => { name => 'critical' }, "timeout:s" => { name => 'timeout' }, "unknown-status:s" => { name => 'unknown_status', default => '' }, "warning-status:s" => { name => 'warning_status' }, "critical-status:s" => { name => 'critical_status', default => '%{http_code} < 200 or %{http_code} >= 300' }, }); $self->{http} = centreon::plugins::http->new(%options); 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(); } $self->{http}->set_options(%{$self->{option_results}}); } sub run { my ($self, %options) = @_; my $timing0 = [gettimeofday]; my $webcontent = $self->{http}->request(); my $timeelapsed = tv_interval ($timing0, [gettimeofday]); my $exit = $self->{perfdata}->threshold_check(value => $timeelapsed, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit, short_msg => sprintf("Response time %.3fs", $timeelapsed)); $self->{output}->perfdata_add(label => "time", unit => 's', value => sprintf('%.3f', $timeelapsed), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check Apache WebServer Time Response =over 8 =item B<--hostname> IP Addr/FQDN of the webserver host =item B<--port> Port used by Apache =item B<--proto> Specify https if needed =item B<--urlpath> Set path to get server-status page in auto mode (Default: '/server-status/?auto') =item B<--credentials> Specify this option if you access server-status page with authentication =item B<--username> Specify username for authentication (Mandatory if --credentials is specified) =item B<--password> Specify password for authentication (Mandatory if --credentials is specified) =item B<--basic> Specify this option if you access server-status page over basic authentication and don't want a '401 UNAUTHORIZED' error to be logged on your webserver. Specify this option if you access server-status page over hidden basic authentication or you'll get a '404 NOT FOUND' error. (Use with --credentials) =item B<--timeout> Threshold for HTTP timeout =item B<--header> Set HTTP headers (Multiple option) =item B<--unknown-status> Threshold warning for http response code =item B<--warning-status> Threshold warning for http response code =item B<--critical-status> Threshold critical for http response code (Default: '%{http_code} < 200 or %{http_code} >= 300') =item B<--warning> Threshold warning in seconds (server-status page response time) =item B<--critical> Threshold critical in seconds (server-status page response time) =back =cut centreon-plugins-20220113/apps/apache/serverstatus/mode/slotstates.pm000066400000000000000000000335411417000230700256670ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::apache::serverstatus::mode::slotstates; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::http; sub custom_value_threshold { my ($self, %options) = @_; my $exit = 'ok'; if ($self->{instance_mode}->{option_results}->{units} eq '%') { $exit = $self->{perfdata}->threshold_check(value => $self->{result_values}->{prct}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ]); } else { $exit = $self->{perfdata}->threshold_check(value => $self->{result_values}->{used}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ]); } return $exit; } sub custom_value_perfdata { my ($self, %options) = @_; my ($warning, $critical); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $warning = $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1); $critical = $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1); } else { $warning = $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}); $critical = $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}); } $self->{output}->perfdata_add( label => $self->{result_values}->{label}, nlabel => $self->{nlabel}, value => $self->{result_values}->{used}, warning => $warning, critical => $critical, min => 0, max => $self->{result_values}->{total} ); } sub custom_value_output { my ($self, %options) = @_; my $label = $self->{result_values}->{label}; $label =~ s/_/ /g; return sprintf( "%s: %s (%.2f %%)", $label, $self->{result_values}->{used}, $self->{result_values}->{prct} ); } sub custom_value_calc { my ($self, %options) = @_; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_total'}; if ($self->{result_values}->{total} == 0) { $self->{error_msg} = "skipped"; return -2; } $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{label_ref}}; $self->{result_values}->{prct} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; $self->{result_values}->{label} = $options{extra_options}->{label_ref}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -2 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'busy', nlabel => 'apache.slot.busy.count', set => { key_values => [ { name => 'busy' }, { name => 'total' } ], closure_custom_calc => $self->can('custom_value_calc'), closure_custom_calc_extra_options => { label_ref => 'busy' }, closure_custom_output => $self->can('custom_value_output'), closure_custom_threshold_check => $self->can('custom_value_threshold'), closure_custom_perfdata => $self->can('custom_value_perfdata'), } }, { label => 'free', nlabel => 'apache.slot.free.count', set => { key_values => [ { name => 'free' }, { name => 'total' } ], closure_custom_calc => $self->can('custom_value_calc'), closure_custom_calc_extra_options => { label_ref => 'free' }, closure_custom_output => $self->can('custom_value_output'), closure_custom_threshold_check => $self->can('custom_value_threshold'), closure_custom_perfdata => $self->can('custom_value_perfdata'), } }, { label => 'waiting', nlabel => 'apache.slot.waiting.count', set => { key_values => [ { name => 'waiting' }, { name => 'total' } ], closure_custom_calc => $self->can('custom_value_calc'), closure_custom_calc_extra_options => { label_ref => 'waiting' }, closure_custom_output => $self->can('custom_value_output'), closure_custom_threshold_check => $self->can('custom_value_threshold'), closure_custom_perfdata => $self->can('custom_value_perfdata'), } }, { label => 'starting', nlabel => 'apache.slot.starting.count', set => { key_values => [ { name => 'starting' }, { name => 'total' } ], closure_custom_calc => $self->can('custom_value_calc'), closure_custom_calc_extra_options => { label_ref => 'starting' }, closure_custom_output => $self->can('custom_value_output'), closure_custom_threshold_check => $self->can('custom_value_threshold'), closure_custom_perfdata => $self->can('custom_value_perfdata'), } }, { label => 'reading', nlabel => 'apache.slot.reading.count', set => { key_values => [ { name => 'reading' }, { name => 'total' } ], closure_custom_calc => $self->can('custom_value_calc'), closure_custom_calc_extra_options => { label_ref => 'reading' }, closure_custom_output => $self->can('custom_value_output'), closure_custom_threshold_check => $self->can('custom_value_threshold'), closure_custom_perfdata => $self->can('custom_value_perfdata'), } }, { label => 'sending', nlabel => 'apache.slot.sending.count', set => { key_values => [ { name => 'sending' }, { name => 'total' } ], closure_custom_calc => $self->can('custom_value_calc'), closure_custom_calc_extra_options => { label_ref => 'sending' }, closure_custom_output => $self->can('custom_value_output'), closure_custom_threshold_check => $self->can('custom_value_threshold'), closure_custom_perfdata => $self->can('custom_value_perfdata'), } }, { label => 'keepalive', nlabel => 'apache.slot.keepalive.count', set => { key_values => [ { name => 'keepalive' }, { name => 'total' } ], closure_custom_calc => $self->can('custom_value_calc'), closure_custom_calc_extra_options => { label_ref => 'keepalive' }, closure_custom_output => $self->can('custom_value_output'), closure_custom_threshold_check => $self->can('custom_value_threshold'), closure_custom_perfdata => $self->can('custom_value_perfdata'), } }, { label => 'dns-lookup', nlabel => 'apache.slot.dnslookup.count', set => { key_values => [ { name => 'dns_lookup' }, { name => 'total' } ], closure_custom_calc => $self->can('custom_value_calc'), closure_custom_calc_extra_options => { label_ref => 'dns_lookup' }, closure_custom_output => $self->can('custom_value_output'), closure_custom_threshold_check => $self->can('custom_value_threshold'), closure_custom_perfdata => $self->can('custom_value_perfdata'), } }, { label => 'closing', nlabel => 'apache.slot.closing.count', set => { key_values => [ { name => 'closing' }, { name => 'total' } ], closure_custom_calc => $self->can('custom_value_calc'), closure_custom_calc_extra_options => { label_ref => 'closing' }, closure_custom_output => $self->can('custom_value_output'), closure_custom_threshold_check => $self->can('custom_value_threshold'), closure_custom_perfdata => $self->can('custom_value_perfdata'), } }, { label => 'logging', nlabel => 'apache.slot.logging.count', set => { key_values => [ { name => 'logging' }, { name => 'total' } ], closure_custom_calc => $self->can('custom_value_calc'), closure_custom_calc_extra_options => { label_ref => 'logging' }, closure_custom_output => $self->can('custom_value_output'), closure_custom_threshold_check => $self->can('custom_value_threshold'), closure_custom_perfdata => $self->can('custom_value_perfdata'), } }, { label => 'gracefuly-finished', nlabel => 'apache.slot.gracefulyfinished.count', set => { key_values => [ { name => 'gracefuly_finished' }, { name => 'total' } ], closure_custom_calc => $self->can('custom_value_calc'), closure_custom_calc_extra_options => { label_ref => 'gracefuly_finished' }, closure_custom_output => $self->can('custom_value_output'), closure_custom_threshold_check => $self->can('custom_value_threshold'), closure_custom_perfdata => $self->can('custom_value_perfdata'), } }, { label => 'idle-cleanup-worker', nlabel => 'apache.slot.idlecleanupworker.count', set => { key_values => [ { name => 'idle_cleanup_worker' }, { name => 'total' } ], closure_custom_calc => $self->can('custom_value_calc'), closure_custom_calc_extra_options => { label_ref => 'idle_cleanup_worker' }, closure_custom_output => $self->can('custom_value_output'), closure_custom_threshold_check => $self->can('custom_value_threshold'), closure_custom_perfdata => $self->can('custom_value_perfdata'), } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port', }, 'proto:s' => { name => 'proto' }, 'urlpath:s' => { name => 'url_path', default => "/server-status/?auto" }, 'credentials' => { name => 'credentials' }, 'basic' => { name => 'basic' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'header:s@' => { name => 'header' }, 'timeout:s' => { name => 'timeout' }, 'units:s' => { name => 'units', default => '%' } }); $self->{http} = centreon::plugins::http->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{http}->set_options(%{$self->{option_results}}); } sub prefix_global_output { my ($self, %options) = @_; return 'Slots '; } sub manage_selection { my ($self, %options) = @_; my ($webcontent) = $self->{http}->request(); my $ScoreBoard = ""; if ($webcontent =~ /^Scoreboard:\s+([^\s]+)/mi) { $ScoreBoard = $1; } $self->{global} = { total => length($ScoreBoard), free => ($ScoreBoard =~ tr/\.//) + ($ScoreBoard =~ tr/\_//), busy => length($ScoreBoard) - ($ScoreBoard =~ tr/\.//) - ($ScoreBoard =~ tr/\_//), waiting => ($ScoreBoard =~ tr/\_//), starting => ($ScoreBoard =~ tr/S//), reading => ($ScoreBoard =~ tr/R//), sending => ($ScoreBoard =~ tr/W//), keepalive => ($ScoreBoard =~ tr/K//), dns_lookup => ($ScoreBoard =~ tr/D//), closing => ($ScoreBoard =~ tr/C//), logging => ($ScoreBoard =~ tr/L//), gracefuly_finished => ($ScoreBoard =~ tr/G//), idle_cleanup_worker => ($ScoreBoard =~ tr/I//) }; } 1; __END__ =head1 MODE Check Apache WebServer Slots informations =over 8 =item B<--hostname> IP Address or FQDN of the webserver host =item B<--port> Port used by Apache =item B<--proto> Protocol used http or https =item B<--urlpath> Set path to get server-status page in auto mode (Default: '/server-status/?auto') =item B<--credentials> Specify this option if you access server-status page with authentication =item B<--username> Specify username for authentication (Mandatory if --credentials is specified) =item B<--password> Specify password for authentication (Mandatory if --credentials is specified) =item B<--basic> Specify this option if you access server-status page over basic authentication and don't want a '401 UNAUTHORIZED' error to be logged on your webserver. Specify this option if you access server-status page over hidden basic authentication or you'll get a '404 NOT FOUND' error. (Use with --credentials) =item B<--timeout> Threshold for HTTP timeout =item B<--header> Set HTTP headers (Multiple option) =item B<--units> Threshold unit (Default: '%'. Can be: '%' or 'absolute') =item B<--warning-*> Warning threshold. Can be: 'busy', 'free', 'waiting', 'starting', 'reading', 'sending', 'keepalive', 'dns-lookup', 'closing', 'logging', 'gracefuly-finished', 'idle-cleanup-worker'. =item B<--critical-*> Critical threshold. Can be: 'busy', 'free', 'waiting', 'starting', 'reading', 'sending', 'keepalive', 'dns-lookup', 'closing', 'logging', 'gracefuly-finished', 'idle-cleanup-worker'. =over 8) =back =cut centreon-plugins-20220113/apps/apache/serverstatus/mode/workers.pm000066400000000000000000000125551417000230700251600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::apache::serverstatus::mode::workers; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::http; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "hostname:s" => { name => 'hostname' }, "port:s" => { name => 'port', }, "proto:s" => { name => 'proto' }, "urlpath:s" => { name => 'url_path', default => "/server-status/?auto" }, "credentials" => { name => 'credentials' }, "basic" => { name => 'basic' }, "username:s" => { name => 'username' }, "password:s" => { name => 'password' }, "header:s@" => { name => 'header' }, "warning:s" => { name => 'warning' }, "critical:s" => { name => 'critical' }, "timeout:s" => { name => 'timeout' }, }); $self->{http} = centreon::plugins::http->new(%options); 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(); } $self->{http}->set_options(%{$self->{option_results}}); } sub run { my ($self, %options) = @_; my $webcontent = $self->{http}->request(); my ($BusyWorkers, $IdleWorkers, $ScoreBoard); if ($webcontent =~ /^BusyWorkers:\s+([^\s]+)/mi) { $BusyWorkers = $1; } if ($webcontent =~ /^IdleWorkers:\s+([^\s]+)/mi) { $IdleWorkers = $1; } if ($webcontent =~ /^Scoreboard:\s+([^\s]+)/mi) { $ScoreBoard = $1; } my $srvLimit = length($ScoreBoard); my $prct_busy = $BusyWorkers / $srvLimit * 100; my $exit = $self->{perfdata}->threshold_check(value => $prct_busy, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit, short_msg => sprintf("Busy workers: %d Idle workers: %d (Server Limit: %d - %d %% Busy)", $BusyWorkers, $IdleWorkers, $srvLimit, $prct_busy)); $self->{output}->perfdata_add(label => "idle_workers", value => $IdleWorkers, min => 0, max => $srvLimit); $self->{output}->perfdata_add(label => "busy_workers", value => $BusyWorkers, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning', total => $srvLimit, cast_int => 1), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical', total => $srvLimit, cast_int => 1), min => 0, max => $srvLimit); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check Apache WebServer busy processes. =over 8 =item B<--hostname> IP Addr/FQDN of the webserver host =item B<--port> Port used by Apache =item B<--proto> Protocol to use http or https, http is default =item B<--urlpath> Set path to get server-status page in auto mode (Default: '/server-status/?auto') =item B<--credentials> Specify this option if you access server-status page with authentication =item B<--username> Specify username for authentication (Mandatory if --credentials is specified) =item B<--password> Specify password for authentication (Mandatory if --credentials is specified) =item B<--basic> Specify this option if you access server-status page over basic authentication and don't want a '401 UNAUTHORIZED' error to be logged on your webserver. Specify this option if you access server-status page over hidden basic authentication or you'll get a '404 NOT FOUND' error. (Use with --credentials) =item B<--timeout> Threshold for HTTP timeout =item B<--header> Set HTTP headers (Multiple option) =item B<--warning> Warning Threshold (%) of busy workers =item B<--critical> Critical Threshold (%) of busy workers =back =cut centreon-plugins-20220113/apps/apache/serverstatus/plugin.pm000066400000000000000000000030471417000230700240320ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::apache::serverstatus::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} = '0.1'; $self->{modes} = { 'cpuload' => 'apps::apache::serverstatus::mode::cpuload', 'responsetime' => 'apps::apache::serverstatus::mode::responsetime', 'requests' => 'apps::apache::serverstatus::mode::requests', 'slotstates' => 'apps::apache::serverstatus::mode::slotstates', 'workers' => 'apps::apache::serverstatus::mode::workers' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Apache and Apache 2 Web Servers through server-status webpage =cut centreon-plugins-20220113/apps/apcupsd/000077500000000000000000000000001417000230700176365ustar00rootroot00000000000000centreon-plugins-20220113/apps/apcupsd/local/000077500000000000000000000000001417000230700207305ustar00rootroot00000000000000centreon-plugins-20220113/apps/apcupsd/local/mode/000077500000000000000000000000001417000230700216545ustar00rootroot00000000000000centreon-plugins-20220113/apps/apcupsd/local/mode/batterycharge.pm000066400000000000000000000122441417000230700250410ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::apcupsd::local::mode::batterycharge; use base qw(centreon::plugins::mode); use strict; use warnings; use apps::apcupsd::local::mode::libgetdata; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $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 => 'apcaccess' }, "command-path:s" => { name => 'command_path', default => '/sbin/' }, "command-options:s" => { name => 'command_options', default => ' status ' }, "command-options2:s" => { name => 'command_options2', default => ' 2>&1' }, "apchost:s" => { name => 'apchost', default => 'localhost' }, "apcport:s" => { name => 'apcport', default => '3551' }, "searchpattern:s" => { name => 'searchpattern', default => 'BCHARGE' }, "warning:s" => { name => 'warning', default => '' }, "critical:s" => { name => 'critical', default => '' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{apchost})) { $self->{output}->add_option_msg(short_msg => "Need to specify an APC Host."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{apcport})) { $self->{output}->add_option_msg(short_msg => "Need to specify an APC Port."); $self->{output}->option_exit(); } 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 $result = apps::apcupsd::local::mode::libgetdata::getdata($self); my $exit = $self->{perfdata}->threshold_check(value => $result, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit, short_msg => sprintf($self->{option_results}->{searchpattern} . ": %f", $result)); $self->{output}->perfdata_add(label => $self->{option_results}->{searchpattern}, value => $result, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical') ); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check apcupsd Status =over 8 =item B<--apchost> IP used by apcupsd =item B<--apcport> Port used by apcupsd =item B<--warning> Warning Threshold =item B<--critical> Critical Threshold =item B<--remote> If you dont wanna install the apcupsd client on your local system you can run it remotely with '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'). =back =cut centreon-plugins-20220113/apps/apcupsd/local/mode/batteryvoltage.pm000066400000000000000000000122421417000230700252470ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::apcupsd::local::mode::batteryvoltage; use base qw(centreon::plugins::mode); use strict; use warnings; use apps::apcupsd::local::mode::libgetdata; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $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 => 'apcaccess' }, "command-path:s" => { name => 'command_path', default => '/sbin/' }, "command-options:s" => { name => 'command_options', default => ' status ' }, "command-options2:s" => { name => 'command_options2', default => ' 2>&1' }, "apchost:s" => { name => 'apchost', default => 'localhost' }, "apcport:s" => { name => 'apcport', default => '3551' }, "searchpattern:s" => { name => 'searchpattern', default => 'BATTV' }, "warning:s" => { name => 'warning', default => '' }, "critical:s" => { name => 'critical', default => '' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{apchost})) { $self->{output}->add_option_msg(short_msg => "Need to specify an APC Host."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{apcport})) { $self->{output}->add_option_msg(short_msg => "Need to specify an APC Port."); $self->{output}->option_exit(); } 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 $result = apps::apcupsd::local::mode::libgetdata::getdata($self); my $exit = $self->{perfdata}->threshold_check(value => $result, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit, short_msg => sprintf($self->{option_results}->{searchpattern} . ": %f", $result)); $self->{output}->perfdata_add(label => $self->{option_results}->{searchpattern}, value => $result, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical') ); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check apcupsd Status =over 8 =item B<--apchost> IP used by apcupsd =item B<--apcport> Port used by apcupsd =item B<--warning> Warning Threshold =item B<--critical> Critical Threshold =item B<--remote> If you dont wanna install the apcupsd client on your local system you can run it remotely with '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'). =back =cutcentreon-plugins-20220113/apps/apcupsd/local/mode/libgetdata.pm000066400000000000000000000045021417000230700243130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::apcupsd::local::mode::libgetdata; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::misc; sub getdata { 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->{option_results}->{apchost} . ":" . $self->{option_results}->{apcport} . $self->{option_results}->{command_options2}); my $searchpattern = $self->{option_results}->{searchpattern}; my ($valueok); my ($value); #print $stdout; foreach (split(/\n/, $stdout)) { if (/^$searchpattern\s*:\s*(.*)\s(Percent Load Capacity|Percent|Minutes|Seconds|Volts|Hz|seconds|C Internal|F Internal|C|F)/i) { $valueok = "1"; $value = $1; #print $value; #print "\n"; }; }; if ($valueok == "1") { #print $value; return $value; } else { $self->{output}->output_add(severity => 'CRITICAL', short_msg => 'NO DATA FOUND'); $self->{output}->display(); $self->{output}->exit(); }; }; 1; centreon-plugins-20220113/apps/apcupsd/local/mode/linefrequency.pm000066400000000000000000000122451417000230700250670ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::apcupsd::local::mode::linefrequency; use base qw(centreon::plugins::mode); use strict; use warnings; use apps::apcupsd::local::mode::libgetdata; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $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 => 'apcaccess' }, "command-path:s" => { name => 'command_path', default => '/sbin/' }, "command-options:s" => { name => 'command_options', default => ' status ' }, "command-options2:s" => { name => 'command_options2', default => ' 2>&1' }, "apchost:s" => { name => 'apchost', default => 'localhost' }, "apcport:s" => { name => 'apcport', default => '3551' }, "searchpattern:s" => { name => 'searchpattern', default => 'LINEFREQ' }, "warning:s" => { name => 'warning', default => '' }, "critical:s" => { name => 'critical', default => '' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{apchost})) { $self->{output}->add_option_msg(short_msg => "Need to specify an APC Host."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{apcport})) { $self->{output}->add_option_msg(short_msg => "Need to specify an APC Port."); $self->{output}->option_exit(); } 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 $result = apps::apcupsd::local::mode::libgetdata::getdata($self); my $exit = $self->{perfdata}->threshold_check(value => $result, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit, short_msg => sprintf($self->{option_results}->{searchpattern} . ": %f", $result)); $self->{output}->perfdata_add(label => $self->{option_results}->{searchpattern}, value => $result, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical') ); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check apcupsd Status =over 8 =item B<--apchost> IP used by apcupsd =item B<--apcport> Port used by apcupsd =item B<--warning> Warning Threshold =item B<--critical> Critical Threshold =item B<--remote> If you dont wanna install the apcupsd client on your local system you can run it remotely with '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'). =back =cut centreon-plugins-20220113/apps/apcupsd/local/mode/linevoltage.pm000066400000000000000000000122401417000230700245220ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::apcupsd::local::mode::linevoltage; use base qw(centreon::plugins::mode); use strict; use warnings; use apps::apcupsd::local::mode::libgetdata; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $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 => 'apcaccess' }, "command-path:s" => { name => 'command_path', default => '/sbin/' }, "command-options:s" => { name => 'command_options', default => ' status ' }, "command-options2:s" => { name => 'command_options2', default => ' 2>&1' }, "apchost:s" => { name => 'apchost', default => 'localhost' }, "apcport:s" => { name => 'apcport', default => '3551' }, "searchpattern:s" => { name => 'searchpattern', default => 'LINEV' }, "warning:s" => { name => 'warning', default => '' }, "critical:s" => { name => 'critical', default => '' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{apchost})) { $self->{output}->add_option_msg(short_msg => "Need to specify an APC Host."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{apcport})) { $self->{output}->add_option_msg(short_msg => "Need to specify an APC Port."); $self->{output}->option_exit(); } 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 $result = apps::apcupsd::local::mode::libgetdata::getdata($self); my $exit = $self->{perfdata}->threshold_check(value => $result, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit, short_msg => sprintf($self->{option_results}->{searchpattern} . ": %f", $result)); $self->{output}->perfdata_add(label => $self->{option_results}->{searchpattern}, value => $result, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical') ); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check apcupsd Status =over 8 =item B<--apchost> IP used by apcupsd =item B<--apcport> Port used by apcupsd =item B<--warning> Warning Threshold =item B<--critical> Critical Threshold =item B<--remote> If you dont wanna install the apcupsd client on your local system you can run it remotely with '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'). =back =cut centreon-plugins-20220113/apps/apcupsd/local/mode/loadpercentage.pm000066400000000000000000000122451417000230700251730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::apcupsd::local::mode::loadpercentage; use base qw(centreon::plugins::mode); use strict; use warnings; use apps::apcupsd::local::mode::libgetdata; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $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 => 'apcaccess' }, "command-path:s" => { name => 'command_path', default => '/sbin/' }, "command-options:s" => { name => 'command_options', default => ' status ' }, "command-options2:s" => { name => 'command_options2', default => ' 2>&1' }, "apchost:s" => { name => 'apchost', default => 'localhost' }, "apcport:s" => { name => 'apcport', default => '3551' }, "searchpattern:s" => { name => 'searchpattern', default => 'LOADPCT' }, "warning:s" => { name => 'warning', default => '' }, "critical:s" => { name => 'critical', default => '' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{apchost})) { $self->{output}->add_option_msg(short_msg => "Need to specify an APC Host."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{apcport})) { $self->{output}->add_option_msg(short_msg => "Need to specify an APC Port."); $self->{output}->option_exit(); } 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 $result = apps::apcupsd::local::mode::libgetdata::getdata($self); my $exit = $self->{perfdata}->threshold_check(value => $result, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit, short_msg => sprintf($self->{option_results}->{searchpattern} . ": %f", $result)); $self->{output}->perfdata_add(label => $self->{option_results}->{searchpattern}, value => $result, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical') ); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check apcupsd Status =over 8 =item B<--apchost> IP used by apcupsd =item B<--apcport> Port used by apcupsd =item B<--warning> Warning Threshold =item B<--critical> Critical Threshold =item B<--remote> If you dont wanna install the apcupsd client on your local system you can run it remotely with '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'). =back =cut centreon-plugins-20220113/apps/apcupsd/local/mode/outputvoltage.pm000066400000000000000000000122441417000230700251370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::apcupsd::local::mode::outputvoltage; use base qw(centreon::plugins::mode); use strict; use warnings; use apps::apcupsd::local::mode::libgetdata; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $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 => 'apcaccess' }, "command-path:s" => { name => 'command_path', default => '/sbin/' }, "command-options:s" => { name => 'command_options', default => ' status ' }, "command-options2:s" => { name => 'command_options2', default => ' 2>&1' }, "apchost:s" => { name => 'apchost', default => 'localhost' }, "apcport:s" => { name => 'apcport', default => '3551' }, "searchpattern:s" => { name => 'searchpattern', default => 'OUTPUTV' }, "warning:s" => { name => 'warning', default => '' }, "critical:s" => { name => 'critical', default => '' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{apchost})) { $self->{output}->add_option_msg(short_msg => "Need to specify an APC Host."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{apcport})) { $self->{output}->add_option_msg(short_msg => "Need to specify an APC Port."); $self->{output}->option_exit(); } 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 $result = apps::apcupsd::local::mode::libgetdata::getdata($self); my $exit = $self->{perfdata}->threshold_check(value => $result, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit, short_msg => sprintf($self->{option_results}->{searchpattern} . ": %f", $result)); $self->{output}->perfdata_add(label => $self->{option_results}->{searchpattern}, value => $result, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical') ); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check apcupsd Status =over 8 =item B<--apchost> IP used by apcupsd =item B<--apcport> Port used by apcupsd =item B<--warning> Warning Threshold =item B<--critical> Critical Threshold =item B<--remote> If you dont wanna install the apcupsd client on your local system you can run it remotely with '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'). =back =cut centreon-plugins-20220113/apps/apcupsd/local/mode/temperature.pm000066400000000000000000000122371417000230700245540ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::apcupsd::local::mode::temperature; use base qw(centreon::plugins::mode); use strict; use warnings; use apps::apcupsd::local::mode::libgetdata; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $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 => 'apcaccess' }, "command-path:s" => { name => 'command_path', default => '/sbin/' }, "command-options:s" => { name => 'command_options', default => ' status ' }, "command-options2:s" => { name => 'command_options2', default => ' 2>&1' }, "apchost:s" => { name => 'apchost', default => 'localhost' }, "apcport:s" => { name => 'apcport', default => '3551' }, "searchpattern:s" => { name => 'searchpattern', default => 'ITEMP' }, "warning:s" => { name => 'warning', default => '' }, "critical:s" => { name => 'critical', default => '' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{apchost})) { $self->{output}->add_option_msg(short_msg => "Need to specify an APC Host."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{apcport})) { $self->{output}->add_option_msg(short_msg => "Need to specify an APC Port."); $self->{output}->option_exit(); } 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 $result = apps::apcupsd::local::mode::libgetdata::getdata($self); my $exit = $self->{perfdata}->threshold_check(value => $result, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit, short_msg => sprintf($self->{option_results}->{searchpattern} . ": %f", $result)); $self->{output}->perfdata_add(label => $self->{option_results}->{searchpattern}, value => $result, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical') ); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check apcupsd Status =over 8 =item B<--apchost> IP used by apcupsd =item B<--apcport> Port used by apcupsd =item B<--warning> Warning Threshold =item B<--critical> Critical Threshold =item B<--remote> If you dont wanna install the apcupsd client on your local system you can run it remotely with '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'). =back =cutcentreon-plugins-20220113/apps/apcupsd/local/mode/timeleft.pm000066400000000000000000000122401417000230700240220ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::apcupsd::local::mode::timeleft; use base qw(centreon::plugins::mode); use strict; use warnings; use apps::apcupsd::local::mode::libgetdata; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $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 => 'apcaccess' }, "command-path:s" => { name => 'command_path', default => '/sbin/' }, "command-options:s" => { name => 'command_options', default => ' status ' }, "command-options2:s" => { name => 'command_options2', default => ' 2>&1' }, "apchost:s" => { name => 'apchost', default => 'localhost' }, "apcport:s" => { name => 'apcport', default => '3551' }, "searchpattern:s" => { name => 'searchpattern', default => 'TIMELEFT' }, "warning:s" => { name => 'warning', default => '' }, "critical:s" => { name => 'critical', default => '' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{apchost})) { $self->{output}->add_option_msg(short_msg => "Need to specify an APC Host."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{apcport})) { $self->{output}->add_option_msg(short_msg => "Need to specify an APC Port."); $self->{output}->option_exit(); } 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 $result = apps::apcupsd::local::mode::libgetdata::getdata($self); my $exit = $self->{perfdata}->threshold_check(value => $result, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit, short_msg => sprintf($self->{option_results}->{searchpattern} . ": %f", $result)); $self->{output}->perfdata_add(label => $self->{option_results}->{searchpattern}, value => $result, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical') ); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check apcupsd Status =over 8 =item B<--apchost> IP used by apcupsd =item B<--apcport> Port used by apcupsd =item B<--warning> Warning Threshold =item B<--critical> Critical Threshold =item B<--remote> If you dont wanna install the apcupsd client on your local system you can run it remotely with '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'). =back =cut centreon-plugins-20220113/apps/apcupsd/local/plugin.pm000066400000000000000000000144541417000230700225740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # # see http://manned.org/apcaccess # #sprung:~# apcaccess # #APC : 001,048,1163 # version, number of records and number of bytes following #DATE : 2014-03-15 19:30:58 +0100 # Date and time of last update from UPS #HOSTNAME : sprung # hostname of computer running apcupsd #VERSION : 3.14.8 (16 January 2010) debian # apcupsd version number, date and operating system #UPSNAME : APC_ESX_SERVER # UPS name from configuration file (dumb) or EEPROM (smart) #CABLE : Custom Cable Smart # Cable type specified in the configuration file #MODEL : Smart-UPS 620 # UPS model derived from UPS information #UPSMODE : ShareUPS Master # Mode in which UPS is operating #STARTTIME: 2014-03-13 22:40:39 +0100 # Date and time apcupsd was started #STATUS : ONLINE # UPS status (online, charging, on battery etc) #LINEV : 224.6 Volts # Current input line voltage #LOADPCT : 58.5 Percent Load Capacity # Percentage of UPS load capacity used as estimated by UPS #BCHARGE : 100.0 Percent # Current battery capacity charge percentage #TIMELEFT : 11.0 Minutes # Remaining runtime left on battery as estimated by UPS #MBATTCHG : 10 Percent # Min battery charge % (BCHARGE) required for system shutdown #MINTIMEL : 4 Minutes # Min battery runtime (MINUTES) required for system shutdown #MAXTIME : 0 Seconds # Max battery runtime (TIMEOUT) after which system is shutdown #MAXLINEV : 227.5 Volts # Maximum input line voltage since apcupsd startup #MINLINEV : 224.6 Volts # Minimum input line voltage since apcupsd startup #OUTPUTV : 227.5 Volts # UPS output voltage #SENSE : High # Current UPS sensitivity setting for voltage fluctuations #DWAKE : 060 Seconds # Time UPS waits after power off when the power is restored #DSHUTD : 600 Seconds # Delay before UPS powers down after command received #DLOWBATT : 02 Minutes # Low battery signal sent when this much runtime remains #LOTRANS : 208.0 Volts # Input line voltage below which UPS will switch to battery #HITRANS : 253.0 Volts # Input line voltage above which UPS will switch to battery #RETPCT : 015.0 Percent # Battery charge % required after power off to restore power #ALARMDEL : 30 seconds # Delay period before UPS starts sounding alarm #BATTV : 13.8 Volts # Current battery voltage #LINEFREQ : 50.0 Hz # Current line frequency in Hertz #LASTXFER : No transfers since turnon # Reason for last transfer to battery since apcupsd startup #NUMXFERS : 0 # Number of transfers to battery since apcupsd startup #TONBATT : 0 seconds # Seconds currently on battery #CUMONBATT: 0 seconds # Cumulative seconds on battery since apcupsd startup #XOFFBATT : N/A # Date, time of last transfer off battery since apcupsd startup #SELFTEST : NO # Date and time of last self test since apcupsd startup #STESTI : OFF # Self-test interval #STATFLAG : 0x07000008 Status Flag # UPS status flag in hex #REG1 : 0x00 Register 1 # Fault register 1 in hex #REG2 : 0x00 Register 2 # Fault register 2 in hex #REG3 : 0x00 Register 3 # Fault register 3 in hex #MANDATE : 08/09/01 # UPS date of manufacture #SERIALNO : NS0132263041 # UPS serial number #BATTDATE : 11/01/08 # Date battery last replaced (if set) #NOMOUTV : 230 Volts # Nominal output voltage to supply when on battery power #NOMBATTV : 12.0 Volts # Nominal battery voltage #FIRMWARE : 22.6.I # UPS firmware version #APCMODEL : CWI # APC model information #END APC : 2014-03-15 19:31:00 +0100 # Date and time of status information was written package apps::apcupsd::local::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} = '0.1'; %{$self->{modes}} = ( 'batterycharge' => 'apps::apcupsd::local::mode::batterycharge', # BCHARGE 'temperature' => 'apps::apcupsd::local::mode::temperature', # ITEMP 'timeleft' => 'apps::apcupsd::local::mode::timeleft', # TIMELEFT MAXTIME MINTIMEL 'linevoltage' => 'apps::apcupsd::local::mode::linevoltage', # LINEV 'batteryvoltage' => 'apps::apcupsd::local::mode::batteryvoltage', # BATTV 'outputvoltage' => 'apps::apcupsd::local::mode::outputvoltage', # OUTPUTV 'linefrequency' => 'apps::apcupsd::local::mode::linefrequency', # LINEFREQ 'loadpercentage' => 'apps::apcupsd::local::mode::loadpercentage', # LOADPCT ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check apcupsd through local commands (the plugin can use SSH). =cut centreon-plugins-20220113/apps/automation/000077500000000000000000000000001417000230700203575ustar00rootroot00000000000000centreon-plugins-20220113/apps/automation/ansible/000077500000000000000000000000001417000230700217745ustar00rootroot00000000000000centreon-plugins-20220113/apps/automation/ansible/cli/000077500000000000000000000000001417000230700225435ustar00rootroot00000000000000centreon-plugins-20220113/apps/automation/ansible/cli/custom/000077500000000000000000000000001417000230700240555ustar00rootroot00000000000000centreon-plugins-20220113/apps/automation/ansible/cli/custom/cli.pm000066400000000000000000000106441417000230700251670ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::automation::ansible::cli::custom::cli; use strict; use warnings; use JSON::XS; 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 => { '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 => 50 }, 'sudo' => { name => 'sudo' }, 'command:s' => { name => 'command', default => 'ANSIBLE_LOAD_CALLBACK_PLUGINS=true ANSIBLE_STDOUT_CALLBACK=json ansible' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'CLI OPTIONS', once => 1); $self->{output} = $options{output}; return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; return 0; } sub execute { my ($self, %options) = @_; $self->{output}->output_add(long_msg => "Command line: '" . $self->{option_results}->{command} . " " . $options{cmd_options} . "'", debug => 1); my ($response) = 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 => $options{cmd_options}, no_errors => { 4 => 1 } ); my $raw_results; eval { $raw_results = JSON::XS->new->utf8->decode($response); }; if ($@) { $self->{output}->output_add(long_msg => $response, debug => 1); $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } return $raw_results; } sub ansible_list_hosts_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "$options{host_pattern} --module-name=setup"; return $cmd_options; } sub ansible_list_hosts { my ($self, %options) = @_; my $cmd_options = $self->ansible_list_hosts_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); return $raw_results; } 1; __END__ =head1 NAME Ansible CLI =head1 CLI OPTIONS Ansible CLI =over 8 =item B<--timeout> Set timeout in seconds (Default: 50). =item B<--sudo> Use 'sudo' to execute the command. =item B<--command> Command to get information (Default: 'ANSIBLE_LOAD_CALLBACK_PLUGINS=true ANSIBLE_STDOUT_CALLBACK=json ansible'). 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: none). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/automation/ansible/cli/mode/000077500000000000000000000000001417000230700234675ustar00rootroot00000000000000centreon-plugins-20220113/apps/automation/ansible/cli/mode/discovery.pm000066400000000000000000000064051417000230700260410ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::automation::ansible::cli::mode::discovery; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'host-pattern:s' => { name => 'host_pattern', default => 'all' }, 'prettify' => { name => 'prettify' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my @disco_data; my $disco_stats; $disco_stats->{start_time} = time(); my $result = $options{custom}->ansible_list_hosts(host_pattern => $self->{option_results}->{host_pattern}); $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; foreach my $play (@{$result->{plays}}) { foreach my $task (@{$play->{tasks}}) { foreach my $host (keys %{$task->{hosts}}) { my %host; $host{ip} = $host; $host{hostname} = $task->{hosts}->{$host}->{ansible_facts}->{ansible_hostname}; $host{fqdn} = $task->{hosts}->{$host}->{ansible_facts}->{ansible_fqdn}; $host{type} = $task->{hosts}->{$host}->{ansible_facts}->{ansible_system}; $host{distribution} = $task->{hosts}->{$host}->{ansible_facts}->{ansible_distribution}; $host{all_ips} = $task->{hosts}->{$host}->{ansible_facts}->{ansible_all_ipv4_addresses}; push @disco_data, \%host; } } } $disco_stats->{discovered_items} = @disco_data; $disco_stats->{results} = \@disco_data; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE Resources discovery. =over 8 =item B<--host-pattern> Specify host pattern to look for (Default: 'all'). =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/apps/automation/ansible/cli/plugin.pm000066400000000000000000000024661417000230700244070ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::automation::ansible::cli::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} = '1.0'; %{$self->{modes}} = ( 'discovery' => 'apps::automation::ansible::cli::mode::discovery', ); $self->{custom_modes}{cli} = 'apps::automation::ansible::cli::custom::cli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Ansible using CLI. =cut centreon-plugins-20220113/apps/automation/ansible/tower/000077500000000000000000000000001417000230700231345ustar00rootroot00000000000000centreon-plugins-20220113/apps/automation/ansible/tower/custom/000077500000000000000000000000001417000230700244465ustar00rootroot00000000000000centreon-plugins-20220113/apps/automation/ansible/tower/custom/api.pm000066400000000000000000000232421417000230700255600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::automation::ansible::tower::custom::api; use strict; use warnings; use centreon::plugins::http; use JSON::XS; 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 => { 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'timeout:s' => { name => 'timeout' }, 'api-path:s' => { name => 'api_path' }, 'unknown-http-status:s' => { name => 'unknown_http_status' }, 'warning-http-status:s' => { name => 'warning_http_status' }, 'critical-http-status:s' => { name => 'critical_http_status' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 80; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'http'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{username} = (defined($self->{option_results}->{username})) ? $self->{option_results}->{username} : ''; $self->{password} = (defined($self->{option_results}->{password})) ? $self->{option_results}->{password} : ''; $self->{api_path} = (defined($self->{option_results}->{api_path})) ? $self->{option_results}->{api_path} : '/api/v2'; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300'; $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } if ($self->{username} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --username option."); $self->{output}->option_exit(); } if ($self->{password} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --password option."); $self->{output}->option_exit(); } return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{credentials} = 1; $self->{option_results}->{basic} = 1; $self->{option_results}->{username} = $self->{username}; $self->{option_results}->{password} = $self->{password}; } sub settings { my ($self, %options) = @_; return if (defined($self->{settings_done})); $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->add_header(key => 'Content-Type', value => 'application/json'); $self->{http}->set_options(%{$self->{option_results}}); $self->{settings_done} = 1; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub request_api { my ($self, %options) = @_; my $results = []; my $page = 1; $self->settings(); while (1) { my $path = defined($options{force_endpoint}) ? $self->{api_path} . $options{force_endpoint} : $self->{api_path} . $options{endpoint} . '?page_size=100&page=' . $page; my $content = $self->{http}->request( method => defined($options{method}) ? $options{method} : 'GET', url_path => $path, query_form_post => $options{query_form_post}, unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status} ); my $code = $self->{http}->get_code(); if (!defined($content) || $content eq '') { $self->{output}->add_option_msg(short_msg => "API returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } return $decoded if (defined($options{direct_hash}) && $options{direct_hash} == 1); push @$results, @{$decoded->{results}}; last if (!defined($decoded->{next})); last if (defined($options{nonext}) && $options{nonext} == 1); $page++; } return $results; } sub tower_list_hosts { my ($self, %options) = @_; return $self->request_api(endpoint => '/hosts/'); } sub tower_list_inventories { my ($self, %options) = @_; return $self->request_api(endpoint => '/inventories/'); } sub tower_list_projects { my ($self, %options) = @_; return $self->request_api(endpoint => '/projects/'); } sub tower_list_job_templates { my ($self, %options) = @_; return $self->request_api(endpoint => '/job_templates/'); } sub tower_list_schedules { my ($self, %options) = @_; my $schedules = $self->request_api(endpoint => '/schedules/'); if (defined($options{add_job_status})) { for (my $i = 0; $i < scalar(@$schedules); $i++) { my $job = $self->request_api( force_endpoint => '/schedules/' . $schedules->[$i]->{id} . '/jobs/?order_by=-id&page_size=1', nonext => 1 ); $schedules->[$i]->{last_job} = $job->[0]; } } return $schedules; } sub tower_list_unified_jobs { my ($self, %options) = @_; return $self->request_api(endpoint => '/unified_jobs/'); } sub tower_launch_job_template { my ($self, %options) = @_; my $json_request = {}; $json_request->{inventory} = $options{launch_inventory} if (defined($options{launch_inventory}) && $options{launch_inventory} ne ''); $json_request->{credential} = $options{launch_credential} if (defined($options{launch_credential})); $json_request->{job_tags} = $options{launch_tags} if (defined($options{launch_tags})); $json_request->{limit} = $options{launch_limit} if (defined($options{launch_limit})); $json_request->{extra_vars} = $options{launch_extra_vars} if (defined($options{launch_extra_vars})); my $encoded; eval { $encoded = JSON::XS->new->utf8->encode($json_request); }; if ($@) { $self->{output}->add_option_msg(short_msg => 'Cannot encode request: ' . $@); $self->{output}->option_exit(); } my $job = $self->request_api( method => 'POST', force_endpoint => '/job_templates/' . $options{launch_job_template_id} . '/launch/', query_form_post => $encoded, direct_hash => 1 ); return $job; } sub tower_get_job { my ($self, %options) = @_; return $self->request_api(force_endpoint => '/jobs/' . $options{job_id} . '/', direct_hash => 1); } 1; __END__ =head1 NAME Ansible Tower Rest API =head1 REST API OPTIONS Ansible Tower Rest API =over 8 =item B<--hostname> Santricity hostname. =item B<--port> Port used (Default: 80) =item B<--proto> Specify https if needed (Default: 'http') =item B<--username> API username. =item B<--password> API password. =item B<--api-path> Specify api path (Default: '/api/v2') =item B<--timeout> Set timeout in seconds (Default: 10). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/automation/ansible/tower/custom/towercli.pm000066400000000000000000000261411417000230700266400ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::automation::ansible::tower::custom::towercli; use strict; use warnings; use JSON::XS; 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 => { 'hostname:s' => { name => 'hostname' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'timeout:s' => { name => 'timeout', default => 50 }, 'sudo' => { name => 'sudo' }, 'command:s' => { name => 'command', default => 'tower-cli' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '' }, 'nossl' => { name => 'nossl' }, 'proxyurl:s' => { name => 'proxyurl' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'TOWERCLI OPTIONS', once => 1); $self->{output} = $options{output}; return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; if (defined($self->{option_results}->{proxyurl}) && $self->{option_results}->{proxyurl} ne '') { $ENV{HTTP_PROXY} = $self->{option_results}->{proxyurl}; $ENV{HTTPS_PROXY} = $self->{option_results}->{proxyurl}; } $self->{hostname} = (defined($self->{option_results}->{hostname})) && $self->{option_results}->{hostname} ne '' ? $self->{option_results}->{hostname} : undef; $self->{username} = (defined($self->{option_results}->{username})) && $self->{option_results}->{username} ne '' ? $self->{option_results}->{username} : undef; $self->{password} = (defined($self->{option_results}->{password})) && $self->{option_results}->{password} ne '' ? $self->{option_results}->{password} : undef; if (defined($self->{option_results}->{nossl})) { $ENV{TOWER_VERIFY_SSL} = 'no'; $self->{hostname} = 'http://' . $self->{hostname} if (defined($self->{hostname})); $ENV{HTTPS_PROXY} = $self->{option_results}->{proxyurl}; } return 0; } sub execute { my ($self, %options) = @_; $self->{output}->output_add(long_msg => "Command line: '" . $self->{option_results}->{command} . " " . $options{cmd_options} . "'", debug => 1); my ($response) = 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 => $options{cmd_options} ); my $raw_results; eval { $raw_results = JSON::XS->new->utf8->decode($response); }; if ($@) { $self->{output}->output_add(long_msg => $response, debug => 1); $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } return $raw_results; } sub tower_list_hosts_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "host list --insecure --all-pages --format json"; $cmd_options .= " --tower-host '$self->{hostname}'" if (defined($self->{hostname})); $cmd_options .= " --tower-username '$self->{username}'" if (defined($self->{username})); $cmd_options .= " --tower-password '$self->{password}'" if (defined($self->{password})); $cmd_options .= " --group '$options{group}'" if (defined($options{group}) && $options{group} ne ''); $cmd_options .= " --inventory '$options{inventory}'" if (defined($options{inventory}) && $options{inventory} ne ''); return $cmd_options; } sub tower_list_hosts { my ($self, %options) = @_; my $cmd_options = $self->tower_list_hosts_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); return $raw_results->{results}; } sub tower_list_inventories_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = 'inventory list --insecure --all-pages --format json'; $cmd_options .= " --tower-host '$self->{hostname}'" if (defined($self->{hostname})); $cmd_options .= " --tower-username '$self->{username}'" if (defined($self->{username})); $cmd_options .= " --tower-password '$self->{password}'" if (defined($self->{password})); return $cmd_options; } sub tower_list_inventories { my ($self, %options) = @_; my $cmd_options = $self->tower_list_inventories_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); return $raw_results->{results}; } sub tower_list_projects_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "project list --insecure --all-pages --format json"; $cmd_options .= " --tower-host '$self->{hostname}'" if (defined($self->{hostname})); $cmd_options .= " --tower-username '$self->{username}'" if (defined($self->{username})); $cmd_options .= " --tower-password '$self->{password}'" if (defined($self->{password})); return $cmd_options; } sub tower_list_projects { my ($self, %options) = @_; my $cmd_options = $self->tower_list_projects_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); return $raw_results->{results}; } sub tower_list_job_templates_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "job_template list --insecure --all-pages --format json"; $cmd_options .= " --tower-host '$self->{hostname}'" if (defined($self->{hostname})); $cmd_options .= " --tower-username '$self->{username}'" if (defined($self->{username})); $cmd_options .= " --tower-password '$self->{password}'" if (defined($self->{password})); return $cmd_options; } sub tower_list_job_templates { my ($self, %options) = @_; my $cmd_options = $self->tower_list_job_templates_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); return $raw_results->{results}; } sub tower_list_schedules { my ($self, %options) = @_; $self->{output}->add_option_msg(short_msg => 'method unsupported (try to use --custommode=api)'); $self->{output}->option_exit(); } sub tower_list_unified_jobs { my ($self, %options) = @_; $self->{output}->add_option_msg(short_msg => 'method unsupported (try to use --custommode=api)'); $self->{output}->option_exit(); } sub tower_launch_job_template_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "job launch --job-template=$options{launch_job_template_id} "; $cmd_options .= " --inventory '$options{launch_inventory}'" if (defined($options{launch_inventory})); $cmd_options .= " --credential '$options{launch_credential}'" if (defined($options{launch_credential})); $cmd_options .= " --tags '$options{launch_tags}'" if (defined($options{launch_tags})); $cmd_options .= " --limit '$options{launch_limit}'" if (defined($options{launch_limit})); $cmd_options .= " --extra-vars '$options{launch_extra_vars}'" if (defined($options{launch_extra_vars})); $cmd_options .= ' --insecure --format json'; $cmd_options .= " --tower-host '$self->{hostname}'" if (defined($self->{hostname})); $cmd_options .= " --tower-username '$self->{username}'" if (defined($self->{username})); $cmd_options .= " --tower-password '$self->{password}'" if (defined($self->{password})); return $cmd_options; } sub tower_launch_job_template { my ($self, %options) = @_; my $cmd_options = $self->tower_launch_job_template_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); return $raw_results; } sub tower_get_job_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "job get $options{job_id} --insecure --format json"; $cmd_options .= " --tower-host '$self->{hostname}'" if (defined($self->{hostname})); $cmd_options .= " --tower-username '$self->{username}'" if (defined($self->{username})); $cmd_options .= " --tower-password '$self->{password}'" if (defined($self->{password})); return $cmd_options; } sub tower_get_job { my ($self, %options) = @_; my $cmd_options = $self->tower_get_job_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); return $raw_results; } 1; __END__ =head1 NAME Ansible Tower CLI =head1 TOWERCLI OPTIONS Ansible Tower CLI To install the Tower CLI : https://docs.ansible.com/ansible-tower/latest/html/towerapi/tower_cli.html#installation =over 8 =item B<--hostname> Ansible Tower hostname (Default uses setting in 'tower config'). =item B<--username> Ansible Tower username (Default uses setting in 'tower config'). =item B<--password> Ansible Tower password (Default uses setting in 'tower config'). =item B<--nossl> Use http connection. =item B<--timeout> Set timeout in seconds (Default: 50). =item B<--sudo> Use 'sudo' to execute the command. =item B<--command> Command to get information (Default: 'tower-cli'). 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: none). =item B<--proxyurl> Proxy URL if any =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/automation/ansible/tower/mode/000077500000000000000000000000001417000230700240605ustar00rootroot00000000000000centreon-plugins-20220113/apps/automation/ansible/tower/mode/discovery.pm000066400000000000000000000060741417000230700264340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::automation::ansible::tower::mode::discovery; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'group' => { name => 'group' }, 'inventory' => { name => 'inventory' }, 'prettify' => { name => 'prettify' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my @disco_data; my $disco_stats; $disco_stats->{start_time} = time(); my $hosts = $options{custom}->tower_list_hosts( group => $self->{option_results}->{group}, inventory => $self->{option_results}->{inventory} ); $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; foreach my $host (@$hosts) { my %host; $host{name} = $host->{name}; $host{id} = $host->{id}; $host{description} = $host->{description}; $host{type} = $host->{type}; $host{inventory_id} = $host->{inventory}; $host{inventory_name} = $host->{summary_fields}->{inventory}->{name}; $host{groups} = $host->{summary_fields}->{groups}->{results}; $host{enabled} = $host->{enabled}; push @disco_data, \%host; } $disco_stats->{discovered_items} = @disco_data; $disco_stats->{results} = \@disco_data; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE Resources discovery. =over 8 =item B<--group> Specify host group. =item B<--inventory> Specify host inventory. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/apps/automation/ansible/tower/mode/hosts.pm000066400000000000000000000114431417000230700255610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::automation::ansible::tower::mode::hosts; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub prefix_output_global { my ($self, %options) = @_; return 'Hosts '; } sub prefix_output_host { my ($self, %options) = @_; return "Host '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_output_global' }, { name => 'hosts', type => 1, cb_prefix_output => 'prefix_output_host', message_multiple => 'All hosts are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'total', nlabel => 'hosts.total.count', set => { key_values => [ { name => 'total' } ], output_template => 'total: %d', perfdatas => [ { value => 'total', template => '%d', min => 0 } ] } }, { label => 'failed', nlabel => 'hosts.failed.count', set => { key_values => [ { name => 'failed' }, { name => 'total' } ], output_template => 'failed: %d', perfdatas => [ { template => '%d', min => 0, max => 'total' } ] } } ]; $self->{maps_counters}->{hosts} = [ { label => 'job-status', type => 2, unknown_default => '%{last_job_status} =~ /default/', critical_default => '%{last_job_status} =~ /failed/', set => { key_values => [ { name => 'last_job_status' }, { name => 'display' } ], output_template => "last job status is '%s'", closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'display-failed-hosts' => { name => 'display_failed_hosts' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $hosts = $options{custom}->tower_list_hosts(); $self->{global} = { total => scalar(@$hosts), failed => 0 }; $self->{hosts} = {}; my $failed_hosts = []; foreach my $host (@$hosts) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $host->{name} !~ /$self->{option_results}->{filter_name}/); $self->{hosts}->{ $host->{id} } = { display => $host->{name}, last_job_status => $host->{summary_fields}->{last_job}->{status} }; if ($host->{has_active_failures}) { $self->{global}->{failed}++; push @$failed_hosts, $host->{name}; } } if (defined($self->{option_results}->{display_failed_hosts})) { $self->{output}->output_add(long_msg => 'Failed hosts list: ' . join(', ', @$failed_hosts)); } } 1; __END__ =head1 MODE Check hosts. =over 8 =item B<--filter-name> Filter host name (Can use regexp). =item B<--display-failed-hosts> Display failed hosts list in verbose output. =item B<--unknown-job-status> Set unknown threshold for status (Default: '%{last_job_status} =~ /default/'). Can used special variables like: %{last_job_status}, %{display} =item B<--warning-job-status> Set warning threshold for status. Can used special variables like: %{last_job_status}, %{display} =item B<--critical-job-status> Set critical threshold for status (Default: '%{last_job_status} =~ /failed/'). Can used special variables like: %{last_job_status}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'total', 'failed'. =back =cut centreon-plugins-20220113/apps/automation/ansible/tower/mode/inventories.pm000066400000000000000000000154121417000230700267660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::automation::ansible::tower::mode::inventories; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_output_global { my ($self, %options) = @_; return 'Inventories '; } sub prefix_output_inventories { my ($self, %options) = @_; return "Inventory '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_output_global' }, { name => 'inventories', type => 1, cb_prefix_output => 'prefix_output_inventories', message_multiple => 'All inventories are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'total', nlabel => 'inventories.total.count', set => { key_values => [ { name => 'total' } ], output_template => 'total: %d', perfdatas => [ { value => 'total', template => '%d', min => 0 } ] } }, { label => 'failed', nlabel => 'inventories.failed.count', set => { key_values => [ { name => 'failed' }, { name => 'total' } ], output_template => 'failed: %d', perfdatas => [ { template => '%d', min => 0, max => 'total' } ] } } ]; $self->{maps_counters}->{inventories} = [ { label => 'hosts-total', nlabel => 'inventory.hosts.total.count', display_ok => 0, set => { key_values => [ { name => 'total_hosts' }, { name => 'display' } ], output_template => 'hosts total: %d', perfdatas => [ { value => 'total_hosts', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'hosts-failed', nlabel => 'inventory.hosts.failed.count', set => { key_values => [ { name => 'hosts_with_active_failures' }, { name => 'total_hosts' }, { name => 'display' } ], output_template => 'hosts failed: %d', perfdatas => [ { template => '%d', min => 0, max => 'total_hosts', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'sources-total', nlabel => 'inventory.sources.total.count', display_ok => 0, set => { key_values => [ { name => 'total_inventory_sources' }, { name => 'display' } ], output_template => 'sources total: %d', perfdatas => [ { template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'sources-failed', nlabel => 'inventory.sources.failed.count', set => { key_values => [ { name => 'inventory_sources_with_failures' }, { name => 'total_inventory_sources' }, { name => 'display' } ], output_template => 'sources failed: %d', perfdatas => [ { template => '%d', min => 0, max => 'total_inventory_sources', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'groups-total', nlabel => 'inventory.groups.total.count', display_ok => 0, set => { key_values => [ { name => 'total_groups' }, { name => 'display' } ], output_template => 'groups total: %d', perfdatas => [ { template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'groups-failed', nlabel => 'inventory.groups.failed.count', set => { key_values => [ { name => 'groups_with_active_failures' }, { name => 'total_groups' }, { name => 'display' } ], output_template => 'Groups failed: %d', perfdatas => [ { template => '%d', min => 0, max => 'total_groups', label_extra_instance => 1, instance_use => 'display' } ] } } ]; } 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-inventory:s' => { name => 'filter_inventory' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $inventories = $options{custom}->tower_list_inventories(); $self->{global} = { total => 0, failed => 0 }; $self->{inventories} = {}; foreach my $inventory (@$inventories) { next if (defined($self->{option_results}->{filter_inventory}) && $self->{option_results}->{filter_inventory} ne '' && $inventory->{name} !~ /$self->{option_results}->{filter_inventory}/); $self->{inventories}->{ $inventory->{id} } = { display => $inventory->{name}, total_hosts => $inventory->{total_hosts}, hosts_with_active_failures => $inventory->{hosts_with_active_failures}, total_inventory_sources => $inventory->{total_inventory_sources}, inventory_sources_with_failures => $inventory->{inventory_sources_with_failures}, total_groups => $inventory->{total_groups}, groups_with_active_failures => $inventory->{groups_with_active_failures} }; $self->{global}->{total}++; $self->{global}->{failed}++ if ($inventory->{has_active_failures}); } } 1; __END__ =head1 MODE Check inventories. =over 8 =item B<--filter-inventory> Filter inventory name (Can use regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'total', 'failed', 'hosts-total', 'hosts-failed', 'sources-total', 'sources-failed', 'groups-total', 'groups-failed'. =back =cut centreon-plugins-20220113/apps/automation/ansible/tower/mode/jobs.pm000066400000000000000000000120751417000230700253600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::automation::ansible::tower::mode::jobs; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::statefile; sub prefix_output_global { my ($self, %options) = @_; return 'Jobs '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_output_global' } ]; $self->{maps_counters}->{global} = [ { label => 'total', nlabel => 'jobs.total.count', set => { key_values => [ { name => 'total' } ], output_template => 'total: %d', perfdatas => [ { value => 'total', template => '%d', min => 0 } ] } } ]; foreach ((['successful', 1], ['failed', 1], ['running', 1], ['canceled', 0], ['pending', 0], ['default', 0])) { push @{$self->{maps_counters}->{global}}, { label => $_->[0], nlabel => 'jobs.' . $_->[0] . '.count', display_ok => $_->[1], set => { key_values => [ { name => $_->[0] }, { name => 'total' } ], output_template => $_->[0] . ': %d', perfdatas => [ { template => '%d', min => 0, max => 'total' } ] } }; } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'display-failed-jobs' => { name => 'display_failed_jobs' }, 'memory' => { name => 'memory' } }); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->check_options(%options); centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'Date::Parse', error_msg => "Cannot load module 'Date::Parse'." ); } } sub manage_selection { my ($self, %options) = @_; my $last_time; if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->read(statefile => 'cache_ansible_tower_' . $self->{mode} . '_' . $options{custom}->get_hostname()); $last_time = $self->{statefile_cache}->get(name => 'last_time'); } my $jobs = $options{custom}->tower_list_unified_jobs(); $self->{global} = { total => 0, failed => 0, successful => 0, canceled => 0, default => 0, pending => 0, running => 0 }; my $current_time = time(); my $failed_jobs = {}; foreach my $job (@$jobs) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $job->{name} !~ /$self->{option_results}->{filter_name}/); if (defined($self->{option_results}->{memory}) && defined($job->{finished})) { my $finished_time = Date::Parse::str2time($job->{finished}); if (!defined($finished_time)) { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => "Can't parse date '" . $job->{finished} . "'" ); next; } next if (defined($last_time) && $last_time > $finished_time); } $self->{global}->{ $job->{status} }++; $self->{global}->{total}++; if ($job->{status} eq 'failed') { $failed_jobs->{ $job->{name} } = 1; } } if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->write(data => { last_time => $current_time }); } if (defined($self->{option_results}->{display_failed_jobs})) { $self->{output}->output_add(long_msg => 'Failed jobs list: ' . join(', ', keys %$failed_jobs)); } } 1; __END__ =head1 MODE Check jobs. =over 8 =item B<--filter-name> Filter job name (Can use regexp). =item B<--display-failed-jobs> Display failed jobs list in verbose output. =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'total', 'successful', 'failed', 'running', 'canceled', 'pending', 'default'. =back =cut centreon-plugins-20220113/apps/automation/ansible/tower/mode/jobtemplates.pm000066400000000000000000000173041417000230700271140ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::automation::ansible::tower::mode::jobtemplates; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub prefix_output_global { my ($self, %options) = @_; return 'Job templates '; } sub prefix_output_jobtpl { my ($self, %options) = @_; return "Job template '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_output_global' }, { name => 'jobtpl', type => 1, cb_prefix_output => 'prefix_output_jobtpl', message_multiple => 'All job templates are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'total', nlabel => 'jobtemplates.total.count', set => { key_values => [ { name => 'total' } ], output_template => 'total: %d', perfdatas => [ { value => 'total', template => '%d', min => 0 } ] } } ]; foreach ((['successful', 1], ['failed', 1], ['running', 1], ['canceled', 0], ['pending', 0], ['default', 0], ['never', 0])) { push @{$self->{maps_counters}->{global}}, { label => $_->[0], nlabel => 'jobtemplates.' . $_->[0] . '.count', display_ok => $_->[1], set => { key_values => [ { name => $_->[0] }, { name => 'total' } ], output_template => $_->[0] . ': %d', perfdatas => [ { template => '%d', min => 0, max => 'total' } ] } }; } $self->{maps_counters}->{jobtpl} = [ { label => 'job-status', type => 2, unknown_default => '%{last_job_status} =~ /default/', critical_default => '%{last_job_status} =~ /failed/', set => { key_values => [ { name => 'last_job_status' }, { name => 'display' } ], output_template => "last job status is '%s'", closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'launch-job-template-id:s' => { name => 'launch_job_template_id' }, 'launch-extra-vars:s' => { name => 'launch_extra_vars' }, 'launch-tags:s' => { name => 'launch_tags' }, 'launch-limit:s' => { name => 'launch_limit' }, 'launch-inventory:s' => { name => 'launch_inventory' }, 'launch-credential:s' => { name => 'launch_credential' }, 'launch-max-retries:s' => { name => 'launch_max_retries', default => 5 }, 'launch-retry-interval:s' => { name => 'launch_retry_interval', default => 10 } }); return $self; } sub launch_job { my ($self, %options) = @_; my $job = $options{custom}->tower_launch_job_template( launch_job_template_id => $self->{option_results}->{launch_job_template_id}, launch_extra_vars => $self->{option_results}->{launch_extra_vars}, launch_tags => $self->{option_results}->{launch_tags}, launch_limit => $self->{option_results}->{launch_limit}, launch_inventory => $self->{option_results}->{launch_inventory}, launch_credential => $self->{option_results}->{launch_credential} ); my $job_id = $job->{id}; my ($job_completed, $retry_idx, $job_result); $retry_idx = 0; while (!defined($job_completed) && $retry_idx < $self->{option_results}->{launch_max_retries}) { sleep($self->{option_results}->{launch_retry_interval}) if ($retry_idx > 0); $job_result = $options{custom}->tower_get_job(job_id => $job_id); $job_completed = $job_result->{finished}; $retry_idx++; } if ($retry_idx >= $self->{option_results}->{launch_max_retries}) { $self->{output}->add_option_msg(short_msg => 'cannot get the last job result'); $self->{output}->option_exit(); } $job->{summary_fields}->{last_job} = $job_result; return [$job]; } sub manage_selection { my ($self, %options) = @_; my $jobs; if (defined($self->{option_results}->{launch_job_template_id}) && $self->{option_results}->{launch_job_template_id} =~ /\d+/) { $jobs = $self->launch_job(custom => $options{custom}); } else { $jobs = $options{custom}->tower_list_job_templates(); } $self->{global} = { total => 0, failed => 0, successful => 0, canceled => 0, default => 0, pending => 0, running => 0, never => 0 }; $self->{jobtpl} = {}; foreach my $job (@$jobs) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $job->{name} !~ /$self->{option_results}->{filter_name}/); $self->{jobtpl}->{ $job->{id} } = { display => $job->{name}, last_job_status => defined($job->{summary_fields}->{last_job}->{status}) ? $job->{summary_fields}->{last_job}->{status} : 'never' }; $self->{global}->{total}++; if (defined($job->{summary_fields}->{last_job}->{status})) { $self->{global}->{ $job->{summary_fields}->{last_job}->{status} }++; } else { $self->{global}->{never}++; } } } 1; __END__ =head1 MODE Check job templates. =over 8 =item B<--filter-name> Filter job template name (Can use regexp). =item B<--launch-job-template-id> The job_template id to launch. =item B<--launch-inventory> Specify inventory for job template to run. =item B<--launch-credential> Specify machine credential for job template to run. =item B<--launch-tags> Specify tagged actions in the playbook to run. =item B<--launch-limit> Specify host limit for job template to run. =item B<--launch-extra-vars> yaml format text that contains extra variables to pass on. =item B<--launch-max-retries> Number of retries to get job result once launched (Default: 5). =item B<--launch-retry-interval> Number of seconds between retries (Default : 10). =item B<--unknown-job-status> Set unknown threshold for status (Default: '%{last_job_status} =~ /default/'). Can used special variables like: %{last_job_status}, %{display} =item B<--warning-job-status> Set warning threshold for status. Can used special variables like: %{last_job_status}, %{display} =item B<--critical-job-status> Set critical threshold for status (Default: '%{last_job_status} =~ /failed/'). Can used special variables like: %{last_job_status}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'total', 'successful', 'failed', 'running', 'canceled', 'pending', 'default', 'never'. =back =cut centreon-plugins-20220113/apps/automation/ansible/tower/mode/schedules.pm000066400000000000000000000143461417000230700264050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::automation::ansible::tower::mode::schedules; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use DateTime; use centreon::plugins::misc; sub custom_start_output { my ($self, %options) = @_; return sprintf( 'last start: %s', $self->{result_values}->{start_last_time} >= 0 ? centreon::plugins::misc::change_seconds(value => $self->{result_values}->{start_last_time}) : 'never' ); } sub prefix_output_global { my ($self, %options) = @_; return 'Schedules '; } sub prefix_output_schedule { my ($self, %options) = @_; return "Schedule '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_output_global' }, { name => 'schedules', type => 1, cb_prefix_output => 'prefix_output_schedule', message_multiple => 'All schedules are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'total', nlabel => 'schedules.total.count', set => { key_values => [ { name => 'total' } ], output_template => 'total: %d', perfdatas => [ { value => 'total', template => '%d', min => 0 } ] } } ]; foreach ((['successful', 1], ['failed', 1], ['running', 1], ['canceled', 0], ['pending', 0], ['default', 0], ['never', 0])) { push @{$self->{maps_counters}->{global}}, { label => $_->[0], nlabel => 'schedules.' . $_->[0] . '.count', display_ok => $_->[1], set => { key_values => [ { name => $_->[0] }, { name => 'total' } ], output_template => $_->[0] . ': %d', perfdatas => [ { template => '%d', min => 0, max => 'total' } ] } }; } $self->{maps_counters}->{schedules} = [ { label => 'job-status', type => 2, unknown_default => '%{last_job_status} =~ /default/', critical_default => '%{last_job_status} =~ /failed/', set => { key_values => [ { name => 'last_job_status' }, { name => 'display' } ], output_template => "last job status is '%s'", closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'start-last-time', nlabel => 'schedule.start.last.time.seconds', set => { key_values => [ { name => 'start_last_time' }, { name => 'display' } ], closure_custom_output => $self->can('custom_start_output'), perfdatas => [ { template => '%d', min => 0, unit => 's', label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $schedules = $options{custom}->tower_list_schedules(add_job_status => 1); $self->{global} = { total => 0, failed => 0, successful => 0, canceled => 0, default => 0, pending => 0, running => 0, never => 0 }; $self->{schedules} = {}; foreach my $schedule (@$schedules) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $schedule->{name} !~ /$self->{option_results}->{filter_name}/); my $start_last_time = -1; if (defined($schedule->{last_job}->{started})) { #2020-07-30T09:36:28.806283Z if ($schedule->{last_job}->{started} =~ /^(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)/) { my $dt = DateTime->new(year => $1, month => $2, day => $3, hour => $4, minute => $5, second => $6); $start_last_time = time() - $dt->epoch(); } } $self->{schedules}->{ $schedule->{id} } = { display => $schedule->{name}, last_job_status => defined($schedule->{last_job}->{status}) ? $schedule->{last_job}->{status} : 'never', start_last_time => $start_last_time }; $self->{global}->{total}++; if (defined($schedule->{last_job}->{status})) { $self->{global}->{ $schedule->{last_job}->{status} }++; } else { $self->{global}->{never}++; } } } 1; __END__ =head1 MODE Check schedules. =over 8 =item B<--filter-name> Filter schedule name (Can use regexp). =item B<--unknown-job-status> Set unknown threshold for status (Default: '%{last_job_status} =~ /default/'). Can used special variables like: %{last_job_status}, %{display} =item B<--warning-job-status> Set warning threshold for status. Can used special variables like: %{last_job_status}, %{display} =item B<--critical-job-status> Set critical threshold for status (Default: '%{last_job_status} =~ /failed/'). Can used special variables like: %{last_job_status}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'total', 'successful', 'failed', 'running', 'canceled', 'pending', 'default', 'never', 'start-last-time' (s). =back =cut centreon-plugins-20220113/apps/automation/ansible/tower/plugin.pm000066400000000000000000000035061417000230700247740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::automation::ansible::tower::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} = '1.0'; $self->{modes} = { 'discovery' => 'apps::automation::ansible::tower::mode::discovery', 'hosts' => 'apps::automation::ansible::tower::mode::hosts', 'inventories' => 'apps::automation::ansible::tower::mode::inventories', 'jobs' => 'apps::automation::ansible::tower::mode::jobs', 'job-templates' => 'apps::automation::ansible::tower::mode::jobtemplates', 'schedules' => 'apps::automation::ansible::tower::mode::schedules' }; $self->{custom_modes}->{api} = 'apps::automation::ansible::tower::custom::api'; $self->{custom_modes}->{towercli} = 'apps::automation::ansible::tower::custom::towercli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Ansible Tower using API (tower-cli or RestAPI). =cut centreon-plugins-20220113/apps/backup/000077500000000000000000000000001417000230700174445ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/arcserve/000077500000000000000000000000001417000230700212565ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/arcserve/udp/000077500000000000000000000000001417000230700220465ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/arcserve/udp/mssql/000077500000000000000000000000001417000230700232055ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/arcserve/udp/mssql/mode/000077500000000000000000000000001417000230700241315ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/arcserve/udp/mssql/mode/jobstatus.pm000066400000000000000000000227051417000230700265130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::arcserve::udp::mssql::mode::jobstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_status_threshold { my ($self, %options) = @_; my $status = 'ok'; # To exclude some OK if (defined($self->{instance_mode}->{option_results}->{ok_status}) && $self->{instance_mode}->{option_results}->{ok_status} ne '' && $self->eval(value => $self->{instance_mode}->{option_results}->{ok_status})) { $status = 'ok'; } elsif (defined($self->{instance_mode}->{option_results}->{critical_status}) && $self->{instance_mode}->{option_results}->{critical_status} ne '' && $self->eval(value => $self->{instance_mode}->{option_results}->{critical_status})) { $status = 'critical'; } elsif (defined($self->{instance_mode}->{option_results}->{warning_status}) && $self->{instance_mode}->{option_results}->{warning_status} ne '' && $self->eval(value => $self->{instance_mode}->{option_results}->{warning_status})) { $status = 'warning'; } return $status; } sub custom_status_output { my ($self, %options) = @_; return sprintf( 'status : %s (%s) [type: %s] [remote hostname: %s] [vmname: %s] [plan name: %s] [end time: %s]', $self->{result_values}->{status} == 1 ? 'ok' : 'failed', $self->{result_values}->{status}, $self->{result_values}->{type}, $self->{result_values}->{rhostname}, $self->{result_values}->{vmname}, $self->{result_values}->{plan_name}, scalar(localtime($self->{result_values}->{end_time})) ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'job', type => 1, cb_prefix_output => 'prefix_job_output', message_multiple => 'All jobs are ok' }, ]; $self->{maps_counters}->{global} = [ { label => 'total', nlabel => 'jobs.total.count', set => { key_values => [ { name => 'total' } ], output_template => 'total jobs : %s', perfdatas => [ { label => 'total', value => 'total', template => '%s', min => 0 }, ], } }, ]; $self->{maps_counters}->{job} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'display' }, { name => 'type' }, { name => 'rhostname' }, { name => 'vmname' }, { name => 'plan_name' }, { name => 'elapsed_time' }, { name => 'end_time' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => $self->can('custom_status_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 => { 'filter-server-name:s' => { name => 'filter_server_name' }, 'filter-type:s' => { name => 'filter_type' }, 'filter-start-time:s' => { name => 'filter_start_time' }, 'filter-end-time:s' => { name => 'filter_end_time', default => 86400 }, 'ok-status:s' => { name => 'ok_status', default => '%{status} == 1' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{status} != 1' }, 'timezone:s' => { name => 'timezone' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => [ 'ok_status', 'warning_status', 'critical_status' ] ); if (defined($self->{option_results}->{timezone}) && $self->{option_results}->{timezone} ne '') { $ENV{TZ} = $self->{option_results}->{timezone}; } } sub prefix_job_output { my ($self, %options) = @_; return "job '" . $options{instance_value}->{display} . "' "; } sub manage_selection { my ($self, %options) = @_; my $query = q{ SELECT lj.jobId, lj.jobStatus, rhostname, vmname, DATEDIFF(s, '1970-01-01 00:00:00', lj.jobLocalStartTime) as start_time, DATEDIFF(s, '1970-01-01 00:00:00', lj.jobLocalEndTime) as end_time, ep.name, lj.jobType, lj.jobStatus FROM as_edge_d2dJobHistory_lastJob lj LEFT OUTER JOIN as_edge_policy ep ON lj.planUUID = ep.uuid LEFT JOIN as_edge_host h on lj.agentId = h.rhostid LEFT JOIN as_edge_vsphere_entity_host_map entityHostMap ON h.rhostid = entityHostMap.hostId LEFT JOIN as_edge_vsphere_vm_detail vmDetail ON entityHostMap.entityId=vmDetail.entityId }; $options{sql}->connect(); $options{sql}->query(query => $query); $self->{global} = { total => 0 }; $self->{job} = {}; my ($count, $current_time) = (0, time()); while ((my $row = $options{sql}->fetchrow_hashref())) { my $rhostname = defined($row->{rhostname}) && $row->{rhostname} ne '' ? $row->{rhostname} : 'unknown'; my $vmname = defined($row->{vmname}) && $row->{vmname} ne '' ? $row->{vmname} : '-'; my $plan_name = defined($row->{name}) && $row->{name} ne '' ? $row->{name} : 'unknown'; if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' && $row->{jobType} !~ /$self->{option_results}->{filter_type}/) { $self->{output}->output_add(long_msg => "skipping job '" . $row->{jobId} . "': no matching filter type.", debug => 1); next; } if (defined($self->{option_results}->{filter_end_time}) && $self->{option_results}->{filter_end_time} =~ /[0-9]+/ && defined($row->{end_time}) && $row->{end_time} =~ /[0-9]+/ && $row->{end_time} < ($current_time - $self->{option_results}->{filter_end_time})) { $self->{output}->output_add(long_msg => "skipping job '" . $row->{jobId} . "': end time too old.", debug => 1); next; } if (defined($self->{option_results}->{filter_start_time}) && $self->{option_results}->{filter_start_time} =~ /[0-9]+/ && defined($row->{start_time}) && $row->{start_time} =~ /[0-9]+/ && $row->{start_time} < ($current_time - $self->{option_results}->{filter_start_time})) { $self->{output}->output_add(long_msg => "skipping job '" . $row->{jobId} . "': start time too old.", debug => 1); next; } if (defined($self->{option_results}->{filter_server_name}) && $self->{option_results}->{filter_server_name} ne '' && ($row->{rhostname} !~ /$self->{option_results}->{filter_server_name}/ && $vmname !~ /$self->{option_results}->{filter_server_name}/)) { $self->{output}->output_add(long_msg => "skipping job '" . $row->{jobId} . "': no matching filter type.", debug => 1); next; } my $elapsed_time = defined($row->{start_time}) ? $current_time - $row->{start_time} : -1; $self->{job}->{$row->{jobId}} = { display => $row->{jobId}, elapsed_time => $elapsed_time, status => $row->{jobStatus}, type => $row->{jobType}, rhostname => $rhostname, vmname => $vmname, plan_name => $plan_name, end_time => $row->{end_time}, }; $self->{global}->{total}++; } } 1; __END__ =head1 MODE Check job status. =over 8 =item B<--filter-server-name> Filter job server name (can be a regexp). =item B<--filter-type> Filter job type (can be a regexp). =item B<--filter-start-time> Filter job with start time greater than current time less value in seconds. =item B<--filter-end-time> Filter job with end time greater than current time less value in seconds (Default: 86400). =item B<--timezone> Timezone of mssql server (If not set, we use current server execution timezone). =item B<--ok-status> Set ok threshold for status (Default: '%{status} == 1') Can used special variables like: %{display}, %{status} =item B<--warning-status> Set warning threshold for status (Default: '%{status} == 1') Can used special variables like: %{display}, %{status}, %{type} =item B<--critical-status> Set critical threshold for status (Default: '%{status} != 1'). Can used special variables like: %{display}, %{status}, %{type} =item B<--warning-total> Set warning threshold for total jobs. =item B<--critical-total> Set critical threshold for total jobs. =back =cut centreon-plugins-20220113/apps/backup/commvault/000077500000000000000000000000001417000230700214535ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/commvault/commserve/000077500000000000000000000000001417000230700234535ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/commvault/commserve/restapi/000077500000000000000000000000001417000230700251225ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/commvault/commserve/restapi/custom/000077500000000000000000000000001417000230700264345ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/commvault/commserve/restapi/custom/api.pm000066400000000000000000000320541417000230700275470ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Authors : Roman Morandell - ivertix # package apps::backup::commvault::commserve::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use centreon::plugins::statefile; use JSON::XS; use Digest::MD5 qw(md5_hex); use MIME::Base64; 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'url-path:s' => { name => 'url_path' }, 'api-username:s' => { name => 'api_username' }, 'api-password:s' => { name => 'api_password' }, 'user-domain:s' => { name => 'user_domain' }, 'timeout:s' => { name => 'timeout' }, 'cache-create' => { name => 'cache_create' }, 'cache-use' => { name => 'cache_use' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); $self->{cache} = centreon::plugins::statefile->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{url_path} = (defined($self->{option_results}->{url_path})) ? $self->{option_results}->{url_path} : '/webconsole/api'; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : ''; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : ''; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 30; $self->{user_domain} = (defined($self->{option_results}->{user_domain})) ? $self->{option_results}->{user_domain} : ''; $self->{cache_create} = $self->{option_results}->{cache_create}; $self->{cache_use} = $self->{option_results}->{cache_use}; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify hostname option.'); $self->{output}->option_exit(); } if ($self->{api_username} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-username option."); $self->{output}->option_exit(); } if ($self->{api_password} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-password option."); $self->{output}->option_exit(); } $self->{cache}->check_options(option_results => $self->{option_results}); return 0; } sub get_connection_infos { my ($self, %options) = @_; return $self->{hostname} . '_' . $self->{http}->get_port(); } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub get_port { my ($self, %options) = @_; return $self->{port}; } sub is_use_cache { my ($self, %options) = @_; return defined($self->{cache_use}) ? 1 : 0; } sub json_decode { my ($self, %options) = @_; $options{content} =~ s/\r//mg; my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($options{content}); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } return $decoded; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->add_header(key => 'Content-Type', value => 'application/json'); $self->{http}->set_options(%{$self->{option_results}}); } sub clean_token { my ($self, %options) = @_; my $datas = {}; $options{statefile}->write(data => $datas); $self->{access_token} = undef; $self->{http}->add_header(key => 'Authorization', value => undef); } sub get_auth_token { my ($self, %options) = @_; my $has_cache_file = $options{statefile}->read(statefile => 'commvault_commserve_' . md5_hex($self->{option_results}->{hostname}) . '_' . md5_hex($self->{option_results}->{api_username})); my $access_token = $options{statefile}->get(name => 'access_token'); # Token expires every 15 minutes if ($has_cache_file == 0 || !defined($access_token)) { my $json_request = { username => $self->{api_username}, password => MIME::Base64::encode_base64($self->{api_password}, '') }; $json_request->{domain} = $self->{user_domain} if ($self->{user_domain} ne ''); my $encoded; eval { $encoded = encode_json($json_request); }; if ($@) { $self->{output}->add_option_msg(short_msg => 'cannot encode json request'); $self->{output}->option_exit(); } my ($content) = $self->{http}->request( method => 'POST', url_path => $self->{url_path} . '/Login', query_form_post => $encoded, warning_status => '', unknown_status => '', critical_status => '' ); if ($self->{http}->get_code() != 200) { $self->{output}->add_option_msg(short_msg => "Authentication error [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded = $self->json_decode(content => $content); if (!defined($decoded->{token})) { $self->{output}->add_option_msg(short_msg => "Cannot get token"); $self->{output}->option_exit(); } $access_token = $decoded->{token}; my $datas = { access_token => $access_token }; $options{statefile}->write(data => $datas); } $self->{access_token} = $access_token; $self->{http}->add_header(key => 'Authtoken', value => $self->{access_token}); } sub request_internal { my ($self, %options) = @_; $self->settings(); if (!defined($self->{access_token})) { $self->get_auth_token(statefile => $self->{cache}); } my $content = $self->{http}->request( url_path => $self->{url_path} . $options{endpoint}, get_param => $options{get_param}, warning_status => '', unknown_status => '', critical_status => '' ); # Maybe there is an issue with the token. So we retry. if ($self->{http}->get_code() < 200 || $self->{http}->get_code() >= 300) { $self->clean_token(statefile => $self->{cache}); $self->get_auth_token(statefile => $self->{cache}); $content = $self->{http}->request( url_path => $self->{url_path} . $options{endpoint}, get_param => $options{get_param}, header => $options{header}, warning_status => '', unknown_status => '', critical_status => '' ); } my $decoded = $self->json_decode(content => $content); if (!defined($decoded)) { $self->{output}->add_option_msg(short_msg => 'Error while retrieving data (add --debug option for detailed message)'); $self->{output}->option_exit(); } if ($self->{http}->get_code() < 200 || $self->{http}->get_code() >= 300) { $self->{output}->add_option_msg(short_msg => 'api request error'); $self->{output}->option_exit(); } return $decoded; } sub get_cache_file_response { my ($self, %options) = @_; $self->{cache}->read(statefile => 'cache_commvault_commserve_' . $options{type} . '_' . md5_hex($self->{option_results}->{hostname}) . '_' . md5_hex($self->{option_results}->{api_username})); my $response = $self->{cache}->get(name => 'response'); my $update_time = $self->{cache}->get(name => 'update_time'); if (!defined($response)) { $self->{output}->add_option_msg(short_msg => 'Cache file missing'); $self->{output}->option_exit(); } return $response; } sub get_cache_file_update { my ($self, %options) = @_; $self->{cache}->read(statefile => 'cache_commvault_commserve_' . $options{type} . '_' . md5_hex($self->{option_results}->{hostname}) . '_' . md5_hex($self->{option_results}->{api_username})); my $update_time = $self->{cache}->get(name => 'update_time'); return $update_time; } sub create_cache_file { my ($self, %options) = @_; $self->{cache}->read(statefile => 'cache_commvault_commserve_' . $options{type} . '_' . md5_hex($self->{option_results}->{hostname}) . '_' . md5_hex($self->{option_results}->{api_username})); $self->{cache}->write(data => { response => $options{response}, update_time => time() }); $self->{output}->output_add( severity => 'ok', short_msg => 'Cache file created successfully' ); $self->{output}->display(); $self->{output}->exit(); } sub request { my ($self, %options) = @_; return $self->get_cache_file_response(type => $options{type}) if (defined($self->{cache_use})); my $response = $self->request_internal( endpoint => $options{endpoint} ); $self->create_cache_file(type => $options{type}, response => $response) if (defined($self->{cache_create})); return $response; } sub request_jobs { my ($self, %options) = @_; return $self->get_cache_file_response(type => 'jobs') if (defined($self->{cache_use})); my $lookup_time = $options{completed_job_lookup_time}; if (defined($self->{cache_create})) { my $update_time = $self->get_cache_file_update(type => 'jobs'); $lookup_time = 3600; if (defined($update_time)) { $lookup_time = time() - $update_time; } } my $response = $self->request_internal( endpoint => $options{endpoint}, get_param => ['completedJobLookupTime=' . $lookup_time] ); $self->create_cache_file(type => 'jobs', response => $response) if (defined($self->{cache_create})); return $response; } sub request_paging { my ($self, %options) = @_; return $self->get_cache_file_response(type => $options{type}) if (defined($self->{cache_use})); my ($page_num, $page_count) = (1, 200); my $alerts = []; while (1) { my $results = $self->request_internal( endpoint => $options{endpoint}, get_param => ['pageNo=' . $page_num, 'pageCount=' . $page_count], header => ['Cache-Control: private'] ); last if (!defined($results->{feedsList})); push @$alerts, @{$results->{feedsList}}; last if ($results->{totalNoOfAlerts} < ($page_num * $page_count)); $page_num++; } $self->create_cache_file(type => $options{type}, response => $alerts) if (defined($self->{cache_create})); return $alerts; } 1; __END__ =head1 NAME Commvault API =head1 SYNOPSIS Commvault api =head1 REST API OPTIONS =over 8 =item B<--hostname> API hostname. =item B<--url-path> API url path (Default: '/webconsole/api') =item B<--port> API port (Default: 443) =item B<--proto> Specify https if needed (Default: 'https') =item B<--api-username> Set API username =item B<--api-password> Set API password =item B<--timeout> Set HTTP timeout =item B<--cache-create> Create a cache file and quit. =item B<--cache-use> Use the cache file (created with --cache-create). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/backup/commvault/commserve/restapi/mode/000077500000000000000000000000001417000230700260465ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/commvault/commserve/restapi/mode/alerts.pm000066400000000000000000000174171417000230700277100ustar00rootroot00000000000000# # Copyright 2018 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::backup::commvault::commserve::restapi::mode::alerts; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use POSIX; use centreon::plugins::misc; use centreon::plugins::statefile; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf( 'alert [severity: %s] [status: %s] [name: %s] [type: %s] %s', $self->{result_values}->{severity}, $self->{result_values}->{status}, $self->{result_values}->{name}, $self->{result_values}->{type}, $self->{result_values}->{generation_time} ); } sub prefix_global_output { my ($self, %options) = @_; return 'Alerts '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', }, { name => 'alarms', type => 2, message_multiple => '0 alert(s) detected', display_counter_problem => { nlabel => 'alerts.problems.current.count', min => 0 }, group => [ { name => 'alarm', skipped_code => { -11 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'alerts-total', nlabel => 'alerts.total.count', display_ok => 0, set => { key_values => [ { name => 'total' } ], output_template => 'total: %s', perfdatas => [ { template => '%s', min => 0 } ] } } ]; foreach (('critical', 'warning', 'info')) { push @{$self->{maps_counters}->{global}}, { label => 'alerts-' . $_, nlabel => 'alerts.' . $_ . '.count', display_ok => 0, set => { key_values => [ { name => $_ }, { name => 'total' } ], output_template => $_ . ': %s', perfdatas => [ { template => '%s', min => 0, max => 'total' } ] } }; } $self->{maps_counters}->{alarm} = [ { label => 'status', type => 2, warning_default => '%{severity} =~ /warning/', critical_default => '%{severity} =~ /critical/', set => { key_values => [ { name => 'name' }, { name => 'type' }, { name => 'severity' }, { name => 'status' }, { name => 'since' }, { name => 'generation_time' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-alert-name:s' => { name => 'filter_alert_name' }, 'filter-alert-type:s' => { name => 'filter_alert_type' }, 'memory' => { name => 'memory' } }); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->check_options(%options); } } my $map_severity = { 0 => 'autoPick', 1 => 'critical', 2 => 'warning', 3 => 'info' }; my $map_status = { 4 => 'read', 8 => 'unread' }; sub manage_selection { my ($self, %options) = @_; my $alarms = $options{custom}->request_paging( type => 'alert', endpoint => '/Alert' ); my $last_time; if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->read( statefile => 'commvault_commserve_' . $options{custom}->get_connection_infos() . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_alert_name}) ? md5_hex($self->{option_results}->{filter_alert_name}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_alert_type}) ? md5_hex($self->{option_results}->{filter_alert_type}) : md5_hex('all')) ); $last_time = $self->{statefile_cache}->get(name => 'last_time'); } $self->{global} = { total => 0, critical => 0, warning => 0, info => 0 }; $self->{alarms} = { global => { alarm => {} } }; my ($i, $current_time) = (1, time()); foreach my $alarm (@$alarms) { my $create_time = $alarm->{detectedTime}->{time}; next if (defined($self->{option_results}->{memory}) && defined($last_time) && $last_time > $create_time); if (defined($self->{option_results}->{filter_alert_name}) && $self->{option_results}->{filter_alert_name} ne '' && $alarm->{alertName} !~ /$self->{option_results}->{filter_alert_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $alarm->{alertName} . "': no matching filter.", debug => 1); next; } if (defined($self->{option_results}->{filter_alert_type}) && $self->{option_results}->{filter_alert_type} ne '' && $alarm->{alertType} !~ /$self->{option_results}->{filter_alert_type}/) { $self->{output}->output_add(long_msg => "skipping '" . $alarm->{alertName} . "': no matching filter.", debug => 1); next; } my $diff_time = $current_time - $create_time; $self->{alarms}->{global}->{alarm}->{$i} = { name => $alarm->{alertName}, type => $alarm->{alertType}, severity => $map_severity->{ $alarm->{severity} }, status => $map_status->{ $alarm->{status} }, since => $diff_time, generation_time => centreon::plugins::misc::change_seconds(value => $diff_time) }; $self->{global}->{total}++; $self->{global}->{ $map_severity->{ $alarm->{severity} } }++ if (defined($self->{global}->{ $map_severity->{ $alarm->{severity} } })); $i++; } if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->write(data => { last_time => $current_time }); } } 1; __END__ =head1 MODE Check alerts. =over 8 =item B<--filter-alert-name> Filter alerts by name (can be a regexp). =item B<--filter-alert-type> Filter alerts by type (can be a regexp). =item B<--warning-status> Set warning threshold for status (Default: '%{severity} =~ /warning/') Can used special variables like: %{severity}, %{status}, %{type}, %{name}, %{since} =item B<--critical-status> Set critical threshold for status (Default: '%{severity} =~ /critical/'). Can used special variables like: %{severity}, %{status}, %{type}, %{name}, %{since} =item B<--memory> Only check new alerts. =back =cut centreon-plugins-20220113/apps/backup/commvault/commserve/restapi/mode/jobs.pm000066400000000000000000000262571417000230700273550ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::commvault::commserve::restapi::mode::jobs; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use centreon::plugins::misc; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return 'status: ' . $self->{result_values}->{status}; } sub custom_long_output { my ($self, %options) = @_; return 'started since: ' . centreon::plugins::misc::change_seconds(value => $self->{result_values}->{elapsed}); } sub prefix_job_output { my ($self, %options) = @_; return "Job '" . $options{instance_value}->{display} . "' [type: " . $options{instance_value}->{type} . "] " ; } sub policy_long_output { my ($self, %options) = @_; return "Checking policy '" . $options{instance_value}->{display} . "'"; } sub prefix_policy_output { my ($self, %options) = @_; return "Policy '" . $options{instance_value}->{display} . "' "; } sub custom_long_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{elapsed} = $options{new_datas}->{$self->{instance} . '_elapsed'}; $self->{result_values}->{type} = $options{new_datas}->{$self->{instance} . '_type'}; return -11 if ($self->{result_values}->{status} !~ /running|queued|waiting/i); return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'policy', type => 2, cb_prefix_output => 'prefix_policy_output', cb_long_output => 'policy_long_output', display_counter_problem => { nlabel => 'jobs.problems.current.count', min => 0 }, message_multiple => 'All policies are ok', group => [ { name => 'job', cb_prefix_output => 'prefix_job_output', skipped_code => { -11 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'jobs-total', nlabel => 'jobs.total.count', set => { key_values => [ { name => 'total' } ], output_template => 'Total jobs: %s', perfdatas => [ { template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{job} = [ { label => 'status', type => 2, warning_default => '%{status} =~ /abnormal/i', critical_default => '%{status} =~ /errors|failed/i', set => { key_values => [ { name => 'status' }, { name => 'display' }, { name => 'type' } ], 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 => \&catalog_status_threshold_ng } }, { label => 'long', type => 2, set => { key_values => [ { name => 'status' }, { name => 'display' }, { name => 'elapsed' }, { name => 'type' } ], closure_custom_calc => $self->can('custom_long_calc'), closure_custom_output => $self->can('custom_long_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-policy-name:s' => { name => 'filter_policy_name' }, 'filter-policy-id:s' => { name => 'filter_policy_id' }, 'filter-type:s' => { name => 'filter_type' }, 'filter-client-group:s' => { name => 'filter_client_group' }, 'filter-client-name:s' => { name => 'filter_client_name' }, 'timeframe:s' => { name => 'timeframe' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = 'commvault_commserve_' . $options{custom}->get_connection_infos() . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_policy_name}) ? md5_hex($self->{option_results}->{filter_policy_name}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_policy_id}) ? md5_hex($self->{option_results}->{filter_policy_id}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_type}) ? md5_hex($self->{option_results}->{filter_type}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_client_group}) ? md5_hex($self->{option_results}->{filter_client_group}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_client_name}) ? md5_hex($self->{option_results}->{filter_client_name}) : md5_hex('all')); my $last_timestamp = $self->read_statefile_key(key => 'last_timestamp'); $last_timestamp = time() - 300 if (!defined($last_timestamp)); my $lookup_time = time() - $last_timestamp; if (defined($self->{option_results}->{timeframe}) && $self->{option_results}->{timeframe} =~ /(\d+)/) { $lookup_time = $1; } # Also we get Pending/Waiting/Running jobs with that my $results = $options{custom}->request_jobs( endpoint => '/Job', completed_job_lookup_time => $lookup_time ); $self->{global} = { total => 0 }; $self->{policy} = {}; my $jobs_checked = {}; my $current_time = time(); foreach (@{$results->{jobs}}) { my $job = $_->{jobSummary}; next if (defined($jobs_checked->{ $job->{jobId} })); $jobs_checked->{ $job->{jobId} } = 1; my $policy_name = defined($job->{storagePolicy}->{storagePolicyName}) && $job->{storagePolicy}->{storagePolicyName} ne '' ? $job->{storagePolicy}->{storagePolicyName} : 'notAvailable'; my $policy_id = defined($job->{storagePolicy}->{storagePolicyId}) && $job->{storagePolicy}->{storagePolicyId} ne '' ? $job->{storagePolicy}->{storagePolicyId} : 'notAvailable'; my $dest_client_name = defined($job->{destClientName}) ? $job->{destClientName} : 'notAvailable'; # when the job is running, end_time = 0 if (defined($self->{option_results}->{filter_policy_name}) && $self->{option_results}->{filter_policy_name} ne '' && $policy_name !~ /$self->{option_results}->{filter_policy_name}/) { $self->{output}->output_add(long_msg => "skipping job '" . $policy_name . "/" . $job->{jobId} . "': no matching filter.", debug => 1); next; } if (defined($self->{option_results}->{filter_policy_id}) && $self->{option_results}->{filter_policy_id} ne '' && $policy_id !~ /$self->{option_results}->{filter_policy_id}/) { $self->{output}->output_add(long_msg => "skipping job '" . $policy_name . "/" . $job->{jobId} . "': no matching filter.", debug => 1); next; } if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' && $job->{jobType} !~ /$self->{option_results}->{filter_type}/) { $self->{output}->output_add(long_msg => "skipping job '" . $policy_name . "/" . $job->{jobId} . "': no matching filter type.", debug => 1); next; } if (defined($self->{option_results}->{filter_client_name}) && $self->{option_results}->{filter_client_name} ne '' && $dest_client_name !~ /$self->{option_results}->{filter_client_name}/) { $self->{output}->output_add(long_msg => "skipping job '" . $policy_name . "/" . $job->{jobId} . "': no matching filter type.", debug => 1); next; } if (defined($job->{clientGroups}) && defined($self->{option_results}->{filter_client_name}) && $self->{option_results}->{filter_client_name} ne '') { my $matched = 0; foreach (@$job->{clientGroups}) { if ($_->{clientGroupName} =~ /$self->{option_results}->{filter_client_group}/) { $matched = 1; last; } } if ($matched == 0) { $self->{output}->output_add(long_msg => "skipping job '" . $policy_name . "/" . $job->{jobId} . "': no matching filter type.", debug => 1); next; } } $self->{policy}->{$policy_name} = { job => {}, display => $policy_name } if (!defined($self->{policy}->{$policy_name})); my $elapsed_time = $current_time - $job->{jobStartTime}; if ($options{custom}->is_use_cache()) { $elapsed_time = $job->{jobElapsedTime}; } $self->{policy}->{$policy_name}->{job}->{ $job->{jobId} } = { display => $job->{jobId}, elapsed => $elapsed_time, status => $job->{status}, type => $job->{jobType} }; $self->{global}->{total}++; } } 1; __END__ =head1 MODE Check jobs. =over 8 =item B<--filter-policy-name> Filter jobs by policy name (can be a regexp). =item B<--filter-policy-id> Filter jobs by policy id (can be a regexp). =item B<--filter-type> Filter jobs by type (can be a regexp). =item B<--filter-client-name> Filter jobs by client name (can be a regexp). =item B<--filter-client-group> Filter jobs by client groups (can be a regexp). =item B<--timeframe> Set timeframe in seconds (E.g '3600' to check last 60 minutes). =item B<--warning-status> Set warning threshold for status (Default: '%{status} =~ /abnormal/i') Can used special variables like: %{display}, %{status}, %{type} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /errors|failed/i'). Can used special variables like: %{display}, %{status}, %{type} =item B<--warning-long> Set warning threshold for long jobs. Can used special variables like: %{display}, %{status}, %{elapsed}, %{type} =item B<--critical-long> Set critical threshold for long jobs. Can used special variables like: %{display}, %{status}, %{elapsed}, %{type} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'jobs-total'. =back =cut centreon-plugins-20220113/apps/backup/commvault/commserve/restapi/mode/listmediaagents.pm000066400000000000000000000057121417000230700315660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::commvault::commserve::restapi::mode::listmediaagents; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-media-agent-name:s' => { name => 'filter_media_agent_name' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; my $agents = $options{custom}->request( type => 'mediaagent', endpoint => '/v2/MediaAgents' ); my $results = []; foreach (@{$agents->{mediaAgentList}}) { next if (defined($self->{option_results}->{filter_media_agent_name}) && $self->{option_results}->{filter_media_agent_name} ne '' && $_->{mediaAgent}->{mediaAgentName} !~ /$self->{option_results}->{filter_media_agent_name}/); push @$results, $_; } return $results; } sub run { my ($self, %options) = @_; my $results = $self->manage_selection(%options); foreach (@$results) { $self->{output}->output_add( long_msg => sprintf( '[id = %s][name = %s]', $_->{mediaAgent}->{mediaAgentId}, $_->{mediaAgent}->{mediaAgentName} ) ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List media agents:' ); $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 => ['id', 'name']); } sub disco_show { my ($self, %options) = @_; my $results = $self->manage_selection(%options); foreach (@$results) { $self->{output}->add_disco_entry( id => $_->{mediaAgent}->{mediaAgentId}, name => $_->{mediaAgent}->{mediaAgentName} ); } } 1; __END__ =head1 MODE List media agents. =over 8 =item B<--filter-media-agent-name> Filter media agents by name (Can be a regexp). =back =cut centreon-plugins-20220113/apps/backup/commvault/commserve/restapi/mode/liststoragepolicies.pm000066400000000000000000000057261417000230700325060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::commvault::commserve::restapi::mode::liststoragepolicies; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-policy-name:s' => { name => 'filter_policy_name' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; my $policies = $options{custom}->request( type => 'storagepolicy', endpoint => '/V2/StoragePolicy' ); my $results = []; foreach (@{$policies->{policies}}) { next if (defined($self->{option_results}->{filter_policy_name}) && $self->{option_results}->{filter_policy_name} ne '' && $_->{storagePolicy}->{storagePolicyName} !~ /$self->{option_results}->{filter_policy_name}/); push @$results, $_; } return $results; } sub run { my ($self, %options) = @_; my $results = $self->manage_selection(%options); foreach (@$results) { $self->{output}->output_add( long_msg => sprintf( '[id = %s][name = %s]', $_->{storagePolicy}->{storagePolicyId}, $_->{storagePolicy}->{storagePolicyName} ) ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List storage policies:' ); $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 => ['id', 'name']); } sub disco_show { my ($self, %options) = @_; my $results = $self->manage_selection(%options); foreach (@$results) { $self->{output}->add_disco_entry( id => $_->{storagePolicy}->{storagePolicyId}, name => $_->{storagePolicy}->{storagePolicyName} ); } } 1; __END__ =head1 MODE List storage policies. =over 8 =item B<--filter-policy-name> Filter policies by name (can be a regexp). =back =cut centreon-plugins-20220113/apps/backup/commvault/commserve/restapi/mode/mediaagents.pm000066400000000000000000000154511417000230700306730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::commvault::commserve::restapi::mode::mediaagents; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_device_status_output { my ($self, %options) = @_; return sprintf( 'status: %s [is maintenance: %s][offline reason: %s]', $self->{result_values}->{status}, $self->{result_values}->{is_maintenance}, $self->{result_values}->{offline_reason} ); } sub prefix_media_output { my ($self, %options) = @_; return "Media agent '" . $options{instance_value}->{name} . "' "; } sub prefix_global_output { my ($self, %options) = @_; return 'Media agents '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } }, { name => 'medias', type => 1, cb_prefix_output => 'prefix_media_output', message_multiple => 'All media agents are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'media-agents-total', nlabel => 'media.agents.total.count', display_ok => 0, set => { key_values => [ { name => 'total' } ], output_template => 'total: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'media-agents-online', nlabel => 'media.agents.online.count', display_ok => 0, set => { key_values => [ { name => 'online' }, { name => 'total' } ], output_template => 'online: %s', perfdatas => [ { template => '%s', min => 0, max => 'total' } ] } }, { label => 'media-agents-offline', nlabel => 'media.agents.offline.count', display_ok => 0, set => { key_values => [ { name => 'offline' }, { name => 'total' } ], output_template => 'offline: %s', perfdatas => [ { template => '%s', min => 0, max => 'total' } ] } } ]; $self->{maps_counters}->{medias} = [ { label => 'status', type => 2, critical_default => '%{is_maintenance} eq "no" and %{status} eq "offline"', set => { key_values => [ { name => 'status' }, { name => 'name' }, { name => 'is_maintenance' }, { name => 'offline_reason' } ], closure_custom_output => $self->can('custom_device_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-media-agent-id:s' => { name => 'filter_media_agent_id' }, 'filter-media-agent-name:s' => { name => 'filter_media_agent_name' } }); return $self; } my $map_status = { 0 => 'offline', 1 => 'online' }; my $map_offline_reason = { 0 => 'default', 1 => 'connectFail', 2 => 'versionMismatch', 3 => 'markedDisabled', 4 => 'olderVersionAndPastGraceperiod', 5 => 'initializing', 6 => 'migrated', 7 => 'powerManagedVm', 8 => 'nodeRefreshError', 9 => 'smartStateManagement', 10 => 'cvfwdDetectedOffline' }; sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->request( type => 'mediaagent', endpoint => '/v2/MediaAgents' ); $self->{global} = { total => 0, online => 0, offline => 0 }; $self->{medias} = {}; foreach (@{$results->{mediaAgentList}}) { if (defined($self->{option_results}->{filter_media_agent_id}) && $self->{option_results}->{filter_media_agent_id} ne '' && $_->{mediaAgent}->{mediaAgentId} !~ /$self->{option_results}->{filter_media_agent_id}/) { $self->{output}->output_add(long_msg => "skipping '" . $_->{mediaAgent}->{mediaAgentName} . "': no matching filter.", debug => 1); next; } if (defined($self->{option_results}->{filter_media_agent_name}) && $self->{option_results}->{filter_media_agent_name} ne '' && $_->{mediaAgent}->{mediaAgentName} !~ /$self->{option_results}->{filter_media_agent_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $_->{mediaAgent}->{mediaAgentName} . "': no matching filter.", debug => 1); next; } $self->{medias}->{ $_->{mediaAgent}->{mediaAgentName} } = { name => $_->{mediaAgent}->{mediaAgentName}, status => $map_status->{ $_->{status} }, is_maintenance => defined($_->{mediaAgentProps}->{markMAOfflineForMaintenance}) && $_->{mediaAgentProps}->{markMAOfflineForMaintenance} =~ /True|1/i ? 'yes' : 'no', offline_reason => $map_offline_reason->{ $_->{offlineReason} } }; $self->{global}->{ $map_status->{ $_->{status} } }++; $self->{global}->{total}++; } } 1; __END__ =head1 MODE Check media agents. =over 8 =item B<--filter-media-agent-id> Filter media agents by id (Can be a regexp). =item B<--filter-media-agent-name> Filter media agents by name (Can be a regexp). =item B<--unknown-device-status> Set unknown threshold for status. Can used special variables like: %{status}, %{name} =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{status}, %{is_maintenance}, %{offline_reason}, %{name} =item B<--critical-status> Set critical threshold for status (Default: '%{is_maintenance} eq "no" and %{status} eq "offline"'). Can used special variables like: %{status}, %{is_maintenance}, %{offline_reason}, %{name} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'media-agents-total', 'media-agents-online', 'media-agents-offline'. =back =cut centreon-plugins-20220113/apps/backup/commvault/commserve/restapi/mode/storagepools.pm000066400000000000000000000154711417000230700311350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::commvault::commserve::restapi::mode::storagepools; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return 'status: ' . $self->{result_values}->{status}; } sub custom_usage_output { my ($self, %options) = @_; my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total_space}); my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used_space}); my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free_space}); return sprintf( 'space usage total: %s used: %s (%.2f%%) free: %s (%.2f%%)', $total_size_value . " " . $total_size_unit, $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used_space}, $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free_space} ); } sub prefix_sp_output { my ($self, %options) = @_; return "Storage pool '" . $options{instance_value}->{display} . "' "; } 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 => 'status', type => 2, critical_default => '%{status} !~ /online/i', set => { key_values => [ { name => 'status' }, { name => 'display' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'usage', nlabel => 'storagepool.space.usage.bytes', set => { key_values => [ { name => 'used_space' }, { name => 'free_space' }, { name => 'prct_used_space' }, { name => 'prct_free_space' }, { name => 'total_space' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total_space', unit => 'B', cast_int => 1, label_extra_instance => 1 } ] } }, { label => 'usage-free', nlabel => 'storagepool.space.free.bytes', display_ok => 0, set => { key_values => [ { name => 'free_space' }, { name => 'used_space' }, { name => 'prct_used_space' }, { name => 'prct_free_space' }, { name => 'total_space' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total_space', unit => 'B', cast_int => 1, label_extra_instance => 1 } ] } }, { label => 'usage-prct', nlabel => 'storagepool.space.usage.percentage', display_ok => 0, set => { key_values => [ { name => 'prct_used_space' }, { name => 'used_space' }, { name => 'free_space' }, { name => 'prct_free_space' }, { name => 'total_space' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } my $map_status_code = { 0 => 'online', 1 => 'offline' }; sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->request( type => 'storagepool', endpoint => '/StoragePool' ); $self->{sp} = {}; foreach (@{$results->{storagePoolList}}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $_->{storagePoolEntity}->{storagePoolName} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping storage resource '" . $_->{storagePoolEntity}->{storagePoolName} . "': no matching filter.", debug => 1); next; } my ($total, $free) = ($_->{totalCapacity} * 1024 * 1024, $_->{totalFreeSpace} * 1024 * 1024); $self->{sp}->{ $_->{storagePoolEntity}->{storagePoolName} } = { display => $_->{storagePoolEntity}->{storagePoolName}, status => defined($map_status_code->{ $_->{statusCode} }) ? $map_status_code->{ $_->{statusCode} } : lc($_->{status}), total_space => $total, used_space => $total - $free, free_space => $free, prct_used_space => 100 - ($free * 100 / $total), prct_free_space => $free * 100 / $total }; } 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 pools. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^usage$' =item B<--filter-name> Filter storage pools by name (can be a regexp). =item B<--unknown-status> Set warning threshold for status. Can used special variables like: %{status}, %{display} =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 (Default: '%{status} !~ /online/i'). Can used special variables like: %{status}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'usage' (B), 'usage-free' (B), 'usage-prct' (%). =back =cut centreon-plugins-20220113/apps/backup/commvault/commserve/restapi/plugin.pm000066400000000000000000000036471417000230700267700ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Authors : Roman Morandell - ivertix # package apps::backup::commvault::commserve::restapi::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} = '1.0'; $self->{modes} = { 'alerts' => 'apps::backup::commvault::commserve::restapi::mode::alerts', 'jobs' => 'apps::backup::commvault::commserve::restapi::mode::jobs', 'list-media-agents' => 'apps::backup::commvault::commserve::restapi::mode::listmediaagents', 'list-storage-policies' => 'apps::backup::commvault::commserve::restapi::mode::liststoragepolicies', 'media-agents' => 'apps::backup::commvault::commserve::restapi::mode::mediaagents', 'storage-pools' => 'apps::backup::commvault::commserve::restapi::mode::storagepools' }; $self->{custom_modes}->{api} = 'apps::backup::commvault::commserve::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Commvault Commserve using Rest API. =over 8 =back =cut centreon-plugins-20220113/apps/backup/netapp/000077500000000000000000000000001417000230700207335ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/netapp/snapcenter/000077500000000000000000000000001417000230700230755ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/netapp/snapcenter/restapi/000077500000000000000000000000001417000230700245445ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/netapp/snapcenter/restapi/custom/000077500000000000000000000000001417000230700260565ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/netapp/snapcenter/restapi/custom/api.pm000066400000000000000000000204741417000230700271740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::netapp::snapcenter::restapi::custom::api; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::http; use centreon::plugins::statefile; use JSON::XS; use Digest::MD5 qw(md5_hex); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port'}, 'proto:s' => { name => 'proto' }, 'api-username:s' => { name => 'api_username' }, 'api-password:s' => { name => 'api_password' }, 'api-version:s' => { name => 'api_version' }, 'timeout:s' => { name => 'timeout' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); $self->{cache} = centreon::plugins::statefile->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : undef; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 30; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : undef; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : undef; $self->{api_version} = (defined($self->{option_results}->{api_version}) && $self->{option_results}->{api_version} ne '') ? $self->{option_results}->{api_version} : '4.1.1'; if (!defined($self->{hostname}) || $self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } if (!defined($self->{api_username}) || $self->{api_username} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-username option."); $self->{output}->option_exit(); } if (!defined($self->{api_password}) || $self->{api_password} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-password option."); $self->{output}->option_exit(); } $self->{cache}->check_options(option_results => $self->{option_results}); return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Content-Type', value => 'application/json;charset=UTF-8'); $self->{http}->add_header(key => 'Accept', value => 'application/json;charset=UTF-8'); if (defined($self->{token})) { $self->{http}->add_header(key => 'Token', value => $self->{token}); } $self->{http}->set_options(%{$self->{option_results}}); } sub json_decode { my ($self, %options) = @_; my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($options{content}); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } return $decoded; } sub clean_token { my ($self, %options) = @_; my $datas = { last_timestamp => time() }; $options{statefile}->write(data => $datas); $self->{token} = undef; } sub authenticate { my ($self, %options) = @_; my $has_cache_file = $options{statefile}->read(statefile => 'netapp_snapcenter_' . md5_hex($self->{option_results}->{hostname}) . '_' . md5_hex($self->{option_results}->{api_username})); my $token = $options{statefile}->get(name => 'token'); if ($has_cache_file == 0 || !defined($token)) { my $login = { UserOperationContext => { User => { Name => $self->{api_username}, Passphrase => $self->{api_password} } } }; my $post_json = JSON::XS->new->utf8->encode($login); my $content = $self->{http}->request( method => 'POST', url_path => '/api/' . $self->{api_version} . '/auth/login?TokenNeverExpires=false', query_form_post => $post_json, warning_status => '', unknown_status => '', critical_status => '', ); if ($self->{http}->get_code() != 200) { $self->{output}->add_option_msg(short_msg => "Login error [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded = $self->json_decode(content => $content); if (defined($decoded) && defined($decoded->{User}->{Token})) { $token = $decoded->{User}->{Token}; } else { $self->{output}->add_option_msg(short_msg => "Error retrieving token"); $self->{output}->option_exit(); } $self->{http}->add_header(key => 'Token', value => $token); my $datas = { last_timestamp => time(), token => $token }; $options{statefile}->write(data => $datas); } $self->{token} = $token; } sub request_api { my ($self, %options) = @_; $self->settings(); if (!defined($self->{token})) { $self->authenticate(statefile => $self->{cache}); } my $content = $self->{http}->request( url_path => '/api/' . $self->{api_version} . '/' . $options{endpoint}, warning_status => '', unknown_status => '', critical_status => '' ); # Maybe there is an issue with the token. So we retry. if ($self->{http}->get_code() != 200) { $self->clean_token(statefile => $self->{cache}); $self->authenticate(statefile => $self->{cache}); $content = $self->{http}->request( url_path => '/api/' . $self->{api_version} . '/' . $options{endpoint}, warning_status => '', unknown_status => '', critical_status => '' ); } my $decoded = $self->json_decode(content => $content); if (!defined($decoded)) { $self->{output}->add_option_msg(short_msg => "Error while retrieving data (add --debug option for detailed message)"); $self->{output}->option_exit(); } return $decoded; } 1; __END__ =head1 NAME Netapp SnapCenter Rest API =head1 REST API OPTIONS =over 8 =item B<--hostname> Set hostname or IP of vsca. =item B<--port> Set port (Default: '443'). =item B<--proto> Specify https if needed (Default: 'https'). =item B<--api-username> Set username. =item B<--api-password> Set password. =item B<--timeout> Threshold for HTTP timeout (Default: '30'). =back =cut centreon-plugins-20220113/apps/backup/netapp/snapcenter/restapi/mode/000077500000000000000000000000001417000230700254705ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/netapp/snapcenter/restapi/mode/jobs.pm000066400000000000000000000241631417000230700267710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::netapp::snapcenter::restapi::mode::jobs; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf('status : %s [type: %s] [end time: %s]: %s', $self->{result_values}->{status}, $self->{result_values}->{type}, $self->{result_values}->{end_time}, $self->{result_values}->{error}, ); return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'jobs', type => 2, message_multiple => '0 problem(s) detected', display_counter_problem => { nlabel => 'alerts.problems.current.count', min => 0 }, group => [ { name => 'job', , cb_prefix_output => 'prefix_job_output', skipped_code => { -11 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'total', nlabel => 'jobs.total.count', set => { key_values => [ { name => 'total' } ], output_template => 'total jobs : %s', perfdatas => [ { label => 'total', value => 'total', template => '%s', min => 0 }, ], } }, ]; $self->{maps_counters}->{job} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'display' }, { name => 'type' }, { name => 'error' }, { name => 'elapsed_time' }, { name => 'end_time' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold, } }, ]; } sub prefix_job_output { my ($self, %options) = @_; return "job '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $self->{version} = '1.0'; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'filter-type:s' => { name => 'filter_type' }, 'filter-start-time:s' => { name => 'filter_start_time' }, 'filter-end-time:s' => { name => 'filter_end_time', default => 86400 }, 'unknown-status:s' => { name => 'unknown_status', default => '' }, 'warning-status:s' => { name => 'warning_status', default => '%{status} =~ /warning/i' }, 'critical-status:s' => { name => 'critical_status', default => '%{status} =~ /failed/i' }, 'timezone:s' => { name => 'timezone' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'DateTime', error_msg => "Cannot load module 'DateTime'." ); $self->change_macros(macros => [ 'warning_status', 'critical_status', 'unknown_status', ]); if (defined($self->{option_results}->{timezone}) && $self->{option_results}->{timezone} ne '') { $ENV{TZ} = $self->{option_results}->{timezone}; } } sub date2ts { my ($self, %options) = @_; return undef if (!defined($options{date}) || $options{date} eq ''); if ($options{date} !~ /^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2}):(\d{2})(?:\s+(AM|PM))?/i) { $self->{output}->add_option_msg(short_msg => "unknown date format: $options{date}"); $self->{output}->option_exit(); } my $hour = $4; $hour += 12 if (defined($7) && $7 eq 'PM'); my $dt = DateTime->new( year => $3, month => $1, day => $2, hour => $4, minute => $5, second => $6 ); return $dt->epoch(); } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->request_api(endpoint => 'jobs'); my $map_status = { -1 => 'None', 0 => 'running', 1 => 'warning', 2 => 'failed', 3 => 'completed', 4 => 'retry', 5 => 'queued', 6 => 'validating', 7 => 'completedWithVerificationPending', 8 => 'canceled', 9 => 'completedWithRMANCatalogingPending', 10 => 'completedWithVerificationAndRMANCatalogingPending', 11 => 'completedPrimaryBackup', 12 => 'transferredBackupToVault', 13 => 'cancelling', }; my $map_type = { -1 => 'None', 0 => 'backup', 1 => 'restore', 2 => 'replication', 3 => 'retention', 4 => 'verification', 5 => 'plug-in installation', 6 => 'clone', 7 => 'delete clone', 8 => 'clone life cycle', 9 => 'ressource group', 10 => 'host', 11 => 'policy', 12 => 'discovery', 13 => 'attach policy', 14 => 'detach policy', 15 => 'storage connection', 16 => 'license check', 17 => 'mount backup', 18 => 'unmount backup', 19 => 'register mount', 20 => 'get mount', 21 => 'delete mount', 22 => 'provision', 23 => 'maintenance', 24 => 'plugin', 25 => 'remote plugin uninstallation', 26 => 'protect snapCenter repository', 27 => 'configure resources', 28 => 'catalog backup', 29 => 'uncatalog backup', 30 => 'resource', 32 => 'apply protection', 33 => 'catalog', 34 => 'plugin modify', 35 => 'repository management', 36 => 'remove protection', 37 => 'clone split', 38 => 'server management', 39 => 'import protection', 40 => 'guest file restore', 41 => 'extend protection', 42 => 'purge jobs', 43 => 'assign assets', }; $self->{global} = { total => 0 }; $self->{jobs}->{global} = { job => {} }; my $current_time = time(); foreach (@{$results->{Results}}) { my $type = defined($_->{Type}) && defined($map_type->{$_->{Type}}) ? $map_type->{$_->{Type}} : 'unknown'; my $status = defined($_->{Status}) && defined($map_status->{$_->{Status}}) ? $map_status->{$_->{Status}} : 'unknown'; my $start_ts = $self->date2ts(date => $_->{StartTime}); my $end_ts = $self->date2ts(date => $_->{EndTime}); 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 job '" . $_->{Id} . "': no matching filter type.", debug => 1); next; } if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' && $type !~ /$self->{option_results}->{filter_type}/) { $self->{output}->output_add(long_msg => "skipping job '" . $_->{Id} . "': no matching filter type.", debug => 1); next; } if (defined($self->{option_results}->{filter_end_time}) && $self->{option_results}->{filter_end_time} =~ /[0-9]+/ && (!defined($end_ts) || $end_ts < ($current_time - $self->{option_results}->{filter_end_time}))) { $self->{output}->output_add(long_msg => "skipping job '" . $_->{Id} . "': end time too old.", debug => 1); next; } if (defined($self->{option_results}->{filter_start_time}) && $self->{option_results}->{filter_start_time} =~ /[0-9]+/ && (!defined($start_ts) || $start_ts < ($current_time - $self->{option_results}->{filter_start_time}))) { $self->{output}->output_add(long_msg => "skipping job '" . $_->{Id} . "': start time too old.", debug => 1); next; } my $error = defined($_->{Error}) && $_->{Error} ne '' ? $_->{Error} : 'no error'; $error =~ s/[\n\|]/ -- /msg; $error =~ s/[\r]//msg; my $elapsed_time = defined($start_ts) ? $current_time - $start_ts : -1; $self->{jobs}->{global}->{job}->{$_->{Id}} = { display => $_->{Name}, elapsed_time => $elapsed_time, status => $status, type => $type, end_time => defined($_->{EndTime}) && $_->{EndTime} ne '' ? $_->{EndTime} : -1, error => $error, }; $self->{global}->{total}++; } } 1; __END__ =head1 MODE Check jobs status. =over 8 =item B<--filter-name> Filter job name (can be a regexp). =item B<--filter-type> Filter job type (can be a regexp). =item B<--filter-start-time> Filter job with start time greater than current time less value in seconds. =item B<--filter-end-time> Filter job with end time greater than current time less value in seconds (Default: 86400). =item B<--timezone> Set timezone (If not set, we use current server execution timezone). =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{display}, %{status}, %{type} =item B<--warning-status> Set warning threshold for status (Default: '%{status} =~ /warning/i'). Can used special variables like: %{display}, %{status}, %{type} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /failed/i'). Can used special variables like: %{display}, %{status}, %{type} =item B<--warning-total> Set warning threshold for total jobs. =item B<--critical-total> Set critical threshold for total jobs. =back =cut centreon-plugins-20220113/apps/backup/netapp/snapcenter/restapi/plugin.pm000066400000000000000000000025631417000230700264060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::netapp::snapcenter::restapi::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} = '1.0'; %{$self->{modes}} = ( 'jobs' => 'apps::backup::netapp::snapcenter::restapi::mode::jobs', ); $self->{custom_modes}{api} = 'apps::backup::netapp::snapcenter::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Netapp SnapCenter through HTTP/REST API. =over 8 =back =cut centreon-plugins-20220113/apps/backup/netbackup/000077500000000000000000000000001417000230700214205ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/netbackup/local/000077500000000000000000000000001417000230700225125ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/netbackup/local/mode/000077500000000000000000000000001417000230700234365ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/netbackup/local/mode/dedupstatus.pm000066400000000000000000000162771417000230700263560ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::netbackup::local::mode::dedupstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return 'status : ' . $self->{result_values}->{status}; } sub custom_usage_threshold { my ($self, %options) = @_; if (!defined($self->{instance_mode}->{option_results}->{'critical-usage'}) || $self->{instance_mode}->{option_results}->{'critical-usage'} eq '') { $self->{perfdata}->threshold_validate(label => 'critical-usage', value => $self->{result_values}->{watermark}); } return $self->{perfdata}->threshold_check(value => $self->{result_values}->{usage}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel}, exit_litteral => 'warning' } ]); } sub prefix_volume_output { my ($self, %options) = @_; return "Disk volume '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'volume', type => 1, cb_prefix_output => 'prefix_volume_output', message_multiple => 'All dedup status are ok' } ]; $self->{maps_counters}->{volume} = [ { label => 'status', type => 2, critical_default => '%{status} !~ /up/i', set => { key_values => [ { name => 'status' }, { name => 'display' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'usage', nlabel => 'disk_pool.deduplication.usage.percentage', set => { key_values => [ { name => 'usage' }, { name => 'watermark' }, { name => 'display' } ], output_template => 'use: %s %%', closure_custom_threshold_check => $self->can('custom_usage_threshold'), perfdatas => [ { label => 'used', template => '%s', unit => '%', min => 0, max => 100, label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'exec-only' => { name => 'exec_only' }, 'filter-name:s' => { name => 'filter_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my ($stdout) = $options{custom}->execute_command( command => 'nbdevquery', command_options => '-listdp -U' ); if (defined($self->{option_results}->{exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); } #Disk Pool Name : NBU-MASTER-DP #Disk Pool Id : NBU-MASTER-DP #Disk Type : PureDisk #Status : UP #Flag : Patchwork #Raw Size (GB) : 19236.97 #Usable Size (GB) : 19236.97 #High Watermark : 99 #Low Watermark : 60 #Num Volumes : 1 #Max IO Streams : -1 my $watermark = {}; while ($stdout =~ /^(Disk Pool Name.*?)(?=Disk Pool Name|\z)/msig) { my $pool = $1; $pool =~ /^Disk Pool Name\s*:\s*(.*?)\n/msi; my $display = centreon::plugins::misc::trim($1); $pool =~ /^High Watermark\s*:\s*(.*?)\n/msi; $watermark->{$display} = centreon::plugins::misc::trim($1); } ($stdout) = $options{custom}->execute_command( command => 'nbdevquery', command_options => '-listdv -U -stype PureDisk' ); if (defined($self->{option_results}->{exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{volume} = {}; #Disk Pool Name : NBU-MASTER-DP #Disk Type : PureDisk #Disk Volume Name : PureDiskVolume #Disk Media ID : @aaaah #Total Capacity (GB) : 9777.56 #Free Space (GB) : 837.72 #Use% : 91 #Status : UP #Flag : ReadOnWrite #Flag : AdminUp #Flag : InternalUp while ($stdout =~ /^(Disk Pool Name.*?)(?=Disk Pool Name|\z)/msig) { my $volume = $1; my ($pool_name, $volume_name, $usage, $status); $pool_name = centreon::plugins::misc::trim($1) if ($volume =~ /^Disk Pool Name\s*:\s*(.*?)\n/msi); $volume_name = centreon::plugins::misc::trim($1) if ($volume =~ /^Disk Volume Name\s*:\s*(.*?)\n/msi); $status = $1 if ($volume =~ /^Status\s*:\s*(.*?)\n/msi); $usage = $1 if ($volume =~ /^Use%\s*:\s*(.*?)\n/msi); my $display = $pool_name . '.' . $volume_name; if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $display !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $display . "': no matching filter.", debug => 1); next; } $self->{volume}->{$display} = { display => $display, usage => $usage, status => $status, watermark => $watermark->{$pool_name} }; } if (scalar(keys %{$self->{volume}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No volume found.'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check deduplication status. Commands used: 'nbdevquery -listdp -U' and 'nbdevquery -listdv -U -stype PureDisk' =over 8 =item B<--exec-only> Print command output =item B<--filter-name> Filter pool name (can be a regexp). =item B<--warning-usage> Set warning threshold in percent. =item B<--critical-usage> Set critical threshold in percent. =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{display}, %{status} =item B<--critical-status> Set critical threshold for status (Default: '%{status} !~ /up/i'). Can used special variables like: %{display}, %{status} =back =cut centreon-plugins-20220113/apps/backup/netbackup/local/mode/drivecleaning.pm000066400000000000000000000074631417000230700266200ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::netbackup::local::mode::drivecleaning; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'drive', type => 0 } ]; $self->{maps_counters}->{drive} = [ { label => 'cleaning', nlabel => 'drives.unclean.count', set => { key_values => [ { name => 'num_cleaning' }, { name => 'total' } ], output_template => '%d drives needs a reset mount time', perfdatas => [ { label => 'cleaning', template => '%s', min => 0, max => 'total' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'exec-only' => { name => 'exec_only' }, 'filter-name:s' => { name => 'filter_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my ($stdout) = $options{custom}->execute_command( command => 'tpconfig', command_options => '-l' ); if (defined($self->{option_results}->{exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{drive} = { total => 0, num_cleaning => 0 }; #Drive Name Type Mount Time Frequency Last Cleaned Comment #********** **** ********** ********* **************** ******* #IBM.ULT3580-HH5.000 hcart2* 18.3 96 05:29 21/12/2015 #IBM.ULT3580-HH5.002 hcart2* 36.8 0 11:10 20/12/2015 my @lines = split /\n/, $stdout; splice(@lines, 0, 2); foreach my $line (@lines) { $line =~ /^(\S+)/; my $name = $1; 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->{output}->output_add(long_msg => "drive '" . $name . "' checked.", debug => 1); $self->{drive}->{total}++; if ($line =~ /NEEDS CLEANING/i) { $self->{drive}->{num_cleaning}++; } } if (scalar(keys %{$self->{drive}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No drives found.'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check drive cleaning. Command used: tpconfig -l =over 8 =item B<--exec-only> Print command output =item B<--filter-name> Filter drive name (can be a regexp). =item B<--warning-*> Threshold warning. Can be: 'cleaning'. =item B<--critical-*> Threshold critical. Can be: 'cleaning'. =back =cut centreon-plugins-20220113/apps/backup/netbackup/local/mode/drivestatus.pm000066400000000000000000000103511417000230700263510ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::netbackup::local::mode::drivestatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return 'status: ' . $self->{result_values}->{status}; } sub prefix_drive_output { my ($self, %options) = @_; return "Drive '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'drive', type => 1, cb_prefix_output => 'prefix_drive_output', message_multiple => 'All drive status are ok' } ]; $self->{maps_counters}->{drive} = [ { label => 'status', type => 2, critical_default => '%{status} !~ /up/i', set => { key_values => [ { name => 'status' }, { name => 'display' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'exec-only' => { name => 'exec_only' }, 'filter-name:s' => { name => 'filter_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my ($stdout) = $options{custom}->execute_command( command => 'tpconfig', command_options => '-l' ); if (defined($self->{option_results}->{exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{drive} = {}; #robot 0 - TLD - - - - {3,0,0,1} # drive - 0 hcart2 2 UP - IBM.ULT3580-HH5.000 {3,0,1,0} # drive - 2 hcart2 1 UP - IBM.ULT3580-HH5.002 {3,0,0,0} while ($stdout =~ /^robot\s+(\d+)(.*?)(?=robot\s+\d+|\z)/msig) { my ($robot_num, $drives) = ($1, $2); while ($drives =~ /drive\s+\S+\s+(\d+)\s+\S+\s+\S+\s+(\S+)/msig) { my $name = $robot_num . '.' . $1; 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->{drive}->{$name} = { display => $name, status => $2 }; } } if (scalar(keys %{$self->{drive}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No drives found.'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check drive status. Command used: tpconfig -l =over 8 =item B<--exec-only> Print command output =item B<--filter-name> Filter drive name (can be a regexp). =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{display}, %{status} =item B<--critical-status> Set critical threshold for status (Default: '%{status} !~ /up/i'). Can used special variables like: %{display}, %{status} =back =cut centreon-plugins-20220113/apps/backup/netbackup/local/mode/jobstatus.pm000066400000000000000000000351171417000230700260210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::netbackup::local::mode::jobstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use Digest::MD5 qw(md5_hex); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return 'Status : ' . $self->{result_values}->{status}; } sub custom_long_output { my ($self, %options) = @_; return 'Started Since: ' . centreon::plugins::misc::change_seconds(value => $self->{result_values}->{elapsed}); } sub custom_long_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{elapsed} = $options{new_datas}->{$self->{instance} . '_elapsed'}; $self->{result_values}->{type} = $options{new_datas}->{$self->{instance} . '_type'}; $self->{result_values}->{state} = $options{new_datas}->{$self->{instance} . '_state'}; return -11 if ($self->{result_values}->{state} !~ /queued|active/); return 0; } sub custom_frozen_threshold { my ($self, %options) = @_; my $status = catalog_status_threshold_ng($self, %options); $self->{instance_mode}->{last_status_frozen} = $status; return $status; } sub custom_frozen_output { my ($self, %options) = @_; my $msg = "Frozen: 'no'"; if (!$self->{output}->is_status(value => $self->{instance_mode}->{last_status_frozen}, compare => 'ok', litteral => 1)) { $msg = "Frozen: 'yes'"; } return $msg; } sub custom_frozen_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{elapsed} = $options{new_datas}->{$self->{instance} . '_elapsed'}; $self->{result_values}->{type} = $options{new_datas}->{$self->{instance} . '_type'}; $self->{result_values}->{state} = $options{new_datas}->{$self->{instance} . '_state'}; $self->{result_values}->{kb} = $options{new_datas}->{$self->{instance} . '_kb'} - $options{old_datas}->{$self->{instance} . '_kb'}; $self->{result_values}->{parentid} = $options{new_datas}->{$self->{instance} . '_parentid'}; $self->{result_values}->{schedule} = $options{new_datas}->{$self->{instance} . '_schedule'}; $self->{result_values}->{jobid} = $options{new_datas}->{$self->{instance} . '_jobid'}; return 0; } sub policy_long_output { my ($self, %options) = @_; return "Checking policy '" . $options{instance_value}->{display} . "'"; } sub prefix_policy_output { my ($self, %options) = @_; return "Policy '" . $options{instance_value}->{display} . "' "; } sub prefix_job_output { my ($self, %options) = @_; return "Job '" . $options{instance_value}->{display} . "' [Type: " . $options{instance_value}->{type} . "] [State: " . $options{instance_value}->{state} . "] " ; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'policy', type => 2, cb_prefix_output => 'prefix_policy_output', cb_long_output => 'policy_long_output', message_multiple => 'All policies are ok', group => [ { name => 'job', cb_prefix_output => 'prefix_job_output', skipped_code => { -11 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'total', nlabel => 'jobs.total.count', set => { key_values => [ { name => 'total' } ], output_template => 'total jobs : %s', perfdatas => [ { label => 'total', value => 'total', template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{job} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'display' }, { name => 'type' }, { name => 'state' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } }, { label => 'long', type => 2, set => { key_values => [ { name => 'status' }, { name => 'display' }, { name => 'elapsed' }, { name => 'type' }, { name => 'state' } ], closure_custom_calc => $self->can('custom_long_calc'), closure_custom_output => $self->can('custom_long_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'frozen', type => 2, critical_default => '%{state} =~ /active|queue/ && %{kb} == 0', set => { key_values => [ { name => 'kb', diff => 1 }, { name => 'status' }, { name => 'display' }, { name => 'elapsed' }, { name => 'type' }, { name => 'state' }, { name => 'parentid' }, { name => 'schedule' }, { name => 'jobid' } ], closure_custom_calc => $self->can('custom_frozen_calc'), closure_custom_output => $self->can('custom_frozen_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => $self->can('custom_frozen_threshold') } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'exec-only' => { name => 'exec_only' }, 'filter-policy-name:s' => { name => 'filter_policy_name' }, 'filter-type:s' => { name => 'filter_type' }, 'filter-end-time:s' => { name => 'filter_end_time', default => 86400 }, 'filter-start-time:s' => { name => 'filter_start_time' }, 'ok-status:s' => { name => 'ok_status', default => '%{status} == 0' }, 'warning-status:s' => { name => 'warning_status', default => '%{status} == 1' }, 'critical-status:s' => { name => 'critical_status', default => '%{status} > 1' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['ok_status', 'warning_status', 'critical_status']); } my %job_type = ( 0 => 'backup', 1 => 'archive', 2 => 'restore', 3 => 'verify', 4 => 'duplicate', 5 => 'phase 1 or phase 2 import', 6 => 'catalog backup', 7 => 'vault duplicate', 8 => 'label tape', 9 => 'erase tape', 10 => 'tape request', 11 => 'clean tape', 12 => 'format tape', 13 => 'physical inventory of robotic library', 14 => 'qualification test of drive or robotic library', 15 => 'catalog recovery', 16 => 'media contents', 17 => 'image cleanup', 18 => 'LiveUpdate', 20 => 'Replication (Auto Image Replication)', 21 => 'Import (Auto Image Replication)', 22 => 'backup From Snapshot', 23 => 'Replication (snap)', 24 => 'Import (snap)', 25 => 'application state capture', 26 => 'indexing', 27 => 'index cleanup', 28 => 'Snapshot', 29 => 'SnapIndex', 30 => 'ActivateInstantRecovery', 31 => 'DeactivateInstantRecovery', 32 => 'ReactivateInstantRecovery', 33 => 'StopInstantRecovery', 34 => 'InstantRecovery', ); my %job_state = ( 0 => 'queued and awaiting resources', 1 => 'active', 2 => 'requeued and awaiting resources', 3 => 'done', 4 => 'suspended', 5 => 'incomplete', ); sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = 'netbackup_' . $self->{mode} . '_' . (defined($self->{option_results}->{hostname}) ? $self->{option_results}->{hostname} : 'me') . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_policy_name}) ? md5_hex($self->{option_results}->{filter_policy_name}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_start_time}) ? md5_hex($self->{option_results}->{filter_start_time}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{job_end_time}) ? md5_hex($self->{option_results}->{job_end_time}) : md5_hex('all')); my ($stdout) = $options{custom}->execute_command( command => 'bpdbjobs', command_options => '-report -most_columns' ); if (defined($self->{option_results}->{exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{global} = { total => 0 }; $self->{policy} = {}; my $current_time = time(); foreach my $line (split /\n/, $stdout) { my @values = split /,/, $line; my ($job_id, $job_type, $job_state, $job_status, $job_pname, $job_schedule, $job_start_time, $job_end_time, $job_kb, $job_parentid) = ($values[0], $values[1], $values[2], $values[3], $values[4], $values[5], $values[8], $values[10], $values[14], $values[33]); $job_pname = defined($job_pname) && $job_pname ne '' ? $job_pname : 'unknown'; $job_status = defined($job_status) && $job_status =~ /[0-9]/ ? $job_status : -1; # when the job is running, end_time = 000000 $job_end_time = undef if (defined($job_end_time) && int($job_end_time) == 0); if (defined($self->{option_results}->{filter_policy_name}) && $self->{option_results}->{filter_policy_name} ne '' && $job_pname !~ /$self->{option_results}->{filter_policy_name}/) { $self->{output}->output_add(long_msg => "skipping job '" . $job_pname . "/" . $job_id . "': no matching filter.", debug => 1); next; } if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' && $job_type{$job_type} !~ /$self->{option_results}->{filter_type}/) { $self->{output}->output_add(long_msg => "skipping job '" . $job_pname . "/" . $job_id . "': no matching filter type.", debug => 1); next; } if (defined($self->{option_results}->{filter_end_time}) && $self->{option_results}->{filter_end_time} =~ /[0-9]+/ && defined($job_end_time) && $job_end_time =~ /[0-9]+/ && $job_end_time < $current_time - $self->{option_results}->{filter_end_time}) { $self->{output}->output_add(long_msg => "skipping job '" . $job_pname . "/" . $job_id . "': end time too old.", debug => 1); next; } if (defined($self->{option_results}->{filter_start_time}) && $self->{option_results}->{filter_start_time} =~ /[0-9]+/ && defined($job_start_time) && $job_start_time =~ /[0-9]+/ && $job_start_time < $current_time - $self->{option_results}->{filter_start_time}) { $self->{output}->output_add(long_msg => "skipping job '" . $job_pname . "/" . $job_id . "': start time too old.", debug => 1); next; } $self->{policy}->{$job_pname} = { job => {}, display => $job_pname } if (!defined($self->{policy}->{$job_pname})); my $elapsed_time = $current_time - $job_start_time; $self->{policy}->{$job_pname}->{job}->{$job_id} = { display => $job_id, elapsed => $elapsed_time, status => $job_status, state => $job_state{$job_state}, type => $job_type{$job_type}, kb => defined($job_kb) && $job_kb =~ /[0-9]+/ ? $job_kb : '0', parentid => defined($job_parentid) ? $job_parentid : '', jobid => $job_id, schedule => defined($job_schedule) ? $job_schedule : '', }; $self->{global}->{total}++; } } 1; __END__ =head1 MODE Check job status. Command used: bpdbjobs -report -most_columns =over 8 =item B<--exec-only> Print command output =item B<--filter-policy-name> Filter job policy name (can be a regexp). =item B<--filter-type> Filter job type (can be a regexp). =item B<--filter-start-time> Filter job with start time greater than current time less value in seconds. =item B<--filter-end-time> Filter job with end time greater than current time less value in seconds (Default: 86400). =item B<--ok-status> Set ok threshold for status (Default: '%{status} == 0') Can used special variables like: %{display}, %{status} =item B<--warning-status> Set warning threshold for status (Default: '%{status} == 1') Can used special variables like: %{display}, %{status}, %{type} =item B<--critical-status> Set critical threshold for status (Default: '%{status} > 1'). Can used special variables like: %{display}, %{status}, %{type} =item B<--warning-long> Set warning threshold for long jobs (Default: none) Can used special variables like: %{display}, %{status}, %{elapsed}, %{type} =item B<--critical-long> Set critical threshold for long jobs (Default: none). Can used special variables like: %{display}, %{status}, %{elapsed}, %{type} =item B<--warning-frozen> Set warning threshold for frozen jobs (Default: none) Can used special variables like: %{display}, %{status}, %{elapsed}, %{type}, %{kb}, %{parentid}, %{schedule}, %{jobid} =item B<--critical-frozen> Set critical threshold for frozen jobs (Default: '%{state} =~ /active|queue/ && %{kb} == 0'). Can used special variables like: %{display}, %{status}, %{elapsed}, %{type}, %{kb}, %{parentid}, %{schedule}, %{jobid} =item B<--warning-total> Set warning threshold for total jobs. =item B<--critical-total> Set critical threshold for total jobs. =back =cut centreon-plugins-20220113/apps/backup/netbackup/local/mode/listpolicies.pm000066400000000000000000000066721417000230700265120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::netbackup::local::mode::listpolicies; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::misc; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach (sort keys %{$self->{policies}}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $_ !~ /$self->{option_results}->{filter_name}/i) { $self->{output}->output_add(long_msg => "skipping policy '" . $_ . "': no type or no matching filter type"); next; } $self->{output}->output_add(long_msg => "'" . $_ . "' [active = " . $self->{policies}->{$_}->{active} . "]"); } $self->{output}->output_add( severity => 'OK', short_msg => 'List policy:' ); $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', 'active']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach (sort keys %{$self->{policies}}) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $_ !~ /$self->{option_results}->{filter_name}/i); $self->{output}->add_disco_entry( name => $_, active => $self->{policies}->{$_}->{active} ); } } sub manage_selection { my ($self, %options) = @_; my ($stdout) = $options{custom}->execute_command( command => 'bppllist' ); $self->{policies} = {}; my @lines = split /\n/, $stdout; foreach my $policy_name (@lines) { ($stdout) = $options{custom}->execute_command( command => 'bpplinfo', command_options => $policy_name . ' -L' ); #Policy Type: NBU-Catalog (35) #Active: yes my $active = ''; $active = $1 if ($stdout =~ /^Active\s*:\s+(\S+)/msi); $self->{policies}->{$policy_name} = { active => $active }; } } 1; __END__ =head1 MODE List policies. Command used: 'bppllist' and 'bpplinfo %{policy_name} -L' =over 8 =item B<--filter-name> Filter policy name (can be a regexp). =back =cut centreon-plugins-20220113/apps/backup/netbackup/local/mode/tapeusage.pm000066400000000000000000000217161417000230700257610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::netbackup::local::mode::tapeusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_usage_perfdata { my ($self, %options) = @_; my $label = 'used'; my $nlabel = $self->{option_results}->{units} eq '%' ? 'tape.usage.percentage' : 'tape.usage.bytes'; my $value_perf = $self->{result_values}->{used}; if (defined($self->{instance_mode}->{option_results}->{free})) { $label = 'free'; $nlabel = $self->{option_results}->{units} eq '%' ? 'tape.free.usage.percentage' : 'tape.free.usage.bytes'; $value_perf = $self->{result_values}->{free}; } my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } $self->{output}->perfdata_add( label => $label, nlabel => $nlabel, 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($self->{instance_mode}->{option_results}->{free})); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; $threshold_value = $self->{result_values}->{prct_free} if (defined($self->{instance_mode}->{option_results}->{free})); } $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{label}, exit_litteral => 'warning' } ]); return $exit; } sub custom_usage_output { my ($self, %options) = @_; return sprintf( "total: %s used: %s (%.2f%%) free: %s (%.2f%%)", $self->{result_values}->{total}, $self->{result_values}->{used}, $self->{result_values}->{prct_used}, $self->{result_values}->{free}, $self->{result_values}->{prct_free} ); } sub custom_usage_calc { my ($self, %options) = @_; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_total'}; $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_used'}; $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; $self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used}; $self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 } ]; $self->{maps_counters}->{global} = [ { label => 'usage', set => { key_values => [ { name => 'total' }, { name => 'used' } ], closure_custom_calc => \&custom_usage_calc, closure_custom_output => \&custom_usage_output, closure_custom_perfdata => \&custom_usage_perfdata, closure_custom_threshold_check => \&custom_usage_threshold } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-scratch:s' => { name => 'filter_scratch', default => 'scratch' }, 'units:s' => { name => 'units', default => '%' }, 'free' => { name => 'free' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my ($stdout) = $options{custom}->execute_command( command => 'vmquery', command_options => '-a -w' ); if (defined($self->{option_results}->{exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{global} = { total => 0, used => 0 }; #media optical media barcode robot robot robot robot side/ volume prev # of max # of create assigned first mount last mount expiration off sent off return off off #ID partner type barcode partner host type # slot face group pool pool # pool mounts mounts cleanings datetime datetime datetime datetime datetime status offsite location datetime datetime slot ses id version description #-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- #000001 - HCART2 000001L5 - - NONE - - - --- VP-05WEEKS-EXT 9 VP-SCRATCH 1250 0 - 30/11/2012 15:30 29/02/2016 20:43 27/01/2013 17:57 02/03/2016 01:36 00/00/0000 00:00 0 - 00/00/0000 00:00 00/00/0000 00:00 - - 50 --- #000002 - HCART2 000002L5 - XXX-NBU-XXX TLD 0 8 - 000_00000_TLD VP-SCRATCH 4 VP-05WEEKS-EXT # Remove header $stdout =~ s/\x00//msg; $stdout =~ s/^.*?----.*?\n//ms; foreach my $line (split /\n/, $stdout) { $line =~ /^\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+(\S+)\s+\S+\s+\S+\s+(\S+)\s+\S+\s+\S+\s+(\S+)/; my ($robot_host, $robot_slot, $pool) = ($1, $2, $3); next if ($robot_slot !~ /[0-9]/); $self->{global}->{total}++; if (defined($self->{option_results}->{filter_scratch}) && $self->{option_results}->{filter_scratch} ne '' && $pool !~ /$self->{option_results}->{filter_scratch}/i) { $self->{global}->{used}++; } } if ($self->{global}->{total} == 0) { $self->{output}->add_option_msg(short_msg => 'No tape found.'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check tapes available in library. Command used: vmquery -a -w =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: 'vmquery'). 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 -w'). =item B<--exec-only> Print command output =item B<--filter-scratch> Filter tape scratch (Default: 'scratch'). =item B<--units> Units of thresholds (Default: '%') ('%', 'absolute'). =item B<--free> Thresholds are on free tape left. =item B<--warning-*> Threshold warning. Can be: 'usage'. =item B<--critical-*> Threshold critical. Can be: 'usage'. =back =cut centreon-plugins-20220113/apps/backup/netbackup/local/plugin.pm000066400000000000000000000033561417000230700243550ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::netbackup::local::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} = { 'dedup-status' => 'apps::backup::netbackup::local::mode::dedupstatus', 'drive-cleaning' => 'apps::backup::netbackup::local::mode::drivecleaning', 'drive-status' => 'apps::backup::netbackup::local::mode::drivestatus', 'job-status' => 'apps::backup::netbackup::local::mode::jobstatus', 'list-policies' => 'apps::backup::netbackup::local::mode::listpolicies', 'tape-usage' => 'apps::backup::netbackup::local::mode::tapeusage' }; $self->{custom_modes}->{cli} = 'centreon::plugins::script_custom::cli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Netbackup through local commands (the plugin can use SSH). =cut centreon-plugins-20220113/apps/backup/quadstor/000077500000000000000000000000001417000230700213065ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/quadstor/local/000077500000000000000000000000001417000230700224005ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/quadstor/local/mode/000077500000000000000000000000001417000230700233245ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/quadstor/local/mode/listvtl.pm000066400000000000000000000124561417000230700253730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::quadstor::local::mode::listvtl; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::misc; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $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 => 'vtconfig' }, "command-path:s" => { name => 'command_path', default => '/quadstorvtl/bin' }, "command-options:s" => { name => 'command_options', default => '-l' }, "filter-name:s" => { name => 'filter_name' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach (sort keys %{$self->{vtl}}) { $self->{output}->output_add(long_msg => "'" . $_ . "' [type = " . $self->{vtl}->{$_}->{type} . "]"); } $self->{output}->output_add(severity => 'OK', short_msg => 'List VTL:'); $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', 'type']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach (sort keys %{$self->{vtl}}) { $self->{output}->add_disco_entry(name => $_, active => $self->{vtl}->{$_}->{type} ); } } 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}); #Name DevType Type #BV00002 VTL IBM IBM System Storage TS3100 $self->{vtl} = {}; my @lines = split /\n/, $stdout; shift @lines; foreach (@lines) { next if (! /^(\S+)\s+(\S+)/); my ($name, $type) = ($1, $2); if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $name !~ /$self->{option_results}->{filter_name}/i) { $self->{output}->output_add(long_msg => "skipping vtl '" . $name . "': no matching filter"); next; } $self->{vtl}->{$name} = { type => $type }; } } 1; __END__ =head1 MODE List VTL. =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: 'vtconfig'). Can be changed if you have output in a file. =item B<--command-path> Command path (Default: '/quadstorvtl/bin'). =item B<--command-options> Command options (Default: '-l'). =item B<--filter-name> Filter vtl name (can be a regexp). =back =cut centreon-plugins-20220113/apps/backup/quadstor/local/mode/vtldiskusage.pm000066400000000000000000000257501417000230700264000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::quadstor::local::mode::vtldiskusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); 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} . '_status'}; $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($self->{instance_mode}->{option_results}->{free})) { $label = 'free'; $value_perf = $self->{result_values}->{free}; } my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } $self->{output}->perfdata_add( label => $label, unit => 'B', instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, 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} ); } sub custom_usage_threshold { my ($self, %options) = @_; my ($exit, $threshold_value); $threshold_value = $self->{result_values}->{used}; $threshold_value = $self->{result_values}->{free} if (defined($self->{instance_mode}->{option_results}->{free})); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; $threshold_value = $self->{result_values}->{prct_free} if (defined($self->{instance_mode}->{option_results}->{free})); } $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel}, 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 => 'disk', type => 1, cb_prefix_output => 'prefix_disk_output', message_multiple => 'All disks are ok' } ]; $self->{maps_counters}->{disk} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { 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 => \&catalog_status_threshold, } }, { label => 'usage', set => { key_values => [ { name => 'total' }, { name => 'used' }, { name => 'display' } ], 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; $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 => 'bdconfig' }, "command-path:s" => { name => 'command_path', default => '/quadstorvtl/bin' }, "command-options:s" => { name => 'command_options', default => '-l -c' }, "filter-name:s" => { name => 'filter_name' }, "warning-status:s" => { name => 'warning_status', default => '' }, "critical-status:s" => { name => 'critical_status', default => '%{status} !~ /active/i' }, "units:s" => { name => 'units', default => '%' }, "free" => { name => 'free' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub prefix_disk_output { my ($self, %options) = @_; return "Disk '" . $options{instance_value}->{display} . "' "; } 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->{disk} = {}; #ID Vendor Model SerialNumber Name Pool Size Used Status #1 Msft Virtual /dev/sdb Default 1024.00 21.28 Active #3 Msft Virtual /dev/sdc Default 1024.00 21.03 Active #2 Msft Virtual /dev/sdd Default 1024.00 44.53 Active #4 Msft Virtual /dev/sde Default 1024.00 165.06 Active my @lines = split /\n/, $stdout; shift @lines; foreach (@lines) { next if (! /(\S+)\s+\S+\s+([0-9\.]+)\s+([0-9\.]+)\s+(\S+)\s*$/); my ($name, $size, $used, $status) = ($1, $2, $3, $4); if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $name !~ /$self->{option_results}->{filter_name}/i) { $self->{output}->output_add(long_msg => "skipping disk '" . $name . "': no matching filter"); next; } $self->{disk}->{$name} = { display => $name, total => $size * 1024 * 1024 * 1024, used => $used * 1024 * 1024 * 1024, status => $status, }; } 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 vtl disk usage. =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: 'bdconfig'). Can be changed if you have output in a file. =item B<--command-path> Command path (Default: '/quadstorvtl/bin'). =item B<--command-options> Command options (Default: '-l -c'). =item B<--filter-name> Filter tape name. =item B<--units> Units of thresholds (Default: '%') ('%', 'absolute'). =item B<--free> Thresholds are on free tape left. =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 (Default: '%{status} !~ /active/i'). Can used special variables like: %{status}, %{display} =item B<--warning-*> Threshold warning. Can be: 'usage'. =item B<--critical-*> Threshold critical. Can be: 'usage'. =back =cut centreon-plugins-20220113/apps/backup/quadstor/local/mode/vtljobstatus.pm000066400000000000000000000207301417000230700264300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::quadstor::local::mode::vtljobstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use Digest::MD5 qw(md5_hex); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return 'status : ' . $self->{result_values}->{status}; } sub custom_long_output { my ($self, %options) = @_; return 'elapsed time : ' . centreon::plugins::misc::change_seconds(value => $self->{result_values}->{elapsed}); } sub custom_frozen_threshold { my ($self, %options) = @_; my $status = catalog_status_threshold_ng($self, %options); $self->{instance_mode}->{last_status_frozen} = $status; return $status; } sub custom_frozen_output { my ($self, %options) = @_; my $msg = 'frozen : no'; if (!$self->{output}->is_status(value => $self->{instance_mode}->{last_status_frozen}, compare => 'ok', litteral => 1)) { $msg = 'frozen: yes'; } return $msg; } sub custom_frozen_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{elapsed} = $options{new_datas}->{$self->{instance} . '_elapsed'}; $self->{result_values}->{kb} = $options{new_datas}->{$self->{instance} . '_kb'} - $options{old_datas}->{$self->{instance} . '_kb'}; return 0; } sub prefix_job_output { my ($self, %options) = @_; return "job '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'jobs', type => 2, message_multiple => '0 problem(s) detected', display_counter_problem => { label => 'alerts', min => 0 }, group => [ { name => 'job', cb_prefix_output => 'prefix_job_output', skipped_code => { -11 => 1 } } ] } ]; $self->{maps_counters}->{job} = [ { label => 'status', type => 2, critical_default => '%{status} =~ /error/i', set => { key_values => [ { name => 'status' }, { name => 'display' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'long', threshold => 2, set => { key_values => [ { name => 'status' }, { name => 'display' }, { name => 'elapsed' } ], closure_custom_output => $self->can('custom_long_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'frozen', threshold => 0, set => { key_values => [ { name => 'kb', diff => 1 }, { name => 'status' }, { name => 'display' }, { name => 'elapsed' } ], closure_custom_calc => $self->can('custom_frozen_calc'), closure_custom_output => $self->can('custom_frozen_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => $self->can('custom_frozen_threshold'), } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $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 => 'impexp' }, 'command-path:s' => { name => 'command_path', default => '/quadstorvtl/bin' }, 'command-options:s' => { name => 'command_options', default => '-l' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = 'quadstor_' . $self->{mode} . '_' . (defined($self->{option_results}->{hostname}) ? $self->{option_results}->{hostname} : 'me') . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); 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->{jobs}->{global} = { job => {} }; #JobID Type Source State Transfer Elapsed #252 Import 701831L2 Error 36.00 GB 572 #253 Export 701849L2 Completed 19.43 GB 262 #254 Export 701850L2 Completed 16.05 GB 1072 #255 Export 701854L2 Completed 6.31 GB 142 my $current_time = time(); my @lines = split /\n/, $stdout; shift @lines; foreach (@lines) { next if (! /^(\d+)\s+\S+\s+(\S+)\s+(\S+)\s+([0-9\.]+)\s+\S+\s+(\d+)/); my ($job_id, $job_source, $job_state, $job_kb, $job_elapsed) = ($1, $2, $3, $4, $5); my $name = $job_source . '.' . $job_id; $self->{jobs}->{global}->{job}->{$name} = { display => $name, status => $job_state, kb => $job_kb * 1024, elapsed => $job_elapsed }; } if (scalar(keys %{$self->{jobs}->{global}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No job found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check job 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: 'impexp'). Can be changed if you have output in a file. =item B<--command-path> Command path (Default: '/quadstorvtl/bin'). =item B<--command-options> Command options (Default: '-l'). =item B<--warning-status> Set warning threshold for status (Default: none) Can used special variables like: %{display}, %{status} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /error/i'). Can used special variables like: %{display}, %{status} =item B<--warning-long> Set warning threshold for long jobs (Default: none) Can used special variables like: %{display}, %{status}, %{elapsed} =item B<--critical-long> Set critical threshold for long jobs (Default: none). Can used special variables like: %{display}, %{status}, %{elapsed} =item B<--warning-frozen> Set warning threshold for frozen jobs (Default: none) Can used special variables like: %{display}, %{status}, %{elapsed}, %{kb} =item B<--critical-frozen> Set critical threshold for frozen jobs (Default: none). Can used special variables like: %{display}, %{status}, %{elapsed}, %{kb} =back =cut centreon-plugins-20220113/apps/backup/quadstor/local/mode/vtltapeusage.pm000066400000000000000000000271061417000230700263740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::quadstor::local::mode::vtltapeusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); 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} . '_status'}; $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($self->{instance_mode}->{option_results}->{free})) { $label = 'free'; $value_perf = $self->{result_values}->{free}; } my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } $self->{output}->perfdata_add( label => $label, unit => 'B', instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, 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} ); } sub custom_usage_threshold { my ($self, %options) = @_; my ($exit, $threshold_value); $threshold_value = $self->{result_values}->{used}; $threshold_value = $self->{result_values}->{free} if (defined($self->{instance_mode}->{option_results}->{free})); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; $threshold_value = $self->{result_values}->{prct_free} if (defined($self->{instance_mode}->{option_results}->{free})); } $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel}, 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}->{prct_used} = $options{new_datas}->{$self->{instance} . '_used_prct'}; $self->{result_values}->{used} = $self->{result_values}->{total} * $self->{result_values}->{prct_used} / 100; $self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used}; $self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'tape', type => 1, cb_prefix_output => 'prefix_tape_output', message_multiple => 'All tapes are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'count', set => { key_values => [ { name => 'count' } ], output_template => 'Number of tapes : %s', perfdatas => [ { label => 'count', value => 'count', template => '%s', unit => 'tapes', min => 0 }, ], } }, ]; $self->{maps_counters}->{tape} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { 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 => \&catalog_status_threshold, } }, { label => 'usage', set => { key_values => [ { name => 'total' }, { name => 'used_prct' }, { name => 'display' } ], 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; $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 => 'vcconfig' }, 'command-path:s' => { name => 'command_path', default => '/quadstorvtl/bin' }, 'command-options:s' => { name => 'command_options', default => '-l -v %{vtl_name}' }, 'vtl-name:s' => { name => 'vtl_name' }, 'filter-name:s' => { name => 'filter_name' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{status} !~ /active/i' }, 'units:s' => { name => 'units', default => '%' }, 'free' => { name => 'free' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{vtl_name}) || $self->{option_results}->{vtl_name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to set vtl-name option."); $self->{output}->option_exit(); } $self->{option_results}->{command_options} =~ s/%\{vtl_name\}/$self->{option_results}->{vtl_name}/; $self->change_macros(macros => ['warning_status', 'critical_status']); } sub prefix_tape_output { my ($self, %options) = @_; return "Tape '" . $options{instance_value}->{display} . "' "; } 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}->{count} = 0; $self->{tape} = {}; #Pool Label Element Address Vtype WORM Size Used% Status #Default 701862L2 Unknown 0 LTO 2 200GB No 200 99 Vaulted #Default 701899L2 Slot 1180 LTO 2 200GB No 200 0 Active #Default 701900L2 Slot 1181 LTO 2 200GB No 200 0 Active #Default 701901L2 Slot 1182 LTO 2 200GB No 200 0 Active #Default 701902L2 Slot 1183 LTO 2 200GB No 200 0 Active #Default 701903L2 Slot 1184 LTO 2 200GB No 200 0 Active #Default 701904L2 Slot 1185 LTO 2 200GB No 200 0 Active my @lines = split /\n/, $stdout; shift @lines; foreach (@lines) { next if (! /([0-9\.]+)\s+([0-9\.]+)\s+(\S+)\s*$/); my ($size, $used_prct, $status) = ($1, $2, $3); next if (! /^\S+\s+(\S+)\s+\S+\s+(\S+)/); my $name = $1 . '.' . $2; if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $name !~ /$self->{option_results}->{filter_name}/i) { $self->{output}->output_add(long_msg => "skipping vtl '" . $name . "': no matching filter"); next; } $self->{tape}->{$name} = { display => $name, total => $size * 1024 * 1024 * 1024, used_prct => $used_prct, status => $status, }; $self->{global}->{count}++; } if (scalar(keys %{$self->{tape}}) == 0) { $self->{output}->add_option_msg(short_msg => "No tape found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check vtl tape usage. =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: 'vcconfig'). Can be changed if you have output in a file. =item B<--command-path> Command path (Default: '/quadstorvtl/bin'). =item B<--command-options> Command options (Default: '-l -v %{vtl_name}'). =item B<--vtl-name> Set VTL name (Required). =item B<--filter-name> Filter tape name. =item B<--units> Units of thresholds (Default: '%') ('%', 'absolute'). =item B<--free> Thresholds are on free tape left. =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 (Default: '%{status} !~ /active/i'). Can used special variables like: %{status}, %{display} =item B<--warning-*> Threshold warning. Can be: 'count', 'usage'. =item B<--critical-*> Threshold critical. Can be: 'count', 'usage'. =back =cut centreon-plugins-20220113/apps/backup/quadstor/local/plugin.pm000066400000000000000000000030051417000230700242320ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::quadstor::local::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} = '0.1'; %{$self->{modes}} = ( 'list-vtl' => 'apps::backup::quadstor::local::mode::listvtl', 'vtl-disk-usage' => 'apps::backup::quadstor::local::mode::vtldiskusage', 'vtl-job-status' => 'apps::backup::quadstor::local::mode::vtljobstatus', 'vtl-tape-usage' => 'apps::backup::quadstor::local::mode::vtltapeusage', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Quadstor through local commands (the plugin can use SSH). =cut centreon-plugins-20220113/apps/backup/rapidrecovery/000077500000000000000000000000001417000230700223225ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/rapidrecovery/snmp/000077500000000000000000000000001417000230700232775ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/rapidrecovery/snmp/mode/000077500000000000000000000000001417000230700242235ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/rapidrecovery/snmp/mode/agent.pm000066400000000000000000000137221417000230700256640ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::rapidrecovery::snmp::mode::agent; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); sub custom_status_output { my ($self, %options) = @_; my $msg = 'status : ' . $self->{result_values}->{status}; return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'agent', type => 1, cb_prefix_output => 'prefix_agent_output', message_multiple => 'All agents are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'total', display_ok => 0, nlabel => 'agents.total.count', set => { key_values => [ { name => 'total' } ], output_template => 'total agents: %d', perfdatas => [ { value => 'total', template => '%d', min => 0 }, ], } }, ]; $self->{maps_counters}->{agent} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'display' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold, } }, { label => 'recoverypoints', nlabel => 'agent.recoverypoints.count', set => { key_values => [ { name => 'recovery_points' }, { name => 'display' } ], output_template => 'recovery points: %s', perfdatas => [ { value => 'recovery_points', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'unknown-status:s' => { name => 'unknown_status', default => '%{status} =~ /unreachable/i' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{status} =~ /failed|authenticationError/i' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status', 'unknown_status']); } sub prefix_agent_output { my ($self, %options) = @_; return "Agent '" . $options{instance_value}->{display} . "' "; } my $map_status = { 0 => 'online', 1 => 'pendingFailover', 2 => 'unreachable', 3 => 'authenticationError', 4 => 'failed', 5 => 'loading' }; my $mapping = { agentName => { oid => '.1.3.6.1.4.1.674.11000.1000.200.100.300.1.3' }, agentStatus => { oid => '.1.3.6.1.4.1.674.11000.1000.200.100.300.1.5', map => $map_status }, agentRecoveryPointsCount => { oid => '.1.3.6.1.4.1.674.11000.1000.200.100.300.1.7' }, }; sub manage_selection { my ($self, %options) = @_; my $oid_agentEntry = '.1.3.6.1.4.1.674.11000.1000.200.100.300.1'; my $snmp_result = $options{snmp}->get_table( oid => $oid_agentEntry, start => $mapping->{agentName}->{oid}, end => $mapping->{agentRecoveryPointsCount}->{oid}, nothing_quit => 1 ); $self->{agent} = {}; foreach my $oid (keys %$snmp_result) { next if ($oid !~ /^$mapping->{agentName}->{oid}\.(.*)/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $result->{agentName} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{agentName} . "': no matching filter.", debug => 1); next; } $self->{agent}->{$instance} = { display => $result->{agentName}, status => $result->{agentStatus}, recovery_points => $result->{agentRecoveryPointsCount} }; } $self->{global} = { total => scalar(keys %{$self->{agent}}) }; } 1; __END__ =head1 MODE Check agents. =over 8 =item B<--unknown-status> Set unknown threshold for status (Default: '%{status} =~ /unreachable/i'). Can used special variables like: %{status}, %{display} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{display} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /failed|authenticationError/i'). Can used special variables like: %{status}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'total', 'recoverypoints'. =item B<--filter-name> Filter agent name (can be a regexp). =back =cut centreon-plugins-20220113/apps/backup/rapidrecovery/snmp/mode/repository.pm000066400000000000000000000173261417000230700270110ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::rapidrecovery::snmp::mode::repository; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); sub custom_status_output { my ($self, %options) = @_; my $msg = 'status : ' . $self->{result_values}->{status}; return $msg; } sub custom_space_output { my ($self, %options) = @_; my $msg = sprintf( "space total: %s %s used: %s %s (%.2f%%) free: %s %s (%.2f%%)", $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}), $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}), $self->{result_values}->{prct_used}, $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}), $self->{result_values}->{prct_free} ); return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'repository', type => 1, cb_prefix_output => 'prefix_repository_output', message_multiple => 'All repositories are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{repository} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'display' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold, } }, { label => 'space-usage', nlabel => 'repository.space.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' }, { name => 'display' } ], closure_custom_output => $self->can('custom_space_output'), perfdatas => [ { value => 'used', template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'space-usage-free', display_ok => 0, nlabel => 'repository.space.free.bytes', set => { key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' }, { name => 'display' } ], closure_custom_output => $self->can('custom_space_output'), perfdatas => [ { value => 'free', template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'space-usage-prct', display_ok => 0, nlabel => 'repository.space.usage.percentage', set => { key_values => [ { name => 'prct_used' }, { name => 'display' } ], output_template => 'space used: %.2f %%', perfdatas => [ { value => 'prct_used', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'unknown-status:s' => { name => 'unknown_status', default => '%{status} =~ /unknown/i' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{status} =~ /error/i' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status', 'unknown_status']); } sub prefix_repository_output { my ($self, %options) = @_; return "Repository '" . $options{instance_value}->{display} . "' "; } my $map_status = { 0 => 'unknown', 1 => 'unmounting', 2 => 'unmounted', 3 => 'mounting', 4 => 'mounted', 5 => 'maintenance', 6 => 'error' }; my $mapping = { repositoryName => { oid => '.1.3.6.1.4.1.674.11000.1000.200.100.200.1.3' }, repositoryStatus => { oid => '.1.3.6.1.4.1.674.11000.1000.200.100.200.1.5', map => $map_status }, repositorySizeMB => { oid => '.1.3.6.1.4.1.674.11000.1000.200.100.200.1.6' }, repositoryFreeMB => { oid => '.1.3.6.1.4.1.674.11000.1000.200.100.200.1.7' }, }; sub manage_selection { my ($self, %options) = @_; my $oid_repositoryEntry = '.1.3.6.1.4.1.674.11000.1000.200.100.200.1'; my $snmp_result = $options{snmp}->get_table( oid => $oid_repositoryEntry, start => $mapping->{repositoryName}->{oid}, nothing_quit => 1 ); $self->{repository} = {}; foreach my $oid (keys %$snmp_result) { next if ($oid !~ /^$mapping->{repositoryName}->{oid}\.(.*)/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $result->{repositoryName} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{repositoryName} . "': no matching filter.", debug => 1); next; } my $total = $result->{repositorySizeMB} * 1024 * 1024; my $free = $result->{repositoryFreeMB} * 1024 * 1024; $self->{repository}->{$instance} = { display => $result->{repositoryName}, status => $result->{repositoryStatus}, free => $free, used => $total - $free, prct_used => ($total - $free) * 100 / $total, prct_free => $free * 100 / $total, total => $total, }; } if (scalar(keys %{$self->{repository}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No repository found.'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check repositories. =over 8 =item B<--unknown-status> Set unknown threshold for status (Default: '%{status} =~ /unknown/i'). Can used special variables like: %{status}, %{display} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{display} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /error/i'). Can used special variables like: %{status}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'space-usage' (B), 'space-usage-free' (B), 'space-usage-prct' (%). =item B<--filter-name> Filter repository name (can be a regexp). =back =cut centreon-plugins-20220113/apps/backup/rapidrecovery/snmp/plugin.pm000066400000000000000000000025131417000230700251340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::rapidrecovery::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}} = ( 'agent' => 'apps::backup::rapidrecovery::snmp::mode::agent', 'repository' => 'apps::backup::rapidrecovery::snmp::mode::repository', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Rapid Recovery from Quest Software in SNMP. =cut centreon-plugins-20220113/apps/backup/rubrik/000077500000000000000000000000001417000230700207425ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/rubrik/restapi/000077500000000000000000000000001417000230700224115ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/rubrik/restapi/custom/000077500000000000000000000000001417000230700237235ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/rubrik/restapi/custom/api.pm000066400000000000000000000221641417000230700250370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::rubrik::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use centreon::plugins::statefile; use JSON::XS; use Digest::MD5 qw(md5_hex); 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 => { 'api-username:s' => { name => 'api_username' }, 'api-password:s' => { name => 'api_password' }, 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'timeout:s' => { name => 'timeout' }, 'unknown-http-status:s' => { name => 'unknown_http_status' }, 'warning-http-status:s' => { name => 'warning_http_status' }, 'critical-http-status:s' => { name => 'critical_http_status' }, 'token:s' => { name => 'token' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); $self->{cache} = centreon::plugins::statefile->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{option_results}->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{option_results}->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{option_results}->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 30; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : ''; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : ''; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300'; $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; $self->{token} = $self->{option_results}->{token}; if (!defined($self->{option_results}->{hostname}) || $self->{option_results}->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --hostname option.'); $self->{output}->option_exit(); } if (defined($self->{token})) { $self->{cache}->check_options(option_results => $self->{option_results}); return 0 if ($self->{token} ne ''); } if ($self->{api_username} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --api-username option.'); $self->{output}->option_exit(); } if ($self->{api_password} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --api-password option.'); $self->{output}->option_exit(); } return 0; } sub settings { my ($self, %options) = @_; return if (defined($self->{settings_done})); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->add_header(key => 'Content-Type', value => 'application/json'); $self->{http}->set_options(%{$self->{option_results}}); $self->{settings_done} = 1; } sub get_connection_info { my ($self, %options) = @_; return $self->{option_results}->{hostname} . ':' . $self->{option_results}->{port}; } sub get_token { my ($self, %options) = @_; my $has_cache_file = $self->{cache}->read(statefile => 'rubrik_api_' . md5_hex($self->{option_results}->{hostname} . '_' . $self->{api_username})); my $token = $self->{cache}->get(name => 'token'); my $md5_secret_cache = $self->{cache}->get(name => 'md5_secret'); my $md5_secret = md5_hex($self->{api_username} . $self->{api_password}); if ($has_cache_file == 0 || !defined($token) || (defined($md5_secret_cache) && $md5_secret_cache ne $md5_secret) ) { $self->settings(); my $content = $self->{http}->request( url_path => '/api/v1/cluster/me', credentials => 1, basic => 1, username => $self->{api_username}, password => $self->{api_password} ); my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response"); $self->{output}->option_exit(); } $token = $decoded->{token}; my $datas = { updated => time(), token => $decoded->{token}, md5_secret => $md5_secret }; $self->{cache}->write(data => $datas); } return $token; } sub clean_token { my ($self, %options) = @_; my $datas = { updated => time() }; $self->{cache}->write(data => $datas); } sub credentials { my ($self, %options) = @_; my $token = $self->{token}; if (defined($self->{token}) && $self->{token} eq '') { $token = $self->get_token(); } my $creds = {}; if (defined($self->{token})) { $creds = { header => ['Authorization: Bearer ' . $token], unknown_status => '', warning_status => '', critical_status => '' }; } else { $creds = { credentials => 1, basic => 1, username => $self->{api_username}, password => $self->{api_password}, unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status} }; } return $creds; } sub request_api { my ($self, %options) = @_; $self->settings(); my $creds = $self->credentials(); my ($content) = $self->{http}->request( url_path => '/api/internal' . $options{endpoint}, get_param => $options{get_param}, %$creds ); # Maybe token is invalid. so we retry if (defined($self->{token}) && $self->{http}->get_code() < 200 || $self->{http}->get_code() >= 300) { $self->clean_token(); $creds = $self->credentials(); $content = $self->{http}->request( url_path => '/api/internal' . $options{endpoint}, get_param => $options{get_param}, %$creds, unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status} ); } if (!defined($content) || $content eq '') { $self->{output}->add_option_msg(short_msg => "API returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded; eval { $decoded = JSON::XS->new->allow_nonref(1)->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } return $decoded; } 1; __END__ =head1 NAME Rubrik Rest API =head1 REST API OPTIONS Rubrik Rest API =over 8 =item B<--hostname> Set hostname. =item B<--port> Port used (Default: 443) =item B<--proto> Specify https if needed (Default: 'https') =item B<--api-username> API username. =item B<--api-password> API password. =item B<--token> Use token authentication. If option is empty, token is created. =item B<--timeout> Set timeout in seconds (Default: 30). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/backup/rubrik/restapi/mode/000077500000000000000000000000001417000230700233355ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/rubrik/restapi/mode/cluster.pm000066400000000000000000000150731417000230700253620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::rubrik::restapi::mode::cluster; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use POSIX; use Digest::MD5 qw(md5_hex); sub custom_status_output { my ($self, %options) = @_; return 'status: ' . $self->{result_values}->{status}; } sub prefix_cluster_output { my ($self, %options) = @_; return "Cluster '" . $options{instance_value}->{name} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'clusters', type => 1, cb_prefix_output => 'prefix_cluster_output', message_multiple => 'All clusters are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{clusters} = [ { label => 'status', type => 2, critical_default => '%{status} !~ /ok/i', set => { key_values => [ { name => 'status' }, { name => 'name' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'read', nlabel => 'cluster.io.read.usage.bytespersecond', display_ok => 0, set => { key_values => [ { name => 'read' } ], output_template => 'read: %s %s/s', output_change_bytes => 1, perfdatas => [ { template => '%d', unit => 'B/s', label_extra_instance => 1 } ] } }, { label => 'write', nlabel => 'cluster.io.write.usage.bytespersecond', display_ok => 0, set => { key_values => [ { name => 'write' } ], output_template => 'write: %s %s/s', output_change_bytes => 1, perfdatas => [ { template => '%d', unit => 'B/s', min => 0, label_extra_instance => 1 } ] } }, { label => 'read-iops', nlabel => 'cluster.io.read.usage.iops', set => { key_values => [ { name => 'read_iops' } ], output_template => 'read iops: %s', perfdatas => [ { template => '%s', unit => 'iops', min => 0, label_extra_instance => 1 } ] } }, { label => 'write-iops', nlabel => 'cluster.io.write.usage.iops', set => { key_values => [ { name => 'write_iops' } ], output_template => 'write iops: %s', perfdatas => [ { template => '%s', unit => 'iops', min => 0, label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'cluster-id:s' => { name => 'cluster_id', default => 'me' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{option_results}->{cluster_id} = 'me' if ($self->{option_results}->{cluster_id} eq ''); } sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = 'rubrik_' . $self->{mode} . '_' . md5_hex($options{custom}->get_connection_info()) . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . md5_hex($self->{option_results}->{cluster_id}); my $last_timestamp = $self->read_statefile_key(key => 'last_timestamp'); $last_timestamp = time() - (5 * 60) if (!defined($last_timestamp)); my $timespan = POSIX::ceil((time() - $last_timestamp) / 60); $timespan = 1 if ($timespan <= 0); my $name = $options{custom}->request_api(endpoint => '/cluster/' . $self->{option_results}->{cluster_id} . '/name'); my $status = $options{custom}->request_api(endpoint => '/cluster/' . $self->{option_results}->{cluster_id} . '/system_status'); my $io_stats = $options{custom}->request_api( endpoint => '/cluster/' . $self->{option_results}->{cluster_id} . '/io_stats', get_param => ['range=-' . $timespan . 'min'] ); $self->{clusters} = { $name => { name => $name, status => $status->{status} } }; foreach my $entry (( ['ioThroughput', 'readBytePerSecond', 'read'], ['ioThroughput', 'writeBytePerSecond', 'write'], ['iops', 'readsPerSecond', 'read_iops'], ['iops', 'writesPerSecond', 'write_iops'] )) { my $count = 0; foreach (@{$io_stats->{ $entry->[0] }->{ $entry->[1] }}) { $self->{clusters}->{$name}->{ $entry->[2] } = 0 if (!defined($self->{clusters}->{$name}->{ $entry->[2] })); $self->{clusters}->{$name}->{ $entry->[2] } += $_->{stat}; $count++; } $self->{clusters}->{$name}->{ $entry->[2] } = int($self->{clusters}->{$name}->{ $entry->[2] } / $count) if ($count > 0); } } 1; __END__ =head1 MODE Check cluster. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='status' =item B<--cluster-id> Which cluster to check (Default: 'me'). =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{status}, %{name} =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{status}, %{name} =item B<--critical-status> Set critical threshold for status (Default: '%{status} !~ /ok/i'). Can used special variables like: %{status}, %{name} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'read' (B/s), 'write' (B/s), 'read-iops', 'write-iops'. =back =cut centreon-plugins-20220113/apps/backup/rubrik/restapi/mode/compliance.pm000066400000000000000000000063711417000230700260140ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::rubrik::restapi::mode::compliance; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_global_output { my ($self, %options) = @_; return 'Backup objects last 24 hours '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'incompliance', nlabel => 'backup.objects.incompliance.24h.count', set => { key_values => [ { name => 'incompliance' } ], output_template => 'in compliance: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'noncompliance', nlabel => 'backup.objects.noncompliance.24h.count', set => { key_values => [ { name => 'noncompliance' } ], output_template => 'non compliance: %s', perfdatas => [ { template => '%s', min => 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 => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $reports = $options{custom}->request_api(endpoint => '/report'); my $report_id; foreach (@{$reports->{data}}) { if ($_->{name} eq 'SLA Compliance Summary') { $report_id = $_->{id}; last; } } if (!defined($report_id)) { $self->{output}->add_option_msg(short_msg => "Cannot find report name 'SLA Compliance Summary'"); $self->{output}->option_exit(); } my $tasks = $options{custom}->request_api( endpoint => '/report/' . $report_id . '/chart', get_param => ['timezone_offset=0', 'chart_id=chart0'] ); $self->{global} = {}; foreach (@{$tasks->[0]->{dataColumns}}) { $self->{global}->{ lc($_->{label}) } = $_->{dataPoints}->[0]->{value}; } } 1; __END__ =head1 MODE Check backup objects compliance. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='noncompliance' =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'incompliance', 'noncompliance'. =back =cut centreon-plugins-20220113/apps/backup/rubrik/restapi/mode/disks.pm000066400000000000000000000137131417000230700250150ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::rubrik::restapi::mode::disks; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf( 'status: %s', $self->{result_values}->{status} ); } sub cluster_long_output { my ($self, %options) = @_; return "checking cluster '" . $options{instance_value}->{name} . "'"; } sub prefix_cluster_output { my ($self, %options) = @_; return "cluster '" . $options{instance_value}->{name} . "' "; } sub prefix_disk_output { my ($self, %options) = @_; return "disk '" . $options{instance_value}->{id} . "' "; } sub prefix_global_cluster_output { my ($self, %options) = @_; return 'disks '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'clusters', type => 3, cb_prefix_output => 'prefix_cluster_output', cb_long_output => 'cluster_long_output', indent_long_output => ' ', message_multiple => 'All clusters are ok', group => [ { name => 'cluster', type => 0, cb_prefix_output => 'prefix_global_cluster_output' }, { name => 'disks', type => 1, display_long => 1, cb_prefix_output => 'prefix_disk_output', message_multiple => 'disks are ok', skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{cluster} = [ { label => 'cluster-disks-total', nlabel => 'cluster.disks.total.count', display_ok => 0, set => { key_values => [ { name => 'disks_total' } ], output_template => 'total %d', perfdatas => [ { template => '%d', min => 0, label_extra_instance => 1 } ] } }, { label => 'cluster-disks-active', nlabel => 'cluster.disks.active.count', display_ok => 0, set => { key_values => [ { name => 'disks_active' }, { name => 'disks_total' } ], output_template => 'active %d', perfdatas => [ { template => '%d', min => 0, max => 'disks_total', label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{disks} = [ { label => 'disk-status', type => 2, critical_default => '%{status} !~ /active/i', set => { key_values => [ { name => 'status' }, { name => 'id' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'cluster-id:s' => { name => 'cluster_id', default => 'me' }, 'filter-disk-id:s' => { name => 'filter_disk_id' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{option_results}->{cluster_id} = 'me' if ($self->{option_results}->{cluster_id} eq ''); } sub manage_selection { my ($self, %options) = @_; my $name = $options{custom}->request_api(endpoint => '/cluster/' . $self->{option_results}->{cluster_id} . '/name'); my $disks = $options{custom}->request_api(endpoint => '/cluster/' . $self->{option_results}->{cluster_id} . '/disk'); $self->{clusters} = { $name => { name => $name, cluster => { disks_total => 0, disks_active => 0 }, disks => {} } }; foreach (@{$disks->{data}}) { my $id = $_->{nodeId} . ':' . $_->{id}; next if (defined($self->{option_results}->{filter_disk_id}) && $self->{option_results}->{filter_disk_id} ne '' && $id !~ /$self->{option_results}->{filter_disk_id}/); $self->{clusters}->{$name}->{disks}->{$id} = { id => $id, status => lc($_->{status}) }; $self->{clusters}->{$name}->{cluster}->{ 'disks_' . lc($_->{status}) }++ if (defined($self->{clusters}->{$name}->{cluster}->{ 'disks_' . lc($_->{status}) })); $self->{clusters}->{$name}->{cluster}->{disks_total}++; } } 1; __END__ =head1 MODE Check cluster disks. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='disk-status' =item B<--cluster-id> Which cluster to check (Default: 'me'). =item B<--filter-disk-id> Filter disks by disk id (can be a regexp). =item B<--unknown-disks-status> Set unknown threshold for status. Can used special variables like: %{status}, %{id} =item B<--warning-disk-status> Set warning threshold for status. Can used special variables like: %{status}, %{id} =item B<--critical-disk-status> Set critical threshold for status (Default: '%{status} !~ /active/i'). Can used special variables like: %{status}, %{id} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'cluster-disks-total', 'cluster-disks-active'. =back =cut centreon-plugins-20220113/apps/backup/rubrik/restapi/mode/nodes.pm000066400000000000000000000141001417000230700247770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::rubrik::restapi::mode::nodes; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf( 'status: %s', $self->{result_values}->{status} ); } sub cluster_long_output { my ($self, %options) = @_; return "checking cluster '" . $options{instance_value}->{name} . "'"; } sub prefix_cluster_output { my ($self, %options) = @_; return "cluster '" . $options{instance_value}->{name} . "' "; } sub prefix_node_output { my ($self, %options) = @_; return "node '" . $options{instance_value}->{id} . "' [ip address: " . $options{instance_value}->{ip_address} . '] '; } sub prefix_global_cluster_output { my ($self, %options) = @_; return 'nodes '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'clusters', type => 3, cb_prefix_output => 'prefix_cluster_output', cb_long_output => 'cluster_long_output', indent_long_output => ' ', message_multiple => 'All clusters are ok', group => [ { name => 'cluster', type => 0, cb_prefix_output => 'prefix_global_cluster_output' }, { name => 'nodes', type => 1, display_long => 1, cb_prefix_output => 'prefix_node_output', message_multiple => 'nodes are ok', skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{cluster} = [ { label => 'cluster-nodes-total', nlabel => 'cluster.nodes.total.count', display_ok => 0, set => { key_values => [ { name => 'nodes_total' } ], output_template => 'total: %d', perfdatas => [ { template => '%d', min => 0, label_extra_instance => 1 } ] } }, { label => 'cluster-nodes-ok', nlabel => 'cluster.nodes.ok.count', display_ok => 0, set => { key_values => [ { name => 'nodes_ok' }, { name => 'nodes_total' } ], output_template => 'ok: %d', perfdatas => [ { template => '%d', min => 0, max => 'nodes_total', label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{nodes} = [ { label => 'node-status', type => 2, critical_default => '%{status} !~ /ok/i', set => { key_values => [ { name => 'status' }, { name => 'id' }, { name => 'ip_address' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'cluster-id:s' => { name => 'cluster_id', default => 'me' }, 'filter-node-id:s' => { name => 'filter_node_id' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{option_results}->{cluster_id} = 'me' if ($self->{option_results}->{cluster_id} eq ''); } sub manage_selection { my ($self, %options) = @_; my $name = $options{custom}->request_api(endpoint => '/cluster/' . $self->{option_results}->{cluster_id} . '/name'); my $nodes = $options{custom}->request_api(endpoint => '/cluster/' . $self->{option_results}->{cluster_id} . '/node'); $self->{clusters} = { $name => { name => $name, cluster => { nodes_total => 0, nodes_ok => 0 }, nodes => {} } }; foreach (@{$nodes->{data}}) { next if (defined($self->{option_results}->{filter_node_id}) && $self->{option_results}->{filter_node_id} ne '' && $_->{id} !~ /$self->{option_results}->{filter_node_id}/); $self->{clusters}->{$name}->{nodes}->{ $_->{id} } = { id => $_->{id}, ip_address => $_->{ipAddress}, status => lc($_->{status}) }; $self->{clusters}->{$name}->{cluster}->{ 'nodes_' . lc($_->{status}) }++ if (defined($self->{clusters}->{$name}->{cluster}->{ 'nodes_' . lc($_->{status}) })); $self->{clusters}->{$name}->{cluster}->{nodes_total}++; } } 1; __END__ =head1 MODE Check cluster nodes. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='node-status' =item B<--cluster-id> Which cluster to check (Default: 'me'). =item B<--filter-node-id> Filter nodes by node id (can be a regexp). =item B<--unknown-node-status> Set unknown threshold for status. Can used special variables like: %{status}, %{ip_address}, %{id} =item B<--warning-node-status> Set warning threshold for status. Can used special variables like: %{status}, %{ip_address}, %{id} =item B<--critical-node-status> Set critical threshold for status (Default: '%{status} !~ /ok/i'). Can used special variables like: %{status}, %{ip_address}, %{id} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'cluster-nodes-total', 'cluster-nodes-ok'. =back =cut centreon-plugins-20220113/apps/backup/rubrik/restapi/mode/storage.pm000066400000000000000000000121101417000230700253320ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::rubrik::restapi::mode::storage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_usage_output { my ($self, %options) = @_; my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total_space}); my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used_space}); my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free_space}); my $msg = sprintf( 'space usage total: %s used: %s (%.2f%%) free: %s (%.2f%%)', $total_size_value . " " . $total_size_unit, $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used_space}, $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free_space} ); return $msg; } sub prefix_ss_output { my ($self, %options) = @_; return 'Storage system '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'ss', type => 0, cb_prefix_output => 'prefix_ss_output' } ]; $self->{maps_counters}->{ss} = [ { label => 'usage', nlabel => 'storage.space.usage.bytes', set => { key_values => [ { name => 'used_space' }, { name => 'free_space' }, { name => 'prct_used_space' }, { name => 'prct_free_space' }, { name => 'total_space' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { value => 'used_space', template => '%d', min => 0, max => 'total_space', unit => 'B', cast_int => 1 } ] } }, { label => 'usage-free', nlabel => 'storage.space.free.bytes', display_ok => 0, set => { key_values => [ { name => 'free_space' }, { name => 'used_space' }, { name => 'prct_used_space' }, { name => 'prct_free_space' }, { name => 'total_space' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { value => 'free_space', template => '%d', min => 0, max => 'total_space', unit => 'B', cast_int => 1 } ] } }, { label => 'usage-prct', nlabel => 'storage.space.usage.percentage', display_ok => 0, set => { key_values => [ { name => 'prct_used_space' }, { name => 'used_space' }, { name => 'free_space' }, { name => 'prct_free_space' }, { name => 'total_space' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%' } ] } }, { label => 'full-remaining-days', nlabel => 'storage.full.remaining.days.count', set => { key_values => [ { name => 'full_remaining_days' } ], output_template => 'remaining days before filled: %s', perfdatas => [ { template => '%s', unit => 'd', min => 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 => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $storage = $options{custom}->request_api(endpoint => '/stats/system_storage'); my $runway = $options{custom}->request_api(endpoint => '/stats/runway_remaining'); $self->{ss} = { total_space => $storage->{total}, used_space => $storage->{total} - $storage->{available}, free_space => $storage->{available}, prct_used_space => (($storage->{total} - $storage->{available}) * 100 / $storage->{total}), prct_free_space => ($storage->{available} * 100 / $storage->{total}), full_remaining_days => $runway->{days} }; } 1; __END__ =head1 MODE Check storage system. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='remaining' =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'usage' (B), 'usage-free' (B), 'usage-prct' (%), 'full-remaining-days'. =back =cut centreon-plugins-20220113/apps/backup/rubrik/restapi/mode/tasks.pm000066400000000000000000000067231417000230700250300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::rubrik::restapi::mode::tasks; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_global_output { my ($self, %options) = @_; return 'Tasks last 24 hours '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'succeeded', nlabel => 'tasks.succeeded.24h.count', set => { key_values => [ { name => 'succeeded' } ], output_template => 'succeeded: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'failed', nlabel => 'tasks.failed.24h.count', set => { key_values => [ { name => 'failed' } ], output_template => 'failed: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'canceled', nlabel => 'tasks.canceled.24h.count', set => { key_values => [ { name => 'canceled' } ], output_template => 'canceled: %s', perfdatas => [ { template => '%s', min => 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 => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $reports = $options{custom}->request_api(endpoint => '/report'); my $report_id; foreach (@{$reports->{data}}) { if ($_->{name} eq 'Protection Tasks Details') { $report_id = $_->{id}; last; } } if (!defined($report_id)) { $self->{output}->add_option_msg(short_msg => "Cannot find report name 'Protection Tasks Details'"); $self->{output}->option_exit(); } my $tasks = $options{custom}->request_api( endpoint => '/report/' . $report_id . '/chart', get_param => ['timezone_offset=0', 'chart_id=chart0'] ); $self->{global} = {}; foreach (@{$tasks->[0]->{dataColumns}}) { $self->{global}->{ lc($_->{label}) } = $_->{dataPoints}->[0]->{value}; } } 1; __END__ =head1 MODE Check tasks. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='failed' =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'succeeded', 'failed', 'canceled'. =back =cut centreon-plugins-20220113/apps/backup/rubrik/restapi/plugin.pm000066400000000000000000000032571417000230700242540ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::rubrik::restapi::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} = { 'cluster' => 'apps::backup::rubrik::restapi::mode::cluster', 'compliance' => 'apps::backup::rubrik::restapi::mode::compliance', 'disks' => 'apps::backup::rubrik::restapi::mode::disks', 'nodes' => 'apps::backup::rubrik::restapi::mode::nodes', 'storage' => 'apps::backup::rubrik::restapi::mode::storage', 'tasks' => 'apps::backup::rubrik::restapi::mode::tasks' }; $self->{custom_modes}->{api} = 'apps::backup::rubrik::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Rubrik using Rest API. =cut centreon-plugins-20220113/apps/backup/tsm/000077500000000000000000000000001417000230700202475ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/tsm/local/000077500000000000000000000000001417000230700213415ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/tsm/local/custom/000077500000000000000000000000001417000230700226535ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/tsm/local/custom/api.pm000066400000000000000000000137071417000230700237720ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::tsm::local::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 => { 'tsm-hostname:s' => { name => 'tsm_hostname' }, 'tsm-username:s' => { name => 'tsm_username' }, 'tsm-password:s' => { name => 'tsm_password' }, 'ssh-hostname:s' => { name => 'ssh_hostname' }, '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 => 45 }, 'sudo' => { name => 'sudo' }, 'command:s' => { name => 'command', default => 'dsmadmc' }, 'command-path:s' => { name => 'command_path', default => '/opt/tivoli/tsm/client/ba/bin' }, 'command-options:s' => { name => 'command_options', default => '' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'TSM CLI OPTIONS', once => 1); $self->{output} = $options{output}; return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; if (!defined($self->{option_results}->{tsm_hostname}) || $self->{option_results}->{tsm_hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to set tsm-hostname option."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{tsm_username}) || $self->{option_results}->{tsm_username} eq '') { $self->{output}->add_option_msg(short_msg => "Need to set tsm-username option."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{tsm_password})) { $self->{output}->add_option_msg(short_msg => "Need to set tsm-password option."); $self->{output}->option_exit(); } return 0; } sub tsm_build_options { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); if (defined($self->{option_results}->{ssh_hostname}) && $self->{option_results}->{ssh_hostname} ne '') { $self->{option_results}->{hostname} = $self->{option_results}->{ssh_hostname}; $self->{option_results}->{remote} = 1; } $self->{option_results}->{command_options} = "-comma -dataonly=yes -SERVER=\"$self->{option_results}->{tsm_hostname}\" -ID=\"$self->{option_results}->{tsm_username}\" -PASSWORD=\"$self->{option_results}->{tsm_password}\" -TAB \"$options{query}\""; } sub get_tsm_id { my ($self, %options) = @_; return $self->{option_results}->{tsm_hostname} . '_' . $self->{option_results}->{tsm_username} . '_' . $self->{option_results}->{tsm_password}; } sub execute_command { my ($self, %options) = @_; $self->tsm_build_options(%options); my ($response, $exit_code) = 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}, no_quit => 1 ); # 11 is for: ANR2034E SELECT: No match found using this criteria. if ($exit_code != 0 && $exit_code != 11) { $self->{output}->output_add(long_msg => $response); $self->{output}->add_option_msg(short_msg => "Execution command issue (details)."); $self->{output}->option_exit(); } $self->{output}->output_add(long_msg => $response, debug => 1); return $response; } 1; __END__ =head1 NAME tsm cli =head1 SYNOPSIS my tsm cli =head1 TSM CLI OPTIONS =over 8 =item B<--tsm-hostname> TSM hostname to query (Required). =item B<--tsm-username> TSM username (Required). =item B<--tsm-password> TSM password (Required). =item B<--ssh-hostname> Specify SSH hostname. =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: 45). =item B<--sudo> Use 'sudo' to execute the command. =item B<--command> Specify command (default: 'dsmadmc'). =item B<--command-path> Specify path (default: '/opt/tivoli/tsm/client/ba/bin') =item B<--command-options> Command options. =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/backup/tsm/local/mode/000077500000000000000000000000001417000230700222655ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/tsm/local/mode/actlog.pm000066400000000000000000000143721417000230700241030ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::tsm::local::mode::actlog; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::statefile; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("alarm [severity: %s] [message: %s] %s", $self->{result_values}->{severity}, $self->{result_values}->{message}, $self->{result_values}->{generation_time}); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{message} = $options{new_datas}->{$self->{instance} . '_message'}; $self->{result_values}->{severity} = $options{new_datas}->{$self->{instance} . '_severity'}; $self->{result_values}->{since} = $options{new_datas}->{$self->{instance} . '_since'}; $self->{result_values}->{generation_time} = $options{new_datas}->{$self->{instance} . '_generation_time'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'alarms', type => 2, message_multiple => '0 problem(s) detected', display_counter_problem => { label => 'alerts', min => 0 }, group => [ { name => 'alarm', skipped_code => { -11 => 1 } } ] } ]; $self->{maps_counters}->{alarm} = [ { label => 'status', type => 2, warning_default => '%{severity} =~ /warning/', critical_default => '%{severity} =~ /error|severe/', set => { key_values => [ { name => 'message' }, { name => 'severity' }, { name => 'since' }, { name => 'generation_time' } ], 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 => \&catalog_status_threshold_ng } } ]; } 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-time:s" => { name => 'filter_time', default => '1' }, "memory" => { name => 'memory' }, "timezone:s" => { name => 'timezone' } }); centreon::plugins::misc::mymodule_load(output => $self->{output}, module => 'DateTime', error_msg => "Cannot load module 'DateTime'."); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->check_options(%options); } $self->{option_results}->{timezone} = 'GMT' if (!defined($self->{option_results}->{timezone}) || $self->{option_results}->{timezone} eq ''); } sub manage_selection { my ($self, %options) = @_; my $response = $options{custom}->execute_command( query => "SELECT date_time, severity, message FROM actlog WHERE date_time>current_timestamp-" . $self->{option_results}->{filter_time} . " hours" ); $self->{alarms}->{global} = { alarm => {} }; my $last_time; if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->read(statefile => 'cache_tsm_' . $self->{mode} . '_' . $options{custom}->get_tsm_id()); $last_time = $self->{statefile_cache}->get(name => 'last_time'); } my %map_severity = (E => 'error', W => 'warning', I => 'information', S => 'severe', K => 'kernel'); my ($i, $current_time) = (1, time()); #2017-09-19 12:08:14.000000,I,"ANR1283I File count is incorrect fo..." my $tz = centreon::plugins::misc::set_timezone(name => $self->{option_results}->{timezone}); while ($response =~ /^(.*?),(.*?),(.*)$/mg) { my ($date, $severity, $message) = ($1, $2, $3); $date =~ /^(\d+)-(\d+)-(\d+)\s+(\d+)[:\/](\d+)[:\/](\d+)/; my $dt = DateTime->new(year => $1, month => $2, day => $3, hour => $4, minute => $5, second => $6, %$tz); next if (defined($self->{option_results}->{memory}) && defined($last_time) && $last_time > $dt->epoch); my $diff_time = $current_time - $dt->epoch; $message =~ s/^"(.*)"$/$1/; $self->{alarms}->{global}->{alarm}->{$i} = { message => $message, severity => $map_severity{$severity}, since => $diff_time, generation_time => centreon::plugins::misc::change_seconds(value => $diff_time) }; $i++; } if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->write(data => { last_time => $current_time }); } } 1; __END__ =head1 MODE Check activity logs. =over 8 =item B<--filter-time> Get activity log more recent than X hour(s) (default: '1'). =item B<--warning-status> Set warning threshold for status (Default: '%{severity} =~ /warning/') Can used special variables like: %{message}, %{severity}, %{since} =item B<--critical-status> Set critical threshold for status (Default: '%{severity} =~ /error|severe/'). Can used special variables like: %{message}, %{severity}, %{since} =item B<--timezone> Timezone of time options. Default is 'GMT'. =item B<--memory> Only check new alarms. =back =cut centreon-plugins-20220113/apps/backup/tsm/local/mode/drives.pm000066400000000000000000000121621417000230700241210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::tsm::local::mode::drives; 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, cb_prefix_output => 'prefix_global_output' } ]; $self->{maps_counters}->{global} = [ { label => 'online', nlabel => 'drives.online.count', set => { key_values => [ { name => 'online' } ], output_template => 'online : %s', perfdatas => [ { label => 'online', template => '%s', min => 0 } ] } }, { label => 'offline', nlabel => 'drives.offline.count', set => { key_values => [ { name => 'offline' } ], output_template => 'offline : %s', perfdatas => [ { label => 'offline', template => '%s', min => 0 } ] } }, { label => 'unavailable', nlabel => 'drives.unavailable.count', set => { key_values => [ { name => 'unavailable' } ], output_template => 'unavailable : %s', perfdatas => [ { label => 'unavailable', template => '%s', min => 0 } ] } }, { label => 'empty', nlabel => 'drives.empty.count', set => { key_values => [ { name => 'empty' } ], output_template => 'empty : %s', perfdatas => [ { label => 'empty', template => '%s', min => 0 } ] } }, { label => 'loaded', nlabel => 'drives.loaded.count', set => { key_values => [ { name => 'loaded' } ], output_template => 'loaded : %s', perfdatas => [ { label => 'loaded', template => '%s', min => 0 } ] } }, { label => 'unloaded', nlabel => 'drives.unloaded.count', set => { key_values => [ { name => 'unloaded' } ], output_template => 'unloaded : %s', perfdatas => [ { label => 'unloaded', template => '%s', min => 0 } ] } }, { label => 'reserved', nlabel => 'drives.reserved.count', set => { key_values => [ { name => 'reserved' } ], output_template => 'reserved : %s', perfdatas => [ { label => 'reserved', template => '%s', min => 0 } ] } }, { label => 'unknown', nlabel => 'drives.unknown.count', set => { key_values => [ { name => 'unknown' } ], output_template => 'unknown : %s', perfdatas => [ { label => 'unknown', template => '%s', min => 0 } ] } } ]; } sub prefix_global_output { my ($self, %options) = @_; return "Total Drives "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $response = $options{custom}->execute_command( query => "SELECT library_name, drive_name, online, drive_state FROM drives" ); $self->{global} = { online => 0, offline => 0, unavailable => 0, empty => 0, loaded => 0, unloaded => 0, reserved => 0, unknown => 0, }; my %mapping_online = (yes => 'online', no => 'offline'); while ($response =~ /^(.*?),(.*?),(yes|no),(unavailable|empty|loaded|unloaded|reserved|unknown)$/mgi) { my ($library, $drive, $online, $state) = ($1, $2, lc($3), lc($4)); $self->{global}->{$mapping_online{$online}}++; $self->{global}->{$state}++; } } 1; __END__ =head1 MODE Check drives. =over 8 =item B<--warning-*> Set warning threshold. Can be : 'online', 'offline', 'unavailable', 'empty', 'loaded', 'unloaded', 'reserved', 'unknown'. =item B<--critical-*> Set critical threshold. Can be : Can be : 'online', 'offline', 'unavailable', 'empty', 'loaded', 'unloaded', 'reserved', 'unknown'. =back =cut centreon-plugins-20220113/apps/backup/tsm/local/mode/nodes.pm000066400000000000000000000065771417000230700237520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::tsm::local::mode::nodes; 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 } ]; $self->{maps_counters}->{global} = [ { label => 'associated', nlabel => 'nodes.associated.count', set => { key_values => [ { name => 'associated' } ], output_template => 'total associated nodes : %s', perfdatas => [ { label => 'associated', template => '%s', min => 0 } ] } }, { label => 'non-associated', nlabel => 'nodes.nonassociated.count', set => { key_values => [ { name => 'non_associated' } ], output_template => 'total non associated nodes : %s', perfdatas => [ { label => 'non_associated', template => '%s', min => 0 } ] } }, { label => 'locked', nlabel => 'nodes.locked.count', set => { key_values => [ { name => 'locked' } ], output_template => 'total locked nodes : %s', perfdatas => [ { label => 'locked', template => '%s', min => 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 => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $response = $options{custom}->execute_command( query => "SELECT node_name, 'non_associated' FROM nodes WHERE node_name NOT IN (SELECT node_name FROM associations) UNION SELECT node_name, 'associated' FROM nodes WHERE node_name IN (SELECT node_name FROM associations) UNION SELECT node_name, 'locked' FROM nodes WHERE locked='YES'" ); $self->{global} = { associated => 0, non_associated => 0, locked => 0 }; while ($response =~ /^(.*?),(non_associated|associated|locked)$/mg) { my ($node_name, $type) = ($1, $2); $self->{global}->{$type}++; $self->{output}->output_add(long_msg => "node '$node_name' is $type"); } } 1; __END__ =head1 MODE Check node status. =over 8 =item B<--warning-*> Set warning threshold. Can be : 'associated', 'non-associated', 'locked'. =item B<--critical-*> Set critical threshold. Can be : Can be : 'associated', 'non-associated', 'locked'. =back =cut centreon-plugins-20220113/apps/backup/tsm/local/mode/sessions.pm000066400000000000000000000163601417000230700244770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::tsm::local::mode::sessions; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("[client name: %s] [state: %s] [session type: %s] started since", $self->{result_values}->{client_name}, $self->{result_values}->{state}, $self->{result_values}->{session_type}, $self->{result_values}->{generation_time}); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{session_id} = $options{new_datas}->{$self->{instance} . '_session_id'}; $self->{result_values}->{client_name} = $options{new_datas}->{$self->{instance} . '_client_name'}; $self->{result_values}->{session_type} = $options{new_datas}->{$self->{instance} . '_session_type'}; $self->{result_values}->{state} = $options{new_datas}->{$self->{instance} . '_state'}; $self->{result_values}->{since} = $options{new_datas}->{$self->{instance} . '_since'}; $self->{result_values}->{generation_time} = $options{new_datas}->{$self->{instance} . '_generation_time'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'sessions', type => 1, cb_prefix_output => 'prefix_sessions_output', message_multiple => 'All sessions are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'total', nlabel => 'sessions.count', set => { key_values => [ { name => 'total' } ], output_template => 'total sessions : %s', perfdatas => [ { label => 'total', template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{sessions} = [ { label => 'status', type => 2, set => { key_values => [ { name => 'session_id' }, { name => 'client_name' }, { name => 'session_type' }, { name => 'state' }, { name => 'since' }, { name => 'generation_time' } ], 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 => \&catalog_status_threshold_ng, } } ]; } sub prefix_sessions_output { my ($self, %options) = @_; return "Session '" . $options{instance_value}->{session_id} . "' "; } 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-clientname:s" => { name => 'filter_clientname' }, "filter-sessiontype:s" => { name => 'filter_sessiontype' }, "filter-state:s" => { name => 'filter_state' }, "timezone:s" => { name => 'timezone' }, }); centreon::plugins::misc::mymodule_load(output => $self->{output}, module => 'DateTime', error_msg => "Cannot load module 'DateTime'."); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); $self->{option_results}->{timezone} = 'GMT' if (!defined($self->{option_results}->{timezone}) || $self->{option_results}->{timezone} eq ''); } sub manage_selection { my ($self, %options) = @_; my $response = $options{custom}->execute_command( query => "SELECT session_id, client_name, start_time, state, session_type FROM sessions" ); $self->{sessions} = {}; $self->{global} = { total => 0 }; my $tz = centreon::plugins::misc::set_timezone(name => $self->{option_results}->{timezone}); while ($response =~ /^(.*?),(.*?),(.*?),(.*?),(.*?)$/mg) { my ($session_id, $client_name, $start_time, $state, $session_type) = ($1, $2, $3, $4, $5); $start_time =~ /^(\d+)-(\d+)-(\d+)\s+(\d+)[:\/](\d+)[:\/](\d+)/; my $dt = DateTime->new(year => $1, month => $2, day => $3, hour => $4, minute => $5, second => $6, %$tz); if (defined($self->{option_results}->{filter_clientname}) && $self->{option_results}->{filter_clientname} ne '' && $client_name !~ /$self->{option_results}->{filter_clientname}/) { $self->{output}->output_add(long_msg => "skipping '" . $client_name . "': no matching client name filter.", debug => 1); next; } if (defined($self->{option_results}->{filter_sessiontype}) && $self->{option_results}->{filter_sessiontype} ne '' && $session_type !~ /$self->{option_results}->{filter_sessiontype}/) { $self->{output}->output_add(long_msg => "skipping '" . $session_type . "': no matching session type filter.", debug => 1); next; } if (defined($self->{option_results}->{filter_state}) && $self->{option_results}->{filter_state} ne '' && $state !~ /$self->{option_results}->{filter_state}/) { $self->{output}->output_add(long_msg => "skipping '" . $session_type . "': no matching state filter.", debug => 1); next; } my $diff_time = time() - $dt->epoch; $self->{global}->{total}++; $self->{sessions}->{$session_id} = { session_id => $session_id, client_name => $client_name, state => $state, session_type => $session_type, since => $diff_time, generation_time => centreon::plugins::misc::change_seconds(value => $diff_time) }; } } 1; __END__ =head1 MODE Check sessions. =over 8 =item B<--filter-clientname> Filter by client name. =item B<--filter-state> Filter by state. =item B<--filter-sessiontype> Filter by session type. =item B<--warning-status> Set warning threshold for status (Default: '') Can used special variables like: %{client_name}, %{state}, %{session_type}, %{since} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{client_name}, %{state}, %{session_type}, %{since} =item B<--warning-*> Set warning threshold. Can be : 'total'. =item B<--critical-*> Set critical threshold. Can be : 'total'. =item B<--timezone> Timezone of time options. Default is 'GMT'. =back =cut centreon-plugins-20220113/apps/backup/tsm/local/mode/volumes.pm000066400000000000000000000142711417000230700243220ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::tsm::local::mode::volumes; 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 }, { name => 'volumes', type => 1, cb_prefix_output => 'prefix_volumes_output', message_multiple => 'All volumes are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'total', nlabel => 'volumes.count', set => { key_values => [ { name => 'total' } ], output_template => 'volumes total : %s', perfdatas => [ { label => 'total', template => '%s', min => 0 } ] } }, { label => 'online', nlabel => 'volumes.online.count', set => { key_values => [ { name => 'online' } ], output_template => 'online : %s', perfdatas => [ { label => 'online', template => '%s', min => 0 } ] } }, { label => 'offline', nlabel => 'volumes.offline.count', set => { key_values => [ { name => 'offline' } ], output_template => 'offline : %s', perfdatas => [ { label => 'offline', template => '%s', min => 0 } ] } }, { label => 'empty', nlabel => 'volumes.empty.count', set => { key_values => [ { name => 'empty' } ], output_template => 'empty : %s', perfdatas => [ { label => 'empty', template => '%s', min => 0 } ] } }, { label => 'pending', nlabel => 'volumes.pending.count', set => { key_values => [ { name => 'pending' } ], output_template => 'pending : %s', perfdatas => [ { label => 'pending', template => '%s', min => 0 } ] } }, { label => 'filling', nlabel => 'volumes.filling.count', set => { key_values => [ { name => 'filling' } ], output_template => 'filling : %s', perfdatas => [ { label => 'filling', template => '%s', min => 0 } ] } }, { label => 'full', nlabel => 'volumes.full.count', set => { key_values => [ { name => 'full' } ], output_template => 'full : %s', perfdatas => [ { label => 'full', template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{volumes} = [ { label => 'used', nlabel => 'volume.space.usage.percentage', set => { key_values => [ { name => 'prct_utilized' }, { name => 'display' } ], output_template => 'Usage : %s %%', perfdatas => [ { label => 'used', template => '%s', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub prefix_volumes_output { my ($self, %options) = @_; return "Volumes '" . $options{instance_value}->{display} . "' "; } 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-volume:s" => { name => 'filter_volume' }, "filter-stgpool:s" => { name => 'filter_stgpool' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $response = $options{custom}->execute_command( query => "SELECT volume_name, stgpool_name, status, pct_utilized FROM volumes" ); $self->{volumes} = {}; $self->{global} = { total => 0, online => 0, offline => 0, empty => 0, pending => 0, filling => 0, full => 0 }; while ($response =~ /^(.*?),(.*?),(.*?),(.*?)$/mg) { my ($volume_name, $stgpool, $status, $pct_utilized) = ($1, $2, $3, $4); if (defined($self->{option_results}->{filter_volume}) && $self->{option_results}->{filter_volume} ne '' && $volume_name !~ /$self->{option_results}->{filter_volume}/) { $self->{output}->output_add(long_msg => "skipping '" . $volume_name . "': no matching volume name filter.", debug => 1); next; } if (defined($self->{option_results}->{filter_stgpool}) && $self->{option_results}->{filter_stgpool} ne '' && $stgpool !~ /$self->{option_results}->{filter_stgpool}/) { $self->{output}->output_add(long_msg => "skipping '" . $stgpool . "': no matching storage pool filter.", debug => 1); next; } $self->{global}->{total}++; $self->{global}->{lc($status)}++; $self->{volumes}->{$volume_name} = { display => $volume_name, prct_utilized => $pct_utilized, }; } } 1; __END__ =head1 MODE Check volumes. =over 8 =item B<--filter-volume> Filter by volume name. =item B<--filter-stgpool> Filter by storage pool name. =item B<--warning-*> Set warning threshold. Can be : 'total', 'used', 'online',' offline', 'empty', 'pending', 'filling', full'. =item B<--critical-*> Set critical threshold. Can be : 'total', 'used', 'online', 'offline', empty', 'pending', 'filling', full'. =back =cut centreon-plugins-20220113/apps/backup/tsm/local/plugin.pm000066400000000000000000000030621417000230700231760ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::tsm::local::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} = '1.0'; $self->{modes} = { 'actlog' => 'apps::backup::tsm::local::mode::actlog', 'drives' => 'apps::backup::tsm::local::mode::drives', 'nodes' => 'apps::backup::tsm::local::mode::nodes', 'sessions' => 'apps::backup::tsm::local::mode::sessions', 'volumes' => 'apps::backup::tsm::local::mode::volumes', }; $self->{custom_modes}{api} = 'apps::backup::tsm::local::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check IBM Tivoli Storage Manager (use dsmadmc). =cut centreon-plugins-20220113/apps/backup/veeam/000077500000000000000000000000001417000230700205415ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/veeam/local/000077500000000000000000000000001417000230700216335ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/veeam/local/mode/000077500000000000000000000000001417000230700225575ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/veeam/local/mode/jobstatus.pm000066400000000000000000000270071417000230700251410ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::veeam::local::mode::jobstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::common::powershell::veeam::jobstatus; use apps::backup::veeam::local::mode::resources::types qw($job_type $job_result); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); use centreon::plugins::misc; use JSON::XS; sub custom_status_output { my ($self, %options) = @_; return 'status : ' . $self->{result_values}->{status} . ' [type: ' . $self->{result_values}->{type} . ']'; } sub custom_long_output { my ($self, %options) = @_; return 'started since : ' . centreon::plugins::misc::change_seconds(value => $self->{result_values}->{elapsed}); } sub custom_long_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{elapsed} = $options{new_datas}->{$self->{instance} . '_elapsed'}; $self->{result_values}->{type} = $options{new_datas}->{$self->{instance} . '_type'}; $self->{result_values}->{is_running} = $options{new_datas}->{$self->{instance} . '_is_running'}; return -11 if ($self->{result_values}->{is_running} != 1); return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'job', type => 1, cb_prefix_output => 'prefix_job_output', message_multiple => 'All jobs are ok', skipped_code => { -11 => 1, -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'total', nlabel => 'jobs.total.count', set => { key_values => [ { name => 'total' } ], output_template => 'Total Jobs : %s', perfdatas => [ { label => 'total', template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{job} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'display' }, { name => 'type' }, { name => 'is_running' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } }, { label => 'long', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'display' }, { name => 'elapsed' }, { name => 'type' }, { name => 'is_running' } ], closure_custom_calc => $self->can('custom_long_calc'), closure_custom_output => $self->can('custom_long_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'timeout:s' => { name => 'timeout', default => 50 }, 'command:s' => { name => 'command', default => 'powershell.exe' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '-InputFormat none -NoLogo -EncodedCommand' }, 'no-ps' => { name => 'no_ps' }, 'ps-exec-only' => { name => 'ps_exec_only' }, 'ps-display' => { name => 'ps_display' }, 'filter-name:s' => { name => 'filter_name' }, 'filter-type:s' => { name => 'filter_type' }, 'filter-end-time:s' => { name => 'filter_end_time', default => 86400 }, 'filter-start-time:s' => { name => 'filter_start_time' }, 'ok-status:s' => { name => 'ok_status', default => '' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{is_running} == 0 and not %{status} =~ /Success/i' }, 'warning-long:s' => { name => 'warning_long' }, 'critical-long:s' => { name => 'critical_long' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['ok_status', 'warning_status', 'critical_status', 'warning_long', 'critical_long']); } sub prefix_job_output { my ($self, %options) = @_; return "Job '" . $options{instance_value}->{display} . "' "; } sub manage_selection { my ($self, %options) = @_; if (!defined($self->{option_results}->{no_ps})) { my $ps = centreon::common::powershell::veeam::jobstatus::get_powershell(); if (defined($self->{option_results}->{ps_display})) { $self->{output}->output_add( severity => 'OK', short_msg => $ps ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{option_results}->{command_options} .= " " . centreon::plugins::misc::powershell_encoded($ps); } my ($stdout) = centreon::plugins::misc::execute( output => $self->{output}, options => $self->{option_results}, command => $self->{option_results}->{command}, command_path => $self->{option_results}->{command_path}, command_options => $self->{option_results}->{command_options} ); if (defined($self->{option_results}->{ps_exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } my $decoded; eval { $decoded = JSON::XS->new->decode($stdout); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } #[ # { name: 'xxxx', type: 0, isRunning: False, result: 0, creationTimeUTC: 1512875246.2, endTimeUTC: 1512883615.377 }, # { name: 'xxxx', type: 0, isRunning: False, result: 1, creationTimeUTC: '', endTimeUTC: '' }, # { name: 'xxxx', type: 1, isRunning: True, result: 0, creationTimeUTC: 1513060425.027, endTimeUTC: -2208992400 } #] $self->{global} = { total => 0 }; $self->{job} = {}; my $current_time = time(); foreach my $job (@$decoded) { $job->{creationTimeUTC} =~ s/,/\./; $job->{endTimeUTC} =~ s/,/\./; my $job_type = defined($job_type->{ $job->{type} }) ? $job_type->{ $job->{type} } : 'unknown'; if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $job->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping job '" . $job->{name} . "': no matching filter.", debug => 1); next; } if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' && $job_type !~ /$self->{option_results}->{filter_type}/) { $self->{output}->output_add(long_msg => "skipping job '" . $job->{name} . "': no matching filter type.", debug => 1); next; } if (defined($self->{option_results}->{filter_end_time}) && $self->{option_results}->{filter_end_time} =~ /[0-9]+/ && $job->{endTimeUTC} =~ /[0-9]+/ && $job->{endTimeUTC} < $current_time - $self->{option_results}->{filter_end_time}) { $self->{output}->output_add(long_msg => "skipping job '" . $job->{name} . "': end time too old.", debug => 1); next; } if (defined($self->{option_results}->{filter_start_time}) && $self->{option_results}->{filter_start_time} =~ /[0-9]+/ && $job->{creationTimeUTC} =~ /[0-9]+/ && $job->{creationTimeUTC} < $current_time - $self->{option_results}->{filter_start_time}) { $self->{output}->output_add(long_msg => "skipping job '" . $job->{name} . "': start time too old.", debug => 1); next; } my $elapsed_time; $elapsed_time = $current_time - $job->{creationTimeUTC} if ($job->{creationTimeUTC} =~ /[0-9]/); #is_running = 2 (never running) $self->{job}->{ $job->{name} } = { display => $job->{name}, elapsed => $elapsed_time, type => $job_type, is_running => $job->{isRunning} =~ /True|1/ ? 1 : ($job->{creationTimeUTC} !~ /[0-9]/ ? 2 : 0), status => defined($job_result->{ $job->{result} }) && $job_result->{ $job->{result} } ne '' ? $job_result->{ $job->{result} } : '-' }; $self->{global}->{total}++; } } 1; __END__ =head1 MODE Check job status. =over 8 =item B<--timeout> Set timeout time for command execution (Default: 50 sec) =item B<--no-ps> Don't encode powershell. To be used with --command and 'type' command. =item B<--command> Command to get information (Default: 'powershell.exe'). Can be changed if you have output in a file. To be used with --no-ps option!!! =item B<--command-path> Command path (Default: none). =item B<--command-options> Command options (Default: '-InputFormat none -NoLogo -EncodedCommand'). =item B<--ps-display> Display powershell script. =item B<--ps-exec-only> Print powershell output. =item B<--filter-name> Filter job name (can be a regexp). =item B<--filter-type> Filter job type (can be a regexp). =item B<--filter-start-time> Filter job with start time greater than current time less value in seconds. =item B<--filter-end-time> Filter job with end time greater than current time less value in seconds (Default: 86400). =item B<--ok-status> Set ok threshold for status (Default: '') Can used special variables like: %{display}, %{status}, %{type}, %{is_running}. =item B<--warning-status> Set warning threshold for status (Default: '') Can used special variables like: %{display}, %{status}, %{type}, %{is_running}. =item B<--critical-status> Set critical threshold for status (Default: '%{is_running} == 0 and not %{status} =~ /Success/i'). Can used special variables like: %{display}, %{status}, %{type}, %{is_running}. =item B<--warning-long> Set warning threshold for long jobs (Default: none) Can used special variables like: %{display}, %{status}, %{type}, %{elapsed}. =item B<--critical-long> Set critical threshold for long jobs (Default: none). Can used special variables like: %{display}, %{status}, %{type}, %{elapsed}. =item B<--warning-total> Set warning threshold for total jobs. =item B<--critical-total> Set critical threshold for total jobs. =back =cut centreon-plugins-20220113/apps/backup/veeam/local/mode/licenses.pm000066400000000000000000000326371417000230700247350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::veeam::local::mode::licenses; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::common::powershell::veeam::licenses; use apps::backup::veeam::local::mode::resources::types qw($license_type $license_status); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use centreon::plugins::misc; use JSON::XS; 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_expires_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel} . '.' . $unitdiv_long->{ $self->{instance_mode}->{option_results}->{unit} }, unit => $self->{instance_mode}->{option_results}->{unit}, 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_expires_threshold { my ($self, %options) = @_; 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_status_output { my ($self, %options) = @_; return 'status: ' . $self->{result_values}->{status}; } sub custom_license_instances_output { my ($self, %options) = @_; return sprintf( 'instances total: %s used: %s (%.2f%%) free: %s (%.2f%%)', $self->{result_values}->{instances_total}, $self->{result_values}->{instances_used}, $self->{result_values}->{instances_prct_used}, $self->{result_values}->{instances_free}, $self->{result_values}->{instances_prct_free} ); } sub prefix_license_output { my ($self, %options) = @_; return sprintf( "License '%s' [type: %s] ", $options{instance_value}->{to}, $options{instance_value}->{type} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'licenses', type => 1, cb_prefix_output => 'prefix_license_output', message_multiple => 'All licenses are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'total', nlabel => 'licenses.total.count', set => { key_values => [ { name => 'total' } ], output_template => 'Number of licenses: %s', perfdatas => [ { template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{licenses} = [ { label => 'status', type => 2, critical_default => '%{status} =~ /expired|invalid/i', set => { key_values => [ { name => 'to' }, { name => 'status' }, { name => 'type' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'expires', nlabel => 'license.expires', set => { key_values => [ { name => 'expires_seconds' }, { name => 'expires_human' } ], output_template => 'expires in %s', output_use => 'expires_human', closure_custom_perfdata => $self->can('custom_expires_perfdata'), closure_custom_threshold_check => $self->can('custom_expires_threshold') } }, { label => 'license-instances-usage', nlabel => 'license.instances.usage.count', set => { key_values => [ { name => 'instances_used' }, { name => 'instances_free' }, { name => 'instances_prct_used' }, { name => 'instances_prct_free' }, { name => 'instances_total' } ], closure_custom_output => $self->can('custom_license_instances_output'), perfdatas => [ { template => '%d', min => 0, max => 'instances_total', label_extra_instance => 1 } ] } }, { label => 'license-instances-free', display_ok => 0, nlabel => 'license.instances.free.count', set => { key_values => [ { name => 'instances_free' }, { name => 'instances_used' }, { name => 'instances_prct_used' }, { name => 'instances_prct_free' }, { name => 'instances_total' } ], closure_custom_output => $self->can('custom_license_instances_output'), perfdatas => [ { template => '%d', min => 0, max => 'instances_total', label_extra_instance => 1 } ] } }, { label => 'license-instances-usage-prct', display_ok => 0, nlabel => 'license.instances.usage.percentage', set => { key_values => [ { name => 'instances_prct_used' }, { name => 'instances_used' }, { name => 'instances_free' }, { name => 'instances_prct_free' }, { name => 'instances_total' } ], closure_custom_output => $self->can('custom_license_instances_output'), perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'timeout:s' => { name => 'timeout', default => 50 }, 'command:s' => { name => 'command', default => 'powershell.exe' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '-InputFormat none -NoLogo -EncodedCommand' }, 'no-ps' => { name => 'no_ps' }, 'ps-exec-only' => { name => 'ps_exec_only' }, 'ps-display' => { name => 'ps_display' }, 'filter-to:s' => { name => 'filter_to' }, 'filter-type:s' => { name => 'filter_type' }, 'filter-status:s' => { name => 'filter_status' }, 'unit:s' => { name => 'unit', default => 's' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if ($self->{option_results}->{unit} eq '' || !defined($unitdiv->{$self->{option_results}->{unit}})) { $self->{option_results}->{unit} = 's'; } } sub manage_selection { my ($self, %options) = @_; if (!defined($self->{option_results}->{no_ps})) { my $ps = centreon::common::powershell::veeam::licenses::get_powershell(); if (defined($self->{option_results}->{ps_display})) { $self->{output}->output_add( severity => 'OK', short_msg => $ps ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{option_results}->{command_options} .= " " . centreon::plugins::misc::powershell_encoded($ps); } my ($stdout) = centreon::plugins::misc::execute( output => $self->{output}, options => $self->{option_results}, command => $self->{option_results}->{command}, command_path => $self->{option_results}->{command_path}, command_options => $self->{option_results}->{command_options} ); if (defined($self->{option_results}->{ps_exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } my $decoded; eval { $decoded = JSON::XS->new->decode($stdout); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } #[ # {"licensed_instances":7150,"expiration_time":"1632960000","type":0,"licensed_to":"Centreon Services","status":0,"used_instances":165} #] $self->{global} = { total => 0 }; $self->{licenses} = {}; my $current_time = time(); foreach my $license (@$decoded) { if (defined($self->{option_results}->{filter_to}) && $self->{option_results}->{filter_to} ne '' && $license->{licensed_to} !~ /$self->{option_results}->{filter_to}/) { $self->{output}->output_add(long_msg => "skipping license '" . $license->{licensed_to} . "': no matching filter.", debug => 1); next; } if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' && $license_type->{ $license->{type} } !~ /$self->{option_results}->{filter_type}/) { $self->{output}->output_add(long_msg => "skipping license '" . $license->{licensed_to} . "': no matching filter type.", debug => 1); next; } if (defined($self->{option_results}->{filter_status}) && $self->{option_results}->{filter_status} ne '' && $license_status->{ $license->{status} } !~ /$self->{option_results}->{filter_status}/) { $self->{output}->output_add(long_msg => "skipping license '" . $license->{licensed_to} . "': no matching filter type.", debug => 1); next; } $self->{licenses}->{ $license->{licensed_to} } = { to => $license->{licensed_to}, type => $license_type->{ $license->{type} }, status => $license_status->{ $license->{status} } }; if (defined($license->{expiration_time})) { $self->{licenses}->{ $license->{licensed_to} }->{expires_seconds} = $license->{expiration_time} - $current_time; $self->{licenses}->{ $license->{licensed_to} }->{expires_human} = centreon::plugins::misc::change_seconds( value => $self->{licenses}->{ $license->{licensed_to} }->{expires_seconds} ); } if (defined($license->{licensed_instances}) && $license->{licensed_instances} > 0) { $self->{licenses}->{ $license->{licensed_to} }->{instances_total} = $license->{licensed_instances}; $self->{licenses}->{ $license->{licensed_to} }->{instances_used} = $license->{used_instances}; $self->{licenses}->{ $license->{licensed_to} }->{instances_free} = $license->{licensed_instances} - $license->{used_instances}; $self->{licenses}->{ $license->{licensed_to} }->{instances_prct_used} = $license->{used_instances} * 100 / $license->{licensed_instances}; $self->{licenses}->{ $license->{licensed_to} }->{instances_prct_free} = 100 - $self->{licenses}->{ $license->{licensed_to} }->{instances_prct_used}; } $self->{global}->{total}++; } } 1; __END__ =head1 MODE Check licenses. =over 8 =item B<--timeout> Set timeout time for command execution (Default: 50 sec) =item B<--no-ps> Don't encode powershell. To be used with --command and 'type' command. =item B<--command> Command to get information (Default: 'powershell.exe'). Can be changed if you have output in a file. To be used with --no-ps option!!! =item B<--command-path> Command path (Default: none). =item B<--command-options> Command options (Default: '-InputFormat none -NoLogo -EncodedCommand'). =item B<--ps-display> Display powershell script. =item B<--ps-exec-only> Print powershell output. =item B<--filter-to> Filter licenses by person/organization (can be a regexp). =item B<--filter-type> Filter licenses by type (can be a regexp). =item B<--filter-status> Filter licenses by status (can be a regexp). =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{to}, %{status}, %{type}. =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /expired|invalid/i'). Can used special variables like: %{to}, %{status}, %{type}. =item B<--unit> Select the unit for expires 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: 'total', 'expires', 'license-instances-usage', 'license-instances-free', 'license-instances-usage-prct'. =back =cut centreon-plugins-20220113/apps/backup/veeam/local/mode/listjobs.pm000066400000000000000000000126641417000230700247570ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::veeam::local::mode::listjobs; use base qw(centreon::plugins::mode); use strict; use warnings; use apps::backup::veeam::local::mode::resources::types qw($job_type); use centreon::common::powershell::veeam::listjobs; use centreon::plugins::misc; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'timeout:s' => { name => 'timeout', default => 50 }, 'command:s' => { name => 'command', default => 'powershell.exe' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '-InputFormat none -NoLogo -EncodedCommand' }, 'no-ps' => { name => 'no_ps' }, 'ps-exec-only' => { name => 'ps_exec_only' }, 'ps-display' => { name => 'ps_display' }, 'filter-name:s' => { name => 'filter_name' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach (sort keys %{$self->{jobs}}) { $self->{output}->output_add(long_msg => "'" . $_ . "' [type = " . $self->{jobs}->{$_}->{type} . "]"); } $self->{output}->output_add( severity => 'OK', short_msg => 'List jobs:' ); $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', 'type']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach (sort keys %{$self->{jobs}}) { $self->{output}->add_disco_entry( name => $_, type => $self->{jobs}->{$_}->{type} ); } } sub manage_selection { my ($self, %options) = @_; if (!defined($self->{option_results}->{no_ps})) { my $ps = centreon::common::powershell::veeam::listjobs::get_powershell(); if (defined($self->{option_results}->{ps_display})) { $self->{output}->output_add( severity => 'OK', short_msg => $ps ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{option_results}->{command_options} .= " " . centreon::plugins::misc::powershell_encoded($ps); } my ($stdout) = centreon::plugins::misc::execute( output => $self->{output}, options => $self->{option_results}, command => $self->{option_results}->{command}, command_path => $self->{option_results}->{command_path}, command_options => $self->{option_results}->{command_options} ); if (defined($self->{option_results}->{ps_exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } my $decoded; eval { $decoded = JSON::XS->new->decode($stdout); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } $self->{jobs} = {}; foreach my $job (@$decoded) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $job->{name} !~ /$self->{option_results}->{filter_name}/i) { $self->{output}->output_add(long_msg => "skipping job '" . $job->{name} . "': no matching filter name", debug => 1); next; } $self->{jobs}->{ $job->{name} } = { type => defined($job_type->{ $job->{type} }) ? $job_type->{ $job->{type} } : 'unknown' }; } } 1; __END__ =head1 MODE List jobs. =over 8 =item B<--timeout> Set timeout time for command execution (Default: 50 sec) =item B<--no-ps> Don't encode powershell. To be used with --command and 'type' command. =item B<--command> Command to get information (Default: 'powershell.exe'). Can be changed if you have output in a file. To be used with --no-ps option!!! =item B<--command-path> Command path (Default: none). =item B<--command-options> Command options (Default: '-InputFormat none -NoLogo -EncodedCommand'). =item B<--ps-display> Display powershell script. =item B<--ps-exec-only> Print powershell output. =item B<--filter-name> Filter job name (can be a regexp). =back =cut centreon-plugins-20220113/apps/backup/veeam/local/mode/resources/000077500000000000000000000000001417000230700245715ustar00rootroot00000000000000centreon-plugins-20220113/apps/backup/veeam/local/mode/resources/types.pm000066400000000000000000000126621417000230700263020ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::veeam::local::mode::resources::types; use strict; use warnings; use Exporter; our $job_type; our $job_result; our $job_tape_type; our $job_tape_result; our $job_tape_state; our $license_type; our $license_status; our @ISA = qw(Exporter); our @EXPORT_OK = qw( $job_type $job_result $job_tape_type $job_tape_result $job_tape_state $license_type $license_status ); $job_type = { 0 => 'Backup', 1 => 'Replica', 2 => 'Copy', 3 => 'DRV', 4 => 'RestoreVm', 5 => 'RestoreVmFiles', 6 => 'RestoreFiles', 7 => 'Failover', 8 => 'QuickMigration', 9 => 'UndoFailover', 10 => 'FileLevelRestore', 11 => 'LinuxFileLevelRestore', 12 => 'InstantRecovery', 13 => 'RestoreHdd', 14 => 'Failback', 15 => 'PermanentFailover', 16 => 'UndoFailback', 17 => 'CommitFailback', 18 => 'ShellRun', 19 => 'VolumesDiscover', 20 => 'HvCtpRescan', 21 => 'CatCleanup', 22 => 'SanRescan', 23 => 'CreateSanSnapshot', 24 => 'FileTapeBackup', 25 => 'FileTapeRestore', 26 => 'TapeValidate', 27 => 'TapeInventory', 28 => 'VmTapeBackup', 29 => 'VmTapeRestore', 30 => 'SanMonitor', 31 => 'DeleteSanSnapshot', 32 => 'TapeErase', 33 => 'TapeEject', 34 => 'TapeExport', 35 => 'TapeImport', 36 => 'TapeCatalog', 37 => 'TapeLibrariesDiscover', 38 => 'PowerShellScript', 39 => 'VmReconfig', 40 => 'VmStart', 41 => 'VcdVAppRestore', 42 => 'VcdVmRestore', 46 => 'HierarchyScan', 47 => 'ViVmConsolidation', 48 => 'ApplicationLevelRestore', 50 => 'RemoteReplica', 51 => 'BackupSync', 52 => 'SqlLogBackup', 53 => 'LicenseAutoUpdate', 54 => 'OracleLogBackup', 55 => 'TapeMarkAsFree', 56 => 'TapeDeleteFromLibrary', 57 => 'TapeMoveToMediaPool', 58 => 'TapeCatalogueDecrypted', 63 => 'SimpleBackupCopyWorker', 64 => 'QuickMigrationCheck', 100 => 'ConfBackup', 101 => 'ConfRestore', 102 => 'ConfResynchronize', 103 => 'WaGlobalDedupFill', 104 => 'DatabaseMaintenance', 105 => 'RepositoryMaintenance', 106 => 'InfrastructureRescan', 200 => 'HvLabDeploy', 201 => 'HvLabDelete', 202 => 'FailoverPlan', 203 => 'UndoFailoverPlan', 204 => 'FailoverPlanTask', 205 => 'UndoFailoverPlanTask', 206 => 'PlannedFailover', 207 => 'ViLabDeploy', 208 => 'ViLabDelete', 209 => 'ViLabStart', 300 => 'Cloud', 301 => 'CloudApplDeploy', 302 => 'HardwareQuotasProcessing', 303 => 'ReconnectVpn', 304 => 'DisconnectVpn', 305 => 'OrchestratedTask', 306 => 'ViReplicaRescan', 307 => 'ExternalRepositoryMaintenance', 308 => 'DeleteBackup', 309 => 'CloudProviderRescan', 401 => 'AzureApplDeploy', 500 => 'TapeTenantRestore', 666 => 'Unknown', 4000 => 'EndpointBackup', 4005 => 'EndpointRestore', 4010 => 'BackupCacheSync', 4020 => 'EndpointSqlLogBackup', 4021 => 'EndpointOracleLogBackup', 4030 => 'OracleRMANBackup', 4031 => 'SapBackintBackup', 5000 => 'CloudBackup', 6000 => 'RestoreVirtualDisks', 6001 => 'RestoreAgentVolumes', 7000 => 'InfraItemSave', 7001 => 'InfraItemUpgrade', 7002 => 'InfraItemDelete', 7003 => 'AzureWinProxySave', 8000 => 'FileLevelRestoreByEnterprise', 9000 => 'RepositoryEvacuate', 10000 => 'LogsExport', 10001 => 'InfraStatistic', 11000 => 'AzureVmRestore', 12000 => 'EpAgentManagement', 12001 => 'EpAgentDiscoveryObsolete', 12002 => 'EpAgentPolicy', 12003 => 'EpAgentBackup', 12004 => 'EpAgentTestCreds', 12005 => 'EpAgentDiscovery', 12006 => 'EpAgentDeletedRetention', 13000 => 'NasBackup', 13001 => 'NasBackupBrowse', 13002 => 'NasRestore', 14000 => 'VmbApiPolicyTempJob', 15000 => 'ExternalInfrastructureRescan', 16000 => 'AmazonRestore', 17000 => 'StagedRestore', 18000 => 'ArchiveBackup', 18001 => 'ArchiveRehydration', 18002 => 'ArchiveDownload', 19000 => 'HvStagedRestore', 20000 => 'VbkExport', 21000 => 'GuestScriptingConnect' }; $job_result = { 0 => 'Success', 1 => 'Warning', 2 => 'Failed', -1 => 'None' }; $job_tape_type = { 0 => 'BackupToTape', 1 => 'FileToTape', 2 => 'TapeCatalog', 3 => 'TapeEject', 4 => 'TapeErase', 5 => 'TapeExport', 6 => 'TapeImport', 7 => 'TapeInventory', 8 => 'TapeRescan', 9 => 'Backup', 10 => 'BackupSync', 11 => 'EndpointBackup', 12 => 'ConfigurationBackup' }; $job_tape_result = { 0 => 'None', 1 => 'Success', 2 => 'Warning', 3 => 'Failed' }; $job_tape_state = { 0 => 'Stopped', 1 => 'Starting', 2 => 'Stopping', 3 => 'Working', 4 => 'Pausing', 5 => 'Resuming', 6 => 'WaitingTape', 7 => 'Idle', 8 => 'Postprocessing', 9 => 'WaitingRepository', 10 => 'Pending' }; $license_type = { 0 => 'rental', 1 => 'perpetual', 2 => 'subscription', 3 => 'evaluation', 4 => 'free', 5 => 'NFR', 6 => 'empty' }; $license_status = { 0 => 'valid', 1 => 'expired', 2 => 'invalid' }; 1; centreon-plugins-20220113/apps/backup/veeam/local/mode/tapejobs.pm000066400000000000000000000206111417000230700247240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::veeam::local::mode::tapejobs; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::common::powershell::veeam::tapejobs; use apps::backup::veeam::local::mode::resources::types qw($job_tape_type $job_tape_result $job_tape_state); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use centreon::plugins::misc; use JSON::XS; sub custom_status_output { my ($self, %options) = @_; return sprintf( "last result: '%s' [type: '%s'][last state: '%s']", $self->{result_values}->{last_result}, $self->{result_values}->{type}, $self->{result_values}->{last_state}, ); } sub prefix_job_output { my ($self, %options) = @_; return "Tape job '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'job', type => 1, cb_prefix_output => 'prefix_job_output', message_multiple => 'All jobs are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'total', nlabel => 'tapejobs.total.count', set => { key_values => [ { name => 'total' } ], output_template => 'total jobs: %s', perfdatas => [ { template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{job} = [ { label => 'status', type => 2, critical => '%{enabled} == 1 and not %{last_result} =~ /Success|None/i', set => { key_values => [ { name => 'display' }, { name => 'enabled' }, { name => 'type' }, { name => 'last_result' }, { name => 'last_state' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'timeout:s' => { name => 'timeout', default => 50 }, 'command:s' => { name => 'command', default => 'powershell.exe' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '-InputFormat none -NoLogo -EncodedCommand' }, 'no-ps' => { name => 'no_ps' }, 'ps-exec-only' => { name => 'ps_exec_only' }, 'ps-display' => { name => 'ps_display' }, 'filter-name:s' => { name => 'filter_name' }, 'filter-type:s' => { name => 'filter_type' } }); return $self; } sub manage_selection { my ($self, %options) = @_; if (!defined($self->{option_results}->{no_ps})) { my $ps = centreon::common::powershell::veeam::tapejobs::get_powershell(); if (defined($self->{option_results}->{ps_display})) { $self->{output}->output_add( severity => 'OK', short_msg => $ps ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{option_results}->{command_options} .= " " . centreon::plugins::misc::powershell_encoded($ps); } my ($stdout) = centreon::plugins::misc::execute( output => $self->{output}, options => $self->{option_results}, command => $self->{option_results}->{command}, command_path => $self->{option_results}->{command_path}, command_options => $self->{option_results}->{command_options} ); if (defined($self->{option_results}->{ps_exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } my $decoded; eval { $decoded = JSON::XS->new->decode($stdout); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } #[ # { name: 'xxxx', type: 0, Enabled: True, lastResult: 0, lastState: 0 }, # { name: 'xxxx', type: 1, Enabled: True, lastResult: 1, lastState: 1 } #] $self->{global} = { total => 0 }; $self->{job} = {}; foreach my $job (@$decoded) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $job->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping job '" . $job->{name} . "': no matching filter.", debug => 1); next; } if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' && $job->{type} !~ /$self->{option_results}->{filter_type}/) { $self->{output}->output_add(long_msg => "skipping job '" . $job->{name} . "': no matching filter type.", debug => 1); next; } # Sometimes we may get such JSON: [{"lastResult":null,"name":null,"lastState":null,"type":null,"enabled":null}] if (!defined($job->{name})) { $self->{output}->output_add(long_msg => "skipping nulled job (empty json)", debug => 1); next; } $self->{job}->{ $job->{name} } = { display => $job->{name}, type => $job_tape_type->{ $job->{type} }, enabled => $job->{enabled} =~ /True|1/ ? 1 : 0, last_result => $job_tape_result->{ $job->{lastResult} }, last_state => $job_tape_state->{ $job->{lastState} } }; $self->{global}->{total}++; if (scalar(keys %{$self->{job}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No tape jobs found. Review filters. More infos with --debug option"); $self->{output}->option_exit(); } } } 1; __END__ =head1 MODE Check tape jobs status. =over 8 =item B<--timeout> Set timeout time for command execution (Default: 50 sec) =item B<--no-ps> Don't encode powershell. To be used with --command and 'type' command. =item B<--command> Command to get information (Default: 'powershell.exe'). Can be changed if you have output in a file. To be used with --no-ps option!!! =item B<--command-path> Command path (Default: none). =item B<--command-options> Command options (Default: '-InputFormat none -NoLogo -EncodedCommand'). =item B<--ps-display> Display powershell script. =item B<--ps-exec-only> Print powershell output. =item B<--filter-name> Filter job name (can be a regexp). =item B<--filter-type> Filter job type (can be a regexp). =item B<--unknown-status> Set unknown threshold for status (Default: '') Can used special variables like: %{display}, %{enabled}, %{type}, %{last_result}, %{last_state}. =item B<--warning-status> Set warning threshold for status (Default: '') Can used special variables like: %{display}, %{enabled}, %{type}, %{last_result}, %{last_state}. =item B<--critical-status> Set critical threshold for status (Default: '%{enabled} == 1 and not %{last_result} =~ /Success|None/i'). Can used special variables like: %{display}, %{enabled}, %{type}, %{last_result}, %{last_state}. =item B<--warning-total> Set warning threshold for total jobs. =item B<--critical-total> Set critical threshold for total jobs. =back =cut centreon-plugins-20220113/apps/backup/veeam/local/plugin.pm000066400000000000000000000026601417000230700234730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::backup::veeam::local::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} = '0.1'; $self->{modes} = { 'job-status' => 'apps::backup::veeam::local::mode::jobstatus', 'licenses' => 'apps::backup::veeam::local::mode::licenses', 'list-jobs' => 'apps::backup::veeam::local::mode::listjobs', 'tape-jobs' => 'apps::backup::veeam::local::mode::tapejobs' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Veeam through powershell. =cut centreon-plugins-20220113/apps/bind9/000077500000000000000000000000001417000230700172045ustar00rootroot00000000000000centreon-plugins-20220113/apps/bind9/web/000077500000000000000000000000001417000230700177615ustar00rootroot00000000000000centreon-plugins-20220113/apps/bind9/web/custom/000077500000000000000000000000001417000230700212735ustar00rootroot00000000000000centreon-plugins-20220113/apps/bind9/web/custom/api.pm000066400000000000000000000326061417000230700224110ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::bind9::web::custom::api; use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::http; 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'url-path:s' => { name => 'url_path' }, 'timeout:s' => { name => 'timeout' }, 'unknown-status:s' => { name => 'unknown_status', default => '%{http_code} < 200 or %{http_code} >= 300' }, 'warning-status:s' => { name => 'warning_status' }, 'critical-status:s' => { name => 'critical_status' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : undef; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 8080; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'http'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{url_path} = (defined($self->{option_results}->{url_path})) ? $self->{option_results}->{url_path} : '/'; $self->{unknown_status} = (defined($self->{option_results}->{unknown_status})) ? $self->{option_results}->{unknown_status} : undef; $self->{warning_status} = (defined($self->{option_results}->{warning_status})) ? $self->{option_results}->{warning_status} : undef; $self->{critical_status} = (defined($self->{option_results}->{critical_status})) ? $self->{option_results}->{critical_status} : undef; if (!defined($self->{hostname})) { $self->{output}->add_option_msg(short_msg => "Need to specify hostname option."); $self->{output}->option_exit(); } return 0; } sub get_uniq_id { my ($self, %options) = @_; return $self->{hostname} . '_' . $self->{port}; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{url_path} = $self->{url_path}; $self->{option_results}->{unknown_status} = $self->{unknown_status}; $self->{option_results}->{warning_status} = $self->{warning_status}; $self->{option_results}->{critical_status} = $self->{critical_status}; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->set_options(%{$self->{option_results}}); } sub load_response { my ($self, %options) = @_; if ($self->{response_type} eq 'xml') { centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'XML::XPath', error_msg => "Cannot load module 'XML::XPath'." ); eval { $self->{xpath_response} = XML::XPath->new(xml => $options{response}); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot load XML response"); $self->{output}->option_exit(); } } } sub request { my ($self, %options) = @_; $self->settings(); my $response = $self->{http}->request(); my ($content_type) = $self->{http}->get_header(name => 'Content-Type'); if (!defined($content_type) || $content_type !~ /(xml|json)/i) { $self->{output}->add_option_msg(short_msg => "content-type not set"); $self->{output}->option_exit(); } $self->{response_type} = $1; if ($self->{response_type} eq 'json') { $self->{output}->add_option_msg(short_msg => "json format unsupported"); $self->{output}->option_exit(); } $self->load_response(response => $response); my $method = $self->can("get_api_version_$self->{response_type}"); if (!defined($method)) { $self->{output}->add_option_msg(short_msg => "method 'get_api_version_$self->{response_type}' unsupported"); $self->{output}->option_exit(); } $self->$method(); if (!defined($self->{api_version}) || $self->{api_version} !~ /^(\d+)/) { $self->{output}->add_option_msg(short_msg => "cannot get api version"); $self->{output}->option_exit(); } $self->{api_version} = $1; } sub get_api_version_xml { my ($self, %options) = @_; eval { my $nodesets = $self->{xpath_response}->find('//statistics/@version'); my $node = $nodesets->get_node(1); $self->{api_version} = $node->getNodeValue(); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot lookup: $@"); $self->{output}->option_exit(); } } sub load_memory_xml_v3 { my ($self, %options) = @_; my $memory = {}; my $nodesets = $self->{xpath_response}->find('//memory/summary'); my $node_memory = $nodesets->get_node(1); foreach my $node ($node_memory->getChildNodes()) { my $name = $node->getLocalName(); next if (!defined($name)); if ($name eq 'TotalUse') { $memory->{total_use} = $node->string_value; } if ($name eq 'InUse') { $memory->{in_use} = $node->string_value; } } return $memory; } sub load_memory_xml_v2 { my ($self, %options) = @_; return $self->load_memory_xml_v3(); } sub load_zones_xml_v3 { my ($self, %options) = @_; my $zones = {}; my $nodesets = $self->{xpath_response}->find('//views//zones/zone'); foreach my $node ($nodesets->get_nodelist()) { my $name = $node->getAttribute('name'); next if (!defined($name)); $zones->{$name} = { counters => { rcode => {}, qtype => {} } }; foreach my $counters_node ($node->getChildNodes()) { next if ($counters_node->getLocalName() ne 'counters'); my $type = $counters_node->getAttribute('type'); foreach my $counter_node ($counters_node->getChildNodes()) { my $counter_name = $counter_node->getAttribute('name'); $zones->{$name}->{counters}->{$type}->{$counter_name} = $counter_node->string_value; } } } return $zones; } sub load_zones_xml_v2 { my ($self, %options) = @_; my $zones = {}; my $nodesets = $self->{xpath_response}->find('//views//zones/zone'); foreach my $node ($nodesets->get_nodelist()) { my $name; my $counters = {}; foreach my $subnode ($node->getChildNodes()) { my $tag_name = $subnode->getLocalName(); $name = $subnode->string_value if ($tag_name eq 'name'); if ($tag_name eq 'counters') { foreach my $counter_node ($subnode->getChildNodes()) { $tag_name = $counter_node->getLocalName(); next if (!defined($tag_name)); $counters->{$tag_name} = $counter_node->string_value; } } } if (defined($name)) { $zones->{$name}->{counters}->{rcode} = $counters; } } return $zones; } sub load_server_xml_v3 { my ($self, %options) = @_; my $server = { counters => { } }; my $nodesets = $self->{xpath_response}->find('//server//counters'); foreach my $node ($nodesets->get_nodelist()) { my $type = $node->getAttribute('type'); next if (!defined($type)); foreach my $counter_node ($node->getChildNodes()) { my $counter_name = $counter_node->getAttribute('name'); $server->{counters}->{$type} = {} if (!defined($server->{counters}->{$type})); $server->{counters}->{$type}->{$counter_name} = $counter_node->string_value; } } return $server; } sub load_server_xml_v2 { my ($self, %options) = @_; my $server = { counters => { opcode => {}, nsstat => {}, qtype => {} } }; my $nodesets = $self->{xpath_response}->find('//server//opcode'); foreach my $node ($nodesets->get_nodelist()) { my ($name, $value); foreach my $counter_node ($node->getChildNodes()) { my $tag_name = $counter_node->getLocalName(); next if (!defined($tag_name)); $name = $counter_node->string_value if ($tag_name eq 'name'); $value = $counter_node->string_value if ($tag_name eq 'counter'); } if (defined($name) && defined($value)) { $server->{counters}->{opcode}->{$name} = $value; } } $nodesets = $self->{xpath_response}->find('//server//rdtype'); foreach my $node ($nodesets->get_nodelist()) { my ($name, $value); foreach my $counter_node ($node->getChildNodes()) { my $tag_name = $counter_node->getLocalName(); next if (!defined($tag_name)); $name = $counter_node->string_value if ($tag_name eq 'name'); $value = $counter_node->string_value if ($tag_name eq 'counter'); } if (defined($name) && defined($value)) { $server->{counters}->{qtype}->{$name} = $value; } } $nodesets = $self->{xpath_response}->find('//server//nsstat'); foreach my $node ($nodesets->get_nodelist()) { my ($name, $value); foreach my $counter_node ($node->getChildNodes()) { my $tag_name = $counter_node->getLocalName(); next if (!defined($tag_name)); $name = $counter_node->string_value if ($tag_name eq 'name'); $value = $counter_node->string_value if ($tag_name eq 'counter'); } if (defined($name) && defined($value)) { $server->{counters}->{nsstat}->{$name} = $value; } } return $server; } sub get_memory { my ($self, %options) = @_; $self->request(); my $method = $self->can("load_memory_$self->{response_type}_v$self->{api_version}"); if (!defined($method)) { $self->{output}->add_option_msg(short_msg => "method 'load_memory_$self->{response_type}_v$self->{api_version}' unsupported"); $self->{output}->option_exit(); } my $memory = $self->$method(); if (!defined($memory->{in_use})) { $self->{output}->add_option_msg(short_msg => "cannot find memory information"); $self->{output}->option_exit(); } return $memory; } sub get_zones { my ($self, %options) = @_; $self->request(); my $method = $self->can("load_zones_$self->{response_type}_v$self->{api_version}"); if (!defined($method)) { $self->{output}->add_option_msg(short_msg => "method 'load_zones_$self->{response_type}_v$self->{api_version}' unsupported"); $self->{output}->option_exit(); } my $zones = $self->$method(); if (scalar(keys %{$zones}) == 0) { $self->{output}->add_option_msg(short_msg => "cannot find zones information"); $self->{output}->option_exit(); } return $zones; } sub get_server { my ($self, %options) = @_; $self->request(); my $method = $self->can("load_server_$self->{response_type}_v$self->{api_version}"); if (!defined($method)) { $self->{output}->add_option_msg(short_msg => "method 'load_server_$self->{response_type}_v$self->{api_version}' unsupported"); $self->{output}->option_exit(); } my $server = $self->$method(); if (scalar(keys %{$server->{counters}}) == 0) { $self->{output}->add_option_msg(short_msg => "cannot find server information"); $self->{output}->option_exit(); } return $server; } 1; __END__ =head1 NAME Statistics Channels API =head1 SYNOPSIS Statistics Channels API custom mode =head1 API OPTIONS =over 8 =item B<--hostname> Statistics Channels hostname. =item B<--port> Port used (Default: 8080) =item B<--proto> Specify https if needed (Default: 'http') =item B<--url-path> Statistics Channel API Path (Default: '/'). =item B<--timeout> Set HTTP timeout =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/bind9/web/mode/000077500000000000000000000000001417000230700207055ustar00rootroot00000000000000centreon-plugins-20220113/apps/bind9/web/mode/memoryusage.pm000066400000000000000000000110061417000230700235760ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::bind9::web::mode::memoryusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_usage_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add(label => 'used', unit => 'B', value => $self->{result_values}->{used}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}, total => $self->{result_values}->{total}, cast_int => 1), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}, total => $self->{result_values}->{total}, cast_int => 1), min => 0, max => $self->{result_values}->{total}); } sub custom_usage_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check(value => $self->{result_values}->{prct_used}, 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("Memory 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}->{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}; $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 => 'memory', type => 0 } ]; $self->{maps_counters}->{memory} = [ { label => 'usage', set => { key_values => [ { 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; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->get_memory(); $self->{memory} = { used => $result->{in_use}, total => $result->{total_use} }; } 1; __END__ =head1 MODE Check bind memory usage. =over 8 =item B<--warning-usage> Threshold warning. =item B<--critical-usage> Threshold critical. =back =cut centreon-plugins-20220113/apps/bind9/web/mode/serverusage.pm000066400000000000000000000256671417000230700236160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::bind9::web::mode::serverusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); # From Bind 9.11.5 counter list # opcode = completed # rcode = not started # qtype = completed # nsstat = completed # zonestat = completed # resstat = not started # Counter name, message, nlabel my @map = ( ['opcode-query', 'opcode query : %s', 'opcode.query.count'], ['opcode-iquery', 'opcode iquery : %s', 'opcode.iquery.count'], ['opcode-status', 'opcode status : %s', 'opcode.status.count'], ['opcode-notify', 'opcode notify : %s', 'opcode.notify.count'], ['opcode-update', 'opcode update : %s', 'opcode.update.count'], ['qtype-a', 'qtype A : %s', 'qtype.a.count'], ['qtype-ns', 'qtype NS : %s', 'qtype.ns.count'], ['qtype-cname', 'qtype CNAME : %s', 'qtype.cname.count'], ['qtype-soa', 'qtype SOA : %s', 'qtype.soa.count'], ['qtype-null', 'qtype NULL : %s', 'qtype.null.count'], ['qtype-wks', 'qtype WKS : %s', 'qtype.wks.count'], ['qtype-ptr', 'qtype PTR : %s', 'qtype.ptr.count'], ['qtype-hinfo', 'qtype HINFO : %s', 'qtype.hinfo.count'], ['qtype-mx', 'qtype MX : %s', 'qtype.mx.count'], ['qtype-txt', 'qtype TXT : %s', 'qtype.txt.count'], ['qtype-aaaa', 'qtype AAAA : %s', 'qtype.aaaa.count'], ['qtype-srv', 'qtype SRV : %s', 'qtype.srv.count'], ['qtype-naptr', 'qtype NAPTR : %s', 'qtype.naptr.count'], ['qtype-a6', 'qtype A6 : %s', 'qtype.a6.count'], ['qtype-ds', 'qtype DS : %s', 'qtype.ds.count'], ['qtype-rrsig', 'qtype RRSIG : %s', 'qtype.rrsig.count'], ['qtype-nsec', 'qtype NSEC : %s', 'qtype.nsec.count'], ['qtype-dnskey', 'qtype DNSKEY : %s', 'qtype.dnskey.count'], ['qtype-tlsa', 'qtype TLSA : %s', 'qtype.tlsa.count'], ['qtype-cds', 'qtype CDS : %s', 'qtype.cds.count'], ['qtype-type65', 'qtype TYPE65 : %s', 'qtype.type65.count'], ['qtype-spf', 'qtype SPF : %s', 'qtype.spf.count'], ['qtype-axfr', 'qtype AXFR : %s', 'qtype.axfr.count'], ['qtype-any', 'qtype ANY : %s', 'qtype.any.count'], ['qtype-others', 'qtype Others : %s', 'qtype.others.count'], ['nsstat-requestv4', 'nsstat Request v4 : %s', 'nsstat.requestv4.count'], ['nsstat-requestv6', 'nsstat Request v6 : %s', 'nsstat.requestv6.count'], ['nsstat-reqedns0', 'nsstat ReqEdns0 : %s', 'nsstat.reqedns0.count'], ['nsstat-reqbadednsver', 'nsstat ReqBadEDNSVer : %s', 'nsstat.reqbadednsver.count'], ['nsstat-reqtsig', 'nsstat ReqTSIG : %s', 'nsstat.reqtsig.count'], ['nsstat-reqsig0', 'nsstat ReqSIG0 : %s', 'nsstat.reqsig0.count'], ['nsstat-reqbadsig', 'nsstat ReqBadSIG : %s', 'nsstat.reqbadsig.count'], ['nsstat-reqtcp', 'nsstat ReqTCP : %s', 'nsstat.reqtcp.count'], ['nsstat-authqryrej', 'nsstat AuthQryRej : %s', 'nsstat.authqryrej.count'], ['nsstat-recqryrej', 'nsstat RecQryRej : %s', 'nsstat.recqryrej.count'], ['nsstat-xfrrej', 'nsstat XfrRej : %s', 'nsstat.xfrrej.count'], ['nsstat-updaterej', 'nsstat UpdateRej : %s', 'nsstat.updaterej.count'], ['nsstat-response', 'nsstat Response : %s', 'nsstat.response.count'], ['nsstat-truncatedresp', 'nsstat TruncatedResp : %s', 'nsstat.truncatedresp.count'], ['nsstat-respedns0', 'nsstat RespEDNS0 : %s', 'nsstat.respedns0.count'], ['nsstat-resptsig', 'nsstat RespTSIG : %s', 'nsstat.resptsig.count'], ['nsstat-respsig0', 'nsstat RespSIG0 : %s', 'nsstat.respsig0.count'], ['nsstat-qrysuccess', 'nsstat QrySuccess : %s', 'nsstat.qrysuccess.count'], ['nsstat-qryauthans', 'nsstat QryAuthAns : %s', 'nsstat.qryauthans.count'], ['nsstat-qrynoauthans', 'nsstat QryNoauthAns : %s', 'nsstat.qrynoauthans.count'], ['nsstat-qryreferral', 'nsstat QryReferral : %s', 'nsstat.qryreferral.count'], ['nsstat-qrynxrrset', 'nsstat QryNxrrset : %s', 'nsstat.qrynxrrset.count'], ['nsstat-qryservfail', 'nsstat QrySERVFAIL : %s', 'nsstat.qryservfail.count'], ['nsstat-qryformerr', 'nsstat QryFORMERR : %s', 'nsstat.qryformerr.count'], ['nsstat-qrynxdomain', 'nsstat QryNXDOMAIN : %s', 'nsstat.qrynxdomain.count'], ['nsstat-qryrecursion', 'nsstat QryRecursion : %s', 'nsstat.qryrecursion.count'], ['nsstat-qryduplicate', 'nsstat QryDuplicate : %s', 'nsstat.qryduplicate.count'], ['nsstat-qrydropped', 'nsstat QryDropped : %s', 'nsstat.qrydropped.count'], ['nsstat-qryfailure', 'nsstat QryFailure : %s', 'nsstat.qryfailure.count'], ['nsstat-xfrreqdone', 'nsstat XfrReqDone : %s', 'nsstat.xfrreqdone.count'], ['nsstat-updatereqfwd', 'nsstat UpdateReqFwd : %s', 'nsstat.updatereqfwd.count'], ['nsstat-updaterespfwd', 'nsstat UpdateRespFwd : %s', 'nsstat.updaterespfwd.count'], ['nsstat-updatefwdfail', 'nsstat UpdateFwdFail : %s', 'nsstat.updatefwdfail.count'], ['nsstat-updatedone', 'nsstat UpdateDone : %s', 'nsstat.updatedone.count'], ['nsstat-updatefail', 'nsstat UpdateFail : %s', 'nsstat.updatefail.count'], ['nsstat-updatebadprereq', 'nsstat UpdateBadPrereq : %s', 'nsstat.updatebadprereq.count'], ['nsstat-recursclients', 'nsstat RecursClients : %s', 'nsstat.recursclients.count'], ['nsstat-dns64', 'nsstat RateDropped : %s', 'nsstat.ratedropped.count'], ['nsstat-ratedropped', 'nsstat RateDropped : %s', 'nsstat.ratedropped.count'], ['nsstat-rateslipped', 'nsstat RateSlipped : %s', 'nsstat.rateslipped.count'], ['nsstat-rpzrewrites', 'nsstat RPZRewrites : %s', 'nsstat.rpzrewrites.count'], ['nsstat-qryudp', 'nsstat QryUDP : %s', 'nsstat.qryudp.count'], ['nsstat-qrytcp', 'nsstat QryTCP : %s', 'nsstat.qrytcp.count'], ['nsstat-nsidopt', 'nsstat NSIDOpt : %s', 'nsstat.nsidopt.count'], ['nsstat-expireopt', 'nsstat ExpireOpt : %s', 'nsstat.expireopt.count'], ['nsstat-otheropt', 'nsstat OtherOpt : %s', 'nsstat.otheropt.count'], ['nsstat-cookiein', 'nsstat CookieIn : %s', 'nsstat.cookiein.count'], ['nsstat-cookienew ', 'nsstat CookieNew : %s', 'nsstat.cookienew .count'], ['nsstat-cookiebadsize', 'nsstat CookieBadSize : %s', 'nsstat.cookiebadsize.count'], ['nsstat-cookiebadtime', 'nsstat CookieBadTime : %s', 'nsstat.cookiebadtime.count'], ['nsstat-cookienomatch', 'nsstat CookieNoMatch : %s', 'nsstat.cookienomatch.count'], ['nsstat-cookiematch', 'nsstat CookieMatch : %s', 'nsstat.cookiematch.count'], ['nsstat-ecsopt', 'nsstat ECSOpt : %s', 'nsstat.ecsopt.count'], ['nsstat-qrynxredir', 'nsstat QryNXRedir : %s', 'nsstat.qrynxredir.count'], ['nsstat-qrynxredirrlookup', 'nsstat QryNXRedirRLookup : %s', 'nsstat.qrynxredirrlookup.count'], ['nsstat-qrybadcookie', 'nsstat QryBADCOOKIE : %s', 'nsstat.qrybadcookie.count'], ['nsstat-keytagopt', 'nsstat KeyTagOpt : %s', 'nsstat.keytagopt.count'], ['zonestat-keytagopt', 'zonestat NotifyOutv4 : %s', 'zonestat.notifyoutv4.count'], ['zonestat-notifyoutv6', 'zonestat NotifyOutv6 : %s', 'zonestat.notifyoutv6.count'], ['zonestat-notifyinv4', 'zonestat NotifyInv4 : %s', 'zonestat.notifyinv4.count'], ['zonestat-notifyinv6', 'zonestat NotifyInv6 : %s', 'zonestat.notifyinv6.count'], ['zonestat-notifyrej', 'zonestat NotifyRej : %s', 'zonestat.notifyrej.count'], ['zonestat-soaoutv4', 'zonestat SOAOutv4 : %s', 'zonestat.soaoutv4.count'], ['zonestat-soaoutv6', 'zonestat SOAOutv6 : %s', 'zonestat.soaoutv6.count'], ['zonestat-axfrreqv4', 'zonestat AXFRReqv4 : %s', 'zonestat.axfrreqv4.count'], ['zonestat-axfrreqv6', 'zonestat AXFRReqv6 : %s', 'zonestat.axfrreqv6.count'], ['zonestat-ixfrreqv4', 'zonestat IXFRReqv4 : %s', 'zonestat.ixfrreqv4.count'], ['zonestat-ixfrreqv6', 'zonestat IXFRReqv6 : %s', 'zonestat.ixfrreqv6.count'], ['zonestat-xfrsuccess', 'zonestat XfrSuccess : %s', 'zonestat.xfrsuccess.count'], ['zonestat-xfrfail', 'zonestat XfrFail : %s', 'zonestat.xfrfail.count'] ); sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'server', type => 0, skipped_code => { -1 => 1, -10 => 1, 11 => -1 } } ]; $self->{maps_counters}->{server} = []; for (my $i = 0; $i < scalar(@map); $i++) { push @{$self->{maps_counters}->{server}}, { label => $map[$i]->[0], nlabel => => $map[$i]->[2], display_ok => 0, set => { key_values => [ { name => $map[$i]->[0], diff => 1 } ], output_template => $map[$i]->[1], perfdatas => [ { template => '%s', min => 0 } ] } }; } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{filter_counters})) { $self->{option_results}->{filter_counters} = 'opcode-query|opcode-iquery|opcode-status|opcode-notify|opcode-update|' . 'qtype-a|qtype-aaaa|qtype-cname|qtype-mx|qtype-txt|qtype-soa|qtype-ptr|' . 'nsstat-requestv4|nsstat-requestv6'; } } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->get_server(); $self->{server} = { }; # Init for all vars, some are not present in response if no request on the server for (my $i = 0; $i < scalar(@map); $i++) { $self->{server}->{ $map[$i]->[0] } = 0; } $self->{output}->output_add( severity => 'OK', short_msg => 'All Bind 9 counters are ok' ); foreach my $type (keys %{$result->{counters}}) { foreach my $counter (keys %{$result->{counters}->{$type}}) { $self->{server}->{lc($type) . '-' . lc($counter)} = $result->{counters}->{$type}->{$counter}; } } $self->{cache_name} = 'bind9_' . $self->{mode} . '_' . $options{custom}->get_uniq_id() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check Bind global server usage. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='nsstat-requestv6' Show the full list with --list-counters. =item B<--warning-*> B<--critical-*> Thresholds. Can be any of the selected counters. =back =cut centreon-plugins-20220113/apps/bind9/web/mode/zoneusage.pm000066400000000000000000000120751417000230700232500ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::bind9::web::mode::zoneusage; 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 => 'zones', type => 1, cb_prefix_output => 'prefix_zone_output', message_multiple => 'All zone counters are ok', skipped_code => { -1 => 1, -10 => 1, 11 => -1 } } ]; $self->{maps_counters}->{zones} = [ { label => 'message', threshold => 0, set => { key_values => [ { name => 'display' } ], closure_custom_calc => sub { return 0; }, closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => sub { return 'ok'; }, closure_custom_output => sub { return 'counters are ok' }, } }, ]; my @map = ( ['qtype_a', 'qtype A : %s', 'qtype-a'], ['qtype_cname', 'qtype CNAME : %s', 'qtype-cname'], ['qtype_mx', 'qtype MX : %s', 'qtype-mx'], ['qtype_txt', 'qtype TXT : %s', 'qtype-txt'], ['qtype_soa', 'qtype SOA : %s', 'qtype-soa'], ['qtype_ptr', 'qtype PTR : %s', 'qtype-ptr'], ['qtype_ns', 'qtype NS : %s', 'qtype-ns'], ['rcode_requestv4', 'rcode request v4 : %s', 'rcode-requestv4'], ['rcode_requestv6', 'rcode request v6 : %s', 'rcode-requestv6'], ); for (my $i = 0; $i < scalar(@map); $i++) { my $perf_label = $map[$i]->[2]; $perf_label =~ s/-/_/g; push @{$self->{maps_counters}->{zones}}, { label => $map[$i]->[2], display_ok => 0, set => { key_values => [ { name => $map[$i]->[0], diff => 1 }, { name => 'display' } ], output_template => $map[$i]->[1], perfdatas => [ { label => $perf_label, value => $map[$i]->[0] , template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }; } } sub prefix_zone_output { my ($self, %options) = @_; return "Zone '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, }); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->get_zones(); $self->{zones} = { }; foreach my $zone_name (keys %{$result}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $zone_name !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $zone_name . "': no matching filter.", debug => 1); next; } $self->{zones}->{$zone_name} = { display => $zone_name }; foreach my $type (keys %{$result->{$zone_name}->{counters}}) { foreach my $counter (keys %{$result->{$zone_name}->{counters}->{$type}}) { $self->{zones}->{$zone_name}->{lc($type) . '_' . lc($counter)} = $result->{$zone_name}->{counters}->{$type}->{$counter}; } } } if (scalar(keys %{$self->{zones}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No zone found."); $self->{output}->option_exit(); } $self->{cache_name} = "bind9_" . $self->{mode} . '_' . $options{custom}->get_uniq_id() . '_' . (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 bind zone usage. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='request' =item B<--filter-name> Filter zone name (can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: qtype-a', 'qtype-cname', 'qtype-mx', 'qtype-txt', 'qtype-soa', 'qtype-ptr', 'qtype-ns', 'nsstat-requestv4', 'nsstat-requestv6'. =back =cut centreon-plugins-20220113/apps/bind9/web/plugin.pm000066400000000000000000000026471417000230700216260ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::bind9::web::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} = '1.1'; $self->{modes} = { 'memory-usage' => 'apps::bind9::web::mode::memoryusage', 'server-usage' => 'apps::bind9::web::mode::serverusage', 'zone-usage' => 'apps::bind9::web::mode::zoneusage' }; $self->{custom_modes}->{api} = 'apps::bind9::web::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Bind9 server through HTTP statistics channels. =cut centreon-plugins-20220113/apps/biztalk/000077500000000000000000000000001417000230700176375ustar00rootroot00000000000000centreon-plugins-20220113/apps/biztalk/sql/000077500000000000000000000000001417000230700204365ustar00rootroot00000000000000centreon-plugins-20220113/apps/biztalk/sql/mode/000077500000000000000000000000001417000230700213625ustar00rootroot00000000000000centreon-plugins-20220113/apps/biztalk/sql/mode/rlocationdisabled.pm000066400000000000000000000115021417000230700254010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::biztalk::sql::mode::rlocationdisabled; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning:s" => { name => 'warning' }, "critical:s" => { name => 'critical' }, "filter-location:s" => { name => 'filter_location' }, "filter-application:s" => { name => 'filter_application' }, }); 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) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; my $query = q{ SELECT RL.Name, RL.Disabled, APP.nvcName FROM BizTalkMgmtDb.dbo.adm_ReceiveLocation AS RL WITH(NOLOCK) INNER JOIN BizTalkMgmtDb.dbo.bts_receiveport AS RP WITH(NOLOCK) ON RL.ReceivePortId = RP.nID INNER JOIN BizTalkMgmtDb.dbo.bts_application AS APP WITH(NOLOCK) ON RP.nApplicationID = APP.nID WHERE RL.[Disabled] = -1 }; $self->{sql}->connect(); $self->{sql}->query(query => $query); my $count = 0; while ((my $row = $self->{sql}->fetchrow_hashref())) { if (defined($self->{option_results}->{filter_location}) && $self->{option_results}->{filter_location} ne '' && $row->{Name} !~ /$self->{option_results}->{filter_location}/) { $self->{output}->output_add(long_msg => "Skipping '" . $row->{Name} . "': no matching filter location.", debug => 1); next; } if (defined($self->{option_results}->{filter_application}) && $self->{option_results}->{filter_application} ne '' && $row->{nvcName} !~ /$self->{option_results}->{filter_application}/) { $self->{output}->output_add(long_msg => "Skipping '" . $row->{nvcName} . "': no matching filter application.", debug => 1); next; } $self->{output}->output_add(long_msg => "'" . $row->{Name} . "' of application '" . $row->{nvcName} . "'"); $count++; } my $exit = $self->{perfdata}->threshold_check(value => $count, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit, short_msg => sprintf("%d receive locations are disabled", $count)); $self->{output}->perfdata_add(label => 'count', value => $count, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check the number of biztalk received locations disabled. The mode should be used with mssql plugin and dyn-mode option. =over 8 =item B<--warning> Threshold warning. =item B<--critical> Threshold critical. =item B<--filter-location> Filter by location (regexp can be used). =item B<--filter-application> Filter by application (regexp can be used). =back =cut centreon-plugins-20220113/apps/bluemind/000077500000000000000000000000001417000230700177765ustar00rootroot00000000000000centreon-plugins-20220113/apps/bluemind/local/000077500000000000000000000000001417000230700210705ustar00rootroot00000000000000centreon-plugins-20220113/apps/bluemind/local/custom/000077500000000000000000000000001417000230700224025ustar00rootroot00000000000000centreon-plugins-20220113/apps/bluemind/local/custom/api.pm000066400000000000000000000114611417000230700235140ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::bluemind::local::custom::api; use strict; use warnings; use centreon::plugins::ssh; 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 => { 'hostname:s' => { name => 'hostname' }, 'timeout:s' => { name => 'timeout', default => 30 }, 'sudo' => { name => 'sudo' }, 'command:s' => { name => 'command' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'BLUEMIND OPTIONS', once => 1); $self->{output} = $options{output}; $self->{ssh} = centreon::plugins::ssh->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub get_hostname { my ($self, %options) = @_; return defined($self->{option_results}->{hostname}) ? $self->{option_results}->{hostname} : 'local'; } sub check_options { my ($self, %options) = @_; if (defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '') { $self->{ssh}->check_options(option_results => $self->{option_results}); } return 0; } sub execute_command { my ($self, %options) = @_; my $content; if (defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '') { ($content) = $self->{ssh}->execute( hostname => $self->{option_results}->{hostname}, command => defined($self->{option_results}->{command}) && $self->{option_results}->{command} ne '' ? $self->{option_results}->{command} : $options{command}, command_path => $self->{option_results}->{command_path}, command_options => defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne '' ? $self->{option_results}->{command_options} : undef, timeout => $self->{option_results}->{timeout}, sudo => $self->{option_results}->{sudo} ); } else { ($content) = centreon::plugins::misc::execute( output => $self->{output}, options => { timeout => $self->{option_results}->{timeout} }, sudo => $self->{option_results}->{sudo}, command => defined($self->{option_results}->{command}) && $self->{option_results}->{command} ne '' ? $self->{option_results}->{command} : $options{command}, command_path => $self->{option_results}->{command_path}, command_options => defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne '' ? $self->{option_results}->{command_options} : undef ); } my $results = {}; foreach (split /\n/, $content) { next if (! /$options{filter}/); my ($key, $value_str) = split /\s/; foreach my $value (split /,/, $value_str) { my ($field1, $field2) = split /=/, $value; $results->{$key}->{$field1} = $field2; } } return $results; } 1; __END__ =head1 NAME bluemind =head1 SYNOPSIS bluemind =head1 BLUEMIND OPTIONS =over 8 =item B<--hostname> Hostname to query. =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. Used it you have output in a file. =item B<--command-path> Command path. =item B<--command-options> Command options. =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/bluemind/local/mode/000077500000000000000000000000001417000230700220145ustar00rootroot00000000000000centreon-plugins-20220113/apps/bluemind/local/mode/core.pm000066400000000000000000000137601417000230700233110ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::bluemind::local::mode::core; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use bigint; sub prefix_core_output { my ($self, %options) = @_; return 'Main engine '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'bm_core', type => 0, cb_prefix_output => 'prefix_core_output' } ]; $self->{maps_counters}->{bm_core} = [ { label => 'calls-received-success', nlabel => 'core.calls.received.success.count', display_ok => 0, set => { key_values => [ { name => 'calls_success', diff => 1 } ], output_template => 'success calls received: %s', perfdatas => [ { value => 'calls_success', template => '%s', min => 0 } ] } }, { label => 'calls-received-failed', nlabel => 'core.calls.received.failure.count', set => { key_values => [ { name => 'calls_failure', diff => 1 } ], output_template => 'failure calls received: %s', perfdatas => [ { value => 'calls_failure', template => '%s', min => 0 } ] } }, { label => 'heartbeat-broadcast', nlabel => 'core.heartbeat.broadcast.running.count', display_ok => 0, set => { key_values => [ { name => 'heartbeat_broadcast', diff => 1 } ], output_template => 'broadcast heartbeat running: %s', perfdatas => [ { value => 'heartbeat_broadcast', template => '%s', min => 0 } ] } }, { label => 'directory-cluster-events', nlabel => 'core.directory.cluster.events.count', display_ok => 0, set => { key_values => [ { name => 'cluster_events', diff => 1 } ], output_template => 'directory cluster events: %s', perfdatas => [ { value => 'cluster_events', template => '%s', min => 0 } ] } }, { label => 'request-handling-total', nlabel => 'core.request.handling.total.milliseconds', set => { key_values => [ { name => 'request_handling_time_total', diff => 1 } ], output_template => 'total request handling: %s ms', perfdatas => [ { value => 'request_handling_time_total', template => '%s', min => 0, unit => 'ms' } ] } }, { label => 'request-handling-mean', nlabel => 'core.request.handling.mean.milliseconds', display_ok => 0, set => { key_values => [ { name => 'request_handling_time_mean' } ], output_template => 'mean request handling: %s ms', perfdatas => [ { value => 'request_handling_time_mean', template => '%s', min => 0, unit => 'ms' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; # bm-core.heartbeat.broadcast,state=core.state.running,meterType=Counter count=1854550 # bm-core.handlingDuration,meterType=Timer count=695244256,totalTime=1911292590914929,mean=2749095 # bm-core.callsCount,status=failure,meterType=Counter count=97 # bm-core.callsCount,status=success,meterType=Counter count=125244086 # bm-core.directory.cluster.events,meterType=Counter count=14300 my $result = $options{custom}->execute_command( command => 'curl --unix-socket /var/run/bm-metrics/metrics-bm-core.sock http://127.0.0.1/metrics', filter => 'bm-core\.heartbeat\.broadcast|bm-core\.handlingDuration|bm-core\.callsCount|bm-core\.directory\.cluster\.events' ); $self->{bm_core} = {}; foreach (keys %$result) { $self->{bm_core}->{'calls_' . $1} = $result->{$_}->{count} if (/bm-core.callsCount.*status=(failure|success)/); $self->{bm_core}->{cluster_events} = $result->{$_}->{count} if (/bm-core\.directory\.cluster\.events/); if (/bm-core\.handlingDuration/) { # in nanoseconds $self->{bm_core}->{request_handling_time_total} = $result->{$_}->{totalTime} / 1000000; $self->{bm_core}->{request_handling_time_mean} = $result->{$_}->{mean} / 1000000; } $self->{bm_core}->{heartbeat_broadcast} = $result->{$_}->{count} if (/bm-core\.heartbeat\.broadcast.*running/); } $self->{cache_name} = 'bluemind_' . $self->{mode} . '_' . $options{custom}->get_hostname() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check main bluemind engine. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^calls' =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'calls-received-success', 'calls-received-failed', 'heartbeat-broadcast', 'directory-cluster-events', 'request-handling-total', 'request-handling-mean'. =back =cut centreon-plugins-20220113/apps/bluemind/local/mode/eas.pm000066400000000000000000000101311417000230700231160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::bluemind::local::mode::eas; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use bigint; sub prefix_eas_output { my ($self, %options) = @_; return 'Mobile connection service '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'bm_eas', type => 0, cb_prefix_output => 'prefix_eas_output' } ]; $self->{maps_counters}->{bm_eas} = [ { label => 'responses-size-total', nlabel => 'eas.responses.size.total.bytes', display_ok => 0, set => { key_values => [ { name => 'response_size', diff => 1 } ], output_template => 'total responses size: %s %s', output_change_bytes => 1, perfdatas => [ { value => 'response_size', template => '%s', min => 0, unit => 'B' } ] } }, { label => 'execution-total', nlabel => 'eas.execution.total.milliseconds', display_ok => 0, set => { key_values => [ { name => 'execution_total', diff => 1 } ], output_template => 'total execution: %s ms', perfdatas => [ { value => 'execution_total', template => '%s', min => 0, unit => 'ms' } ] } }, { label => 'execution-mean', nlabel => 'eas.execution.mean.milliseconds', set => { key_values => [ { name => 'execution_mean' } ], output_template => 'mean execution: %s ms', perfdatas => [ { value => 'execution_mean', template => '%s', min => 0, unit => 'ms' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; # bm-eas.executionTime,meterType=Timer count=23865528,totalTime=48394780739993049,mean=2027811022 # bm-eas.responseSize,meterType=DistSum count=31508001,totalAmount=736453775233,mean=23373 my $result = $options{custom}->execute_command( command => 'curl --unix-socket /var/run/bm-metrics/metrics-bm-eas.sock http://127.0.0.1/metrics', filter => 'executionTime|responseSize' ); $self->{bm_eas} = {}; foreach (keys %$result) { $self->{bm_eas}->{response_size} = $result->{$_}->{totalAmount} if (/bm-eas.responseSize/); if (/bm-eas\.executionTime/) { $self->{bm_eas}->{execution_total} = $result->{$_}->{totalTime} / 100000; $self->{bm_eas}->{execution_mean} = $result->{$_}->{mean} / 100000; } } $self->{cache_name} = 'bluemind_' . $self->{mode} . '_' . $options{custom}->get_hostname() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check mobile connection service. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^execution' =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'responses-size-total', 'execution-total', 'execution-mean'. =back =cut centreon-plugins-20220113/apps/bluemind/local/mode/hps.pm000066400000000000000000000203211417000230700231420ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::bluemind::local::mode::hps; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use bigint; sub prefix_hps_output { my ($self, %options) = @_; return 'Authentication service '; } sub prefix_upstream_output { my ($self, %options) = @_; return "Upstream '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'bm_hps', type => 0, cb_prefix_output => 'prefix_hps_output' }, { name => 'bm_hps_upstream', type => 1, cb_prefix_output => 'prefix_upstream_output', message_multiple => 'All upstreams are ok' } ]; $self->{maps_counters}->{bm_hps} = [ { label => 'authentication-success', nlabel => 'hps.authentication.success.count', display_ok => 0, set => { key_values => [ { name => 'auth_success', diff => 1 } ], output_template => 'success authentication: %s', perfdatas => [ { value => 'auth_success', template => '%s', min => 0 } ] } }, { label => 'authentication-failure', nlabel => 'hps.authentication.failure.count', set => { key_values => [ { name => 'auth_failure', diff => 1 } ], output_template => 'failure authentication: %s', perfdatas => [ { value => 'auth_failure', template => '%s', min => 0 } ] } }, { label => 'requests-protected', nlabel => 'hps.requests.protected.count', display_ok => 0, set => { key_values => [ { name => 'requests_protected', diff => 1 } ], output_template => 'protected requests: %s', perfdatas => [ { value => 'requests_protected', template => '%s', min => 0 } ] } }, { label => 'requests-maintenance', nlabel => 'hps.requests.maintenance.count', set => { key_values => [ { name => 'requests_maintenance', diff => 1 } ], output_template => 'maintenance requests: %s', perfdatas => [ { value => 'requests_maintenance', template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{bm_hps_upstream} = [ { label => 'upstream-requests-time-total', nlabel => 'hps.upstream.requests.time.milliseconds', display_ok => 0, set => { key_values => [ { name => 'requests_time_total', diff => 1 }, { name => 'display' } ], output_template => 'total requests time: %s ms', perfdatas => [ { value => 'requests_time_total', template => '%s', min => 0, unit => 'ms', label_extra_instance => 1 } ] } }, { label => 'upstream-requests-time-mean', nlabel => 'hps.upstream.requests.time.mean.milliseconds', set => { key_values => [ { name => 'requests_time_mean' }, { name => 'display' } ], output_template => 'mean requests time: %s ms', perfdatas => [ { value => 'requests_time_mean', template => '%s', min => 0, unit => 'ms', label_extra_instance => 1 } ] } }, { label => 'upstream-requests-size-total', nlabel => 'hps.upstream.requests.size.total.bytes', display_ok => 0, set => { key_values => [ { name => 'requests_size', diff => 1 } ], output_template => 'total requests size: %s %s', output_change_bytes => 1, perfdatas => [ { value => 'requests_size', template => '%s', min => 0, unit => 'B' } ] } }, { label => 'upstream-requests-total', nlabel => 'hps.upstream.requests.total.count', display_ok => 0, set => { key_values => [ { name => 'requests', diff => 1 } ], output_template => 'total requests: %s', perfdatas => [ { value => 'requests', template => '%s', min => 0 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-upstream:s' => { name => 'filter_upstream' } }); return $self; } sub manage_selection { my ($self, %options) = @_; # bm-hps.authCount,status=failure,meterType=Counter count=855 # bm-hps.authCount,status=success,meterType=Counter count=11957 # bm-hps.ftlTemplates.requests,meterType=Counter count=23064 # bm-hps.requestsCount,kind=protected,meterType=Counter count=3080815 # bm-hps.requestsCount,kind=maintenance,meterType=Counter count=1 # bm-hps.upstreamRequestSize,path=/login,meterType=DistSum count=331977,totalAmount=0,mean=0 # bm-hps.upstreamRequestTime,path=/login,meterType=Timer count=37864,totalTime=70405376220,mean=1859427 # bm-hps.upstreamRequestsCount,path=/login,meterType=Counter count=1383 my $result = $options{custom}->execute_command( command => 'curl --unix-socket /var/run/bm-metrics/metrics-bm-hps.sock http://127.0.0.1/metrics', filter => 'authCount|ftlTemplates\.requests|requestsCount|upstreamRequestSize|upstreamRequestTime|upstreamRequestsCount' ); $self->{bm_hps} = {}; $self->{bm_hps_upstream} = {}; foreach (keys %$result) { $self->{bm_hps}->{'auth_' . $1} = $result->{$_}->{count} if (/bm-hps\.authCount.*status=(failure|success)/); $self->{bm_hps}->{'requests_' . $1} = $result->{$_}->{count} if (/bm-hps\.requestsCount.*kind=(maintenance|protected)/); if (/bm-hps\.upstreamRequestTime.*path=(.*?),/) { my $upstream = $1; if (defined($self->{option_results}->{filter_upstream}) && $self->{option_results}->{filter_upstream} ne '' && $upstream !~ /$self->{option_results}->{filter_upstream}/) { $self->{output}->output_add(long_msg => "skipping upstream '" . $upstream . "': no matching filter.", debug => 1); next; } $self->{bm_hps_upstream}->{$upstream} = { display => $upstream, requests_time_total => $result->{$_}->{totalTime} / 100000, requests_time_mean => $result->{$_}->{mean} / 100000, requests_size => $result->{"bm-hps.upstreamRequestSize,path=$upstream,meterType=DistSum"}->{totalAmount}, requests => $result->{"bm-hps.upstreamRequestsCount,path=$upstream,meterType=Counter"}->{count} }; } } $self->{cache_name} = 'bluemind_' . $self->{mode} . '_' . $options{custom}->get_hostname() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check authentication service. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='maintenance' =item B<--filter-upstream> Filter upstream name (can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'authentication-success', 'authentication-failure', 'requests-protected', 'requests-maintenance', 'upstream-requests-time-total', 'upstream-requests-time-mean', 'upstream-requests-size-total, 'upstream-requests-total'. =back =cut centreon-plugins-20220113/apps/bluemind/local/mode/ips.pm000066400000000000000000000046761417000230700231620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::bluemind::local::mode::ips; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_ips_output { my ($self, %options) = @_; return 'IMAP operations tracking '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'bm_ips', type => 0, cb_prefix_output => 'prefix_ips_output' } ]; $self->{maps_counters}->{bm_ips} = [ { label => 'connections-active', nlabel => 'ips.connections.active.count', set => { key_values => [ { name => 'active_connections' } ], output_template => 'active connections: %s', perfdatas => [ { value => 'active_connections', template => '%s', min => 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 => { }); return $self; } sub manage_selection { my ($self, %options) = @_; # bm-ips.activeConnections,meterType=Gauge value=718 my $result = $options{custom}->execute_command( command => 'curl --unix-socket /var/run/bm-metrics/metrics-bm-ips.sock http://127.0.0.1/metrics', filter => 'activeConnections' ); $self->{bm_ips} = {}; foreach (keys %$result) { $self->{bm_ips}->{active_connections} = $result->{$_}->{value} if (/bm-ips\.activeConnections/); } } 1; __END__ =head1 MODE Check IMAP operations tracking. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'active-connections'. =back =cut centreon-plugins-20220113/apps/bluemind/local/mode/lmtpd.pm000066400000000000000000000173461417000230700235050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::bluemind::local::mode::lmtpd; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use bigint; sub prefix_lmtpd_output { my ($self, %options) = @_; return 'Email delivery service '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'bm_lmtpd', type => 0, cb_prefix_output => 'prefix_lmtpd_output' } ]; $self->{maps_counters}->{bm_lmtpd} = [ { label => 'connections-active', nlabel => 'lmtpd.connections.active.count', set => { key_values => [ { name => 'active_connections' } ], output_template => 'active connections: %s', perfdatas => [ { value => 'active_connections', template => '%s', min => 0 } ] } }, { label => 'connections-total', nlabel => 'lmtpd.connections.total.count', display_ok => 0, set => { key_values => [ { name => 'connections', diff => 1 } ], output_template => 'total connections: %s', perfdatas => [ { value => 'connections', template => '%s', min => 0 } ] } }, { label => 'deliveries-success', nlabel => 'lmtpd.deliveries.success.count', display_ok => 0, set => { key_values => [ { name => 'deliveries_ok', diff => 1 } ], output_template => 'success deliveries: %s', perfdatas => [ { value => 'deliveries_ok', template => '%s', min => 0 } ] } }, { label => 'deliveries-failure', nlabel => 'lmtpd.deliveries.failure.count', display_ok => 0, set => { key_values => [ { name => 'deliveries_ko', diff => 1 } ], output_template => 'failure deliveries: %s', perfdatas => [ { value => 'deliveries_ko', template => '%s', min => 0 } ] } }, { label => 'emails-size-total', nlabel => 'lmtpd.emails.size.total.bytes', display_ok => 0, set => { key_values => [ { name => 'email_size', diff => 1 } ], output_template => 'total emails size: %s %s', output_change_bytes => 1, perfdatas => [ { value => 'email_size', template => '%s', min => 0, unit => 'B' } ] } }, { label => 'sessions-duration-total', nlabel => 'lmtpd.sessions.duration.total.milliseconds', set => { key_values => [ { name => 'session_duration_total', diff => 1 } ], output_template => 'total sessions duration: %s ms', perfdatas => [ { value => 'session_duration_total', template => '%s', min => 0, unit => 'ms' } ] } }, { label => 'sessions-duration-mean', nlabel => 'lmtpd.sessions.duration.mean.milliseconds', set => { key_values => [ { name => 'session_duration_mean' } ], output_template => 'mean sessions duration: %s ms', perfdatas => [ { value => 'session_duration_mean', template => '%s', min => 0, unit => 'ms' } ] } }, { label => 'traffic-transport-latency-total', nlabel => 'lmtpd.traffic.transport.latency.total.milliseconds', set => { key_values => [ { name => 'traffic_latency_total', diff => 1 } ], output_template => 'total traffic transport latency: %s ms', perfdatas => [ { value => 'traffic_latency_total', template => '%s', min => 0, unit => 'ms' } ] } }, { label => 'traffic-transport-latency-mean', nlabel => 'lmtpd.traffic.transport.latency.mean.milliseconds', set => { key_values => [ { name => 'traffic_latency_mean' } ], output_template => 'mean traffic transport latency: %s ms', perfdatas => [ { value => 'traffic_latency_mean', template => '%s', min => 0, unit => 'ms' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; # bm-lmtpd.activeConnections,meterType=Gauge value=0 # bm-lmtpd.connectionCount,meterType=Counter count=1236057 # bm-lmtpd.deliveries,status=ko,meterType=Counter count=410 # bm-lmtpd.deliveries,status=ok,meterType=Counter count=1390933 # bm-lmtpd.emailSize,meterType=DistSum count=5020456,totalAmount=1170102671020,mean=233067 # bm-lmtpd.sessionDuration,meterType=Timer count=4941893,totalTime=1052591049892285,mean=212993492 # bm-lmtpd.traffic.transportLatency,meterType=Timer count=5017208,totalTime=272844528075000000,mean=54381745400 my $result = $options{custom}->execute_command( command => 'curl --unix-socket /var/run/bm-metrics/metrics-bm-lmtpd.sock http://127.0.0.1/metrics', filter => 'activeConnections|connectionCount|deliveries|emailSize|sessionDuration|traffic\.transportLatency' ); $self->{bm_lmtpd} = {}; foreach (keys %$result) { $self->{bm_lmtpd}->{'deliveries_' . $1} = $result->{$_}->{count} if (/bm-lmtpd\.deliveries.*status=(ok|ko)/); $self->{bm_lmtpd}->{active_connections} = $result->{$_}->{value} if (/bm-lmtpd\.activeConnections/); $self->{bm_lmtpd}->{connections} = $result->{$_}->{count} if (/bm-lmtpd\.connectionCount/); $self->{bm_lmtpd}->{email_size} = $result->{$_}->{totalAmount} if (/bm-lmtpd\.emailSize/); if (/bm-lmtpd\.sessionDuration/) { $self->{bm_lmtpd}->{session_duration_total} = $result->{$_}->{totalTime} / 100000; $self->{bm_lmtpd}->{session_duration_mean} = $result->{$_}->{mean} / 100000; } if (/bm-lmtpd\.traffic\.transportLatency/) { $self->{bm_lmtpd}->{traffic_latency_total} = $result->{$_}->{totalTime} / 100000; $self->{bm_lmtpd}->{traffic_latency_mean} = $result->{$_}->{mean} / 100000; } } $self->{cache_name} = 'bluemind_' . $self->{mode} . '_' . $options{custom}->get_hostname() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check email delivery service. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^deliveries' =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'connections-active', 'connections-total', 'deliveries-success', 'deliveries-failure', 'emails-size-total', 'sessions-duration-total', 'sessions-duration-mean', 'traffic-transport-latency-total', 'traffic-transport-latency-mean'. =back =cut centreon-plugins-20220113/apps/bluemind/local/mode/milter.pm000066400000000000000000000151111417000230700236450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::bluemind::local::mode::milter; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use bigint; sub prefix_milter_output { my ($self, %options) = @_; return 'Milter service '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'bm_milter', type => 0, cb_prefix_output => 'prefix_milter_output' } ]; $self->{maps_counters}->{bm_milter} = [ { label => 'connections-total', nlabel => 'milter.connections.total.count', set => { key_values => [ { name => 'connections', diff => 1 } ], output_template => 'total connections: %s', perfdatas => [ { value => 'connections', template => '%s', min => 0 } ] } }, { label => 'traffic-class-inbound', nlabel => 'milter.traffic.class.inbound.count', display_ok => 0, set => { key_values => [ { name => 'traffic_class_inbound', diff => 1 } ], output_template => 'traffic class inbound: %s', perfdatas => [ { value => 'traffic_class_inbound', template => '%s', min => 0 } ] } }, { label => 'traffic-class-outbound', nlabel => 'milter.traffic.class.outbound.count', display_ok => 0, set => { key_values => [ { name => 'traffic_class_outbound', diff => 1 } ], output_template => 'traffic class outbound: %s', perfdatas => [ { value => 'traffic_class_outbound', template => '%s', min => 0 } ] } }, { label => 'traffic-size-inbound', nlabel => 'milter.traffic.size.inbound.bytes', display_ok => 0, set => { key_values => [ { name => 'traffic_size_inbound', diff => 1 } ], output_template => 'traffic size inbound: %s %s', output_change_bytes => 1, perfdatas => [ { value => 'traffic_size_inbound', template => '%s', min => 0, unit => 'B' } ] } }, { label => 'traffic-size-outbound', nlabel => 'milter.traffic.size.outbound.bytes', display_ok => 0, set => { key_values => [ { name => 'traffic_size_outbound', diff => 1 } ], output_template => 'traffic size outbound: %s %s', output_change_bytes => 1, perfdatas => [ { value => 'traffic_size_outbound', template => '%s', min => 0, unit => 'B' } ] } }, { label => 'sessions-duration-total', nlabel => 'milter.sessions.duration.total.milliseconds', display_ok => 0, set => { key_values => [ { name => 'session_duration_total', diff => 1 } ], output_template => 'total sessions duration: %s ms', perfdatas => [ { value => 'session_duration_total', template => '%s', min => 0, unit => 'ms' } ] } }, { label => 'sessions-duration-mean', nlabel => 'milter.sessions.duration.mean.milliseconds', set => { key_values => [ { name => 'session_duration_mean' } ], output_template => 'mean sessions duration: %s ms', perfdatas => [ { value => 'session_duration_mean', template => '%s', min => 0, unit => 'ms' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; # bm-milter.connectionsCount,meterType=Counter count=2017123 # bm-milter.sessionDuration,meterType=Timer count=11553431,totalTime=21943249233042775,mean=1899284224 # bm-milter.traffic.class,type=INBOUND,meterType=Counter count=1289087 # bm-milter.traffic.class,type=OUTBOUND,meterType=Counter count=415711 # bm-milter.traffic.size,type=INBOUND,meterType=Counter count=29063863392 # bm-milter.traffic.size,type=OUTBOUND,meterType=Counter count=10763275492 my $result = $options{custom}->execute_command( command => 'curl --unix-socket /var/run/bm-metrics/metrics-bm-milter.sock http://127.0.0.1/metrics', filter => 'connectionsCount|sessionDuration|traffic\.class|traffic\.size' ); $self->{bm_milter} = {}; foreach (keys %$result) { $self->{bm_milter}->{'traffic_class_' . lc($1)} = $result->{$_}->{count} if (/bm-milter\.traffic\.class.*type=(INBOUND|OUTBOUND)/i); $self->{bm_milter}->{'traffic_size_' . lc($1)} = $result->{$_}->{count} if (/bm-milter\.traffic\.size.*type=(INBOUND|OUTBOUND)/i); $self->{bm_milter}->{connections} = $result->{$_}->{count} if (/bm-milter\.connectionsCount/); if (/bm-milter\.sessionDuration/) { $self->{bm_milter}->{session_duration_total} = $result->{$_}->{totalTime} / 100000; $self->{bm_milter}->{session_duration_mean} = $result->{$_}->{mean} / 100000; } } $self->{cache_name} = 'bluemind_' . $self->{mode} . '_' . $options{custom}->get_hostname() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check milter service. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^deliveries' =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'connections-total', 'traffic-class-inbound', 'traffic-class-outbound', 'traffic-size-inbound', 'traffic-size-outbound', 'sessions-duration-total', 'sessions-duration-mean' . =back =cut centreon-plugins-20220113/apps/bluemind/local/mode/webserver.pm000066400000000000000000000124471417000230700243660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::bluemind::local::mode::webserver; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use bigint; sub prefix_webserver_output { my ($self, %options) = @_; return 'Web application server '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'bm_webserver', type => 0, cb_prefix_output => 'prefix_webserver_output' }, ]; $self->{maps_counters}->{bm_webserver} = [ { label => 'requests-time-total', nlabel => 'webserver.requests.time.milliseconds', display_ok => 0, set => { key_values => [ { name => 'requests_time_total', diff => 1 } ], output_template => 'total requests time: %s ms', perfdatas => [ { value => 'requests_time_total', template => '%s', min => 0, unit => 'ms' } ] } }, { label => 'requests-time-mean', nlabel => 'webserver.requests.time.mean.milliseconds', set => { key_values => [ { name => 'requests_time_mean' } ], output_template => 'mean requests time: %s ms', perfdatas => [ { value => 'requests_time_mean', template => '%s', min => 0, unit => 'ms' } ] } }, { label => 'requests-total', nlabel => 'webserver.requests.total.count', set => { key_values => [ { name => 'requests', diff => 1 } ], output_template => 'total requests: %s', perfdatas => [ { value => 'requests', template => '%s', min => 0 } ] } }, { label => 'requests-status-200', nlabel => 'webserver.requests.status.200.count', display_ok => 0, set => { key_values => [ { name => 'requests_200', diff => 1 } ], output_template => 'total 200 requests: %s', perfdatas => [ { value => 'requests_200', template => '%s', min => 0 } ] } }, { label => 'requests-status-304', nlabel => 'webserver.requests.status.304.count', display_ok => 0, set => { key_values => [ { name => 'requests_304', diff => 1 } ], output_template => 'total 304 requests: %s', perfdatas => [ { value => 'requests_304', template => '%s', min => 0 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; # bm-webserver.appCache.requestTime,meterType=Timer count=91005,totalTime=46688008481,mean=513026 # bm-webserver.appCache.requests,meterType=Counter count=8552 # bm-webserver.staticFile.requests,status=200,meterType=Counter count=318881 # bm-webserver.staticFile.requests,status=304,meterType=Counter count=3485778 my $result = $options{custom}->execute_command( command => 'curl --unix-socket /var/run/bm-metrics/metrics-bm-webserver.sock http://127.0.0.1/metrics', filter => 'appCache|staticFile\.requests' ); $self->{bm_webserver} = {}; foreach (keys %$result) { $self->{bm_webserver}->{'requests_' . $1} = $result->{$_}->{count} if (/bm-webserver\.staticFile\.requests.*,status=(200|304)/); $self->{bm_webserver}->{requests} = $result->{$_}->{count} if (/bm-webserver\.appCache\.requests/); if (/bm-webserver\.appCache\.requestTime/) { $self->{bm_webserver}->{requests_time_total} = $result->{$_}->{totalTime} / 100000; $self->{bm_webserver}->{requests_time_mean} = $result->{$_}->{mean} / 100000; } } $self->{cache_name} = 'bluemind_' . $self->{mode} . '_' . $options{custom}->get_hostname() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check web application server. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='requests-time-mean' =item B<--filter-upstream> Filter upstream name (can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'requests-time-total', 'requests-time-mean', 'requests-total', 'requests-status-200', 'requests-status-304'. =back =cut centreon-plugins-20220113/apps/bluemind/local/mode/xmpp.pm000066400000000000000000000064431417000230700233450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::bluemind::local::mode::xmpp; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use bigint; sub prefix_xmpp_output { my ($self, %options) = @_; return 'Instant messaging service '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'bm_xmpp', type => 0, cb_prefix_output => 'prefix_xmpp_output' } ]; $self->{maps_counters}->{bm_xmpp} = [ { label => 'packets-all', nlabel => 'xmpp.packets.all.count', set => { key_values => [ { name => 'packets_all', diff => 1 } ], output_template => 'all packets sent: %s', perfdatas => [ { value => 'packets_all', template => '%s', min => 0 } ] } }, { label => 'packets-chat', nlabel => 'xmpp.packets.chat.count', display_ok => 0, set => { key_values => [ { name => 'packets_chat', diff => 1 } ], output_template => 'chat packets sent: %s', perfdatas => [ { value => 'packets_chat', template => '%s', min => 0 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; # bm-xmpp.packetsCount,type=all,meterType=Counter count=517791 # bm-xmpp.packetsCount,type=chat,meterType=Counter count=12 my $result = $options{custom}->execute_command( command => 'curl --unix-socket /var/run/bm-metrics/metrics-bm-xmpp.sock http://127.0.0.1/metrics', filter => 'packetsCount' ); $self->{bm_xmpp} = {}; foreach (keys %$result) { $self->{bm_xmpp}->{'packets_' . $1} = $result->{$_}->{count} if (/bm-xmpp\.packetsCount.*type=(all|chat)/); } $self->{cache_name} = 'bluemind_' . $self->{mode} . '_' . $options{custom}->get_hostname() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check instant messaging service. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='chat' =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'packets-all', 'packets-chat'. =back =cut centreon-plugins-20220113/apps/bluemind/local/plugin.pm000066400000000000000000000033121417000230700227230ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::bluemind::local::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} = { 'core' => 'apps::bluemind::local::mode::core', 'eas' => 'apps::bluemind::local::mode::eas', 'hps' => 'apps::bluemind::local::mode::hps', 'ips' => 'apps::bluemind::local::mode::ips', 'lmtpd' => 'apps::bluemind::local::mode::lmtpd', 'milter' => 'apps::bluemind::local::mode::milter', 'webserver' => 'apps::bluemind::local::mode::webserver', 'xmpp' => 'apps::bluemind::local::mode::xmpp' }; $self->{custom_modes}{api} = 'apps::bluemind::local::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check BlueMind through bm-metrics sockets =cut centreon-plugins-20220113/apps/centreon/000077500000000000000000000000001417000230700200145ustar00rootroot00000000000000centreon-plugins-20220113/apps/centreon/local/000077500000000000000000000000001417000230700211065ustar00rootroot00000000000000centreon-plugins-20220113/apps/centreon/local/mode/000077500000000000000000000000001417000230700220325ustar00rootroot00000000000000centreon-plugins-20220113/apps/centreon/local/mode/bamservice.pm000066400000000000000000000073101417000230700245110ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::centreon::local::mode::bamservice; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::dbi; use vars qw($centreon_config); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'centreon-config:s' => { name => 'centreon_config', default => '/etc/centreon/centreon-config.pm' }, 'bam-id:s' => { name => 'bam_id', }, }); $self->{options} = $options{options}; return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{bam_id}) || $self->{option_results}->{bam_id} !~ /^[0-9]+$/) { $self->{output}->add_option_msg(short_msg => "Need to specify bam-id (numeric value) option."); $self->{output}->option_exit(); } require $self->{option_results}->{centreon_config}; } sub run { my ($self, %options) = @_; my $sql = centreon::plugins::dbi->new(options => $self->{options}, output => $self->{output}, nooptions => 1); $sql->{data_source} = 'mysql:host=' . $centreon_config->{db_host} . 'port=' . $centreon_config->{db_port}; $sql->{username} = $centreon_config->{db_user}; $sql->{password} = $centreon_config->{db_passwd}; $sql->connect(); $sql->query(query => "SELECT `name`,`current_level`,`level_w`,`level_c` FROM " . $centreon_config->{centreon_db} . ".`mod_bam` WHERE `ba_id` = '" . $self->{option_results}->{bam_id} . "'" ); my ($name, $current_level, $level_w, $level_c) = $self->{sql}->fetchrow_array(); if (!defined($current_level)) { $self->{output}->add_option_msg(short_msg => "Cannot get bam information"); $self->{output}->option_exit(); } $self->{perfdata}->threshold_validate(label => 'warning', value => $level_w . ':'); $self->{perfdata}->threshold_validate(label => 'critical', value => $level_c . ':'); my $exit = $self->{perfdata}->threshold_check(value => $current_level, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add( severity => $exit, short_msg => sprintf('BA : %s - current_level = %s%%', $name, $current_level) ); $self->{output}->perfdata_add( label => 'BA_Level', unit => '%', value => $current_level, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0, max => 100, ); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Do Centreon bam-service checks. =over 8 =item B<--centreon-config> Centreon Database Config File (Default: '/etc/centreon/centreon-config.pm'). =item B<--bam-id> Bam-id to check (required). =back =cut centreon-plugins-20220113/apps/centreon/local/mode/brokerstats.pm000066400000000000000000000223121417000230700247330ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::centreon::local::mode::brokerstats; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use JSON; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg; if ($self->{result_values}->{type} eq 'input') { $msg = sprintf("state : %s", $self->{result_values}->{state}); } else { $msg = sprintf("state : %s [status : %s] [queue file enabled : %s]", $self->{result_values}->{state}, $self->{result_values}->{status}, $self->{result_values}->{queue_file_enabled}); } return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{queue_file_enabled} = $options{new_datas}->{$self->{instance} . '_queue_file_enabled'}; $self->{result_values}->{state} = $options{new_datas}->{$self->{instance} . '_state'}; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; $self->{result_values}->{type} = $options{new_datas}->{$self->{instance} . '_type'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'endpoint', type => 1, cb_prefix_output => 'prefix_endpoint_output', message_multiple => 'Broker statistics are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{endpoint} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'queue_file_enabled' }, { name => 'state' }, { name => 'status' }, { name => 'type' }, { 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 => \&catalog_status_threshold, } }, { label => 'speed-events', set => { key_values => [ { name => 'speed_events' }, { name => 'display' } ], output_template => 'Speed Events: %s/s', perfdatas => [ { label => 'speed_events', value => 'speed_events', template => '%s', unit => 'events/s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'queued-events', set => { key_values => [ { name => 'queued_events' }, { name => 'display' } ], output_template => 'Queued Events: %s', perfdatas => [ { label => 'queued_events', value => 'queued_events', template => '%s', unit => 'events', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'unacknowledged-events', set => { key_values => [ { name => 'unacknowledged_events' }, { name => 'display' } ], output_template => 'Unacknowledged Events: %s', perfdatas => [ { label => 'unacknowledged_events', value => 'unacknowledged_events', template => '%s', unit => 'events', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'broker-stats-file:s@' => { name => 'broker_stats_file' }, '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' }, 'filter-name:s' => { name => 'filter_name' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{type} eq "output" and %{queue_file_enabled} =~ /yes/i' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{broker_stats_file}) || scalar(@{$self->{option_results}->{broker_stats_file}}) == 0) { $self->{output}->add_option_msg(short_msg => "Please set broker-stats-file option."); $self->{output}->option_exit(); } $self->change_macros(macros => ['warning_status', 'critical_status']); } sub prefix_endpoint_output { my ($self, %options) = @_; return "Endpoint $options{instance_value}->{type} '" . $options{instance_value}->{display} . "' "; } sub manage_selection { my ($self, %options) = @_; $self->{endpoint} = {}; foreach my $config (@{$self->{option_results}->{broker_stats_file}}) { my ($stdout) = centreon::plugins::misc::execute( output => $self->{output}, options => $self->{option_results}, sudo => $self->{option_results}->{sudo}, command => 'cat', command_options => $config ); my $json; eval { $json = decode_json($stdout); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } foreach my $entry (keys %$json) { next if ($entry !~ /^endpoint/); my $endpoint = $entry; $endpoint =~ s/endpoint //; if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $endpoint !~ /$self->{option_results}->{filter_name}/i) { $self->{output}->output_add(long_msg => "skipping endpoint '" . $endpoint . "': no matching filter name"); next; } my $state = $json->{$entry}->{state}; my $type = 'output'; $type = 'input' if (!defined($json->{$entry}->{status})); $self->{endpoint}->{$endpoint} = { display => $endpoint, state => $state, type => $type, status => defined($json->{$entry}->{status}) ? $json->{$entry}->{status} : '-', speed_events => $json->{$entry}->{event_processing_speed}, queued_events => $json->{$entry}->{queued_events}, unacknowledged_events => $json->{$entry}->{bbdo_unacknowledged_events}, queue_file_enabled => defined($json->{$entry}->{queue_file_enabled}) ? $json->{$entry}->{queue_file_enabled} : '-', }; } } if (scalar(keys %{$self->{endpoint}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No endpoint found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check Centreon Broker statistics files. =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<--broker-stats-file> Specify the centreon-broker json stats file (Required). Can be multiple. =item B<--filter-name> Filter endpoint name. =item B<--warning-*> Threshold warning. Can be: 'speed-events', 'queued-events', 'unacknowledged-events'. =item B<--critical-*> Threshold critical. Can be: 'speed-events', 'queued-events', 'unacknowledged-events'. =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{queue_file_enabled}, %{state}, %{status}, %{type}, %{display} =item B<--critical-status> Set critical threshold for status (Default: '%{type} eq "output" and %{queue_file_enabled} =~ /yes/i'). Can used special variables like: %{queue_file_enabled}, %{state}, %{status}, %{type}, %{display} =back =cut centreon-plugins-20220113/apps/centreon/local/mode/centenginestats.pm000066400000000000000000000351001417000230700255650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::centreon::local::mode::centenginestats; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; sub custom_hosts_execution_time_output { my ($self, %options) = @_; return sprintf( 'hosts active execution time (avg/min/max): %.3f/%.3f/%.3f sec', $self->{result_values}->{avg}, $self->{result_values}->{min}, $self->{result_values}->{max} ); } sub custom_services_execution_time_output { my ($self, %options) = @_; return sprintf( 'services active execution time (avg/min/max): %.3f/%.3f/%.3f sec', $self->{result_values}->{avg}, $self->{result_values}->{min}, $self->{result_values}->{max} ); } sub custom_hosts_checked_output { my ($self, %options) = @_; return sprintf( 'hosts active checked last 1/5/15/60 min: %d/%d/%d/%d', $self->{result_values}->{last1min}, $self->{result_values}->{last5min}, $self->{result_values}->{last15min}, $self->{result_values}->{last60min}, ); } sub custom_services_checked_output { my ($self, %options) = @_; return sprintf( 'services active checked last 1/5/15/60 min: %d/%d/%d/%d', $self->{result_values}->{last1min}, $self->{result_values}->{last5min}, $self->{result_values}->{last15min}, $self->{result_values}->{last60min}, ); } sub custom_hosts_latency_output { my ($self, %options) = @_; return sprintf( 'hosts active latency (avg/min/max): %.3f/%.3f/%.3f sec', $self->{result_values}->{avg}, $self->{result_values}->{min}, $self->{result_values}->{max} ); } sub custom_services_latency_output { my ($self, %options) = @_; return sprintf( 'services active latency (avg/min/max): %.3f/%.3f/%.3f sec', $self->{result_values}->{avg}, $self->{result_values}->{min}, $self->{result_values}->{max} ); } sub custom_hosts_status_output { my ($self, %options) = @_; return sprintf( 'hosts status up/down/unreach: %d/%d/%d', $self->{result_values}->{up}, $self->{result_values}->{down}, $self->{result_values}->{unreach} ); } sub custom_services_status_output { my ($self, %options) = @_; return sprintf( 'services status ok/warn/unk/crit: %d/%d/%d/%d', $self->{result_values}->{ok}, $self->{result_values}->{warn}, $self->{result_values}->{unk}, $self->{result_values}->{crit} ); } sub custom_commands_buffer_output { my ($self, %options) = @_; return sprintf( 'commands buffer current/max: %d/%d', $self->{result_values}->{current}, $self->{result_values}->{max} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'stats', type => 3, indent_long_output => ' ', message_multiple => 'All centengine stats are ok', group => [ { name => 'hosts_status', type => 0, skipped_code => { -10 => 1 } }, { name => 'hosts_active_execution_time', type => 0, skipped_code => { -10 => 1 } }, { name => 'hosts_active_checked', type => 0, skipped_code => { -10 => 1 } }, { name => 'hosts_active_latency', type => 0, skipped_code => { -10 => 1 } }, { name => 'services_active_execution_time', type => 0, skipped_code => { -10 => 1 } }, { name => 'services_active_checked', type => 0, skipped_code => { -10 => 1 } }, { name => 'services_active_latency', type => 0, skipped_code => { -10 => 1 } }, { name => 'services_status', type => 0, skipped_code => { -10 => 1 } }, { name => 'commands_buffer', type => 0, skipped_code => { -10 => 1 } }, ], }, ]; foreach my $type ('hosts', 'services') { $self->{maps_counters}->{$type . '_active_execution_time'} = []; foreach ((['avg', 'average', 1], ['min', 'minimum', 0], ['max', 'maximum', 0])) { push @{$self->{maps_counters}->{$type . '_active_execution_time'}}, { label => $type . '-active-execution-time-' . $_->[1], nlabel => $type . '.active.execution.time.' . $_->[1] . '.seconds', display_ok => $_->[2], set => { key_values => [ { name => 'avg' }, { name => 'max' }, { name => 'min' } ], threshold_use => $_->[0] , closure_custom_output => $self->can('custom_' . $type . '_execution_time_output'), perfdatas => [ { value => $_->[0] , template => '%.3f', min => 0, unit => 's' }, ], } } ; } $self->{maps_counters}->{$type . '_active_checked'} = []; foreach ((['last1min', 'last1min', 1], ['last5min', 'last5min', 0], ['last15min', 'last15min', 0], ['last60min', 'last60min', 0])) { push @{$self->{maps_counters}->{$type . '_active_checked'}}, { label => $type . '-active-checked-' . $_->[1], nlabel => $type . '.active.checked.' . $_->[1] . '.count', display_ok => $_->[2], set => { key_values => [ { name => 'last1min' }, { name => 'last5min' }, { name => 'last15min' }, { name => 'last60min' } ], threshold_use => $_->[0] , closure_custom_output => $self->can('custom_' . $type . '_checked_output'), perfdatas => [ { value => $_->[0] , template => '%d', min => 0 }, ], } } ; } $self->{maps_counters}->{$type . '_active_latency'} = []; foreach ((['avg', 'average', 1], ['min', 'minimum', 0], ['max', 'maximum', 0])) { push @{$self->{maps_counters}->{$type . '_active_latency'}}, { label => $type . '-active-latency-' . $_->[1], nlabel => $type . '.active.latency.' . $_->[1] . '.seconds', display_ok => $_->[2], set => { key_values => [ { name => 'avg' }, { name => 'max' }, { name => 'min' } ], threshold_use => $_->[0] , closure_custom_output => $self->can('custom_' . $type . '_latency_output'), perfdatas => [ { value => $_->[0] , template => '%.3f', min => 0, unit => 's' }, ], } } ; } } $self->{maps_counters}->{hosts_status} = []; foreach ((['up', 'up', 1], ['down', 'down', 0], ['unreach', 'unreachable', 0])) { push @{$self->{maps_counters}->{hosts_status}}, { label => 'hosts-status-' . $_->[1], nlabel => 'hosts.status.' . $_->[1] . '.count', display_ok => $_->[2], set => { key_values => [ { name => 'up' }, { name => 'down' }, { name => 'unreach' } ], threshold_use => $_->[0] , closure_custom_output => $self->can('custom_hosts_status_output'), perfdatas => [ { value => $_->[0] , template => '%s', min => 0, max => 'total' }, ], } } ; } $self->{maps_counters}->{services_status} = []; foreach ((['ok', 'ok', 1], ['warn', 'warning', 0], ['crit', 'critical', 0], ['unk', 'unknown', 0])) { push @{$self->{maps_counters}->{services_status}}, { label => 'services-status-' . $_->[1], nlabel => 'services.status.' . $_->[1] . '.count', display_ok => $_->[2], set => { key_values => [ { name => 'ok' }, { name => 'warn' }, { name => 'unk' }, { name => 'crit' }, { name => 'total' } ], threshold_use => $_->[0] , closure_custom_output => $self->can('custom_services_status_output'), perfdatas => [ { value => $_->[0] , template => '%s', min => 0, max => 'total' }, ], } } ; } $self->{maps_counters}->{commands_buffer} = []; foreach ((['current', 'current', 1], ['max', 'maximum', 0])) { push @{$self->{maps_counters}->{commands_buffer}}, { label => 'commands-buffer-' . $_->[1], nlabel => 'commands.buffer.' . $_->[1] . '.count', display_ok => $_->[2], set => { key_values => [ { name => 'current' }, { name => 'max' }, { name => 'total' } ], threshold_use => $_->[0] , closure_custom_output => $self->can('custom_commands_buffer_output'), perfdatas => [ { value => $_->[0] , template => '%s', min => 0, max => 'total' }, ], } } ; } } 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 => { 'command:s' => { name => 'command', default => 'centenginestats' }, 'command-path:s' => { name => 'command_path', default => '/usr/sbin' }, 'command-options:s' => { name => 'command_options', default => '2>&1' }, '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' }, }); return $self; } 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->{stats} = {}; if ($stdout =~ /^Active\s+Host\s+Execution\s+Time\s*:\s*(\S+)\s*\/\s*(\S+)\s*\/\s*(\S+)/mi) { $self->{stats}->{0} = { hosts_active_execution_time => { min => $1, max => $2, avg => $3 } }; } if ($stdout =~ /^Active\s+Hosts\s+Last\s+1\/5\/15\/60\s+min:\s*(\d+)\s*\/\s*(\d+)\s*\/\s*(\d+)\s*\/\s*(\d+)/mi) { $self->{stats}->{1} = { hosts_active_checked => { last1min => $1, last5min => $2, last15min => $3, last60min => $4 } }; } if ($stdout =~ /^Active\s+Host\s+Latency\s*:\s*(\S+)\s*\/\s*(\S+)\s*\/\s*(\S+)/mi) { $self->{stats}->{2} = { hosts_active_latency => { min => $1, max => $2, avg => $3 } }; } if ($stdout =~ /^Hosts\s+Up\/Down\/Unreach\s*:\s*(\S+)\s*\/\s*(\S+)\s*\/\s*(\S+)/mi) { $self->{stats}->{3} = { hosts_status => { up => $1, down => $2, unreach => $3 } }; $self->{stats}->{3}->{hosts_status}->{total} = $1 if ($stdout =~ /^Total\s+Hosts\s*:\s*(\d+)/mi); } if ($stdout =~ /^Active\s+Service\s+Execution\s+Time\s*:\s*(\S+)\s*\/\s*(\S+)\s*\/\s*(\S+)/mi) { $self->{stats}->{5} = { services_active_execution_time => { min => $1, max => $2, avg => $3 } }; } if ($stdout =~ /^Active\s+Services\s+Last\s+1\/5\/15\/60\s+min:\s*(\d+)\s*\/\s*(\d+)\s*\/\s*(\d+)\s*\/\s*(\d+)/mi) { $self->{stats}->{6} = { services_active_checked => { last1min => $1, last5min => $2, last15min => $3, last60min => $4 } }; } if ($stdout =~ /^Active\s+Service\s+Latency\s*:\s*(\S+)\s*\/\s*(\S+)\s*\/\s*(\S+)/mi) { $self->{stats}->{7} = { services_active_latency => { min => $1, max => $2, avg => $3 } }; } if ($stdout =~ /^Services\s+Ok\/Warn\/Unk\/Crit\s*:\s*(\d+)\s*\/\s*(\d+)\s*\/\s*(\d+)\s*\/\s*(\d+)/mi) { $self->{stats}->{8} = { services_status => { ok => $1, warn => $2, unk => $3, crit => $4 } }; $self->{stats}->{8}->{services_status}->{total} = $1 if ($stdout =~ /^Total\s+Services\s*:\s*(\d+)/mi); } if ($stdout =~ /^Used\/High\/Total\s+Command\s+Buffers\s*:\s*(\d+)\s*\/\s*(\d+)\s*\/\s*(\d+)/mi) { $self->{stats}->{9} = { commands_buffer => { current => $1, max => $2, total => $3 } }; } } 1; __END__ =head1 MODE Check centengine statistics. =over 8 =item B<--command> Command to get information (Default: 'centenginestats'). Can be changed if you have output in a file. =item B<--command-path> Command path (Default: '/usr/sbin'). =item B<--command-options> Command options (Default: '2>&1'). =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<--warning-*> B<--critical-*> Thresholds. please use --list-counters to display. =back =cut centreon-plugins-20220113/apps/centreon/local/mode/centreonpluginsversion.pm000066400000000000000000000055621417000230700272250ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package 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; $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 centreon-plugins-20220113/apps/centreon/local/mode/downtimetrap.pm000066400000000000000000000274111417000230700251120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::centreon::local::mode::downtimetrap; use base qw(centreon::plugins::mode); my $use_module_snmp; my $use_module_netsnmp; BEGIN { eval { require SNMP; SNMP->import(); }; if ($@) { $use_module_snmp = 0; eval { require Net::SNMP; Net::SNMP->import(); }; if ($@) { $use_module_netsnmp = 0; } else { $use_module_netsnmp = 1; } } else { $use_module_snmp = 1; } } use strict; use warnings; use Sys::Hostname; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "oid-trap:s" => { name => 'oid_trap', default => '.1.3.6.1.4.1.50000.1.1' }, "oid-hostname:s" => { name => 'oid_hostname', default => '.1.3.6.1.4.1.50000.2.1' }, "oid-start:s" => { name => 'oid_start', default => '.1.3.6.1.4.1.50000.2.2' }, "oid-end:s" => { name => 'oid_end', default => '.1.3.6.1.4.1.50000.2.4' }, "oid-author:s" => { name => 'oid_author', default => '.1.3.6.1.4.1.50000.2.5' }, "oid-comment:s" => { name => 'oid_comment', default => '.1.3.6.1.4.1.50000.2.6' }, "oid-duration:s" => { name => 'oid_duration', default => '.1.3.6.1.4.1.50000.2.7' }, "centreon-server:s" => { name => 'centreon_server' }, "author:s" => { name => 'author', default => 'system reboot' }, "comment:s" => { name => 'comment', default => 'the system reboots.' }, "duration:s" => { name => 'duration', default => 300 }, "wait:s" => { name => 'wait' }, "snmptrap-command:s" => { name => 'snmptrap_command', default => 'snmptrap' }, "display-options" => { name => 'display_options' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{centreon_server}) || $self->{option_results}->{centreon_server} eq '') { $self->{output}->add_option_msg(short_msg => "Please set centreon-server option."); $self->{output}->option_exit(); } } sub snmp_build_args { my ($self, %options) = @_; $self->{snmp_args} = { hostname => {}, duration => {} }; if ($self->{option_results}->{oid_hostname} =~ /^(.*)\.(\d+)$/) { $self->{snmp_args}->{hostname} = { oid => $1, instance => $2, val => hostname(), type => 'OCTETSTR', type_cmd => 's' }; } if ($self->{option_results}->{oid_start} =~ /^(.*)\.(\d+)$/) { $self->{snmp_args}->{start} = { oid => $1, instance => $2, val => time(), type => 'INTEGER', type_cmd => 'i' }; } if ($self->{option_results}->{oid_end} =~ /^(.*)\.(\d+)$/) { $self->{snmp_args}->{end} = { oid => $1, instance => $2, val => time() + $self->{option_results}->{duration}, type => 'INTEGER', type_cmd => 'i' }; } if ($self->{option_results}->{oid_author} =~ /^(.*)\.(\d+)$/) { $self->{snmp_args}->{author} = { oid => $1, instance => $2, val => $self->{option_results}->{author}, type => 'OCTETSTR', type_cmd => 's' }; } if ($self->{option_results}->{oid_comment} =~ /^(.*)\.(\d+)$/) { $self->{snmp_args}->{comment} = { oid => $1, instance => $2, val => $self->{option_results}->{comment}, type => 'OCTETSTR', type_cmd => 's' }; } if ($self->{option_results}->{oid_duration} =~ /^(.*)\.(\d+)$/) { $self->{snmp_args}->{duration} = { oid => $1, instance => $2, val => $self->{snmp_args}->{end}->{val} - $self->{snmp_args}->{start}->{val}, type => 'INTEGER', type_cmd => 'i' }; } } sub send_trap_snmp { my ($self, %options) = @_; $SNMP::auto_init_mib = 0; $self->snmp_build_args(); my $varlist = new SNMP::VarList( new SNMP::Varbind([$self->{snmp_args}->{hostname}->{oid}, $self->{snmp_args}->{hostname}->{instance}, $self->{snmp_args}->{hostname}->{val}, $self->{snmp_args}->{hostname}->{type}]), new SNMP::Varbind([$self->{snmp_args}->{start}->{oid}, $self->{snmp_args}->{start}->{instance}, $self->{snmp_args}->{start}->{val}, $self->{snmp_args}->{start}->{type}]), new SNMP::Varbind([$self->{snmp_args}->{end}->{oid}, $self->{snmp_args}->{end}->{instance}, $self->{snmp_args}->{end}->{val}, $self->{snmp_args}->{end}->{type}]), new SNMP::Varbind([$self->{snmp_args}->{author}->{oid}, $self->{snmp_args}->{author}->{instance}, $self->{snmp_args}->{author}->{val}, $self->{snmp_args}->{author}->{type}]), new SNMP::Varbind([$self->{snmp_args}->{comment}->{oid}, $self->{snmp_args}->{comment}->{instance}, $self->{snmp_args}->{comment}->{val}, $self->{snmp_args}->{comment}->{type}]), new SNMP::Varbind([$self->{snmp_args}->{duration}->{oid}, $self->{snmp_args}->{duration}->{instance}, $self->{snmp_args}->{duration}->{val}, $self->{snmp_args}->{duration}->{type}]), ); my $trapsess = new SNMP::TrapSession(DestHost => $self->{option_results}->{centreon_server}, RemotePort => 162, UseNumeric => 1, Version => '2c', Community => 'public'); $trapsess->trap(oid => $self->{option_results}->{oid_trap}, uptime => time(), $varlist); } sub send_trap_netsnmp { my ($self, %options) = @_; $self->snmp_build_args(); my ($snmp_session, $error) = Net::SNMP->session(-hostname => $self->{option_results}->{centreon_server}, -community => "public", -port => 162, -version => "snmpv2c", -translate => [-all => 0]); if (!defined($snmp_session)) { $self->{output}->add_option_msg(short_msg => "SNMP Session : $error"); $self->{output}->option_exit(); } my $args = []; push @$args, ('1.3.6.1.2.1.1.3.0', eval "Net::SNMP::TIMETICKS", time()); push @$args, ('1.3.6.1.6.3.1.1.4.1.0', eval "Net::SNMP::OBJECT_IDENTIFIER", $self->{option_results}->{oid_trap}); foreach (('hostname', 'start', 'end', 'author', 'comment', 'duration')) { my $type = $self->{snmp_args}->{$_}->{type}; $type = 'OCTET_STRING' if ($type eq 'OCTETSTR'); my $result; my $ltmp = "\$result = Net::SNMP::$type;"; eval $ltmp; push @$args, ($self->{snmp_args}->{$_}->{oid} . '.' . $self->{snmp_args}->{$_}->{instance}, $result, $self->{snmp_args}->{$_}->{val}); } $snmp_session->snmpv2_trap(-varbindlist => $args); $snmp_session->close(); } sub send_trap_cmd { my ($self, %options) = @_; $self->snmp_build_args(); my $options = '-v 2c -c public ' . $self->{option_results}->{centreon_server} . ' ' . time() . ' ' . $self->{option_results}->{oid_trap}; $options .= ' ' . $self->{snmp_args}->{hostname}->{oid} . '.' . $self->{snmp_args}->{hostname}->{instance} . ' ' . $self->{snmp_args}->{hostname}->{type_cmd} . ' "' . $self->{snmp_args}->{hostname}->{val} . '"'; $options .= ' ' . $self->{snmp_args}->{start}->{oid} . '.' . $self->{snmp_args}->{start}->{instance} . ' ' . $self->{snmp_args}->{start}->{type_cmd} . ' "' . $self->{snmp_args}->{start}->{val} . '"'; $options .= ' ' . $self->{snmp_args}->{end}->{oid} . '.' . $self->{snmp_args}->{end}->{instance} . ' ' . $self->{snmp_args}->{end}->{type_cmd} . ' "' . $self->{snmp_args}->{end}->{val} . '"'; $options .= ' ' . $self->{snmp_args}->{author}->{oid} . '.' . $self->{snmp_args}->{author}->{instance} . ' ' . $self->{snmp_args}->{author}->{type_cmd} . ' "' . $self->{snmp_args}->{author}->{val} . '"'; $options .= ' ' . $self->{snmp_args}->{comment}->{oid} . '.' . $self->{snmp_args}->{comment}->{instance} . ' ' . $self->{snmp_args}->{comment}->{type_cmd} . ' "' . $self->{snmp_args}->{comment}->{val} . '"'; $options .= ' ' . $self->{snmp_args}->{duration}->{oid} . '.' . $self->{snmp_args}->{duration}->{instance} . ' ' . $self->{snmp_args}->{duration}->{type_cmd} . ' "' . $self->{snmp_args}->{duration}->{val} . '"'; if (defined($self->{option_results}->{display_options})) { $self->{output}->output_add(severity => 'OK', short_msg => $options); $self->{output}->display(force_ignore_perfdata => 1, nolabel => 1); $self->{output}->exit(); } $self->{option_results}->{timeout} = 10; centreon::plugins::misc::execute(output => $self->{output}, options => $self->{option_results}, command => $self->{option_results}->{snmptrap_command}, command_options => $options); } sub run { my ($self, %options) = @_; if ($use_module_snmp == 1 && !defined($self->{option_results}->{display_options})) { $self->send_trap_snmp(); } elsif ($use_module_netsnmp == 1 && !defined($self->{option_results}->{display_options})) { $self->send_trap_netsnmp(); } else { $self->send_trap_cmd(); } if (defined($self->{option_results}->{wait}) && $self->{option_results}->{wait} =~ /\d+/) { sleep($self->{option_results}->{wait}); } $self->{output}->output_add(severity => 'OK', short_msg => 'SNMP trap sent.'); $self->{output}->display(force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE Send a SNMP trap to set a downtime. =over 8 =item B<--oid-trap> Specify OID trap (Default: '.1.3.6.1.4.1.50000.1.1') =item B<--oid-hostname> Specify OID for hostname (Default: '.1.3.6.1.4.1.50000.2.1') =item B<--oid-start> Specify OID for downtime start time (Default: '.1.3.6.1.4.1.50000.2.2') =item B<--oid-end> Specify OID for downtime end time (Default: '.1.3.6.1.4.1.50000.2.3') =item B<--oid-author> Specify OID for downtime author (Default: '.1.3.6.1.4.1.50000.2.4') =item B<--oid-comment> Specify OID for downtime comment (Default: '.1.3.6.1.4.1.50000.2.5') =item B<--oid-duration> Specify OID for downtime duration (Default: '.1.3.6.1.4.1.50000.2.6') =item B<--centreon-server> Address of centreon server to send the trap (Required) =item B<--author> Set the downtime author (Default: 'system reboot'). =item B<--comment> Set the downtime comment (Default: 'the system reboots.'). =item B<--duration> Set the downtime duration in seconds (Default: 300) =item B<--wait> Time in seconds to wait =item B<--snmptrap-command> snmptrap command used (Default: 'snmptrap'). Use if the SNMP perl module is not installed. =item B<--display-options> Only display snmptrap command options. =back =cut centreon-plugins-20220113/apps/centreon/local/mode/dummy.pm000066400000000000000000000051251417000230700235260ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::centreon::local::mode::dummy; use base qw(centreon::plugins::mode); use strict; use warnings; my %errors_num = (0 => 'OK', 1 => 'WARNING', 2 => 'CRITICAL', 3 => 'UNKNOWN'); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "status:s" => { name => 'status' }, "output:s" => { name => 'output' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{status}) || ($self->{option_results}->{status} !~ /^[0-3]$/ && $self->{option_results}->{status} !~ /ok|warning|critical|unknown/i)) { $self->{output}->add_option_msg(short_msg => "Need to specify --status option."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{output}) || $self->{option_results}->{output} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --output option."); $self->{output}->option_exit(); } } sub run { my ($self, %options) = @_; my $status = $self->{option_results}->{status}; $status = $errors_num{$status} if $status =~ /^[0-3]$/; $self->{output}->output_add(severity => $status, short_msg => $self->{option_results}->{output}); $self->{output}->display(force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE Do a dummy check. =over 8 =item B<--status> Status to be returned (Should be numeric value between 0 and 3, or string in ok, warning, critical, unknown). =item B<--output> Output to be returned. =back =cut centreon-plugins-20220113/apps/centreon/local/mode/metaservice.pm000066400000000000000000000223321417000230700247010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::centreon::local::mode::metaservice; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::common::db; use centreon::common::logger; use vars qw($centreon_config); my %DSTYPE = ( '0' => 'g', '1' => 'c', '2' => 'd', '3' => 'a'); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'centreon-config:s' => { name => 'centreon_config', default => '/etc/centreon/centreon-config.pm' }, 'meta-id:s' => { name => 'meta_id' } }); $self->{metric_selected} = {}; return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{meta_id}) || $self->{option_results}->{meta_id} !~ /^[0-9]+$/) { $self->{output}->add_option_msg(short_msg => "Need to specify meta-id (numeric value) option."); $self->{output}->option_exit(); } require $self->{option_results}->{centreon_config}; } sub execute_query { my ($self, $db, $query) = @_; my ($status, $stmt) = $db->query($query); if ($status == -1) { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => 'SQL Query error: ' . $query ); $self->{output}->display(); $self->{output}->exit(); } return $stmt; } sub select_by_regexp { my ($self, %options) = @_; my $count = 0; my $stmt = $self->execute_query( $self->{centreon_db_centstorage}, "SELECT metrics.metric_id, metrics.metric_name, metrics.current_value FROM index_data, metrics WHERE index_data.service_description LIKE " . $self->{centreon_db_centstorage}->quote($options{regexp_str}) . " AND index_data.id = metrics.index_id" ); while ((my $row = $stmt->fetchrow_hashref())) { if ($options{metric_select} eq $row->{metric_name}) { $self->{metric_selected}->{$row->{metric_id}} = $row->{current_value}; $count++; } } if ($count == 0) { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => 'Cannot find a metric.' ); $self->{output}->display(); $self->{output}->exit(); } } sub select_by_list { my ($self, %options) = @_; my $count = 0; my $metric_ids = {}; my $stmt = $self->execute_query($self->{centreon_db_centreon}, "SELECT metric_id FROM `meta_service_relation` WHERE meta_id = '". $self->{option_results}->{meta_id} . "' AND activate = '1'"); while ((my $row = $stmt->fetchrow_hashref())) { $metric_ids->{$row->{metric_id}} = 1; $count++; } if ($count == 0) { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => 'Cannot find a metric_id in table meta_service_relation.' ); $self->{output}->display(); $self->{output}->exit(); } $count = 0; $stmt = $self->execute_query( $self->{centreon_db_centstorage}, "SELECT metric_id, current_value FROM metrics WHERE metric_id IN (" . join(',', keys %{$metric_ids}) . ")" ); while ((my $row = $stmt->fetchrow_hashref())) { $self->{metric_selected}->{$row->{metric_id}} = $row->{current_value}; $count++; } if ($count == 0) { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => 'Cannot find a metric_id in metrics table.' ); $self->{output}->display(); $self->{output}->exit(); } } sub calculate { my ($self, %options) = @_; my $result = 0; if ($options{calculation} eq 'MIN') { my @values = sort { $a <=> $b } values(%{$self->{metric_selected}}); if (defined($values[0])) { $result = $values[0]; } } elsif ($options{calculation} eq 'MAX') { my @values = sort { $a <=> $b } values(%{$self->{metric_selected}}); if (defined($values[0])) { $result = $values[scalar(@values) - 1]; } } elsif ($options{calculation} eq 'SOM') { foreach my $value (values %{$self->{metric_selected}}) { $result += $value; } } elsif ($options{calculation} eq 'AVE') { my @values = values %{$self->{metric_selected}}; foreach my $value (@values) { $result += $value; } my $total = scalar(@values); if ($total == 0) { $total = 1; } $result = $result / $total; } return $result; } sub run { my ($self, %options) = @_; $self->{logger} = centreon::common::logger->new(); $self->{logger}->severity('none'); $self->{centreon_db_centreon} = centreon::common::db->new( db => $centreon_config->{centreon_db}, host => $centreon_config->{db_host}, port => $centreon_config->{db_port}, user => $centreon_config->{db_user}, password => $centreon_config->{db_passwd}, force => 0, logger => $self->{logger} ); my $status = $self->{centreon_db_centreon}->connect(); if ($status == -1) { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => 'Cannot connect to Centreon Database.' ); $self->{output}->display(); $self->{output}->exit(); } $self->{centreon_db_centstorage} = centreon::common::db->new( db => $centreon_config->{centstorage_db}, host => $centreon_config->{db_host}, port => $centreon_config->{db_port}, user => $centreon_config->{db_user}, password => $centreon_config->{db_passwd}, force => 0, logger => $self->{logger} ); $status = $self->{centreon_db_centstorage}->connect(); if ($status == -1) { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => 'Cannot connect to Centstorage Database.' ); $self->{output}->display(); $self->{output}->exit(); } my $stmt = $self->execute_query($self->{centreon_db_centreon}, "SELECT meta_display, calcul_type, regexp_str, warning, critical, metric, meta_select_mode, data_source_type FROM `meta_service` WHERE meta_id = '". $self->{option_results}->{meta_id} . "' LIMIT 1"); my $row = $stmt->fetchrow_hashref(); if (!defined($row)) { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => 'Cannot get meta service informations.' ); $self->{output}->display(); $self->{output}->exit(); } # Set threshold if (($self->{perfdata}->threshold_validate(label => 'warning', value => $row->{warning})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning threshold '" . $row->{warning} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'critical', value => $row->{critical})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical threshold '" . $row->{critical} . "'."); $self->{output}->option_exit(); } if ($row->{meta_select_mode} == 2) { $self->select_by_regexp(regexp_str => $row->{regexp_str}, metric_select => $row->{metric}); } else { $self->select_by_list(); } my $result = $self->calculate(calculation => $row->{calcul_type}); my $exit = $self->{perfdata}->threshold_check(value => $result, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); my $display = defined($row->{meta_display}) ? $row->{meta_display} : $row->{calcul_type} . ' - value : %f'; $self->{output}->output_add( severity => $exit, short_msg => sprintf($display, $result) ); $self->{output}->perfdata_add( label => sprintf( '%s[%s]', (defined($DSTYPE{$row->{data_source_type}}) ? $DSTYPE{$row->{data_source_type}} : 'g'), defined($row->{metric}) && $row->{metric} ne '' ? $row->{metric} : 'value', ), value => sprintf('%02.2f', $result), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical') ); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Do Centreon meta-service checks. =over 8 =item B<--centreon-config> Centreon Database Config File (Default: '/etc/centreon/centreon-config.pm'). =item B<--meta-id> Meta-id to check (required). =back =cut centreon-plugins-20220113/apps/centreon/local/mode/notsodummy.pm000066400000000000000000000243041417000230700246110ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::centreon::local::mode::notsodummy; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::statefile; use Digest::MD5 qw(md5_hex); my %errors_service = (0 => 'OK', 1 => 'WARNING', 2 => 'CRITICAL', 3 => 'UNKNOWN'); my %errors_host = (0 => 'UP', 1 => 'DOWN'); my %errors_hash = ('UP' => 'OK', 'DOWN' => 'CRITICAL'); 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 => { "status-sequence:s" => { name => 'status_sequence' }, "host" => { name => 'host' }, "output:s" => { name => 'output' }, "metrics-count:s" => { name => 'metrics_count' }, "metrics-name:s" => { name => 'metrics_name', default => 'metrics.number' }, "metrics-values-range:s" => { name => 'metrics_values_range' }, "show-sequence" => { name => 'show_sequence' }, "show-index" => { name => 'show_index' }, "restart-sequence" => { name => 'restart_sequence' }, }); $self->{cache} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{status_sequence}) || $self->{option_results}->{status_sequence} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --status-sequence option."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{output}) || $self->{option_results}->{output} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --output option."); $self->{output}->option_exit(); } 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}->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}->option_exit(); } push @{$self->{status_sequence}}, $status; } if (defined($self->{option_results}->{metrics_count}) && $self->{option_results}->{metrics_count} < 1) { $self->{output}->add_option_msg(short_msg => "Need to specify --metrics-count value > 0."); $self->{output}->option_exit(); } if (defined($self->{option_results}->{metrics_values_range}) && $self->{option_results}->{metrics_values_range} =~ /(([0-9-.,]*):)?([0-9-.,]*)/) { $self->{metrics_range_start} = $2; $self->{metrics_range_end} = $3; } $self->{metrics_range_start} = 0 if (!defined($self->{metrics_range_start}) || $self->{metrics_range_start} eq ''); $self->{metrics_range_end} = 100 if (!defined($self->{metrics_range_end}) || $self->{metrics_range_end} eq ''); if ($self->{metrics_range_start} !~ /^-?\d+$/ || $self->{metrics_range_end} !~ /^-?\d+$/) { $self->{output}->add_option_msg(short_msg => "Need to specify --metrics-values-range where range start and range end are integer."); $self->{output}->option_exit(); } if ($self->{metrics_range_start} > $self->{metrics_range_end}) { $self->{output}->add_option_msg(short_msg => "Need to specify --metrics-values-range where range start is lower than range end."); $self->{output}->option_exit(); } $self->{cache}->check_options(option_results => $self->{option_results}); } sub get_next_status { my ($self, %options) = @_; my $index; my $has_cache_file = $options{statefile}->read(statefile => 'centreon_notsodummy_' . md5_hex(@{$self->{status_sequence}}) . '_' . md5_hex($self->{option_results}->{output})); if ($has_cache_file == 0 || $self->{option_results}->{restart_sequence}) { $index = 0; my $datas = { last_timestamp => time(), status_sequence => $self->{status_sequence}, status_sequence_index => $index }; $options{statefile}->write(data => $datas); } else { $index = $options{statefile}->get(name => 'status_sequence_index'); $index = ($index < scalar(@{$self->{status_sequence}} - 1)) ? $index + 1 : 0; my $datas = { last_timestamp => time(), status_sequence => $self->{status_sequence}, status_sequence_index => $index }; $options{statefile}->write(data => $datas); } return $self->{status_sequence}[$index], $index; } sub get_sequence_output { my ($self, %options) = @_; my @sequence_output; my $i = 0; foreach my $status (split(',', $self->{option_results}->{status_sequence})) { $status = $errors_service{$status} if ($status =~ /^[0-3]$/ && !defined($self->{option_results}->{host})); $status = $errors_host{$status} if ($status =~ /^[0-1]$/ && defined($self->{option_results}->{host})); push @sequence_output, uc($status) if ($i == $options{index}); push @sequence_output, lc($status) if ($i != $options{index}); $i++ } return join(',', @sequence_output); } sub run { my ($self, %options) = @_; my ($status, $index) = $self->get_next_status(statefile => $self->{cache}); my $status_label = $status; if (defined($self->{option_results}->{host})) { $status_label = $errors_host{$status} if ($status =~ /^[0-1]$/); $status = $errors_host{$status} if ($status =~ /^[0-1]$/); $status = $errors_hash{uc($status)}; } else { $status_label = $errors_service{$status} if ($status =~ /^[0-3]$/); $status = $errors_service{$status} if ($status =~ /^[0-3]$/); } my $output = $self->{option_results}->{output}; $output .= ' [' . $self->get_sequence_output(index => $index) . ']' if ($self->{option_results}->{show_sequence}); $self->{output}->output_add( severity => $status, short_msg => uc($status_label) . ': ' . $output ); $self->{output}->output_add( long_msg => "Current status '" . uc($status_label) . "'" ); $self->{output}->output_add( long_msg => "Sequence '" . $self->get_sequence_output(index => $index) . "'" ); if (defined($self->{option_results}->{metrics_count}) > 0) { for (my $i = 1; $i <= $self->{option_results}->{metrics_count}; $i++) { my $metric_name = $self->{option_results}->{metrics_name} . '.' . $i; my $metric_value = $self->{metrics_range_start} + int(rand($self->{metrics_range_end} - $self->{metrics_range_start})) + 1; $self->{output}->perfdata_add( nlabel => $metric_name, value => $metric_value, min => $self->{metrics_range_start}, max => $self->{metrics_range_end} ); $self->{output}->output_add( long_msg => "Metric '" . $metric_name . "' value is '" . $metric_value . "'" ); } } if (defined($self->{option_results}->{show_index})) { $self->{output}->perfdata_add( nlabel => 'sequence.index.position', value => ++$index, min => 1, max => scalar(@{$self->{status_sequence}}) ); } $self->{output}->display(nolabel => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE Do a not-so-dummy check. Sequence and sequence index are stored in cache file. Use --statefile* options to defined the way cache file is managed. Examples: perl centreon_plugin.pl --plugin=apps::centreon::local::plugin --mode=not-so-dummy --status-sequence='ok,warning,ok,critical,critical,critical' --output='Not so dummy service' --show-sequence --statefile-dir='/tmp' perl centreon_plugin.pl --plugin=apps::centreon::local::plugin --mode=not-so-dummy --status-sequence='up,down,down' --host --output='Not so dummy host' perl centreon_plugin.pl --plugin=apps::centreon::local::plugin --mode=not-so-dummy --status-sequence='ok,ok,ok' --output='Not so dummy' --metrics-count=5 --metrics-name='met.rics' --metrics-values-range='-15:42' =over 8 =item B<--status-sequence> Comma separated sequence of statuses from which the mode should pick is return code from. (Example: --status-sequence='ok,critical,ok,ok' or --status-sequence='up,up,down' --host) (Should be numeric value between 0 and 3, or string in ok, warning, critical, unknown, up, down). =item B<--host> To be set if sequence is for host statuses. =item B<--output> Output to be returned. =item B<--metrics-count> Number of metrics to generate. =item B<--metrics-name> Name of the metrics (Default: 'metrics.number'). Metrics are suffixed by a number between 1 and metrics count. =item B<--metrics-values-range> Range of values from which metrics values can be picked (Default: '0:100'). =item B<--show-sequence> Show the sequence is the output (in addition to the defined output). =item B<--show-index> Show the index as a metric (in addition to the defined metrics count). =item B<--restart-sequence> Restart the sequence from the beginning (ie. reset the sequence in cache file). =back =cut centreon-plugins-20220113/apps/centreon/local/mode/retentionbroker.pm000066400000000000000000000140331417000230700256050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::centreon::local::mode::retentionbroker; use base qw(centreon::plugins::mode); use strict; use warnings; use XML::LibXML; use File::Basename; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'broker-config:s@' => { name => 'broker_config' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{broker_config}) || scalar(@{$self->{option_results}->{broker_config}}) == 0) { $self->{output}->add_option_msg(short_msg => "Please set broker-config option."); $self->{output}->option_exit(); } } sub check_directory { my ($self, %options) = @_; my ($current_total, $current_size) = (0, 0); my $dirname = dirname($options{path}); my $basename = basename($options{path}); my $dh; if (!opendir($dh, $dirname)) { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => "'$options{config}': cannot open directory '$dirname'"); return 0; } while (my $file = readdir($dh)) { if ($file =~ /^$basename\d*$/) { $current_total++; $current_size += -s $dirname . '/' . $file; } } closedir $dh; return (1, $current_total, $current_size); } sub run { my ($self, %options) = @_; $self->{output}->output_add(severity => 'OK', short_msg => 'centreon-broker failover/temporary files are ok'); my $total_size = 0; foreach my $config (@{$self->{option_results}->{broker_config}}) { $self->{output}->output_add(long_msg => "Checking config '$config'"); if (! -f $config or ! -r $config) { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => "'$config': not a file or cannot be read" ); next; } my $parser = XML::LibXML->new(); my $xml; eval { $xml = $parser->parse_file($config); }; if ($@) { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => "'$config': cannot parse xml" ); next; } my %failover_found = (); my %file_found = (); my $temporary; foreach my $node ($xml->findnodes('/centreonBroker/output')) { my %load = (); foreach my $element ($node->getChildrenByTagName('*')) { if ($element->nodeName eq 'failover') { $failover_found{$element->textContent} = 1; } elsif ($element->nodeName =~ /^(name|type|path)$/) { $load{$element->nodeName} = $element->textContent; } } if (defined($load{type}) && $load{type} eq 'file') { $file_found{$load{name}} = {%load}; } } foreach my $node ($xml->findnodes('/centreonBroker/temporary')) { foreach my $element ($node->getChildrenByTagName('path')) { $temporary = $element->textContent; } } # Check failovers my $current_total = 0; foreach my $failover (sort keys %failover_found) { next if (!defined($file_found{$failover})); my ($status, $total, $size) = $self->check_directory(config => $config, path => $file_found{$failover}->{path}); next if (!$status); $current_total += $total; $total_size += $size; my ($size_value, $size_unit) = $self->{perfdata}->change_bytes(value => $size); $self->{output}->output_add(long_msg => sprintf("failover '%s': %d file(s) found (%s)", $failover, $total, $size_value . ' ' . $size_unit)); } if ($current_total > 0) { $self->{output}->output_add(severity => 'CRITICAL', short_msg => sprintf("Some failover(s) are active")); } # Check temporary if (!defined($temporary)) { $self->{output}->output_add(long_msg => "skipping temporary: no configuration set"); next; } my ($status, $total, $size) = $self->check_directory(config => $config, path => $temporary); if ($status) { my ($size_value, $size_unit) = $self->{perfdata}->change_bytes(value => $size); $self->{output}->output_add(long_msg => sprintf("temporary: %d file(s) found (%s)", $total, $size_value . ' ' . $size_unit)); if ($total > 0) { $self->{output}->output_add(severity => 'CRITICAL', short_msg => sprintf("Temporary is active")); } } } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check failover file retention or temporary is active. =over 8 =item B<--broker-config> Specify the centreon-broker config (Required). Can be multiple. =back =cut centreon-plugins-20220113/apps/centreon/local/plugin.pm000066400000000000000000000036021417000230700227430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::centreon::local::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} = '0.1'; %{$self->{modes}} = ( 'bamservice' => 'apps::centreon::local::mode::bamservice', 'broker-stats' => 'apps::centreon::local::mode::brokerstats', 'centengine-stats' => 'apps::centreon::local::mode::centenginestats', 'centreon-plugins-version' => 'apps::centreon::local::mode::centreonpluginsversion', 'downtime-trap' => 'apps::centreon::local::mode::downtimetrap', 'dummy' => 'apps::centreon::local::mode::dummy', 'metaservice' => 'apps::centreon::local::mode::metaservice', 'not-so-dummy' => 'apps::centreon::local::mode::notsodummy', 'retention-broker' => 'apps::centreon::local::mode::retentionbroker', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Specific Centreon Indicators. =cut centreon-plugins-20220113/apps/centreon/map/000077500000000000000000000000001417000230700205715ustar00rootroot00000000000000centreon-plugins-20220113/apps/centreon/map/jmx/000077500000000000000000000000001417000230700213675ustar00rootroot00000000000000centreon-plugins-20220113/apps/centreon/map/jmx/mode/000077500000000000000000000000001417000230700223135ustar00rootroot00000000000000centreon-plugins-20220113/apps/centreon/map/jmx/mode/brokerstats.pm000066400000000000000000000124551417000230700252230ustar00rootroot00000000000000# Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::centreon::map::jmx::mode::brokerstats; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("Packets Delta: %d [%d/%d]", $self->{result_values}->{diff_packets}, $self->{result_values}->{processed_packets}, $self->{result_values}->{received_packets}); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{received_packets} = $options{new_datas}->{$self->{instance} . '_ReceivedPackets'}; $self->{result_values}->{processed_packets} = $options{new_datas}->{$self->{instance} . '_ProcessedPackets'}; $self->{result_values}->{diff_packets} = $self->{result_values}->{received_packets} - $self->{result_values}->{processed_packets}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, ]; $self->{maps_counters}->{global} = [ { label => 'status', set => { key_values => [ { name => 'ReceivedPackets', diff => 1 }, { name => 'ProcessedPackets', diff => 1 } ], 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 => \&catalog_status_threshold } }, { label => 'received-packets-rate', set => { key_values => [ { name => 'ReceivedPackets', per_second => 1 } ], output_template => 'Received Packets: %.2f/s', perfdatas => [ { label => 'received_packets_rate', template => '%.2f', min => 0, unit => 'packets/s' } ] } }, { label => 'processed-packets-rate', set => { key_values => [ { name => 'ProcessedPackets', per_second => 1 } ], output_template => 'Processed Packets: %.2f/s', perfdatas => [ { label => 'processed_packets_rate', template => '%.2f', min => 0, unit => 'packets/s' }, ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{processed_packets} < %{received_packets}' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } my $mbean_broker = "com.centreon.studio.map:type=broker,name=statistics"; sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = "centreon_map_" . md5_hex($options{custom}->{url}) . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); $self->{request} = [ { mbean => $mbean_broker } ]; my $result = $options{custom}->get_attributes(request => $self->{request}, nothing_quit => 0); $self->{global} = {}; $self->{global} = { ReceivedPackets => $result->{$mbean_broker}->{ReceivedPackets}, ProcessedPackets => $result->{$mbean_broker}->{ProcessedPackets}, }; } 1; __END__ =head1 MODE Check broker packets rate received and processed. Example: perl centreon_plugins.pl --plugin=apps::centreon::map::jmx::plugin --custommode=jolokia --url=http://10.30.2.22:8080/jolokia-war --mode=broker-stats =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). (Example: --filter-counters='session') =item B<--warning-status> Set warning threshold for status. (Default: ''). Can use special variables like: %{processed_packets}, %{received_packets}, %{diff_packets}. =item B<--critical-status> Set critical threshold for status. (Default: '%{processed_packets} < %{received_packets}'). Can use special variables like: %{processed_packets}, %{received_packets}, %{diff_packets}. =item B<--warning-*> Threshold warning. Can be: 'received-packets-rate', 'processed-packets-rate'. =item B<--critical-*> Threshold critical. Can be: 'received-packets-rate', 'processed-packets-rate'. =back =cut centreon-plugins-20220113/apps/centreon/map/jmx/mode/enginestats.pm000066400000000000000000000110541417000230700251760ustar00rootroot00000000000000# Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::centreon::map::jmx::mode::enginestats; 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 => 'global', type => 0 }, ]; $self->{maps_counters}->{global} = [ { label => 'drilldown-candidates-queue', set => { key_values => [ { name => 'DrilldownCandidatesQueue' } ], output_template => 'Drilldown Canditates Queue: %d', perfdatas => [ { label => 'drilldown_candidates_queue', template => '%d', min => 0 }, ], } }, { label => 'cutback-computation-rate', set => { key_values => [ { name => 'Cutbackcomputation', per_second => 1 } ], output_template => 'Cutback Computation: %.2f/s', perfdatas => [ { label => 'cutback_computation_rate', template => '%.2f', min => 0 }, ], } }, { label => 'minimal-computation-rate', set => { key_values => [ { name => 'Minimalcomputation', per_second => 1 } ], output_template => 'Minimal Computation: %.2f/s', perfdatas => [ { label => 'minimal_computation_rate', template => '%.2f', min => 0 }, ], } }, { label => 'recursive-computation-rate', set => { key_values => [ { name => 'Recursivecomputation', per_second => 1 } ], output_template => 'Recursive Computation: %.2f/s', perfdatas => [ { label => 'recursive_computation_rate', template => '%.2f', min => 0 }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } my $mbean_engine = "com.centreon.studio.map:type=engine,name=statistics"; sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = "centreon_map_" . md5_hex($options{custom}->{url}) . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); $self->{request} = [ { mbean => $mbean_engine } ]; my $result = $options{custom}->get_attributes(request => $self->{request}, nothing_quit => 0); $self->{global} = {}; $self->{global} = { DrilldownCandidatesQueue => $result->{$mbean_engine}->{DrilldownCandidatesQueue}, Cutbackcomputation => $result->{$mbean_engine}->{Cutbackcomputation}, Recursivecomputation => $result->{$mbean_engine}->{Recursivecomputation}, Minimalcomputation => $result->{$mbean_engine}->{Minimalcomputation}, }; } 1; __END__ =head1 MODE Check computation engine statistics. Example: perl centreon_plugins.pl --plugin=apps::centreon::map::jmx::plugin --custommode=jolokia --url=http://10.30.2.22:8080/jolokia-war --mode=engine-stats =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). (Example: --filter-counters='computation') =item B<--warning-*> Threshold warning. Can be: ''drilldown-candidates-queue', 'cutback-computation-rate', 'minimal-computation-rate', 'recursive-computation-rate'. =item B<--critical-*> Threshold critical. Can be: ''drilldown-candidates-queue', 'cutback-computation-rate', 'minimal-computation-rate', 'recursive-computation-rate'. =back =cut centreon-plugins-20220113/apps/centreon/map/jmx/mode/events.pm000066400000000000000000000112541417000230700241600ustar00rootroot00000000000000# Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::centreon::map::jmx::mode::events; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); my @map_counters = ( 'OPEN_GATE', 'CLOSE_GATE', 'ADD_RESOURCE', 'POLLER_RESTART', 'UPDATE_RESOURCE', 'SESSION_EXPIRED', 'UPDATE_ACL_CHILDREN', 'SYNC_CHILDREN', 'REMOVE_CHILD', 'UPDATE_STATUS_RESOURCE', 'REMOVE_RESOURCE', 'UPDATE_STATUS_INHERITED', 'ADD_CHILD', 'REMOVE_SELF', 'REMOVE_PARENT', 'ADD_PREFERENCE', 'CREATE_GATE', 'ADD_PARENT', 'UPDATE_ACL', 'REMOVE_PREFERENCE', 'UPDATE_SELF', 'ADD_SELF', 'DESYNC_CHILDREN', 'UPDATE_PREFERENCE', ); sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, ]; foreach my $counter (@map_counters) { my $label_perf = lc($counter); my $label = lc($counter); my $output = lc($counter); $label =~ s/_/-/g; $output =~ s/_/ /g; my $entry = { label => $label . '-rate', set => { key_values => [ { name => $counter, per_second => 1 } ], output_template => ucfirst($output) . ': %.2f/s', perfdatas => [ { label => $label_perf . '_rate', template => '%.2f', min => 0, unit => '/s' } ] } }; push @{$self->{maps_counters}->{global}}, $entry; } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } my $mbean_event = "com.centreon.studio.map:type=event,name=statistics"; sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = "centreon_map_" . md5_hex($options{custom}->{url}) . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); $self->{request} = [ { mbean => $mbean_event } ]; my $result = $options{custom}->get_attributes(request => $self->{request}, nothing_quit => 0); $self->{global} = {}; foreach my $counter (keys %{$result->{$mbean_event}->{EventCounter}}) { $self->{global}->{$counter} = $result->{$mbean_event}->{EventCounter}->{$counter}; } } 1; __END__ =head1 MODE Check event types rate. Example: perl centreon_plugins.pl --plugin=apps::centreon::map::jmx::plugin --custommode=jolokia --url=http://10.30.2.22:8080/jolokia-war --mode=events =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). (Example: --filter-counters='session') =item B<--warning-*> Threshold warning. Can be: 'open-gate-rate', 'close-gate-rate', 'add-resource-rate', 'poller-restart-rate', 'update-resource-rate', 'session-expired-rate', 'update-acl-children-rate', 'sync-children-rate', 'remove-child-rate', 'update-status-resource-rate', 'remove-resource-rate', 'update-status-inherited-rate', 'add-child-rate', 'remove-self-rate',' remove-parent-rate','add-preference-rate', 'create-gate-rate', 'add-parent-rate', 'update-acl-rate', 'remove-preference-rate', 'update-self-rate', 'add-self-rate', 'desync-children-rate', 'update-preference-rate'. =item B<--critical-*> Threshold critical. Can be: 'open-gate-rate', 'close-gate-rate', 'add-resource-rate', 'poller-restart-rate', 'update-resource-rate', 'session-expired-rate', 'update-acl-children-rate', 'sync-children-rate', 'remove-child-rate', 'update-status-resource-rate', 'remove-resource-rate', 'update-status-inherited-rate', 'add-child-rate', 'remove-self-rate',' remove-parent-rate','add-preference-rate', 'create-gate-rate', 'add-parent-rate', 'update-acl-rate', 'remove-preference-rate', 'update-self-rate', 'add-self-rate', 'desync-children-rate', 'update-preference-rate'. =back =cut centreon-plugins-20220113/apps/centreon/map/jmx/mode/openviews.pm000066400000000000000000000050721417000230700246740ustar00rootroot00000000000000# Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::centreon::map::jmx::mode::openviews; 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 }, ]; $self->{maps_counters}->{global} = [ { label => 'open-views', set => { key_values => [ { name => 'OpenContextCount' } ], output_template => 'Open Views: %d', perfdatas => [ { label => 'open_views', value => 'OpenContextCount', template => '%d', min => 0, unit => 'views' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } my $mbean_context = "com.centreon.studio.map:type=context,name=statistics"; sub manage_selection { my ($self, %options) = @_; $self->{request} = [ { mbean => $mbean_context } ]; my $result = $options{custom}->get_attributes(request => $self->{request}, nothing_quit => 0); $self->{global} = {}; $self->{global} = { OpenContextCount => $result->{$mbean_context}->{OpenContextCount}, }; } 1; __END__ =head1 MODE Check open views count. Example: perl centreon_plugins.pl --plugin=apps::centreon::map::jmx::plugin --custommode=jolokia --url=http://10.30.2.22:8080/jolokia-war --mode=open-views =over 8 =item B<--warning-*> Threshold warning. Can be: 'open-views'. =item B<--critical-*> Threshold critical. Can be: 'open-views'. =back =cut centreon-plugins-20220113/apps/centreon/map/jmx/mode/sessions.pm000066400000000000000000000065301417000230700245230ustar00rootroot00000000000000# Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::centreon::map::jmx::mode::sessions; 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 }, ]; $self->{maps_counters}->{global} = [ { label => 'active-session', set => { key_values => [ { name => 'SessionCount' } ], output_template => 'Active Sessions: %d', perfdatas => [ { label => 'active_sessions', value => 'SessionCount', template => '%d', min => 0, unit => 'sessions' }, ], } }, { label => 'queue-size', set => { key_values => [ { name => 'AverageEventQueueSize' } ], output_template => 'Average Event Queue Size: %d', perfdatas => [ { label => 'queue_size', value => 'AverageEventQueueSize', template => '%d', min => 0 }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-counters:s" => { name => 'filter_counters', default => '' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } my $mbean_session = "com.centreon.studio.map:type=session,name=statistics"; sub manage_selection { my ($self, %options) = @_; $self->{request} = [ { mbean => $mbean_session } ]; my $result = $options{custom}->get_attributes(request => $self->{request}, nothing_quit => 0); $self->{global} = {}; $self->{global} = { SessionCount => $result->{$mbean_session}->{SessionCount}, AverageEventQueueSize => $result->{$mbean_session}->{AverageEventQueueSize}, }; } 1; __END__ =head1 MODE Check active sessions count and the number of whatsup events by user session (queue size). Example: perl centreon_plugins.pl --plugin=apps::centreon::map::jmx::plugin --custommode=jolokia --url=http://10.30.2.22:8080/jolokia-war --mode=sessions =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). (Example: --filter-counters='session') =item B<--warning-*> Threshold warning. Can be: 'active-session', 'queue-size'. =item B<--critical-*> Threshold critical. Can be: 'active-session', 'queue-size'. =back =cut centreon-plugins-20220113/apps/centreon/map/jmx/mode/syncstats.pm000066400000000000000000000247551417000230700247210ustar00rootroot00000000000000# Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::centreon::map::jmx::mode::syncstats; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use JSON::XS; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'centreon', type => 0, cb_prefix_output => 'prefix_output_centreon' }, { name => 'acl', type => 1, cb_prefix_output => 'prefix_output_acl', message_multiple => 'All ACL synchronizations metrics are ok' }, { name => 'resource', type => 1, cb_prefix_output => 'prefix_output_resource', message_multiple => 'All resource synchronizations metrics are ok' }, ]; $self->{maps_counters}->{centreon} = [ { label => 'map-synchronization-centreon-count', nlabel => 'map.synchronization.centreon.count', set => { key_values => [ { name => 'count' } ], output_template => 'Count: %d', perfdatas => [ { label => 'map.synchronization.centreon.count', value => 'count', template => '%d', min => 0 }, ], } }, { label => 'map-synchronization-centreon-duration-average-milliseconds', nlabel => 'map.synchronization.centreon.duration.average.milliseconds', set => { key_values => [ { name => 'average' } ], output_template => 'Average Duration: %.2f ms', perfdatas => [ { label => 'map.synchronization.centreon.duration.average.milliseconds', value => 'average', template => '%.2f', min => 0, unit => 'ms' }, ], } }, { label => 'map-synchronization-centreon-duration-max-milliseconds', nlabel => 'map.synchronization.centreon.duration.max.milliseconds', set => { key_values => [ { name => 'max' } ], output_template => 'Max Duration: %.2f ms', perfdatas => [ { label => 'map.synchronization.centreon.duration.max.milliseconds', value => 'max', template => '%.2f', min => 0, unit => 'ms' }, ], } }, ]; $self->{maps_counters}->{acl} = [ { label => 'map-synchronization-acl-count', nlabel => 'map.synchronization.acl.count', set => { key_values => [ { name => 'count' }, { name => 'name' } ], output_template => 'Count: %d', perfdatas => [ { label => 'map.synchronization.acl.count', value => 'count', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'name' }, ], } }, { label => 'map-synchronization-acl-duration-average-milliseconds', nlabel => 'map.synchronization.acl.duration.average.milliseconds', set => { key_values => [ { name => 'average' }, { name => 'name' } ], output_template => 'Average Duration: %.2f ms', perfdatas => [ { label => 'map.synchronization.acl.duration.average.milliseconds', value => 'average', template => '%.2f', min => 0, unit => 'ms', label_extra_instance => 1, instance_use => 'name' }, ], } }, { label => 'map-synchronization-acl-duration-max-milliseconds', nlabel => 'map.synchronization.acl.duration.max.milliseconds', set => { key_values => [ { name => 'max' }, { name => 'name' } ], output_template => 'Max Duration: %.2f ms', perfdatas => [ { label => 'map.synchronization.acl.duration.max.milliseconds', value => 'max', template => '%.2f', min => 0, unit => 'ms', label_extra_instance => 1, instance_use => 'name' }, ], } }, ]; $self->{maps_counters}->{resource} = [ { label => 'map-synchronization-resource-count', nlabel => 'map.synchronization.resource.count', set => { key_values => [ { name => 'count' }, { name => 'name' } ], output_template => 'Count: %d', perfdatas => [ { label => 'map.synchronization.resource.count', value => 'count', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'name' }, ], } }, { label => 'map-synchronization-resource-duration-average-milliseconds', nlabel => 'map.synchronization.resource.duration.average.milliseconds', set => { key_values => [ { name => 'average' }, { name => 'name' } ], output_template => 'Average Duration: %.2f ms', perfdatas => [ { label => 'map.synchronization.resource.duration.average.milliseconds', value => 'average', template => '%.2f', min => 0, unit => 'ms', label_extra_instance => 1, instance_use => 'name' }, ], } }, { label => 'map-synchronization-resource-duration-max-milliseconds', nlabel => 'map.synchronization.resource.duration.max.milliseconds', set => { key_values => [ { name => 'max' }, { name => 'name' } ], output_template => 'Max Duration: %.2f ms', perfdatas => [ { label => 'map.synchronization.resource.duration.max.milliseconds', value => 'max', template => '%.2f', min => 0, unit => 'ms', label_extra_instance => 1, instance_use => 'name' }, ], } }, ]; } sub prefix_output_centreon { my ($self, %options) = @_; return "Centreon Synchronization "; } sub prefix_output_acl { my ($self, %options) = @_; return "ACL Synchronization '" . $options{instance_value}->{name} . "' "; } sub prefix_output_resource { my ($self, %options) = @_; return "Resource Synchronization '" . $options{instance_value}->{name} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } my $mbean_engine = "com.centreon.studio.map:type=synchronizer,name=statistics"; sub manage_selection { my ($self, %options) = @_; $self->{request} = [ { mbean => $mbean_engine } ]; my $result = $options{custom}->get_attributes(request => $self->{request}, nothing_quit => 0); $self->{centreon} = {}; $self->{acl} = {}; $self->{resource} = {}; my $decoded_centreon_stats; my $decoded_acl_stats; my $decoded_resource_stats; eval { $decoded_centreon_stats = JSON::XS->new->utf8->decode($result->{$mbean_engine}->{CentreonSyncStatistics}); $decoded_acl_stats = JSON::XS->new->utf8->decode($result->{$mbean_engine}->{AclSyncStatistics}); $decoded_resource_stats = JSON::XS->new->utf8->decode($result->{$mbean_engine}->{ResourceSyncStatistics}); }; if ($@) { $self->{output}->output_add(long_msg => $result, debug => 1); $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } $self->{centreon} = { count => $decoded_centreon_stats->{count}, average => $decoded_centreon_stats->{average}, max => ($decoded_centreon_stats->{count} == 0) ? 0 : $decoded_centreon_stats->{max}, }; foreach my $name (keys %{$decoded_acl_stats}) { $self->{acl}->{$name}= { name => $name, count => $decoded_acl_stats->{$name}->{count}, average => $decoded_acl_stats->{$name}->{average}, max => ($decoded_acl_stats->{$name}->{count} == 0) ? 0 : $decoded_acl_stats->{$name}->{max}, }; } foreach my $name (keys %{$decoded_resource_stats}) { $self->{resource}->{$name}= { name => $name, count => $decoded_resource_stats->{$name}->{count}, average => $decoded_resource_stats->{$name}->{average}, max => ($decoded_resource_stats->{$name}->{count} == 0) ? 0 : $decoded_resource_stats->{$name}->{max}, }; } } 1; __END__ =head1 MODE Check synchronizer statistics. Example: perl centreon_plugins.pl --plugin=apps::centreon::map::jmx::plugin --custommode=jolokia --url=http://10.30.2.22:8080/jolokia-war --mode=sync-stats =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). (Example: --filter-counters='centreon') =item B<--warning-*> Threshold warning. Can be: 'map-synchronization-centreon-count', 'map-synchronization-centreon-duration-average-milliseconds', 'map-synchronization-centreon-duration-max-milliseconds'. =item B<--critical-*> Threshold critical. Can be: 'map-synchronization-centreon-count', 'map-synchronization-centreon-duration-average-milliseconds', 'map-synchronization-centreon-duration-max-milliseconds'. =item B<--warning-instance-*> Threshold warning. Can be: 'map-synchronization-acl-count', 'map-synchronization-acl-duration-average-milliseconds', 'map-synchronization-acl-duration-max-milliseconds', 'map-synchronization-resource-count', 'map-synchronization-resource-duration-average-milliseconds', 'map-synchronization-resource-duration-max-milliseconds'. =item B<--critical-instance-*> Threshold critical. Can be: 'map-synchronization-acl-count', 'map-synchronization-acl-duration-average-milliseconds', 'map-synchronization-acl-duration-max-milliseconds', 'map-synchronization-resource-count', 'map-synchronization-resource-duration-average-milliseconds', 'map-synchronization-resource-duration-max-milliseconds'. =back =cut centreon-plugins-20220113/apps/centreon/map/jmx/plugin.pm000066400000000000000000000033341417000230700232260ustar00rootroot00000000000000# Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::centreon::map::jmx::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}} = ( 'broker-stats' => 'apps::centreon::map::jmx::mode::brokerstats', 'events' => 'apps::centreon::map::jmx::mode::events', 'engine-stats' => 'apps::centreon::map::jmx::mode::enginestats', 'open-views' => 'apps::centreon::map::jmx::mode::openviews', 'sessions' => 'apps::centreon::map::jmx::mode::sessions', 'sync-stats' => 'apps::centreon::map::jmx::mode::syncstats', ); $self->{custom_modes}{jolokia} = 'centreon::common::protocols::jmx::custom::jolokia'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check statistic counters of Centreon Map >= 18.10 (Needs Jolokia). =cut centreon-plugins-20220113/apps/centreon/map4/000077500000000000000000000000001417000230700206555ustar00rootroot00000000000000centreon-plugins-20220113/apps/centreon/map4/jmx/000077500000000000000000000000001417000230700214535ustar00rootroot00000000000000centreon-plugins-20220113/apps/centreon/map4/jmx/mode/000077500000000000000000000000001417000230700223775ustar00rootroot00000000000000centreon-plugins-20220113/apps/centreon/map4/jmx/mode/elements.pm000066400000000000000000000074361417000230700245630ustar00rootroot00000000000000# Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::centreon::map4::jmx::mode::elements; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "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) = @_; $self->{connector} = $options{custom}; $self->{request} = [ { mbean => "com.centreon.studio.map:name=BusinessElement,type=repo" } ]; my $result = $self->{connector}->get_attributes(request => $self->{request}, nothing_quit => 1); my $elements = $result->{"com.centreon.studio.map:name=BusinessElement,type=repo"}->{LoadedModelCount}; my $exit = $self->{perfdata}->threshold_check(value => $elements, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning'} ]); $self->{output}->output_add(severity => $exit, short_msg => sprintf("Element loaded : %d", $result->{"com.centreon.studio.map:name=BusinessElement,type=repo"}->{LoadedModelCount})); $self->{output}->perfdata_add(label => 'elements', value => $result->{"com.centreon.studio.map:name=BusinessElement,type=repo"}->{LoadedModelCount}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check Centreon Map Open Gates Example: perl centreon_plugins.pl --plugin=apps::centreon::map::jmx::plugin --custommode=jolokia --url=http://10.30.2.22:8080/jolokia-war --mode=elements =over 8 =item B<--warning> Set this threshold if you want a warning if opened gates match condition =item B<--critical> Set this threshold if you want a warning if opened gates match condition =back =cut centreon-plugins-20220113/apps/centreon/map4/jmx/mode/eventqueue.pm000066400000000000000000000074661417000230700251400ustar00rootroot00000000000000# Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::centreon::map4::jmx::mode::eventqueue; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "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) = @_; $self->{connector} = $options{custom}; $self->{request} = [ { mbean => "com.centreon.studio:name=statistics,type=session" } ]; my $result = $self->{connector}->get_attributes(request => $self->{request}, nothing_quit => 0); my $exit = $self->{perfdata}->threshold_check(value => $result->{"com.centreon.studio:name=statistics,type=session"}->{AverageEventQueueSize}, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning'} ]); $self->{output}->output_add(severity => $exit, short_msg => sprintf("Average event queue size : %d", $result->{"com.centreon.studio:name=statistics,type=session"}->{AverageEventQueueSize})); $self->{output}->perfdata_add(label => 'events', value => $result->{"com.centreon.studio:name=statistics,type=session"}->{AverageEventQueueSize}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check Centreon Map Session event queue size Example: perl centreon_plugins.pl --plugin=apps::centreon::map::jmx::plugin --custommode=jolokia --url=http://10.30.2.22:8080/jolokia-war --mode=event-queue =over 8 =item B<--warning> Set this threshold if you want a warning if global sessions event queue size match threshold =item B<--critical> Set this threshold if you want a warning if global sessions event queue size match threshold =back =cut centreon-plugins-20220113/apps/centreon/map4/jmx/mode/eventstatistics.pm000066400000000000000000000150231417000230700261720ustar00rootroot00000000000000# Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::centreon::map4::jmx::mode::eventstatistics; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::statefile; use Digest::MD5 qw(md5_hex); my %mapping_eventtype = ( 'EventCount' => 'global', 'EventTypeCreate' => 'create', 'EventTypeRemove' => 'remove', 'EventTypeUpdate' => 'update', ); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning-global:s" => { name => 'warning_global', }, "critical-global:s" => { name => 'critical_global', }, "warning-create:s" => { name => 'warning_create', }, "critical-create:s" => { name => 'critical_create', }, "warning-update:s" => { name => 'warning_update', }, "critical-update:s" => { name => 'critical_update', }, "warning-remove:s" => { name => 'warning_remove', }, "critical-remove:s" => { name => 'critical_remove', }, }); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); foreach my $label ('warning_global', 'critical_global', 'warning_create', 'critical_create', 'warning_update', 'critical_update', 'warning_remove', 'critical_remove') { if (($self->{perfdata}->threshold_validate(label => $label, value => $self->{option_results}->{$label})) == 0) { my ($label_opt) = $label; $label_opt =~ tr/_/-/; $self->{output}->add_option_msg(short_msg => "Wrong " . $label_opt . " threshold '" . $self->{option_results}->{$label} . "'."); $self->{output}->option_exit(); } } $self->{statefile_cache}->check_options(%options); } sub run { my ($self, %options) = @_; $self->{connector} = $options{custom}; $self->{request} = [ { mbean => "com.centreon.studio.map:name=statistics,type=whatsup" } ]; my $result = $self->{connector}->get_attributes(request => $self->{request}, nothing_quit => 0); my $new_datas = {}; $self->{statefile_cache}->read(statefile => 'centreon_map_' . $self->{mode} . '-' . md5_hex($self->{connector}->{url})); my $old_timestamp = $self->{statefile_cache}->get(name => 'last_timestamp'); $new_datas->{last_timestamp} = time(); if (defined($old_timestamp) && $new_datas->{last_timestamp} - $old_timestamp == 0) { $self->{output}->add_option_msg(short_msg => "Need at least one second between two checks."); $self->{output}->option_exit(); } foreach my $type ('EventCount', 'EventTypeCreate', 'EventTypeUpdate', 'EventTypeRemove') { $new_datas->{$type} = $result->{"com.centreon.studio.map:name=statistics,type=whatsup"}->{$type}->{andIncrement}; my $old_val = $self->{statefile_cache}->get(name => $type); next if (!defined($old_val) || $result->{"com.centreon.studio.map:name=statistics,type=whatsup"}->{$type}->{andIncrement} < $old_val); my $value = int(($result->{"com.centreon.studio.map:name=statistics,type=whatsup"}->{$type}->{andIncrement} - $old_val) / ($new_datas->{last_timestamp} - $old_timestamp)); $self->{output}->perfdata_add(label => $type, value => $value, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning_' . $mapping_eventtype{$type}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical_' . $mapping_eventtype{$type}), min => 0); my $exit = $self->{perfdata}->threshold_check(value => $value, threshold => [ { label => 'critical_' . $mapping_eventtype{$type}, exit_litteral => 'critical' }, { label => 'warning_' . $mapping_eventtype{$type}, exit_litteral => 'warning' } ]); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("%s = %d", $type, $value)); } $self->{output}->output_add(severity => 'ok', short_msg => sprintf("%s = %s", $type, $value)); } $self->{statefile_cache}->write(data => $new_datas); if (!defined($old_timestamp)) { $self->{output}->output_add(severity => 'OK', short_msg => "Buffer creation..."); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check Centreon Map Event Statistics Example: perl centreon_plugins.pl --plugin=apps::centreon::jmx::map::plugin --custommode=jolokia --url=http://10.30.2.22:8080/jolokia-war --mode=event-statistics =over 8 =item B<--warning-global> Warning threshold for global event count =item B<--critical-global> Critical threshold for global event count =item B<--warning-create> Warning threshold for create event count =item B<--critical-create> Critical threshold for create event count =item B<--warning-update> Warning threshold for update event count =item B<--critical-update> Critical threshold for update event count =item B<--warning-remove> Warning threshold for remove event count =item B<--critical-remove> Critical threshold for remove event count =back =cut centreon-plugins-20220113/apps/centreon/map4/jmx/mode/gates.pm000066400000000000000000000074161417000230700240500ustar00rootroot00000000000000# Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::centreon::map4::jmx::mode::gates; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "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) = @_; $self->{connector} = $options{custom}; $self->{request} = [ { mbean => "com.centreon.studio.map:name=statistics,type=context" } ]; my $result = $self->{connector}->get_attributes(request => $self->{request}, nothing_quit => 1); my $gates = $result->{"com.centreon.studio.map:name=statistics,type=context"}->{OpenContextCount}; my $exit = $self->{perfdata}->threshold_check(value => $gates, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning'} ]); $self->{output}->output_add(severity => $exit, short_msg => sprintf("Business gates opened : %d", $result->{"com.centreon.studio.map:name=statistics,type=context"}->{OpenContextCount})); $self->{output}->perfdata_add(label => 'gates', value => $result->{"com.centreon.studio.map:name=statistics,type=context"}->{OpenContextCount}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check Centreon Map Open Gates Example: perl centreon_plugins.pl --plugin=apps::centreon::map::jmx::plugin --custommode=jolokia --url=http://10.30.2.22:8080/jolokia-war --mode=gates =over 8 =item B<--warning> Set this threshold if you want a warning if opened gates match condition =item B<--critical> Set this threshold if you want a warning if opened gates match condition =back =cut centreon-plugins-20220113/apps/centreon/map4/jmx/mode/sessions.pm000066400000000000000000000073651417000230700246160ustar00rootroot00000000000000# Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::centreon::map4::jmx::mode::sessions; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "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) = @_; $self->{connector} = $options{custom}; $self->{request} = [ { mbean => "com.centreon.studio:name=statistics,type=session" } ]; my $result = $self->{connector}->get_attributes(request => $self->{request}, nothing_quit => 0); my $exit = $self->{perfdata}->threshold_check(value => $result->{"com.centreon.studio:name=statistics,type=session"}->{SessionCount}, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning'} ]); $self->{output}->output_add(severity => $exit, short_msg => sprintf("Current sessions : %d", $result->{"com.centreon.studio:name=statistics,type=session"}->{SessionCount})); $self->{output}->perfdata_add(label => 'sessions', value => $result->{"com.centreon.studio:name=statistics,type=session"}->{SessionCount}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check Centreon Map Number of sessions Example: perl centreon_plugins.pl --plugin=apps::centreon::map::jmx::plugin --custommode=jolokia --url=http://10.30.2.22:8080/jolokia-war --mode=sessions =over 8 =item B<--warning> Set this threshold if you want a warning if current session number match condition =item B<--critical> Set this threshold if you want a warning if current session number match condition =back =cut centreon-plugins-20220113/apps/centreon/map4/jmx/plugin.pm000066400000000000000000000032251417000230700233110ustar00rootroot00000000000000# Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::centreon::map4::jmx::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}} = ( 'elements' => 'apps::centreon::map4::jmx::mode::elements', 'event-queue' => 'apps::centreon::map4::jmx::mode::eventqueue', 'event-statistics' => 'apps::centreon::map4::jmx::mode::eventstatistics', 'gates' => 'apps::centreon::map4::jmx::mode::gates', 'sessions' => 'apps::centreon::map4::jmx::mode::sessions', ); $self->{custom_modes}{jolokia} = 'centreon::common::protocols::jmx::custom::jolokia'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Centreon Map 4 informations. Need Jolokia agent and Map >= 4.0. =cut centreon-plugins-20220113/apps/centreon/restapi/000077500000000000000000000000001417000230700214635ustar00rootroot00000000000000centreon-plugins-20220113/apps/centreon/restapi/custom/000077500000000000000000000000001417000230700227755ustar00rootroot00000000000000centreon-plugins-20220113/apps/centreon/restapi/custom/api.pm000066400000000000000000000200141417000230700241010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::centreon::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use centreon::plugins::statefile; use JSON::XS; use Digest::MD5 qw(md5_hex); 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'api-username:s' => { name => 'api_username' }, 'api-password:s' => { name => 'api_password' }, 'api-path:s' => { name => 'api_path' }, 'timeout:s' => { name => 'timeout' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); $self->{cache} = centreon::plugins::statefile->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : undef; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'http'; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 80; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : undef; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : undef; $self->{api_path} = (defined($self->{option_results}->{api_path})) ? $self->{option_results}->{api_path} : '/centreon/api/index.php'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; if (!defined($self->{hostname}) || $self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } if (!defined($self->{api_username}) || $self->{api_username} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-username option."); $self->{output}->option_exit(); } if (!defined($self->{api_password}) || $self->{api_password} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-password option."); $self->{output}->option_exit(); } $self->{cache}->check_options(option_results => $self->{option_results}); return 0; } sub get_connection_infos { my ($self, %options) = @_; return $self->{hostname} . '_' . $self->{http}->get_port(); } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); if (defined($self->{auth_token})) { $self->{http}->add_header(key => 'Centreon-Auth-Token', value => $self->{auth_token}); } $self->{http}->set_options(%{$self->{option_results}}); } sub get_auth_token { my ($self, %options) = @_; my $has_cache_file = $options{statefile}->read(statefile => 'centreon_api_' . md5_hex($self->{hostname}) . '_' . md5_hex($self->{api_username})); my $expires_on = $options{statefile}->get(name => 'expires_on'); my $auth_token = $options{statefile}->get(name => 'auth_token'); if ($has_cache_file == 0 || !defined($auth_token) || (($expires_on - time()) < 10)) { my $post_param = [ 'username=' . $self->{api_username}, 'password=' . $self->{api_password} ]; $self->settings(); my $content = $self->{http}->request( method => 'POST', url_path => '/centreon/api/index.php?action=authenticate', post_param => $post_param ); my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response"); $self->{output}->option_exit(); } if (!defined($decoded->{authToken})) { $self->{output}->add_option_msg(short_msg => "Cannot get token"); $self->{output}->option_exit(); } $auth_token = $decoded->{authToken}; my $datas = { last_timestamp => time(), auth_token => $decoded->{authToken}, expires_on => time() + 3600 }; $options{statefile}->write(data => $datas); } return $auth_token; } sub request_api { my ($self, %options) = @_; if (!defined($self->{auth_token})) { $self->{auth_token} = $self->get_auth_token(statefile => $self->{cache}); } $self->settings(); my $encoded_form_post; eval { $encoded_form_post = JSON::XS->new->utf8->encode($options{query_form_post}); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot encode json request"); $self->{output}->option_exit(); } my $content = $self->{http}->request( method => $options{method}, url_path => $options{url_path}, query_form_post => $encoded_form_post, header => $options{header}, critical_status => '', warning_status => '', unknown_status => '' ); my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response"); $self->{output}->option_exit(); } return ($decoded, JSON::XS->new->utf8->pretty->encode($decoded)); } sub submit_result { my ($self, %options) = @_; my ($response, $raw) = $self->request_api( method => 'POST', url_path => $self->{api_path} . '?action=submit&object=centreon_submit_results', query_form_post => $options{post_data}, header => ['Content-Type: application/json'] ); return ($response, $raw); } 1; __END__ =head1 NAME Centreon REST API =head1 SYNOPSIS Centreon Rest API custom mode =head1 REST API OPTIONS =over 8 =item B<--hostname> Centreon hostname. =item B<--port> Port used (Default: 80) =item B<--proto> Specify https if needed (Default: 'http') =item B<--api-username> Centreon username. =item B<--api-password> Centreon password. =item B<--api-path> API base url path (Default: '/centreon/api/index.php'). =item B<--timeout> Set HTTP timeout in seconds (Default: '10'). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/centreon/restapi/mode/000077500000000000000000000000001417000230700224075ustar00rootroot00000000000000centreon-plugins-20220113/apps/centreon/restapi/mode/submitresult.pm000066400000000000000000000103261417000230700255110ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::centreon::restapi::mode::submitresult; 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, cb_prefix_output => 'prefix_output', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ { label => 'results-202', nlabel => 'results.202.count', set => { key_values => [ { name => '202' } ], output_template => '202: %d', perfdatas => [ { template => '%d', min => 0 } ] } }, { label => 'results-400', nlabel => 'results.400.count', set => { key_values => [ { name => '400' } ], output_template => '400: %d', perfdatas => [ { template => '%d', min => 0 } ] } }, { label => 'results-404', nlabel => 'results.404.count', set => { key_values => [ { name => '404' } ], output_template => '404: %d', perfdatas => [ { template => '%d', min => 0 } ] } } ]; } sub prefix_output { my ($self, %options) = @_; return "Results "; } 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 => { 'host:s@' => { name => 'host' }, 'service:s@' => { name => 'service' }, 'status:s@' => { name => 'status' }, 'output:s@' => { name => 'output' }, 'perfdata:s@' => { name => 'perfdata' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $post_data; my $i = 0; foreach (@{$self->{option_results}->{host}}) { my %result; $result{updatetime} = time(); $result{host} = $_; $result{service} = ${$self->{option_results}->{service}}[$i] if (defined(${$self->{option_results}->{service}}[$i])); $result{status} = ${$self->{option_results}->{status}}[$i]; $result{output} = ${$self->{option_results}->{output}}[$i]; $result{perfdata} = ${$self->{option_results}->{perfdata}}[$i] if (defined(${$self->{option_results}->{perfdata}}[$i])); push @{$post_data->{results}}, \%result; $i++; } my ($response, $raw) = $options{custom}->submit_result(post_data => $post_data); $self->{global} = { 202 => 0, 400 => 0, 404 => 0 }; foreach my $result (@{$response->{results}}) { $self->{global}->{$result->{code}}++; } $self->{output}->output_add(long_msg => $raw); } 1; __END__ =head1 MODE Submit one or several results to the API. Examples: perl centreon_plugins --plugin=apps::centreon::restapi::plugin --mode=submit-result --hostname=10.30.2.245 --api-username=admin --api-password=centreon --host='MyHost' --service='TheService' --status=2 --output='Hi!' --perfdata='france=3,brazil=0' --verbose =over 8 =item B<--host> Hostname (Mandatory). =item B<--service> Service description (If result's for a service). =item B<--status> Status in 0, 1, 2, 3 or ok, warning, critical, unknown for services, or in 0, 1 or up, down for hosts (Mandatory). =item B<--output> Short output (Mandatory). =item B<--perfdata> Comma separated list of perfdata (Optionnal). =back =cut centreon-plugins-20220113/apps/centreon/restapi/plugin.pm000066400000000000000000000024631417000230700233240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::centreon::restapi::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}} = ( 'submit-result' => 'apps::centreon::restapi::mode::submitresult', ); $self->{custom_modes}{api} = 'apps::centreon::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Interacts with Centreon RestAPI. =cut centreon-plugins-20220113/apps/centreon/sql/000077500000000000000000000000001417000230700206135ustar00rootroot00000000000000centreon-plugins-20220113/apps/centreon/sql/mode/000077500000000000000000000000001417000230700215375ustar00rootroot00000000000000centreon-plugins-20220113/apps/centreon/sql/mode/countnotifications.pm000066400000000000000000000117301417000230700260210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::centreon::sql::mode::countnotifications; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::statefile; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); 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' }, }); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); 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(); } $self->{statefile_cache}->check_options(%options); } sub execute { my ($self, %options) = @_; $self->{sql}->connect(); $self->{sql}->query(query => "SELECT name, count(NULLIF(log_id, 0)) as num FROM " . $self->{option_results}->{centreon_storage_database} . ".instances LEFT JOIN " . $self->{option_results}->{centreon_storage_database} . ".logs ON logs.ctime > " . $options{time} . " AND logs.msg_type IN ('2', '3') AND logs.instance_name = instances.name WHERE deleted = '0' GROUP BY name"); my $total_notifications = 0; 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); } 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); } sub run { my ($self, %options) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{statefile_cache}->read(statefile => 'sql_' . $self->{mode} . '_' . $self->{sql}->get_unique_id4save()); my $old_timestamp = $self->{statefile_cache}->get(name => 'last_timestamp'); my $new_datas = { last_timestamp => time() }; $self->{statefile_cache}->write(data => $new_datas); if (!defined($old_timestamp)) { $self->{output}->output_add(severity => 'OK', short_msg => "Buffer creation..."); } else { $self->execute(time => $old_timestamp); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check the number of notifications (works only with centreon-broker). The mode should be used with mysql plugin and dyn-mode option. =over 8 =item B<--centreon-storage-database> Centreon storage database name (default: 'centreon_storage'). =item B<--warning> Threshold warning. =item B<--critical> Threshold critical. =back =cut centreon-plugins-20220113/apps/centreon/sql/mode/countproblems.pm000066400000000000000000000153631417000230700250010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::centreon::sql::mode::countproblems; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::statefile; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); 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' }, }); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); 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(); } $self->{statefile_cache}->check_options(%options); } sub execute { my ($self, %options) = @_; $self->{sql}->connect(); $self->{sql}->query(query => "SELECT name, msg_type, status, count(NULLIF(log_id, 0)) as num FROM " . $self->{option_results}->{centreon_storage_database} . ".instances LEFT JOIN " . $self->{option_results}->{centreon_storage_database} . ".logs ON logs.ctime > " . $options{time} . " AND logs.msg_type IN ('0', '1') AND type = '1' AND status NOT IN ('0') AND logs.instance_name = instances.name WHERE deleted = '0' GROUP BY name, msg_type, status"); my $total_problems = { total => 0, hosts => 0, services => 0 }; my $total_problems_by_poller = {}; 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 } }; } if ($row->{num} != 0 && defined($total_problems_by_poller->{$row->{name}}->{$row->{msg_type} . '_' . $row->{status}})) { $total_problems_by_poller->{$row->{name}}->{$row->{msg_type} . '_' . $row->{status}}->{num} = $row->{num}; if ($row->{msg_type} == 0) { $total_problems->{hosts} += $row->{num}; } else { $total_problems->{services} += $row->{num}; } $total_problems->{total} += $row->{num}; } } $self->{output}->output_add(long_msg => sprintf("%d total hosts problems", $total_problems->{services})); $self->{output}->output_add(long_msg => sprintf("%d total services problems", $total_problems->{services})); foreach my $poller (sort keys %{$total_problems_by_poller}) { foreach my $id (sort keys %{$total_problems_by_poller->{$poller}}) { $self->{output}->output_add( long_msg => sprintf( "%d %s problems on %s", $total_problems_by_poller->{$poller}->{$id}->{num}, $total_problems_by_poller->{$poller}->{$id}->{label}, $poller ) ); $self->{output}->perfdata_add( label => $total_problems_by_poller->{$poller}->{$id}->{label_perf} . "_" . $poller, value => $total_problems_by_poller->{$poller}->{$id}->{num}, min => 0 ); } } 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}->perfdata_add( label => 'total', 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', value => $total_problems->{hosts}, min => 0); $self->{output}->perfdata_add( label => 'total_services', value => $total_problems->{services}, min => 0 ); } sub run { my ($self, %options) = @_; $self->{sql} = $options{sql}; $self->{statefile_cache}->read(statefile => 'sql_' . $self->{mode} . '_' . $self->{sql}->get_unique_id4save()); my $old_timestamp = $self->{statefile_cache}->get(name => 'last_timestamp'); my $new_datas = { last_timestamp => time() }; $self->{statefile_cache}->write(data => $new_datas); if (!defined($old_timestamp)) { $self->{output}->output_add(severity => 'OK', short_msg => "Buffer creation..."); } else { $self->execute(time => $old_timestamp); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check the number of problems (works only with centreon-broker). The mode should be used with mysql plugin and dyn-mode option. =over 8 =item B<--centreon-storage-database> Centreon storage database name (default: 'centreon_storage'). =item B<--warning> Threshold warning. =item B<--critical> Threshold critical. =back =cut centreon-plugins-20220113/apps/centreon/sql/mode/countservices.pm000066400000000000000000000110141417000230700247660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::centreon::sql::mode::countservices; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'poller', type => 1, cb_prefix_output => 'prefix_poller_output', message_multiple => 'All poller hosts/services are ok' } ]; $self->{maps_counters}->{poller} = [ { label => 'host', nlabel => 'centreon.hosts.count', set => { key_values => [ { name => 'hosts' }, { name => 'display' } ], output_template => 'Number of hosts : %s', perfdatas => [ { label => 'total_hosts', value => 'hosts', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, { label => 'service', nlabel => 'centreon.services.count', set => { key_values => [ { name => 'services' }, { name => 'display' } ], output_template => 'Number of services : %s', perfdatas => [ { label => 'total_services', value => 'services', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, ]; } sub prefix_poller_output { my ($self, %options) = @_; return "Poller '" . $options{instance_value}->{display} . "' "; } 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' }, }); return $self; } sub manage_selection { my ($self, %options) = @_; my $query = "SELECT instances.name, COUNT(DISTINCT hosts.host_id) as num_hosts, count(DISTINCT services.host_id, services.service_id) as num_services FROM " . $self->{option_results}->{centreon_storage_database} . ".instances, " . $self->{option_results}->{centreon_storage_database} . ".hosts, " . $self->{option_results}->{centreon_storage_database} . ".services WHERE instances.running = '1' AND instances.instance_id = hosts.instance_id AND hosts.enabled = '1' AND hosts.host_id = services.host_id AND services.enabled = '1' GROUP BY hosts.instance_id"; $options{sql}->connect(); $options{sql}->query(query => $query); # check by poller $self->{poller} = {}; while ((my $row = $options{sql}->fetchrow_hashref())) { if (defined($self->{option_results}->{filter_poller}) && $self->{option_results}->{filter_poller} ne '' && $row->{name} !~ /$self->{option_results}->{filter_poller}/) { $self->{output}->output_add(long_msg => "Skipping '" . $row->{name} . "': no matching filter.", debug => 1); next; } $self->{poller}->{$row->{name}} = { display => $row->{name}, hosts => $row->{num_hosts}, services => $row->{num_services} }; } if (scalar(keys %{$self->{poller}}) == 0) { $self->{output}->add_option_msg(short_msg => "No poller found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check the number of hosts/services by poller. =over 8 =item B<--centreon-storage-database> Centreon storage database name (default: 'centreon_storage'). =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^services$' =item B<--warning-*> Threshold warning. Can be: 'host', 'service'. =item B<--critical-*> Threshold critical. Can be: Can be: 'host', 'service'. =item B<--filter-poller> Filter by poller name (regexp can be used). =back =cut centreon-plugins-20220113/apps/centreon/sql/mode/dsmqueue.pm000066400000000000000000000134451417000230700237340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::centreon::sql::mode::dsmqueue; 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 }, { name => 'host', type => 1, cb_prefix_output => 'prefix_host_output', message_multiple => 'All host queues are ok' }, ]; $self->{maps_counters}->{global} = [ { label => 'total-queue-cache', nlabel => 'centreon.dsm.queue.cache.count', set => { key_values => [ { name => 'total_queue_cache' } ], output_template => 'Total current cache queue : %s', perfdatas => [ { label => 'total_queue_cache', value => 'total_queue_cache', template => '%s', min => 0 }, ], } }, { label => 'total-queue-lock', nlabel => 'centreon.dsm.queue.lock.count', set => { key_values => [ { name => 'total_queue_lock' } ], output_template => 'Total current lock queue : %s', perfdatas => [ { label => 'total_queue_lock', value => 'total_queue_lock', template => '%s', min => 0 }, ], } }, ]; $self->{maps_counters}->{host} = [ { label => 'host-queue-cache', nlabel => 'centreon.dsm.host.queue.cache.count', set => { key_values => [ { name => 'num' }, { name => 'display' } ], output_template => 'current cache queue : %s', perfdatas => [ { label => 'host_queue_cache', value => 'num', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, ]; } sub prefix_host_output { my ($self, %options) = @_; return "Host '" . $options{instance_value}->{display} . "' "; } 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-host-queue:s" => { name => 'filter_host_queue' }, "centreon-storage-database:s" => { name => 'centreon_storage_database', default => 'centreon_storage' }, "centreon-database:s" => { name => 'centreon_database', default => 'centreon' }, }); return $self; } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); $self->{global} = { total_queue_cache => 0, total_queue_lock => 0 }; my $query = "SELECT COUNT(*) as nb FROM " . $self->{option_results}->{centreon_storage_database} . ".mod_dsm_cache"; $options{sql}->query(query => $query); if ((my $row = $options{sql}->fetchrow_hashref())) { $self->{global}->{total_queue_cache} = $row->{nb}; } $query = "SELECT COUNT(*) as nb FROM " . $self->{option_results}->{centreon_storage_database} . ".mod_dsm_locks"; $options{sql}->query(query => $query); if ((my $row = $options{sql}->fetchrow_hashref())) { $self->{global}->{total_queue_lock} = $row->{nb}; } # check by poller $self->{host} = {}; $query = "SELECT mod_dsm_pool.pool_host_id, mod_dsm_pool.pool_prefix, COUNT(*) as nb FROM " . $self->{option_results}->{centreon_database} . ".mod_dsm_pool" . " LEFT JOIN " . $self->{option_results}->{centreon_storage_database} . ".mod_dsm_cache ON mod_dsm_pool.pool_host_id = mod_dsm_cache.host_id AND mod_dsm_pool.pool_prefix = mod_dsm_cache.pool_prefix" . " GROUP BY mod_dsm_pool.pool_host_id, mod_dsm_pool.pool_prefix"; $options{sql}->query(query => $query); while ((my $row = $options{sql}->fetchrow_hashref())) { my $name = $row->{pool_host_id} . '/' . $row->{pool_prefix}; if (defined($self->{option_results}->{filter_host_queue}) && $self->{option_results}->{filter_host_queue} ne '' && $name !~ /$self->{option_results}->{filter_host_queue}/) { $self->{output}->output_add(long_msg => "Skipping '" . $row->{name} . "': no matching filter.", debug => 1); next; } $self->{host}->{$name} = { display => $name, num => $row->{nb} }; } } 1; __END__ =head1 MODE Check Centreon DSM queue usage. =over 8 =item B<--centreon-storage-database> Centreon storage database name (default: 'centreon_storage'). =item B<--centreon-database> Centreon storage database name (default: 'centreon'). =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^total-queue-cache$' =item B<--warning-*> Threshold warning. Can be: Can be: 'total-queue-cache', 'total-queue-lock', 'host-queue-cache'. =item B<--critical-*> Threshold critical. Can be: Can be: 'total-queue-cache', 'total-queue-lock', 'host-queue-cache'. =item B<--filter-host-queue> Filter by host and pool prefix name (regexp can be used). Example: host1.queue1 =back =cut centreon-plugins-20220113/apps/centreon/sql/mode/multiservices.pm000066400000000000000000000537121417000230700250030ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::centreon::sql::mode::multiservices; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use JSON; 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) = @_; return "[up:".$self->{result_values}->{total_up}."][down:".$self->{result_values}->{total_down}."][unreachable:".$self->{result_values}->{total_unreachable}."]"; } 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 $status = 'ok'; if (defined($self->{instance_mode}->{option_results}->{critical_total}) && $self->{instance_mode}->{option_results}->{critical_total} ne '' && $self->eval(value => $self->{instance_mode}->{option_results}->{critical_total})) { $status = 'critical'; } elsif (defined($self->{instance_mode}->{option_results}->{warning_total}) && $self->{instance_mode}->{option_results}->{warning_total} ne '' && $self->eval(value => $self->{instance_mode}->{option_results}->{warning_total})) { $status = 'warning'; } return $status; } sub custom_services_calc { my ($self, %options) = @_; $self->{result_values}->{ok_total} = $options{new_datas}->{$self->{instance} . '_ok'}; $self->{result_values}->{warning_total} = $options{new_datas}->{$self->{instance} . '_warning'}; $self->{result_values}->{critical_total} = $options{new_datas}->{$self->{instance} . '_critical'}; $self->{result_values}->{unknown_total} = $options{new_datas}->{$self->{instance} . '_unknown'}; return 0 } sub custom_services_output { my ($self, %options) = @_; my $msg .= "[ok:$self->{result_values}->{ok_total}][warning:$self->{result_values}->{warning_total}][critical:$self->{result_values}->{critical_total}][unknown:$self->{result_values}->{unknown_total}]\n"; return $msg } sub custom_services_perfdata { my ($self, %options) = @_; foreach my $sstate ('ok', 'warning', 'critical', 'unknown') { $self->{output}->perfdata_add( label => 'total_service_' . $sstate, value => $self->{result_values}->{$sstate . '_total'}, min => 0 ); } } sub custom_services_threshold { my ($self, %options) = @_; my $status = 'ok'; if (defined($self->{instance_mode}->{option_results}->{critical_total}) && $self->{instance_mode}->{option_results}->{critical_total} ne '' && $self->eval(value => $self->{instance_mode}->{option_results}->{critical_total})) { $status = 'critical'; } elsif (defined($self->{instance_mode}->{option_results}->{warning_total}) && $self->{instance_mode}->{option_results}->{warning_total} ne '' && $self->eval(value => $self->{instance_mode}->{option_results}->{warning_total})) { $status = 'warning'; } 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 = ''; if ($config_data->{formatting}->{display_details} eq 'true') { $msg_host .= (defined($self->{instance_mode}->{inventory}->{groups}->{$self->{result_values}->{instance}}->{list_up})) ? "HOSTS: [up: $self->{result_values}->{up} (" . join(' - ', @{$self->{instance_mode}->{inventory}->{groups}->{$self->{result_values}->{instance}}->{list_up}}) . ")]" : "HOSTS: [up: $self->{result_values}->{up}]"; $msg_host .= (defined($self->{instance_mode}->{inventory}->{groups}->{$self->{result_values}->{instance}}->{list_down})) ? "[down: $self->{result_values}->{down} (" . join(' - ', @{$self->{instance_mode}->{inventory}->{groups}->{$self->{result_values}->{instance}}->{list_down}}) . ")]" : "[down: $self->{result_values}->{down}]"; $msg_host .= (defined($self->{instance_mode}->{inventory}->{groups}->{unreachable}->{$self->{result_values}->{instance}}->{list_unreachable})) ? "[unreachable: $self->{result_values}->{unreachable} (" . join('-', @{$self->{instance_mode}->{inventory}->{groups}->{$self->{result_values}->{instance}}->{list_unreachable}}) . ")" : "[unreachable: $self->{result_values}->{unreachable}]"; $msg_svc .= (defined($self->{instance_mode}->{inventory}->{groups}->{$self->{result_values}->{instance}}->{list_ok})) ? "SERVICES: [ok: $self->{result_values}->{ok} (" . join(' - ', @{$self->{instance_mode}->{inventory}->{groups}->{$self->{result_values}->{instance}}->{list_ok}}) .")]" : "SERVICES: [ok: $self->{result_values}->{ok}]"; $msg_svc .= (defined($self->{instance_mode}->{inventory}->{groups}->{$self->{result_values}->{instance}}->{list_warning})) ? "[warning: $self->{result_values}->{warning} (" . join(' - ', @{$self->{instance_mode}->{inventory}->{groups}->{$self->{result_values}->{instance}}->{list_warning}}) .")]" : "[warning: $self->{result_values}->{warning}]"; $msg_svc .= (defined($self->{instance_mode}->{inventory}->{groups}->{$self->{result_values}->{instance}}->{list_critical}) > 0) ? "[critical: $self->{result_values}->{critical} (" . join(' - ', @{$self->{instance_mode}->{inventory}->{groups}->{$self->{result_values}->{instance}}->{list_critical}}) .")]" : "[critical: $self->{result_values}->{critical}]"; $msg_svc .= (defined($self->{instance_mode}->{inventory}->{groups}->{$self->{result_values}->{instance}}->{list_unknown}) > 0) ? "[unknown: $self->{result_values}->{unknown} (" . join(' - ', @{$self->{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'; if (defined($self->{instance_mode}->{option_results}->{critical_groups}) && $self->{instance_mode}->{option_results}->{critical_groups} ne '' && $self->eval(value => $self->{instance_mode}->{option_results}->{critical_groups})) { $status = 'critical'; } elsif (defined($self->{instance_mode}->{option_results}->{warning_groups}) && $self->{instance_mode}->{option_results}->{warning_groups} ne '' && $self->eval(value => $self->{instance_mode}->{option_results}->{warning_groups})) { $status = 'warning'; } 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; $options{options}->add_options(arguments => { 'config:s' => { name => 'config' }, '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); 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 (!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->{counters}->{totalhosts})) { $config_data->{counters}->{totalhosts} = 'true'; } if (!exists($config_data->{counters}->{totalservices})) { $config_data->{counters}->{totalservices} = 'true'; } if (!exists($config_data->{counters}->{groups})) { $config_data->{counters}->{groups} = 'false'; } 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(macros => ['warning_groups', 'critical_groups', 'warning_total', 'critical_total']); } 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, $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 } 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($self->{instance_mode}->{inventory}->{hosts}->{$group}->{$row->{name}})) { push @{$self->{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 @{$self->{instance_mode}->{inventory}->{groups}->{$group}->{'list_'.$map_service_state{$row->{sstate}}}}, $row->{name} . ${config_data}->{formatting}->{host_service_separator} . $row->{description}; $self->{instance_mode}->{inventory}->{hosts}->{$group}->{$row->{name}} = $row->{hstate}; $self->{instance_mode}->{inventory}->{services}{ $row->{name} . ${config_data}->{formatting}->{host_service_separator} . $row->{description} } = { state => $row->{sstate}, output => $row->{soutput} } ; $self->{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($self->{instance_mode}->{inventory}->{hosts}->{$group}->{$row->{name}})) { push @{$self->{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 @{$self->{instance_mode}->{inventory}->{groups}->{$group}->{'list_'.$map_service_state{$row->{sstate}}}}, $row->{name} . ${config_data}->{formatting}->{host_service_separator} . $row->{description}; $self->{instance_mode}->{inventory}->{hosts}->{$group}->{$row->{name}} = $row->{hstate}; $self->{instance_mode}->{inventory}->{services}{ $row->{name} . ${config_data}->{formatting}->{host_service_separator} . $row->{description} } = { state => $row->{sstate}, output => $row->{soutput} } ; $self->{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> Specify the config (can be a file or a json string directly). =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 && %{critical_total} > 4' =item B<--critical-*> Can be 'total' for host and service, 'groups' for groups =back =cut centreon-plugins-20220113/apps/centreon/sql/mode/partitioning.pm000066400000000000000000000125561417000230700246150ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::centreon::sql::mode::partitioning; use base qw(centreon::plugins::mode); use strict; use warnings; use POSIX; sub new { my ($class, %options) = @_; 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' }, }); 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->{warn1} . "'."); $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->{critical} . "'."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{tablename}) || scalar(@{$self->{option_results}->{tablename}}) == 0) { $self->{output}->add_option_msg(short_msg => "Please set tablename option."); $self->{output}->option_exit(); } if (defined($self->{option_results}->{timezone}) && $self->{option_results}->{timezone} ne '') { $ENV{TZ} = $self->{option_results}->{timezone}; } } sub run { my ($self, %options) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); $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)); 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)); 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); while ($current_time < $last_time) { $retention_forward_current++; $current_time = mktime(0, 0, 0, ++$day, $month, $year); } $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}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check that partitions for MySQL/MariaDB tables are correctly created. The mode should be used with mysql plugin and dyn-mode option. =over 8 =item B<--tablename> This option is mandatory (can be multiple). Example: centreon_storage.data_bin =item B<--warning> Threshold warning (number of retention forward days) =item B<--critical> Threshold critical (number of retention forward days) =item B<--timezone> Timezone use for partitioning (If not set, we use current server execution timezone) =back =cut centreon-plugins-20220113/apps/centreon/sql/mode/pollerdelay.pm000066400000000000000000000067231417000230700244210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::centreon::sql::mode::pollerdelay; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'poller', type => 1, cb_prefix_output => 'prefix_poller_output', message_multiple => 'All poller delay for last update are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{poller} = [ { label => 'delay', nlabel => 'centreon.poller.delay.seconds', set => { key_values => [ { name => 'delay' }, { name => 'display' } ], output_template => 'delay for last update is %d seconds', perfdatas => [ { label => 'delay', value => 'delay', template => '%s', unit => 's', label_extra_instance => 1 }, ], } }, ]; } sub prefix_poller_output { my ($self, %options) = @_; return "Poller '" . $options{instance_value}->{display} . "' : "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, }); return $self; } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); $options{sql}->query(query => q{ SELECT instance_id, name, last_alive, running FROM centreon_storage.instances WHERE deleted = '0'; }); my $result = $options{sql}->fetchall_arrayref(); $self->{poller} = {}; foreach my $row (@{$result}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $$row[1] !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping poller '" . $$row[1] . "': no matching filter.", debug => 1); next; } if ($$row[3] == 0) { $self->{output}->output_add(severity => 'CRITICAL', short_msg => sprintf("%s is not running", $$row[1])); next; } my $delay = time() - $$row[2]; $self->{poller}->{$$row[1]} = { display => $$row[1], delay => abs($delay), }; } } 1; __END__ =head1 MODE Check the delay of the last update from a poller to the Central server. The mode should be used with mysql plugin and dyn-mode option. =over 8 =item B<--filter-name> Filter by poller name (can be a regexp). =item B<--warning-delay> Threshold warning in seconds. =item B<--critical-delay> Threshold critical in seconds. =back =cut centreon-plugins-20220113/apps/centreon/sql/mode/virtualservice.pm000066400000000000000000000554041417000230700251540ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::centreon::sql::mode::virtualservice; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use List::Util qw (min max sum); use JSON; my $config_data; sub get_printf_vars { my ($self, %options) = @_; # compat if (ref($options{printf_var}) ne 'ARRAY') { $options{printf_var} = [split /,/, $options{printf_var}]; } my $message; my $vars = []; eval { local $SIG{__WARN__} = sub { $message = $_[0]; }; local $SIG{__DIE__} = sub { $message = $_[0]; }; foreach my $var (@{$options{printf_var}}) { $var =~ s/\$self->\{result_values\}/\$values/; push @$vars, $self->{output}->assign_eval(eval => $var, values => $options{values}); } }; if (defined($message)) { $self->{output}->output_add(long_msg => 'eval printf_var problem: ' . $message); $self->{output}->option_exit(); } return $vars; } sub custom_metric_output { my ($self, %options) = @_; my $output; 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})) { my $vars = $self->{instance_mode}->get_printf_vars( printf_var => $config_data->{selection}->{ $self->{result_values}->{instance} }->{formatting}->{printf_var}, values => $self->{result_values} ); $output = sprintf( $config_data->{selection}->{ $self->{result_values}->{instance} }->{formatting}->{printf_msg}, @$vars ); } elsif (defined($config_data->{filters}->{formatting}->{printf_var}) && defined($config_data->{filters}->{formatting}->{printf_msg})) { my $vars = $self->{instance_mode}->get_printf_vars( printf_var => $config_data->{filters}->{formatting}->{printf_var}, values => $self->{result_values} ); $output = sprintf( $config_data->{filters}->{formatting}->{printf_msg}, @$vars ); } else { $output = 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})) { my $vars = $self->{instance_mode}->get_printf_vars( printf_var => $config_data->{virtualcurve}->{ $self->{result_values}->{instance} }->{formatting}->{printf_var}, values => $self->{result_values} ); $output = sprintf( $config_data->{virtualcurve}->{ $self->{result_values}->{instance} }->{formatting}->{printf_msg}, @$vars ); } elsif (defined($config_data->{formatting}->{printf_var}) && defined($config_data->{formatting}->{printf_msg})) { my $vars = $self->{instance_mode}->get_printf_vars( printf_var => $config_data->{formatting}->{printf_var}, values => $self->{result_values} ); $output = sprintf( $config_data->{formatting}->{printf_msg}, @$vars ); } else { $output = sprintf("Metric '%s' value is '%s'", $self->{result_values}->{instance}, $self->{result_values}->{value}); } } return $output; } 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, $change_bytes_network) = (0, 0); if (defined($config_data->{filters}->{formatting}) && defined($config_data->{filters}->{formatting}->{change_bytes})) { $change_bytes = $config_data->{filters}->{formatting}->{change_bytes}; $change_bytes_network = $config_data->{filters}->{formatting}->{change_bytes_network}; } elsif (defined($config_data->{$elem}->{$self->{result_values}->{instance}}->{formatting}) && defined($config_data->{$elem}->{$self->{result_values}->{instance}}->{formatting}->{change_bytes})) { $change_bytes = $config_data->{$elem}->{$self->{result_values}->{instance}}->{formatting}->{change_bytes}; $change_bytes_network = $config_data->{$elem}->{$self->{result_values}->{instance}}->{formatting}->{change_bytes_network}; } elsif (defined($config_data->{formatting}) && defined($config_data->{formatting}->{change_bytes})) { $change_bytes = $config_data->{formatting}->{change_bytes}; $change_bytes_network = $config_data->{formatting}->{change_bytes_network}; } if ($change_bytes) { ($self->{result_values}->{value}, $self->{result_values}->{unit}) = $self->{perfdata}->change_bytes( value => $self->{result_values}->{value}, network => defined($change_bytes_network) && $change_bytes_network ? 1 : undef ); } 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; $options{options}->add_options(arguments => { 'config-file:s' => { name => 'config_file' }, 'json-data:s' => { name => 'json_data' }, 'database:s' => { name => 'database' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); 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->{selection}) && !exists($config_data->{filters})) { $self->{output}->add_option_msg(short_msg => "Config_error: there is neither filters nor 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})); $config_data->{formatting}->{change_bytes_network} = 0 if (!exists($config_data->{formatting}->{change_bytes_network})); $self->{option_results}->{database} = (defined($self->{option_results}->{database}) && $self->{option_results}->{database} ne '') ? $self->{option_results}->{database} . '.' : 'centreon_storage.'; } 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 } sub manage_selection { my ($self, %options) = @_; $self->{sql} = $options{sql}; $self->{sql}->connect(); $self->{metrics} = {}; $self->{vmetrics} = {}; if (exists($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}, }; } # Selection is prefered can't mix selection and sql matching if (exists($config_data->{selection})) { push @{$self->{maps_counters_type}}, { name => 'metric', type => 1, message_separator => $config_data->{formatting}->{message_separator}, message_multiple => $config_data->{formatting}->{custom_message_metric}, }; foreach my $id (keys %{$config_data->{selection}}) { my $query = "SELECT index_data.host_name, index_data.service_description, metrics.metric_name, metrics.current_value, metrics.unit_name, metrics.min, metrics.max "; $query .= "FROM $self->{option_results}->{database}index_data, $self->{option_results}->{database}metrics WHERE index_data.id = metrics.index_id "; $query .= "AND index_data.service_description = '" . $config_data->{selection}->{$id}->{service_name} . "'"; $query .= "AND index_data.host_name = '" . $config_data->{selection}->{$id}->{host_name} . "'" ; $query .= "AND metrics.metric_name = '" . $config_data->{selection}->{$id}->{metric_name} . "'"; $self->{sql}->query(query => $query); while ((my $row = $self->{sql}->fetchrow_hashref())) { my $metric_key = $id; $self->{metrics}->{$metric_key} = { name => $row->{metric_name} }; $self->{metrics}->{$metric_key}->{display_name} = $id; $self->{metrics}->{$metric_key}->{current} = $row->{current_value}; $self->{metrics}->{$metric_key}->{unit} = defined($row->{unit_name}) ? $row->{unit_name} : ''; $self->{metrics}->{$metric_key}->{min} = defined($row->{min}) ? $row->{min} : ''; $self->{metrics}->{$metric_key}->{max} = defined($row->{max}) ? $row->{max} : ''; $self->{metrics}->{$metric_key}->{display} = (defined($config_data->{selection}->{$id}->{display}) && $config_data->{selection}->{$id}->{display}) ? 1 : 0; } } } elsif (exists($config_data->{filters})) { push @{$self->{maps_counters_type}}, { name => 'metric', type => 1, message_separator => $config_data->{formatting}->{message_separator}, message_multiple => $config_data->{formatting}->{custom_message_metric}, }; my $query = "SELECT index_data.host_name, index_data.service_description, metrics.metric_name, metrics.current_value, metrics.unit_name, metrics.min, metrics.max "; $query .= "FROM $self->{option_results}->{database}index_data, $self->{option_results}->{database}metrics, $self->{option_results}->{database}services WHERE index_data.id = metrics.index_id AND services.service_id = index_data.service_id AND services.host_id = index_data.host_id "; $query .= "AND index_data.service_description LIKE '" . $config_data->{filters}->{service} . "' " if (defined($config_data->{filters}->{service}) && ($config_data->{filters}->{service} ne '')); $query .= "AND index_data.host_name LIKE '" . $config_data->{filters}->{host} . "' " if (defined($config_data->{filters}->{host}) && ($config_data->{filters}->{host} ne '')); $query .= "AND metrics.metric_name LIKE '" . $config_data->{filters}->{metric} . "' " if (defined($config_data->{filters}->{metric}) && ($config_data->{filters}->{metric} ne '')); $query .= "AND services.enabled = '1'"; $self->{sql}->query(query => $query); while ((my $row = $self->{sql}->fetchrow_hashref())) { my $metric_key = $row->{host_name}.$config_data->{formatting}->{cannonical_separator}.$row->{service_description}.$config_data->{formatting}->{cannonical_separator}.$row->{metric_name}; $self->{metrics}->{$metric_key} = { display_name => $metric_key}; $self->{metrics}->{$metric_key}->{name} = $row->{metric_name}; $self->{metrics}->{$metric_key}->{current} = $row->{current_value}; $self->{metrics}->{$metric_key}->{unit} = defined($row->{unit_name}) ? $row->{unit_name} : ''; $self->{metrics}->{$metric_key}->{min} = defined($row->{min}) ? $row->{min} : ''; $self->{metrics}->{$metric_key}->{max} = defined($row->{max}) ? $row->{max} : ''; $self->{metrics}->{$metric_key}->{display} = (defined($config_data->{filters}->{display}) && $config_data->{filters}->{display}) ? 1 : 0; } } foreach my $metric (keys %{$self->{metrics}}) { foreach my $vcurve (keys %{$config_data->{virtualcurve}}) { $self->{vmetrics}->{$vcurve}->{values} = [] if (!defined($self->{vmetrics}->{$vcurve}->{values})); 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 (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'); if ($config_data->{virtualcurve}->{$vcurve}->{aggregation} eq 'none') { $self->{vmetrics}->{$vcurve}->{aggregated_value} = ( $config_data->{virtualcurve}->{$vcurve}->{aggregation} eq 'none' && defined($config_data->{virtualcurve}->{$vcurve}->{custom})) ? eval "$config_data->{virtualcurve}->{$vcurve}->{custom}" : eval "$self->{vmetrics}->{$vcurve}->{aggregated_value} $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} }; } $self->{metric}->{$metric} = { display => $self->{metrics}->{$metric}->{display_name}, type => 'unique', unit => $self->{metrics}->{$metric}->{unit}, value => $self->{metrics}->{$metric}->{current}, min => $self->{metrics}->{$metric}->{min}, max => $self->{metrics}->{$metric}->{max} } if ($self->{metrics}->{$metric}->{display} == 1); } if (scalar(keys %{$self->{metric}}) <= 0 && scalar(keys %{$self->{vmetrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics returned - are your selection/filters correct ?'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Mode to play with centreon 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<--database> Specify the database (default: 'centreon_storage') =item B<--config-file> Specify the full path to a json config file =item B<--json-data> Specify the full path to a json config file =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_file if set) =item B<--critical-*> Critical threshold (can be 'unique' or 'global') (Override config_file if set) =back =cut centreon-plugins-20220113/apps/checkmyws/000077500000000000000000000000001417000230700201745ustar00rootroot00000000000000centreon-plugins-20220113/apps/checkmyws/mode/000077500000000000000000000000001417000230700211205ustar00rootroot00000000000000centreon-plugins-20220113/apps/checkmyws/mode/status.pm000066400000000000000000000153031417000230700230030ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::checkmyws::mode::status; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::http; use JSON; my $thresholds = { ws => [ ['^0$', 'OK'], ['^1$', 'WARNING'], ['^2$', 'CRITICAL'], ['.*', 'UNKNOWN'], ], }; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "hostname:s" => { name => 'hostname', default => 'api.checkmy.ws'}, "port:s" => { name => 'port', }, "proto:s" => { name => 'proto', default => "https" }, "urlpath:s" => { name => 'url_path', default => "/api/status" }, "uid:s" => { name => 'uid' }, "timeout:s" => { name => 'timeout' }, "threshold-overload:s@" => { name => 'threshold_overload' }, }); $self->{http} = centreon::plugins::http->new(%options); 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}->{uid}))) { $self->{output}->add_option_msg(short_msg => "You need to set uid option"); $self->{output}->option_exit(); } $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) = ('ws', $1, $2); 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->{option_results}->{url_path} = $self->{option_results}->{url_path}."/".$self->{option_results}->{uid}; $self->{http}->set_options(%{$self->{option_results}}); } sub run { my ($self, %options) = @_; my $jsoncontent = $self->{http}->request(); my $json = JSON->new; my $webcontent; eval { $webcontent = $json->decode($jsoncontent); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response"); $self->{output}->option_exit(); } my %map_output = ( -3 => 'Disable', -2 => 'Not scheduled', -1 => 'Pending...', ); my $state = $webcontent->{state}; my $output = defined($map_output{$state}) ? $map_output{$state} : $webcontent->{state_code_str}; my $exit = $self->get_severity(section => 'ws', value => $state); $self->{output}->output_add(severity => $exit, short_msg => $output); if (defined($webcontent->{lastvalues}->{httptime})) { my $perfdata = $webcontent->{lastvalues}->{httptime}; my $mean_time = 0; foreach my $location (keys %$perfdata) { $mean_time += $perfdata->{$location}; $self->{output}->perfdata_add(label => $location, unit => 'ms', value => $perfdata->{$location}, min => 0 ); } $self->{output}->perfdata_add(label => 'mean_time', unit => 'ms', value => $mean_time / scalar(keys %$perfdata), min => 0 ) if (scalar(keys %$perfdata) > 0); $self->{output}->perfdata_add(label => 'yslow_page_load_time', unit => 'ms', value => $webcontent->{metas}->{yslow_page_load_time}, min => 0 ) if (defined($webcontent->{metas}->{yslow_page_load_time})); $self->{output}->perfdata_add(label => 'yslow_score', value => $webcontent->{metas}->{yslow_score}, min => 0, max => 100 ) if (defined($webcontent->{metas}->{yslow_score})); } $self->{output}->display(); $self->{output}->exit(); } 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__ =head1 MODE Check website status =over 8 =item B<--hostname> Checkmyws api host (Default: 'api.checkmy.ws') =item B<--port> Port used by checkmyws =item B<--proto> Specify https if needed (Default: 'https') =item B<--urlpath> Set path to get checkmyws information (Default: '/api/status') =item B<--timeout> Threshold for HTTP timeout (Default: 5) =item B<--uid> ID for checkmyws API =item B<--threshold-overload> Set to overload default threshold values (syntax: status,regexp) It used before default thresholds (order stays). Example: --threshold-overload='CRITICAL,^(?!(0)$)' =back =cut centreon-plugins-20220113/apps/checkmyws/plugin.pm000066400000000000000000000023161417000230700220320ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::checkmyws::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}} = ( 'status' => 'apps::checkmyws::mode::status', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Check my Website through its API =cut centreon-plugins-20220113/apps/cisco/000077500000000000000000000000001417000230700172775ustar00rootroot00000000000000centreon-plugins-20220113/apps/cisco/cms/000077500000000000000000000000001417000230700200615ustar00rootroot00000000000000centreon-plugins-20220113/apps/cisco/cms/restapi/000077500000000000000000000000001417000230700215305ustar00rootroot00000000000000centreon-plugins-20220113/apps/cisco/cms/restapi/custom/000077500000000000000000000000001417000230700230425ustar00rootroot00000000000000centreon-plugins-20220113/apps/cisco/cms/restapi/custom/xmlapi.pm000066400000000000000000000141361417000230700246770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::cisco::cms::restapi::custom::xmlapi; use strict; use warnings; use centreon::plugins::http; use XML::Simple; 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 => { 'hostname:s' => { name => 'hostname' }, 'url-path:s' => { name => 'url_path' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'timeout:s' => { name => 'timeout' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'XMLAPI OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : undef; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 445; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{username} = (defined($self->{option_results}->{username})) ? $self->{option_results}->{username} : undef; $self->{password} = (defined($self->{option_results}->{password})) ? $self->{option_results}->{password} : undef; $self->{url_path} = (defined($self->{option_results}->{url_path})) ? $self->{option_results}->{url_path} : '/api/v1'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; if (!defined($self->{option_results}->{username}) || $self->{option_results}->{username} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --username option."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{password}) || $self->{option_results}->{password} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --password option."); $self->{output}->option_exit(); } return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{username} = $self->{username}; $self->{option_results}->{password} = $self->{password}; $self->{option_results}->{credentials} = 1; $self->{option_results}->{basic} = 1; $self->{option_results}->{warning_status} = ''; $self->{option_results}->{critical_status} = ''; $self->{option_results}->{unknown_status} = ''; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->set_options(%{$self->{option_results}}); } sub get_connection_info { my ($self, %options) = @_; return $self->{hostname} . ":" . $self->{port}; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub get_port { my ($self, %options) = @_; return $self->{port}; } sub get_endpoint { my ($self, %options) = @_; $self->settings; my $content = $self->{http}->request(url_path => $self->{url_path} . $options{method}); if ($self->{http}->get_code() != 200) { my $xml_result; eval { $xml_result = XMLin($content); }; if ($@) { $self->{output}->output_add(long_msg => $content, debug => 1); $self->{output}->add_option_msg(short_msg => "Cannot decode xml response: $@"); $self->{output}->option_exit(); } if (defined($xml_result)) { $self->{output}->output_add(long_msg => $content, debug => 1); $self->{output}->add_option_msg(short_msg => "Api return errors: " . join(', ', keys %{$xml_result})); $self->{output}->option_exit(); } } my $xml_result; eval { $xml_result = XMLin($content, ForceArray => ['node', 'call', 'alarm'], KeyAttr => []); }; if ($@) { $self->{output}->output_add(long_msg => $content, debug => 1); $self->{output}->add_option_msg(short_msg => "Cannot decode xml response: $@"); $self->{output}->option_exit(); } return $xml_result; } 1; __END__ =head1 NAME Cisco CMS XML API =head1 SYNOPSIS Cisco CMS XML API =head1 XMLAPI OPTIONS =over 8 =item B<--hostname> API hostname. =item B<--url-path> API url path (Default: '/api/v1') =item B<--port> API port (Default: 445) =item B<--proto> Specify https if needed (Default: 'https') =item B<--username> Set API username =item B<--password> Set API password =item B<--timeout> Set HTTP timeout =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/cisco/cms/restapi/mode/000077500000000000000000000000001417000230700224545ustar00rootroot00000000000000centreon-plugins-20220113/apps/cisco/cms/restapi/mode/alarms.pm000066400000000000000000000123511417000230700242730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::cisco::cms::restapi::mode::alarms; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::statefile; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("alarm '%s' active for %s", $self->{result_values}->{type}, centreon::plugins::misc::change_seconds(value => $self->{result_values}->{active_time})); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{type} = $options{new_datas}->{$self->{instance} . '_type'}; $self->{result_values}->{active_time} = $options{new_datas}->{$self->{instance} . '_activeTimeSeconds'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'alarms', type => 2, message_multiple => '0 problem(s) detected', display_counter_problem => { label => 'alerts', min => 0 }, group => [ { name => 'alarm', skipped_code => { -11 => 1 } } ] } ]; $self->{maps_counters}->{alarm} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'type' }, { name => 'activeTimeSeconds' } ], 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 => \&catalog_status_threshold, } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-type:s" => { name => 'filter_type' }, "warning-status:s" => { name => 'warning_status', default => '' }, "critical-status:s" => { name => 'critical_status', default => '' }, "memory" => { name => 'memory' }, }); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->check_options(%options); } } sub manage_selection { my ($self, %options) = @_; $self->{alarms}->{global} = { alarm => {} }; my $results = $options{custom}->get_endpoint(method => '/system/alarms'); my $last_time; if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->read(statefile => "cache_cisco_cms_" . $options{custom}->get_hostname() . '_' . $options{custom}->get_port(). '_' . $self->{mode}); $last_time = $self->{statefile_cache}->get(name => 'last_time'); } my ($i, $current_time) = (1, time()); foreach my $alarm (@{$results->{alarm}}) { my $create_time = $current_time - $alarm->{activeTimeSeconds}; next if (defined($self->{option_results}->{memory}) && defined($last_time) && $last_time > $create_time); if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' && $alarm->{type} !~ /$self->{option_results}->{filter_type}/) { $self->{output}->output_add(long_msg => "skipping '" . $alarm->{type} . "': no matching filter.", debug => 1); next; } my $diff_time = $current_time - $create_time; $self->{alarms}->{global}->{alarm}->{$i} = { %$alarm, since => $diff_time }; $i++; } if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->write(data => { last_time => $current_time }); } } 1; __END__ =head1 MODE Check alarms. =over 8 =item B<--filter-type> Filter by type (can be a regexp). =item B<--warning-status> Set warning threshold for status (Default: '') Can used special variables like: %{type}, %{active_time} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{type}, %{active_time} =item B<--memory> Only check new alarms. =back =cut centreon-plugins-20220113/apps/cisco/cms/restapi/mode/calls.pm000066400000000000000000000102121417000230700241040ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::cisco::cms::restapi::mode::calls; 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 }, ]; $self->{maps_counters}->{global} = [ { label => 'active-calls', set => { key_values => [ { name => 'calls' } ], output_template => 'Active calls: %d', perfdatas => [ { label => 'active_calls', value => 'calls', template => '%d', min => 0, unit => 'calls' }, ], } }, { label => 'local-participants', set => { key_values => [ { name => 'numParticipantsLocal' } ], output_template => 'Local participants: %d', perfdatas => [ { label => 'local_participants', value => 'numParticipantsLocal', template => '%d', min => 0, unit => 'participants' }, ], } }, { label => 'remote-participants', set => { key_values => [ { name => 'numParticipantsRemote' } ], output_template => 'Remote participants: %d', perfdatas => [ { label => 'remote_participants', value => 'numParticipantsRemote', template => '%d', min => 0, unit => 'participants' }, ], } }, { label => 'call-legs', set => { key_values => [ { name => 'numCallLegs' } ], output_template => 'Call legs: %d', perfdatas => [ { label => 'call_legs', value => 'numCallLegs', template => '%d', min => 0, unit => 'legs' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-counters:s" => { name => 'filter_counters' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->get_endpoint(method => '/calls'); $self->{global} = { calls => 0, numParticipantsLocal => 0, numParticipantsRemote => 0 , numCallLegs => 0 }; $self->{global}->{calls} = $results->{total}; foreach my $call (@{$results->{call}}) { my $result = $options{custom}->get_endpoint(method => '/calls/' . $call->{id}); $self->{global}->{numParticipantsLocal} += $result->{numParticipantsLocal}; $self->{global}->{numParticipantsRemote} += $result->{numParticipantsRemote}; $self->{global}->{numCallLegs} += $result->{numCallLegs}; } } 1; __END__ =head1 MODE Check number of calls and participants. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). (Example: --filter-counters='calls') =item B<--warning-*> Threshold warning. Can be: 'active-calls', 'local-participants', 'remote-participants', 'call-legs'. =item B<--critical-*> Threshold critical. Can be: 'active-calls', 'local-participants', 'remote-participants', 'call-legs'. =back =cut centreon-plugins-20220113/apps/cisco/cms/restapi/mode/databasestatus.pm000066400000000000000000000106641417000230700260310ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::cisco::cms::restapi::mode::databasestatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("master status is '%s', up is '%s' [Sync behind: %s B]", $self->{result_values}->{master}, $self->{result_values}->{up}, $self->{result_values}->{sync_behind}); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{sync_behind} = $options{new_datas}->{$self->{instance} . '_syncBehind'}; $self->{result_values}->{master} = $options{new_datas}->{$self->{instance} . '_master'}; $self->{result_values}->{up} = $options{new_datas}->{$self->{instance} . '_up'}; $self->{result_values}->{hostname} = $options{new_datas}->{$self->{instance} . '_hostname'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'nodes', type => 1, cb_prefix_output => 'prefix_node_output', message_multiple => 'All database hosts are ok' }, ]; $self->{maps_counters}->{nodes} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'syncBehind' }, { name => 'master' }, { name => 'up' }, { name => 'hostname' } ], 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 => \&catalog_status_threshold, } }, ]; } sub prefix_node_output { my ($self, %options) = @_; return "Node '" . $options{instance_value}->{hostname} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning-status:s" => { name => 'warning_status', default => '' }, "critical-status:s" => { name => 'critical_status', default => '%{up} !~ /true/i' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->get_endpoint(method => '/system/database'); $self->{nodes} = {}; if (defined($results->{clustered}) && $results->{clustered} ne 'enabled' ) { $self->{output}->add_option_msg(short_msg => "Database clustering is not enabled"); $self->{output}->option_exit(); } foreach my $node (@{$results->{cluster}->{node}}) { $self->{nodes}->{$node->{hostname}} = { hostname => $node->{hostname}, master => $node->{master}, up => $node->{up}, syncBehind => $node->{syncBehind}, }; } if (scalar(keys %{$self->{nodes}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No nodes found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check database status. =over 8 =item B<--warning-status> Set warning threshold for status. (Default: ''). Can use special variables like: %{hostname}, %{master}, %{up}, %{sync_behind} =item B<--critical-status> Set critical threshold for status. (Default: '%{up} !~ /true/i'). Can use special variables like: %{hostname}, %{master}, %{up}, %{sync_behind} =back =cut centreon-plugins-20220113/apps/cisco/cms/restapi/mode/licenses.pm000066400000000000000000000123551417000230700246250ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::cisco::cms::restapi::mode::licenses; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use DateTime; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("status is '%s'", $self->{result_values}->{status}); $msg .= sprintf(", expires in %d days [%s]", $self->{result_values}->{expiry_days}, $self->{result_values}->{expiry_date}) if (defined($self->{result_values}->{expiry_date}) && $self->{result_values}->{expiry_date} ne ''); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{feature} = $options{new_datas}->{$self->{instance} . '_feature'}; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; $self->{result_values}->{expiry_date} = $options{new_datas}->{$self->{instance} . '_expiry_date'}; $self->{result_values}->{expiry_seconds} = $options{new_datas}->{$self->{instance} . '_expiry_seconds'}; $self->{result_values}->{expiry_days} = ($self->{result_values}->{expiry_seconds} ne '') ? $self->{result_values}->{expiry_seconds} / 86400 : 0; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'features', type => 1, cb_prefix_output => 'prefix_feature_output', message_multiple => 'All features licensing are ok' }, ]; $self->{maps_counters}->{features} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'feature' }, { name => 'status' }, { name => 'expiry_date' }, { name => 'expiry_seconds' } ], 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 => \&catalog_status_threshold, } }, ]; } sub prefix_feature_output { my ($self, %options) = @_; return "Feature '" . $options{instance_value}->{feature} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning-status:s" => { name => 'warning_status', default => '%{status} eq "activated" && %{expiry_days} < 60' }, "critical-status:s" => { name => 'critical_status', default => '%{status} eq "activated" && %{expiry_days} < 30' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->get_endpoint(method => '/system/licensing'); $self->{features} = {}; foreach my $feature (keys %{$results->{features}}) { my %months = ("Jan" => 1, "Feb" => 2, "Mar" => 3, "Apr" => 4, "May" => 5, "Jun" => 6, "Jul" => 7, "Aug" => 8, "Sep" => 9, "Oct" => 10, "Nov" => 11, "Dec" => 12); $results->{features}->{$feature}->{expiry} =~ /^(\d+)-(\w+)-(\d+)$/ if (defined($results->{features}->{$feature}->{expiry})); # 2100-Jan-01 my $dt = DateTime->new(year => $1, month => $months{$2}, day => $3); $self->{features}->{$feature} = { feature => $feature, status => $results->{features}->{$feature}->{status}, expiry_date => (defined($results->{features}->{$feature}->{expiry})) ? $results->{features}->{$feature}->{expiry} : '', expiry_seconds => (defined($results->{features}->{$feature}->{expiry})) ? $dt->epoch - time() : '', }; } if (scalar(keys %{$self->{features}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No features found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check features licensing. =over 8 =item B<--warning-status> Set warning threshold for status. (Default: '%{status} eq "activated" && %{expiry_days} < 60'). Can use special variables like: %{status}, %{expiry_days}, %{feature} =item B<--critical-status> Set critical threshold for status. (Default: '%{status} eq "activated" && %{expiry_days} < 30'). Can use special variables like: %{status}, %{expiry_days}, %{feature} =back =cut centreon-plugins-20220113/apps/cisco/cms/restapi/mode/systemstatus.pm000066400000000000000000000167141417000230700256130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::cisco::cms::restapi::mode::systemstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("Call Bridge activation is '%s', cluster enabled is '%s'", $self->{result_values}->{activated}, $self->{result_values}->{cluster_enabled}); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{activated} = $options{new_datas}->{$self->{instance} . '_activated'}; $self->{result_values}->{cluster_enabled} = $options{new_datas}->{$self->{instance} . '_clusterEnabled'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'legs', type => 0, cb_prefix_output => 'prefix_leg_output', skipped_code => { -10 => 1 } }, { name => 'rates', type => 0, cb_prefix_output => 'prefix_rate_output', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ { label => 'status', set => { key_values => [ { name => 'activated' }, { name => 'clusterEnabled' } ], 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 => \&catalog_status_threshold, } }, ]; $self->{maps_counters}->{legs} = [ { label => 'active-legs', set => { key_values => [ { name => 'callLegsActive' } ], output_template => 'Active: %d', perfdatas => [ { label => 'active_legs', value => 'callLegsActive', template => '%d', min => 0, unit => 'legs' }, ], } }, { label => 'completed-legs', set => { key_values => [ { name => 'callLegsCompleted' } ], output_template => 'Completed: %d', perfdatas => [ { label => 'completed_legs', value => 'callLegsCompleted', template => '%d', min => 0, unit => 'legs' }, ], } }, ]; $self->{maps_counters}->{rates} = [ { label => 'audio-outgoing-rate', set => { key_values => [ { name => 'audioBitRateOutgoing' } ], output_template => 'outgoing audio streams: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'audio_outgoing_rate', value => 'audioBitRateOutgoing', template => '%d', min => 0, unit => 'b/s' }, ], } }, { label => 'audio-incoming-rate', set => { key_values => [ { name => 'audioBitRateIncoming' } ], output_template => 'incoming audio streams: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'audio_incoming_rate', value => 'audioBitRateIncoming', template => '%d', min => 0, unit => 'b/s' }, ], } }, { label => 'video-outgoing-rate', set => { key_values => [ { name => 'videoBitRateOutgoing' } ], output_template => 'outgoing video streams: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'video_outgoing_rate', value => 'videoBitRateOutgoing', template => '%d', min => 0, unit => 'b/s' }, ], } }, { label => 'video-incoming-rate', set => { key_values => [ { name => 'videoBitRateIncoming' } ], output_template => 'incoming video streams: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'video_incoming_rate', value => 'videoBitRateIncoming', template => '%d', min => 0, unit => 'b/s' }, ], } }, ]; } sub prefix_leg_output { my ($self, %options) = @_; return "Legs "; } sub prefix_rate_output { my ($self, %options) = @_; return "Rates "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-counters:s" => { name => 'filter_counters' }, "warning-status:s" => { name => 'warning_status', default => '' }, "critical-status:s" => { name => 'critical_status', default => '%{activated} !~ /true/i' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->get_endpoint(method => '/system/status'); $self->{global} = ''; $self->{legs} = ''; $self->{rates} = ''; $self->{global} = { activated => $results->{activated}, clusterEnabled => $results->{clusterEnabled}, }; $self->{legs} = { callLegsActive => $results->{callLegsActive}, callLegsCompleted => $results->{callLegsCompleted}, }; $self->{rates} = { audioBitRateOutgoing => $results->{audioBitRateOutgoing}, audioBitRateIncoming => $results->{audioBitRateIncoming}, videoBitRateOutgoing => $results->{videoBitRateOutgoing}, videoBitRateIncoming => $results->{videoBitRateIncoming}, }; } 1; __END__ =head1 MODE Check system status. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). (Example: --filter-counters='rate') =item B<--warning-status> Set warning threshold for status. (Default: ''). Can use special variables like: %{activated}, %{cluster_enabled} =item B<--critical-status> Set critical threshold for status. (Default: '%{activated} !~ /true/i'). Can use special variables like: %{activated}, %{cluster_enabled} =item B<--warning-*> Threshold warning. Can be: 'active-legs', 'completed-legs', 'audio-outgoing-rate', 'audio-incoming-rate', 'video-outgoing-rate', 'video-incoming-rate'. =item B<--critical-*> Threshold critical. Can be: 'active-legs', 'completed-legs', 'audio-outgoing-rate', 'audio-incoming-rate', 'video-outgoing-rate', 'video-incoming-rate'. =back =cut centreon-plugins-20220113/apps/cisco/cms/restapi/plugin.pm000066400000000000000000000031621417000230700233660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::cisco::cms::restapi::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} = '1.0'; %{$self->{modes}} = ( 'alarms' => 'apps::cisco::cms::restapi::mode::alarms', 'calls' => 'apps::cisco::cms::restapi::mode::calls', 'database-status' => 'apps::cisco::cms::restapi::mode::databasestatus', 'licenses' => 'apps::cisco::cms::restapi::mode::licenses', 'system-status' => 'apps::cisco::cms::restapi::mode::systemstatus', ); $self->{custom_modes}{xmlapi} = 'apps::cisco::cms::restapi::custom::xmlapi'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Cisco Meeting Server (CMS) API. =cut centreon-plugins-20220113/apps/cisco/dnac/000077500000000000000000000000001417000230700202045ustar00rootroot00000000000000centreon-plugins-20220113/apps/cisco/dnac/restapi/000077500000000000000000000000001417000230700216535ustar00rootroot00000000000000centreon-plugins-20220113/apps/cisco/dnac/restapi/custom/000077500000000000000000000000001417000230700231655ustar00rootroot00000000000000centreon-plugins-20220113/apps/cisco/dnac/restapi/custom/api.pm000066400000000000000000000216371417000230700243050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::cisco::dnac::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use centreon::plugins::statefile; use JSON::XS; use Digest::MD5 qw(md5_hex); 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 => { 'api-username:s' => { name => 'api_username' }, 'api-password:s' => { name => 'api_password' }, 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'timeout:s' => { name => 'timeout' }, 'unknown-http-status:s' => { name => 'unknown_http_status' }, 'warning-http-status:s' => { name => 'warning_http_status' }, 'critical-http-status:s' => { name => 'critical_http_status' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); $self->{cache} = centreon::plugins::statefile->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 50; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300'; $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : ''; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : ''; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } if ($self->{api_username} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-username option."); $self->{output}->option_exit(); } if ($self->{api_password} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-password option."); $self->{output}->option_exit(); } $self->{cache}->check_options(option_results => $self->{option_results}); return 0; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub get_port { my ($self, %options) = @_; return $self->{port}; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Content-Type', value => 'application/json'); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->set_options(%{$self->{option_results}}); } sub json_decode { my ($self, %options) = @_; my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($options{content}); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } return $decoded; } sub clean_session_token { my ($self, %options) = @_; my $datas = { last_timestamp => time() }; $options{statefile}->write(data => $datas); $self->{session_token} = undef; $self->{http}->add_header(key => 'X-Auth-Token', value => undef); } sub authenticate { my ($self, %options) = @_; my $has_cache_file = $options{statefile}->read(statefile => 'cisco_dnac_' . md5_hex($self->{option_results}->{hostname}) . '_' . md5_hex($self->{option_results}->{api_username})); my $session_token = $options{statefile}->get(name => 'session_token'); if ($has_cache_file == 0 || !defined($session_token)) { my ($content) = $self->{http}->request( method => 'POST', query_form_post => '', url_path => '/dna/system/api/v1/auth/token', credentials => 1, basic => 1, username => $self->{api_username}, password => $self->{api_password}, warning_status => '', unknown_status => '', critical_status => '' ); if ($self->{http}->get_code() < 200 || $self->{http}->get_code() >= 300) { $self->{output}->add_option_msg(short_msg => "login error [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded = $self->json_decode(content => $content); if (!defined($decoded->{Token})) { $self->{output}->add_option_msg(short_msg => 'error retrieving session_token'); $self->{output}->option_exit(); } $session_token = $decoded->{Token}; my $datas = { last_timestamp => time(), session_token => $session_token }; $options{statefile}->write(data => $datas); } $self->{session_token} = $session_token; $self->{http}->add_header(key => 'X-Auth-Token', value => $self->{session_token}); } sub request_api { my ($self, %options) = @_; $self->settings(); if (!defined($self->{session_token})) { $self->authenticate(statefile => $self->{cache}); } my ($content) = $self->{http}->request( url_path => '/dna/intent/api/v1' . $options{endpoint}, get_param => $options{get_param}, unknown_status => '', warning_status => '', critical_status => '' ); if ($self->{http}->get_code() < 200 || $self->{http}->get_code() >= 300) { $self->clean_session_token(statefile => $self->{cache}); $self->authenticate(statefile => $self->{cache}); ($content) = $self->{http}->request( url_path => '/dna/intent/api/v1' . $options{endpoint}, get_param => $options{get_param}, unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status}, ); } my $decoded = $self->json_decode(content => $content); if (!defined($decoded)) { $self->{output}->add_option_msg(short_msg => 'error while retrieving data (add --debug option for detailed message)'); $self->{output}->option_exit(); } return $decoded; } 1; __END__ =head1 NAME Cisco DNA Center Rest API =head1 REST API OPTIONS Cisco DNA Center Rest API =over 8 =item B<--hostname> Set hostname. =item B<--port> Port used (Default: 443) =item B<--proto> Specify https if needed (Default: 'https') =item B<--api-username> Set username. =item B<--api-password> Set password. =item B<--timeout> Set timeout in seconds (Default: 50). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/cisco/dnac/restapi/mode/000077500000000000000000000000001417000230700225775ustar00rootroot00000000000000centreon-plugins-20220113/apps/cisco/dnac/restapi/mode/discovery.pm000066400000000000000000000070111417000230700251430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::cisco::dnac::restapi::mode::discovery; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'resource-type:s' => { name => 'resource_type' }, 'prettify' => { name => 'prettify' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{resource_type}) || $self->{option_results}->{resource_type} eq '') { $self->{option_results}->{resource_type} = 'network-device'; } if ($self->{option_results}->{resource_type} !~ /^network-device$/) { $self->{output}->add_option_msg(short_msg => 'unknown resource type'); $self->{output}->option_exit(); } } sub discovery_network_device { my ($self, %options) = @_; my $devices = $options{custom}->request_api( endpoint => '/network-device' ); my $disco_data = []; foreach my $device (@{$devices->{response}}) { my $node = {}; $node->{uuid} = $device->{id}; $node->{mac_address} = $device->{macAddress}; $node->{hostname} = $device->{hostname}; $node->{serial} = $device->{serialNumber}; $node->{software_type} = $device->{softwareType}; $node->{software_version} = $device->{softwareVersion}; $node->{role} = $device->{role}; $node->{family} = $device->{family}; push @$disco_data, $node; } return $disco_data; } sub run { my ($self, %options) = @_; my $disco_stats; $disco_stats->{start_time} = time(); my $results = $self->discovery_network_device( custom => $options{custom} ); $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; $disco_stats->{discovered_items} = scalar(@$results); $disco_stats->{results} = $results; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE Resources discovery. =over 8 =item B<--resource-type> Choose the type of resources to discover (Can be: 'network-device'). =back =cut centreon-plugins-20220113/apps/cisco/dnac/restapi/mode/networkdevices.pm000066400000000000000000000155601417000230700262000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::cisco::dnac::restapi::mode::networkdevices; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_health_output { my ($self, %options) = @_; return sprintf( '%.2f%% (%s on %s)', $self->{result_values}->{prct}, $self->{result_values}->{count}, $self->{result_values}->{total} ); } sub category_long_output { my ($self, %options) = @_; return "checking network category '" . $options{instance_value}->{name} . "'"; } sub prefix_category_output { my ($self, %options) = @_; return "Network category '" . $options{instance_value}->{name} . "' "; } sub prefix_global_output { my ($self, %options) = @_; return 'Network devices '; } sub prefix_good_output { my ($self, %options) = @_; return 'good devices: '; } sub prefix_fair_output { my ($self, %options) = @_; return 'fair devices: '; } sub prefix_bad_output { my ($self, %options) = @_; return 'bad devices: '; } sub prefix_unmonitored_output { my ($self, %options) = @_; return 'unmonitored devices: '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } }, { name => 'categories', type => 3, cb_prefix_output => 'prefix_categorie_output', cb_long_output => 'category_long_output', indent_long_output => ' ', message_multiple => 'All network categories are ok', group => [ { name => 'good', type => 0, cb_prefix_output => 'prefix_good_output', skipped_code => { -10 => 1 } }, { name => 'fair', type => 0, cb_prefix_output => 'prefix_fair_output', skipped_code => { -10 => 1 } }, { name => 'bad', type => 0, cb_prefix_output => 'prefix_bad_output', skipped_code => { -10 => 1 } }, { name => 'unmonitored', type => 0, cb_prefix_output => 'prefix_unmonitored_output', skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'devices-total', nlabel => 'network.devices.total.count', display_ok => 0, set => { key_values => [ { name => 'devices_total' } ], output_template => 'total: %s', perfdatas => [ { template => '%s', min => 0 } ] } } ]; foreach (('good', 'fair', 'bad', 'unmonitored')) { $self->{maps_counters}->{$_} = [ { label => 'category-devices-health-' . $_ . '-usage', nlabel => 'category.network.devices.health.' . $_ . '.count', set => { key_values => [ { name => 'count' }, { name => 'prct' }, { name => 'total' } ], closure_custom_output => $self->can('custom_health_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', label_extra_instance => 1 } ] } }, { label => 'category-devices-health-' . $_ . '-usage-prct', nlabel => 'category.network.devices.health.' . $_ . '.percentage', display_ok => 0, set => { key_values => [ { name => 'count' }, { name => 'prct' }, { name => 'total' } ], closure_custom_output => $self->can('custom_health_output'), perfdatas => [ { template => '%.2f', min => 0, max => 100, label_extra_instance => 1 } ] } } ]; } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-category-name:s' => { name => 'filter_category_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $networks = $options{custom}->request_api( endpoint => '/network-health' ); $self->{global} = { devices_total => 0 }; $self->{categories} = {}; foreach (@{$networks->{healthDistirubution}}) { if (defined($self->{option_results}->{filter_category_name}) && $self->{option_results}->{filter_category_name} ne '' && $_->{category} !~ /$self->{option_results}->{filter_category_name}/) { $self->{output}->output_add(long_msg => "skipping category '" . $_->{category} . "': no matching filter.", debug => 1); next; } $self->{categories}->{ $_->{category} } = { name => $_->{category}, good => { name => $_->{category}, total => $_->{totalCount}, count => $_->{goodCount}, prct => $_->{goodCount} * 100 / $_->{totalCount} }, fair => { name => $_->{category}, total => $_->{totalCount}, count => $_->{fairCount}, prct => $_->{fairCount} * 100 / $_->{totalCount} }, bad => { name => $_->{category}, total => $_->{totalCount}, count => $_->{badCount}, prct => $_->{badCount} * 100 / $_->{totalCount} }, unmonitored => { name => $_->{category}, total => $_->{totalCount}, count => $_->{unmonCount}, prct => $_->{unmonCount} * 100 / $_->{totalCount} } }; $self->{global}->{devices_total} += $_->{totalCount}; } } 1; __END__ =head1 MODE Check network devices by categories. =over 8 =item B<--filter-category-name> Filter categories by name (Can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'category-devices-health-good-usage', 'category-devices-health-good-usage-prct', 'category-devices-health-unmonitored-usage', 'category-devices-health-unmonitored-usage-prct', 'category-devices-health-fair-usage', 'category-devices-health-fair-usage-prct', 'category-devices-health-bad-usage', 'category-devices-health-bad-usage-prct', 'devices-total'. =back =cut centreon-plugins-20220113/apps/cisco/dnac/restapi/mode/sites.pm000066400000000000000000000160371417000230700242730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::cisco::dnac::restapi::mode::sites; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; sub custom_health_output { my ($self, %options) = @_; return sprintf( 'healthy %.2f%% (%s on %s)', $self->{result_values}->{prct}, $self->{result_values}->{count}, $self->{result_values}->{total} ); } sub site_long_output { my ($self, %options) = @_; return "checking site '" . $options{instance_value}->{name} . "'"; } sub prefix_site_output { my ($self, %options) = @_; return "Site '" . $options{instance_value}->{name} . "' "; } sub prefix_devices_output { my ($self, %options) = @_; return 'devices: '; } sub prefix_clients_output { my ($self, %options) = @_; return 'clients: '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'sites', type => 3, cb_prefix_output => 'prefix_site_output', cb_long_output => 'site_long_output', indent_long_output => ' ', message_multiple => 'All sites are ok', group => [ { name => 'devices', type => 0, cb_prefix_output => 'prefix_devices_output', skipped_code => { -10 => 1 } }, { name => 'clients', type => 0, cb_prefix_output => 'prefix_clients_output', skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{devices} = [ { label => 'site-devices-healthy-usage', nlabel => 'site.network.devices.healthy.count', set => { key_values => [ { name => 'count' }, { name => 'prct' }, { name => 'total' } ], closure_custom_output => $self->can('custom_health_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', label_extra_instance => 1 } ] } }, { label => 'site-devices-healthy-usage-prct', nlabel => 'site.network.devices.healthy.percentage', display_ok => 0, set => { key_values => [ { name => 'count' }, { name => 'prct' }, { name => 'total' } ], closure_custom_output => $self->can('custom_health_output'), perfdatas => [ { template => '%.2f', min => 0, max => 100, label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{clients} = [ { label => 'site-clients-healthy-usage', nlabel => 'site.clients.healthy.count', set => { key_values => [ { name => 'count' }, { name => 'prct' }, { name => 'total' } ], closure_custom_output => $self->can('custom_health_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', label_extra_instance => 1 } ] } }, { label => 'site-clients-healthy-usage-prct', nlabel => 'site.clients.healthy.percentage', display_ok => 0, set => { key_values => [ { name => 'count' }, { name => 'prct' }, { name => 'total' } ], closure_custom_output => $self->can('custom_health_output'), perfdatas => [ { template => '%.2f', min => 0, max => 100, label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-site-name:s' => { name => 'filter_site_name' }, 'use-site-fullname' => { name => 'use_site_fullname' } }); return $self; } sub get_fullname { my ($self, %options) = @_; return $options{name} if (!defined($options{parent_id})); my $name = $options{name}; foreach (@{$options{response}}) { if ($_->{siteId} eq $options{parent_id}) { $name = $self->get_fullname( response => $options{response}, name => centreon::plugins::misc::trim($_->{siteName}) . '>' . $name, parent_id => $_->{parentSiteId} ); last; } } return $name; } sub manage_selection { my ($self, %options) = @_; my $sites = $options{custom}->request_api( endpoint => '/site-health' ); $self->{categories} = {}; foreach (@{$sites->{response}}) { my $site_fullname = $self->get_fullname( response => $sites->{response}, name => centreon::plugins::misc::trim($_->{siteName}), parent_id => $_->{parentSiteId} ); my $site_name = defined($self->{option_results}->{use_site_fullname}) ? $site_fullname : centreon::plugins::misc::trim($_->{siteName}); if (defined($self->{option_results}->{filter_site_name}) && $self->{option_results}->{filter_site_name} ne '' && $site_name !~ /$self->{option_results}->{filter_site_name}/) { $self->{output}->output_add(long_msg => "skipping site '" . $site_name . "': no matching filter.", debug => 1); next; } $self->{sites}->{ $site_name } = { name => $site_name, devices => { name => $site_name, total => $_->{numberOfNetworkDevice}, count => int($_->{numberOfNetworkDevice} * $_->{healthyNetworkDevicePercentage} / 100), prct => $_->{healthyNetworkDevicePercentage} }, clients => { name => $site_name, total => $_->{numberOfClients}, count => int($_->{numberOfClients} * $_->{healthyClientsPercentage} / 100), prct => $_->{healthyClientsPercentage} } }; } } 1; __END__ =head1 MODE Check sites. =over 8 =item B<--filter-site-name> Filter sites by name (Can be a regexp). =item B<--use-site-fullname> Use site fullname (with parents name). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'category-devices-health-good-usage', 'category-devices-health-good-usage-prct', 'category-devices-health-unmonitored-usage', 'category-devices-health-unmonitored-usage-prct', 'category-devices-health-fair-usage', 'category-devices-health-fair-usage-prct', 'category-devices-health-bad-usage', 'category-devices-health-bad-usage-prct', 'devices-total'. =back =cut centreon-plugins-20220113/apps/cisco/dnac/restapi/plugin.pm000066400000000000000000000027231417000230700235130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::cisco::dnac::restapi::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} = { 'discovery' => 'apps::cisco::dnac::restapi::mode::discovery', 'network-devices' => 'apps::cisco::dnac::restapi::mode::networkdevices', 'sites' => 'apps::cisco::dnac::restapi::mode::sites' }; $self->{custom_modes}->{api} = 'apps::cisco::dnac::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Cisco DNA Center using Rest API. =cut centreon-plugins-20220113/apps/cisco/ise/000077500000000000000000000000001417000230700200575ustar00rootroot00000000000000centreon-plugins-20220113/apps/cisco/ise/restapi/000077500000000000000000000000001417000230700215265ustar00rootroot00000000000000centreon-plugins-20220113/apps/cisco/ise/restapi/custom/000077500000000000000000000000001417000230700230405ustar00rootroot00000000000000centreon-plugins-20220113/apps/cisco/ise/restapi/custom/xmlapi.pm000066400000000000000000000140371417000230700246750ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::cisco::ise::restapi::custom::xmlapi; use strict; use warnings; use centreon::plugins::http; use XML::Simple; 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 => { 'hostname:s' => { name => 'hostname' }, 'url-path:s' => { name => 'url_path' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'timeout:s' => { name => 'timeout' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'XMLAPI OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : undef; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{username} = (defined($self->{option_results}->{username})) ? $self->{option_results}->{username} : undef; $self->{password} = (defined($self->{option_results}->{password})) ? $self->{option_results}->{password} : undef; $self->{url_path} = (defined($self->{option_results}->{url_path})) ? $self->{option_results}->{url_path} : '/admin/API/mnt'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; if (!defined($self->{option_results}->{username}) || $self->{option_results}->{username} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --username option."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{password}) || $self->{option_results}->{password} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --password option."); $self->{output}->option_exit(); } return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{username} = $self->{username}; $self->{option_results}->{password} = $self->{password}; $self->{option_results}->{credentials} = 1; $self->{option_results}->{basic} = 1; $self->{option_results}->{warning_status} = ''; $self->{option_results}->{critical_status} = ''; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->set_options(%{$self->{option_results}}); } sub get_connection_info { my ($self, %options) = @_; return $self->{hostname} . ":" . $self->{port}; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub get_port { my ($self, %options) = @_; return $self->{port}; } sub get_endpoint { my ($self, %options) = @_; $self->settings; my $content = $self->{http}->request(url_path => $self->{url_path} . $options{category}); if ($self->{http}->get_code() != 200) { my $xml_result; eval { $xml_result = XMLin($content); }; if ($@) { $self->{output}->output_add(long_msg => $content, debug => 1); $self->{output}->add_option_msg(short_msg => "Cannot decode xml response: $@"); $self->{output}->option_exit(); } if (defined($xml_result)) { $self->{output}->output_add(long_msg => $content, debug => 1); $self->{output}->add_option_msg(short_msg => "Api return errors: " . join(', ', keys %{$xml_result})); $self->{output}->option_exit(); } } my $xml_result; eval { $xml_result = XMLin($content, ForceArray => [], KeyAttr => []); }; if ($@) { $self->{output}->output_add(long_msg => $content, debug => 1); $self->{output}->add_option_msg(short_msg => "Cannot decode xml response: $@"); $self->{output}->option_exit(); } return $xml_result; } 1; __END__ =head1 NAME Cisco ISE XML API =head1 SYNOPSIS Cisco ISE XML API =head1 XMLAPI OPTIONS =over 8 =item B<--hostname> API hostname. =item B<--url-path> API url path (Default: '/admin/API/mnt') =item B<--port> API port (Default: 443) =item B<--proto> Specify https if needed (Default: 'https') =item B<--username> Set API username =item B<--password> Set API password =item B<--timeout> Set HTTP timeout =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/cisco/ise/restapi/mode/000077500000000000000000000000001417000230700224525ustar00rootroot00000000000000centreon-plugins-20220113/apps/cisco/ise/restapi/mode/session.pm000066400000000000000000000064161417000230700245020ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::cisco::ise::restapi::mode::session; 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, skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'active-sessions', nlabel => 'sessions.active.count', set => { key_values => [ { name => 'active' } ], output_template => 'Active sessions: %d', perfdatas => [ { label => 'active_sessions', template => '%d', min => 0 } ] } }, { label => 'postured-endpoints', nlabel => 'endpoints.postured.count', set => { key_values => [ { name => 'postured' } ], output_template => 'Postured endpoints: %d', perfdatas => [ { label => 'postured_endpoints', template => '%d', min => 0 } ] } }, { label => 'profiler-service-sessions', nlabel => 'sessions.profiler.count', set => { key_values => [ { name => 'profiler' } ], output_template => 'Profiler service sessions: %d', perfdatas => [ { label => 'profiler_service_sessions', template => '%d', min => 0 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $active = $options{custom}->get_endpoint(category => '/Session/ActiveCount'); my $posture = $options{custom}->get_endpoint(category => '/Session/PostureCount'); my $profiler = $options{custom}->get_endpoint(category => '/Session/ProfilerCount'); $self->{global} = ''; $self->{global} = { active => $active->{count}, postured => $posture->{count}, profiler => $profiler->{count}, }; } 1; __END__ =head1 MODE Check sessions counters. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). (Example: --filter-counters='active') =item B<--warning-*> Threshold warning. Can be: 'active-sessions', 'postured-endpoints', 'profiler-service-sessions'. =item B<--critical-*> Threshold critical. Can be: 'active-sessions', 'postured-endpoints', 'profiler-service-sessions'. =back =cut centreon-plugins-20220113/apps/cisco/ise/restapi/plugin.pm000066400000000000000000000024721417000230700233670ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::cisco::ise::restapi::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} = '1.0'; $self->{modes} = { 'session' => 'apps::cisco::ise::restapi::mode::session' }; $self->{custom_modes}->{xmlapi} = 'apps::cisco::ise::restapi::custom::xmlapi'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Cisco ISE (Identity Services Engine) API. =cut centreon-plugins-20220113/apps/cisco/ssms/000077500000000000000000000000001417000230700202645ustar00rootroot00000000000000centreon-plugins-20220113/apps/cisco/ssms/restapi/000077500000000000000000000000001417000230700217335ustar00rootroot00000000000000centreon-plugins-20220113/apps/cisco/ssms/restapi/custom/000077500000000000000000000000001417000230700232455ustar00rootroot00000000000000centreon-plugins-20220113/apps/cisco/ssms/restapi/custom/api.pm000066400000000000000000000210661417000230700243610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::cisco::ssms::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use centreon::plugins::statefile; use JSON::XS; use Digest::MD5 qw(md5_hex); 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 => { 'client-id:s' => { name => 'client_id' }, 'client-secret:s' => { name => 'client_secret' }, 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'timeout:s' => { name => 'timeout' }, 'unknown-http-status:s' => { name => 'unknown_http_status' }, 'warning-http-status:s' => { name => 'warning_http_status' }, 'critical-http-status:s' => { name => 'critical_http_status' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); $self->{cache} = centreon::plugins::statefile->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 8443; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{client_id} = (defined($self->{option_results}->{client_id})) ? $self->{option_results}->{client_id} : ''; $self->{client_secret} = (defined($self->{option_results}->{client_secret})) ? $self->{option_results}->{client_secret} : ''; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300'; $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } if ($self->{client_id} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --client-id option."); $self->{output}->option_exit(); } if ($self->{client_secret} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --client-secret option."); $self->{output}->option_exit(); } $self->{cache}->check_options(option_results => $self->{option_results}); return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Content-Type', value => 'application/json'); $self->{http}->add_header(key => 'Accept', value => 'application/json'); if (defined($self->{access_token})) { $self->{http}->add_header(key => 'Authorization', value => 'Bearer ' . $self->{access_token}); } $self->{http}->set_options(%{$self->{option_results}}); } sub get_access_token { my ($self, %options) = @_; my $has_cache_file = $options{statefile}->read( statefile => 'cisco_ssms_api_' . $self->get_hostname() . '_' . md5_hex($self->{client_id}) ); my $expires_on = $options{statefile}->get(name => 'expires_on'); my $access_token = $options{statefile}->get(name => 'access_token'); if ($has_cache_file == 0 || !defined($access_token) || (($expires_on - time()) < 10)) { my $json_request = { grant_type => 'client_credentials', client_id => $self->{client_id}, client_secret => $self->{client_secret} }; my $encoded; eval { $encoded = encode_json($json_request); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot encode json request"); $self->{output}->option_exit(); } $self->settings(); my ($content) = $self->{http}->request( method => 'POST', url_path => '/backend/oauth/token', query_form_post => $encoded, unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status} ); my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } $access_token = $decoded->{access_token}; my $datas = { last_timestamp => time(), access_token => $decoded->{access_token}, expires_on => (time() + $decoded->{expires_in}) }; $options{statefile}->write(data => $datas); } return $access_token; } sub request_api { my ($self, %options) = @_; if (!defined($self->{access_token})) { $self->{access_token} = $self->get_access_token(statefile => $self->{cache}); } $self->settings(); my ($content) = $self->{http}->request( method => 'POST', url_path => $options{endpoint}, query_form_post => encode_json({ limit => -1 }), unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status} ); my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } return $decoded; } sub get_alerts { my ($self, %options) = @_; return $self->request_api(endpoint => '/api/v1/accounts/' . $options{account} . '/alerts'); } sub get_licenses { my ($self, %options) = @_; return $self->request_api(endpoint => '/api/v1/accounts/' . $options{account} . '/licenses'); } 1; __END__ =head1 NAME Cisco SSMS Rest API =head1 REST API OPTIONS Cisco SSMS Rest API =over 8 =item B<--hostname> Set hostname. =item B<--port> Port used (Default: 8443) =item B<--proto> Specify https if needed (Default: 'https') =item B<--client-id> Set client ID. =item B<--client-secret> Set client secret. =item B<--timeout> Set timeout in seconds (Default: 10). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/cisco/ssms/restapi/mode/000077500000000000000000000000001417000230700226575ustar00rootroot00000000000000centreon-plugins-20220113/apps/cisco/ssms/restapi/mode/alerts.pm000066400000000000000000000134231417000230700245120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::cisco::ssms::restapi::mode::alerts; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_alert_output { my ($self, %options) = @_; return sprintf( '[message type: %s] [severity: %s] [source: %s]', $self->{result_values}->{message_type}, $self->{result_values}->{severity}, $self->{result_values}->{source} ne '' ? $self->{result_values}->{source} : '-' ); } sub account_long_output { my ($self, %options) = @_; return "checking account '" . $options{instance_value}->{display} . "'"; } sub prefix_account_output { my ($self, %options) = @_; return "account '" . $options{instance_value}->{display} . "' "; } sub prefix_alerts_global_output { my ($self, %options) = @_; return 'alerts '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'accounts', type => 3, cb_prefix_output => 'prefix_account_output', cb_long_output => 'account_long_output', indent_long_output => ' ', message_multiple => 'All accounts are ok', group => [ { name => 'alerts_global', type => 0, cb_prefix_output => 'prefix_alerts_global_output' }, { name => 'alerts', type => 1, display_short => 0 } ] } ]; $self->{maps_counters}->{alerts_global} = [ { label => 'alerts-minor', nlabel => 'account.alerts.minor.count', set => { key_values => [ { name => 'minor' } ], output_template => 'minor: %s', perfdatas => [ { template => '%d', min => 0, label_extra_instance => 1 } ] } }, { label => 'alerts-major', nlabel => 'account.alerts.major.count', set => { key_values => [ { name => 'major' } ], output_template => 'major: %s', perfdatas => [ { template => '%d', min => 0, label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{alerts} = [ { label => 'alert-status', threshold => 0, set => { key_values => [ { name => 'severity' }, { name => 'message_type' }, { name => 'source' } ], closure_custom_output => $self->can('custom_alert_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => sub { return 'ok'; } } } ]; } 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 => { 'account:s@' => { name => 'account' }, 'filter-message-type:s' => { name => 'filter_message_type' }, 'display-alerts' => { name => 'display_alerts' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{account_names} = []; if (defined($self->{option_results}->{account})) { foreach my $account (@{$self->{option_results}->{account}}) { push @{$self->{account_names}}, $account if ($account ne ''); } } if (scalar(@{$self->{account_names}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'need to specify --account option.'); $self->{output}->option_exit(); } } sub manage_selection { my ($self, %options) = @_; $self->{accounts} = {}; foreach my $account (@{$self->{account_names}}) { my $results = $options{custom}->get_alerts( account => $account ); next if (!defined($results->{alerts})); $self->{accounts}->{$account} = { display => $account, alerts_global => { minor => 0, major => 0 }, alerts => {} }; my $i = 0; foreach (@{$results->{alerts}}) { next if (defined($self->{option_results}->{filter_message_type}) && $self->{option_results}->{filter_message_type} ne '' && $_->{messageType} !~ /$self->{option_results}->{filter_message_type}/); $self->{accounts}->{$account}->{alerts_global}->{ lc($_->{severity}) }++; next if (!defined($self->{option_results}->{display_alerts})); $self->{accounts}->{$account}->{alerts}->{$i} = { message_type => $_->{messageType}, severity => lc($_->{severity}), source => $_->{source} }; $i++; } } } 1; __END__ =head1 MODE Check alerts. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='minor' =item B<--account> Check account name (Required. Multiple option). =item B<--filter-message-type> Filter alerts by message type (can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'alerts-minor', 'alerts-major'. =back =cut centreon-plugins-20220113/apps/cisco/ssms/restapi/mode/licenses.pm000066400000000000000000000161361417000230700250310ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::cisco::ssms::restapi::mode::licenses; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf( "status: '%s'", $self->{result_values}->{status} ); } sub custom_license_output { my ($self, %options) = @_; return sprintf( "usage total: %s used: %s (%.2f%%) free: %s (%.2f%%)", $self->{result_values}->{total}, $self->{result_values}->{used}, $self->{result_values}->{prct_used}, $self->{result_values}->{free}, $self->{result_values}->{prct_free} ); } sub account_long_output { my ($self, %options) = @_; return "checking account '" . $options{instance_value}->{display} . "'"; } sub prefix_account_output { my ($self, %options) = @_; return "account '" . $options{instance_value}->{display} . "' "; } sub prefix_license_output { my ($self, %options) = @_; return "license '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'accounts', type => 3, cb_prefix_output => 'prefix_account_output', cb_long_output => 'account_long_output', indent_long_output => ' ', message_multiple => 'All accounts are ok', group => [ { name => 'licenses', display_long => 1, cb_prefix_output => 'prefix_license_output', message_multiple => 'licenses are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{licenses} = [ { label => 'license-status', type => 2, critical_default => '%{status} !~ /in compliance/i', set => { key_values => [ { name => 'status' }, { name => 'display' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'usage', nlabel => 'licenses.usage.count', set => { key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_license_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', label_extra_instance => 1 } ] } }, { label => 'usage-free', display_ok => 0, nlabel => 'licenses.free.count', set => { key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_license_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', label_extra_instance => 1 } ] } }, { label => 'usage-prct', display_ok => 0, nlabel => 'licenses.usage.percentage', set => { key_values => [ { name => 'prct_used' }, { name => 'used' }, { name => 'free' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_license_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'account:s@' => { name => 'account' }, 'filter-license-name:s' => { name => 'filter_license_name' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{account_names} = []; if (defined($self->{option_results}->{account})) { foreach my $account (@{$self->{option_results}->{account}}) { push @{$self->{account_names}}, $account if ($account ne ''); } } if (scalar(@{$self->{account_names}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'need to specify --account option.'); $self->{output}->option_exit(); } } sub manage_selection { my ($self, %options) = @_; $self->{accounts} = {}; foreach my $account (@{$self->{account_names}}) { my $results = $options{custom}->get_licenses( account => $account ); next if (!defined($results->{licenses})); $self->{accounts}->{$account} = { display => $account, licenses => {} }; foreach (@{$results->{licenses}}) { next if (defined($self->{option_results}->{filter_license_name}) && $self->{option_results}->{filter_license_name} ne '' && $_->{license} !~ /$self->{option_results}->{filter_license_name}/); $self->{accounts}->{$account}->{licenses}->{ $_->{license} } = { display => $_->{license}, status => $_->{status}, used => $_->{inUse}, free => $_->{available}, total => $_->{quantity}, prct_used => $_->{quantity} > 0 ? ($_->{inUse} * 100 / $_->{quantity}) : undef, prct_free => $_->{quantity} > 0 ? ($_->{available} * 100 / $_->{quantity}) : undef }; } } } 1; __END__ =head1 MODE Check licenses. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='status' =item B<--account> Check account name (Required. Multiple option). =item B<--filter-license-name> Filter license name (can be a regexp). =item B<--unknown-license-status> Set unknown threshold for status. Can used special variables like: %{status}, %{display} =item B<--warning-license-status> Set warning threshold for status. Can used special variables like: %{status}, %{display} =item B<--critical-license-status> Set critical threshold for status (Default: '%{status} !~ /in compliance/i'). Can used special variables like: %{status}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'usage' (B), 'usage-free' (B), 'usage-prct' (%). =back =cut centreon-plugins-20220113/apps/cisco/ssms/restapi/plugin.pm000066400000000000000000000026071417000230700235740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::cisco::ssms::restapi::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} = { 'alerts' => 'apps::cisco::ssms::restapi::mode::alerts', 'licenses' => 'apps::cisco::ssms::restapi::mode::licenses' }; $self->{custom_modes}->{api} = 'apps::cisco::ssms::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Cisco Smart Software Manager Satellite in Rest API. =cut centreon-plugins-20220113/apps/citrix/000077500000000000000000000000001417000230700175015ustar00rootroot00000000000000centreon-plugins-20220113/apps/citrix/local/000077500000000000000000000000001417000230700205735ustar00rootroot00000000000000centreon-plugins-20220113/apps/citrix/local/mode/000077500000000000000000000000001417000230700215175ustar00rootroot00000000000000centreon-plugins-20220113/apps/citrix/local/mode/folder.pm000066400000000000000000000110731417000230700233320ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::citrix::local::mode::folder; use base qw(centreon::plugins::mode); use strict; use warnings; use Win32::OLE; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'warning:s' => { name => 'warning' }, 'critical:s' => { name => 'critical' }, 'folder:s' => { name => 'folder' }, 'filter-folder' => { name => 'filter_folder' } }); $self->{wql_filter} = ''; return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (($self->{perfdata}->threshold_validate(label => 'warning', value => $self->{option_results}->{warning})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning threshold '" . $self->{option_results}->{warning} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'critical', value => $self->{option_results}->{critical})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical threshold '" . $self->{option_results}->{critical} . "'."); $self->{output}->option_exit(); } if (defined($self->{option_results}->{folder})) { if (defined($self->{option_results}->{filter_folder})) { $self->{wql_filter} .= " FolderDN like '" . $self->{option_results}->{folder} . "'"; } else { $self->{wql_filter} .= " FolderDN='" . $self->{option_results}->{folder} . "'"; } } else { $self->{wql_filter} .= " FolderDN like '%'"; } } sub run { my ($self, %options) = @_; $self->{output}->output_add( severity => 'Ok', short_msg => 'All folders are ok' ); my $wmi = Win32::OLE->GetObject('winmgmts:root\citrix'); if (!defined($wmi)) { $self->{output}->add_option_msg(short_msg => "Cant create server object:" . Win32::OLE->LastError()); $self->{output}->option_exit(); } my $query = "Select FolderDN from Citrix_ServerFolder where " . $self->{wql_filter}; my $resultset = $wmi->ExecQuery($query); foreach my $obj (in $resultset) { my $folderDN = $obj->{FolderDN}; my $query2 = "ASSOCIATORS OF {Citrix_ServerFolder.FolderDN='" . $folderDN . "'} WHERE AssocClass=Citrix_ServersInFolder Role=Antecedent"; my $resultset2 = $wmi->ExecQuery($query2); my $numServers = keys %$resultset2; $self->{output}->output_add(long_msg => $numServers . " servers in folder '" . $folderDN . "'"); my $exit = $self->{perfdata}->threshold_check(value => $numServers, 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 => $numServers . " servers in in folder '" . $folderDN . "'" ); } $self->{output}->perfdata_add( label => 'servers', nlabel => 'folder.servers.count', instances => $folderDN, value => $numServers, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0 ); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check Citrix servers per folder. =over 8 =item B<--warning> Threshold warning of servers per folder. =item B<--critical> Threshold critical of servers per folder. =item B<--folder> Specify a folder. =item B<--filter-folder> Use like request in WQL for folder (use with --folder). =back =cut centreon-plugins-20220113/apps/citrix/local/mode/license.pm000066400000000000000000000163351417000230700235070ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::citrix::local::mode::license; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Win32::OLE; sub custom_license_output { my ($self, %options) = @_; return sprintf( 'total: %s used: %s (%.2f%%) free: %s (%.2f%%)', $self->{result_values}->{total}, $self->{result_values}->{used}, $self->{result_values}->{prct_used}, $self->{result_values}->{free}, $self->{result_values}->{prct_free} ); } sub prefix_global_output { my ($self, %options) = @_; return 'Licenses '; } sub prefix_license_output { my ($self, %options) = @_; return "License '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } }, { name => 'licenses', type => 1, cb_prefix_output => 'prefix_license_output', message_multiple => 'All licenses are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'licenses-usage', nlabel => 'licenses.usage.count', set => { key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_license_output'), perfdatas => [ { template => '%d', min => 0, max => 'total' } ] } }, { label => 'licenses-usage-free', display_ok => 0, nlabel => 'licenses.free.count', set => { key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_license_output'), perfdatas => [ { template => '%d', min => 0, max => 'total' } ] } }, { label => 'licenses-usage-prct', display_ok => 0, nlabel => 'licenses.usage.percentage', set => { key_values => [ { name => 'prct_used' } ], output_template => 'used: %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%' } ] } } ]; $self->{maps_counters}->{licenses} = [ { label => 'license-usage', nlabel => 'license.usage.count', set => { key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' }, { name => 'display' } ], closure_custom_output => $self->can('custom_license_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'license-usage-free', display_ok => 0, nlabel => 'license.free.count', set => { key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' }, { name => 'display' } ], closure_custom_output => $self->can('custom_license_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'license-usage-prct', display_ok => 0, nlabel => 'license.usage.percentage', set => { key_values => [ { name => 'prct_used' }, { name => 'used' }, { name => 'free' }, { name => 'prct_free' }, { name => 'total' }, { name => 'display' } ], closure_custom_output => $self->can('custom_license_output'), perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $wmi = Win32::OLE->GetObject('winmgmts:root\CitrixLicensing'); if (!defined($wmi)) { $self->{output}->add_option_msg(short_msg => 'Cant create server object:' . Win32::OLE->LastError()); $self->{output}->option_exit(); } $self->{global} = { total => 0, used => 0 }; my $query = "Select PLD,InUseCount,Count from Citrix_GT_License_Pool"; my $resultset = $wmi->ExecQuery($query); $self->{licenses} = {}; foreach my $obj (in $resultset) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $obj->{PLD} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping license '" . $obj->{PLD} . "': no matching filter.", debug => 1); next; } $self->{global}->{used} += $obj->{InUseCount}; $self->{global}->{total} += $obj->{Count}; $self->{licenses}->{ $obj->{PLD} }->{display} = $obj->{PLD}; $self->{licenses}->{ $obj->{PLD} }->{used} = $obj->{InUseCount}; $self->{licenses}->{ $obj->{PLD} }->{total} = $obj->{Count}; $self->{licenses}->{ $obj->{PLD} }->{prct_used} = $obj->{InUseCount} * 100 / $obj->{Count}; $self->{licenses}->{ $obj->{PLD} }->{prct_free} = 100 - $self->{licenses}->{ $obj->{PLD} }->{prct_used}; $self->{licenses}->{ $obj->{PLD} }->{free} = $obj->{Count} - $obj->{InUseCount}; } if (scalar(keys %{$self->{licenses}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'Cannot get licenses'); $self->{output}->option_exit(); } $self->{global}->{prct_used} = $self->{global}->{used} * 100 / $self->{global}->{total}; $self->{global}->{prct_free} = 100 - $self->{global}->{prct_used}; $self->{global}->{free} = $self->{global}->{total} - $self->{global}->{used}; } 1; __END__ =head1 MODE Check Citrix licenses. =over 8 =item B<--filter-name> Filter license name. =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'license-usage', 'license-usage-free, 'license-usage-prct' (%), 'licenses-usage', 'licenses-usage-free', 'licenses-usage-prct' (%). =back =cut centreon-plugins-20220113/apps/citrix/local/mode/session.pm000066400000000000000000000155261417000230700235510ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::citrix::local::mode::session; use base qw(centreon::plugins::mode); use strict; use warnings; use Win32::OLE; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'warning:s' => { name => 'warning' }, 'critical:s' => { name => 'critical' }, 'domain:s' => { name => 'domain' }, 'filter-domain' => { name => 'filter_domain' }, 'farm:s' => { name => 'farm' }, 'filter-farm' => { name => 'filter_farm' }, 'server:s' => { name => 'server' }, 'filter-server' => { name => 'filter_server' }, 'zone:s' => { name => 'zone' }, 'filter-zone' => { name => 'filter_zone' } }); $self->{wql_filter} = ''; 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}->{domain})) { if (defined($self->{option_results}->{filter_domain})) { $self->{wql_filter} .= "Domain like '" . $self->{option_results}->{domain} . "'"; } else { $self->{wql_filter} .= "Domain='" . $self->{option_results}->{domain} . "'"; } } else { $self->{wql_filter} .= "Domain like '%'"; } if (defined($self->{option_results}->{farm})) { if (defined($self->{option_results}->{filter_farm})) { $self->{wql_filter} .= " and FarmName like '" . $self->{option_results}->{farm} . "'"; } else { $self->{wql_filter} .= " and FarmName='" . $self->{option_results}->{farm} . "'"; } } else { $self->{wql_filter} .= " and FarmName like '%'"; } if (defined($self->{option_results}->{server})) { if (defined($self->{option_results}->{filter_server})) { $self->{wql_filter} .= " and ServerName like '" . $self->{option_results}->{server} . "'"; } else { $self->{wql_filter} .= " and ServerName='" . $self->{option_results}->{server} . "'"; } } else { $self->{wql_filter} .= " and ServerName like '%'"; } if (defined($self->{option_results}->{zone})) { if (defined($self->{option_results}->{filter_zone})) { $self->{wql_filter} .= " and ZoneName like '" . $self->{option_results}->{zone} . "'"; } else { $self->{wql_filter} .= " and ZoneName='" . $self->{option_results}->{zone} . "'"; } } else { $self->{wql_filter} .= " and ZoneName like '%'"; } } sub run { my ($self, %options) = @_; $self->{output}->output_add( severity => 'Ok', short_msg => 'All sessions are ok' ); my $wmi = Win32::OLE->GetObject('winmgmts:root\citrix'); if (!defined($wmi)) { $self->{output}->add_option_msg(short_msg => "Cant create server object:" . Win32::OLE->LastError()); $self->{output}->option_exit(); } my $query = "Select Domain,FarmName,NumberOfActiveSessions,NumberOfDisconnectedSessions,NumberOfSessions,ServerName,ZoneName from MetaFrame_Server where " . $self->{wql_filter}; my $resultset = $wmi->ExecQuery($query); foreach my $obj (in $resultset) { my $domain = $obj->{Domain}; my $farm = $obj->{FarmName}; my $activeSessions = $obj->{NumberOfActiveSessions}; my $disconnectedSessions = $obj->{NumberOfDisconnectedSessions}; my $sessions = $obj->{NumberOfSessions}; my $server = $obj->{ServerName}; my $zone = $obj->{ZoneName}; $self->{output}->output_add(long_msg => "Server '" . $server . "' active sessions : " . $activeSessions . " [disconnected sessions : " . $disconnectedSessions . "] [total sessions : " . $sessions . "] [Domain '" . $domain . "', Farm '" . $farm . "', Zone '" . $zone . "']"); my $exit = $self->{perfdata}->threshold_check(value => $activeSessions, 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 => "Server '" . $server . "' active sessions : " . $activeSessions . " [disconnected sessions : " . $disconnectedSessions . "] [total sessions : " . $sessions . "]"); } $self->{output}->perfdata_add( label => 'active_sessions', nlabel => 'sessions.active.count', instances => $server, value => $activeSessions, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0 ); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check Citrix sessions. =over 8 =item B<--warning> Threshold warning of active sessions. =item B<--critical> Threshold critical of active sessions. =item B<--domain> Specify a domain. =item B<--filter-domain> Use like request in WQL for domain (use with --domain). =item B<--farm> Specify a farm name. =item B<--filter-farm> Use like request in WQL for farm name (use with --farm). =item B<--server> Specify a server name. =item B<--filter-server> Use like request in WQL for server name (use with --server). =item B<--zone> Specify a zone. =item B<--filter-zone> Use like request in WQL for zone (use with --zone). =back =cut centreon-plugins-20220113/apps/citrix/local/mode/zone.pm000066400000000000000000000104751417000230700230370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::citrix::local::mode::zone; use base qw(centreon::plugins::mode); use strict; use warnings; use Win32::OLE; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'warning:s' => { name => 'warning' }, 'critical:s' => { name => 'critical' }, 'zone:s' => { name => 'zone' }, 'filter-zone' => { name => 'filter_zone' } }); $self->{wql_filter} = ''; 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}->{zone})) { if (defined($self->{option_results}->{filter_zone})) { $self->{wql_filter} .= " ZoneName like '" . $self->{option_results}->{zone} . "'"; } else { $self->{wql_filter} .= " ZoneName='" . $self->{option_results}->{zone} . "'"; } } else { $self->{wql_filter} .= " ZoneName like '%'"; } } sub run { my ($self, %options) = @_; $self->{output}->output_add( severity => 'Ok', short_msg => 'All zones are ok' ); my $wmi = Win32::OLE->GetObject('winmgmts:root\citrix'); if (!defined($wmi)) { $self->{output}->add_option_msg(short_msg => "Cant create server object:" . Win32::OLE->LastError()); $self->{output}->option_exit(); } my $query = "Select ZoneName,NumServersInZone from Citrix_Zone where " . $self->{wql_filter}; my $resultset = $wmi->ExecQuery($query); foreach my $obj (in $resultset) { my $zone = $obj->{ZoneName}; my $numServers = $obj->{NumServersInZone}; $self->{output}->output_add(long_msg => $numServers . " servers in zone '" . $zone . "'"); my $exit = $self->{perfdata}->threshold_check(value => $numServers, 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 => $numServers . " servers in zone '" . $zone . "'"); } $self->{output}->perfdata_add( label => 'servers', nlabel => 'zone.servers.count', instances => $zone, value => $numServers, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0 ); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check Citrix servers per zone. =over 8 =item B<--warning> Threshold warning of servers per zone. =item B<--critical> Threshold critical of servers per zone. =item B<--zone> Specify a zone. =item B<--filter-zone> Use like request in WQL for zone (use with --zone). =back =cut centreon-plugins-20220113/apps/citrix/local/plugin.pm000066400000000000000000000025561417000230700224370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::citrix::local::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} = '0.1'; $self->{modes} = { 'folder' => 'apps::citrix::local::mode::folder', 'license' => 'apps::citrix::local::mode::license', 'session' => 'apps::citrix::local::mode::session', 'zone' => 'apps::citrix::local::mode::zone' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Citrix locally. =cut centreon-plugins-20220113/apps/drbd/000077500000000000000000000000001417000230700171125ustar00rootroot00000000000000centreon-plugins-20220113/apps/drbd/local/000077500000000000000000000000001417000230700202045ustar00rootroot00000000000000centreon-plugins-20220113/apps/drbd/local/mode/000077500000000000000000000000001417000230700211305ustar00rootroot00000000000000centreon-plugins-20220113/apps/drbd/local/mode/resources.pm000066400000000000000000000526451417000230700235140ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::drbd::local::mode::resources; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use Digest::MD5 qw(md5_hex); sub custom_role_output { my ($self, %options) = @_; return sprintf( 'role: %s', $self->{result_values}->{role} ); } sub custom_disk_status_output { my ($self, %options) = @_; return sprintf( 'status: %s', $self->{result_values}->{disk_status} ); } sub custom_peer_role_output { my ($self, %options) = @_; return sprintf( 'role: %s', $self->{result_values}->{role} ); } sub custom_peer_connection_output { my ($self, %options) = @_; return sprintf( 'connection status: %s', $self->{result_values}->{connection_status} ); } sub custom_peer_device_replication_output { my ($self, %options) = @_; return sprintf( 'replication status: %s', $self->{result_values}->{device_replication_status} ); } sub custom_peer_device_disk_output { my ($self, %options) = @_; return sprintf( 'disk status: %s', $self->{result_values}->{device_disk_status} ); } sub resource_long_output { my ($self, %options) = @_; return "checking resource '" . $options{instance_value}->{display} . "'"; } sub prefix_resource_output { my ($self, %options) = @_; return "resource '" . $options{instance_value}->{display} . "' "; } sub prefix_device_output { my ($self, %options) = @_; return 'device disk '; } sub prefix_peer_output { my ($self, %options) = @_; return "peer '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'resources', type => 3, cb_prefix_output => 'prefix_resource_output', cb_long_output => 'resource_long_output', indent_long_output => ' ', message_multiple => 'All drbd resources are ok', group => [ { name => 'role', type => 0, skipped_code => { -10 => 1 } }, { name => 'device', type => 0, cb_prefix_output => 'prefix_device_output', skipped_code => { -10 => 1 } }, { name => 'peers', display_long => 1, cb_prefix_output => 'prefix_peer_output', message_multiple => 'All peers are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'resources-total', nlabel => 'resources.total.count', set => { key_values => [ { name => 'resources_total' } ], output_template => 'total resources: %s', perfdatas => [ { template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{role} = [ { label => 'role', type => 2, unknown_default => '%{role} =~ /unknown/i', critical_default => '%{role} =~ /unconfigured/i', set => { key_values => [ { name => 'role' }, { name => 'display' } ], closure_custom_output => $self->can('custom_role_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{device} = [ { label => 'disk-status', type => 2, unknown_default => '%{disk_status} =~ /dunknown/i', warning_default => '%{disk_status} =~ /attaching|detaching|negotiating/i', critical_default => '%{disk_status} =~ /outdated|inconsistent|failed|diskless/i', set => { key_values => [ { name => 'disk_status' }, { name => 'display' } ], closure_custom_output => $self->can('custom_disk_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'data-read', nlabel => 'disk.data.read.bytespersecond', set => { key_values => [ { name => 'data_read', per_second => 1 }, { name => 'display' } ], output_template => 'data read: %s%s/s', output_change_bytes => 1, perfdatas => [ { template => '%s', min => 0, unit => 'B/s', label_extra_instance => 1 } ] } }, { label => 'data-written', nlabel => 'disk.data.written.bytespersecond', set => { key_values => [ { name => 'data_written', per_second => 1 }, { name => 'display' } ], output_template => 'data written: %s%s/s', output_change_bytes => 1, perfdatas => [ { template => '%s', min => 0, unit => 'B/s', label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{peers} = [ { label => 'peer-role', type => 2, unknown_default => '%{role} =~ /unknown/i', critical_default => '%{role} =~ /unconfigured/i', set => { key_values => [ { name => 'role' }, { name => 'display' } ], closure_custom_output => $self->can('custom_peer_role_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'peer-connection-status', type => 2, warning_default => '%{connection_status} =~ /^(?:connecting|disconnecting|standalone|teardown)$/i', critical_default => '%{connection_status} =~ /^(?:brokenpipe|networkfailure|protocolerror|timeout|unconnected|wfconnection|wfreportparams)$/i', set => { key_values => [ { name => 'connection_status' }, { name => 'display' } ], closure_custom_output => $self->can('custom_peer_connection_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'peer-device-replication-status', type => 2, warning_default => '%{device_replication_status} =~ /^(?:ahead|off|startingsyncs|startingsynct|syncsource|synctarget|verifys|verifyt|wfsyncuuid|syncingall|syncingquick)$/i', critical_default => '%{device_replication_status} =~ /^(?:behind|pausedsyncs|pausedsynct|wfbitmaps|wfbitmapt|syncpaused|skippedsyncs|skippedsynct)$/i', set => { key_values => [ { name => 'device_replication_status' }, { name => 'display' } ], closure_custom_output => $self->can('custom_peer_device_replication_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'peer-device-disk-status', type => 2, unknown_default => '%{device_disk_status} =~ /dunknown/i', warning_default => '%{device_disk_status} =~ /^(?:attaching|detaching|diskless|failed|inconsistent|negotiating|outdated)$/i', set => { key_values => [ { name => 'device_disk_status' }, { name => 'display' } ], closure_custom_output => $self->can('custom_peer_device_disk_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'peer-traffic-in', nlabel => 'peer.traffic.in.bitspersecond', set => { key_values => [ { name => 'traffic_in', per_second => 1 }, { name => 'display' } ], output_template => 'traffic in: %s %s/s', output_change_bytes => 2, perfdatas => [ { template => '%s', min => 0, unit => 'b/s', label_extra_instance => 1 } ] } }, { label => 'peer-traffic-out', nlabel => 'peer.traffic.out.bitspersecond', set => { key_values => [ { name => 'traffic_out', per_second => 1 }, { name => 'display' } ], output_template => 'traffic out: %s %s/s', output_change_bytes => 2, perfdatas => [ { template => '%s', min => 0, unit => 'b/s', label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-resource-name:s' => { name => 'filter_resource_name' }, 'legacy-proc' => { name => 'legacy_proc' } }); return $self; } =pod replication: ahead [WARN] behind [CRIT] off [WARN] established [OK] pausedsyncs [CRIT] pausedsynct [CRIT] startingsyncs [WARN] startingsynct [WARN] syncsource [WARN] synctarget [WARN] verifys [WARN] verifyt [WARN] wfbitmaps [CRIT] wfbitmapt [CRIT] wfsyncuuid [WARN] connection states: brokenpipe [CRIT] connected [OK] connecting [WARN] disconnecting [WARN] networkfailure [CRIT] protocolerror [CRIT] standalone [WARN] teardown [WARN] timeout [CRIT] unconnected [CRIT] wfconnection [CRIT] wfreportparams [CRIT] # old version - connection and replication are merged (and also unconfigured) unconfigured [CRIT] syncingall [WARN] syncingquick [WARN] syncpaused [CRIT] skippedsyncs [CRIT] skippedsynct [CRIT] disk states: attaching [WARN] consistent [OK] detaching [WARN] diskless [CRIT] dunknown [WARN] failed [CRIT] inconsistent [CRIT] negotiating [WARN] outdated [CRIT] uptodate [OK] peer-disk: attaching [WARN] consistent [OK] detaching [WARN] diskless [WARN] dunknown [WARN] failed [WARN] inconsistent [WARN] negotiating [WARN] outdated [WARN] uptodate [OK] role: primary [OK] secondary [OK] unknown [WARN] unconfigured [CRIT] ----------------------- old versions /proc/drbd ----------------------- 0: cs:Connected st:Secondary/Secondary ld:Inconsistent ns:0 nr:0 dw:0 dr:0 al:0 bm:17408 lo:0 pe:0 ua:0 ap:0 1: cs:Unconfigured st = role ld = Local data consistency ------------------------- version: 8.3.7 (api:88/proto:86-91) GIT-hash: ea9e28dbff98e331a62bcbcc63a6135808fe2917 build by root@xxxx, 2012-05-09 11:46:08 0: cs:Connected ro:Secondary/Primary ds:UpToDate/UpToDate C r---- ns:17 nr:4207 dw:4224 dr:24 al:1 bm:1 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:0 1: cs:Connected ro:Secondary/Primary ds:UpToDate/UpToDate C r---- ns:100808 nr:1272593360 dw:1272711944 dr:19001 al:13 bm:23 lo:0 pe:0 ua:0 ap:0 ep:1 wo:d oos:0 =cut sub legacy_proc { my ($self, %options) = @_; # 0 = replication # 1 = connection # 2 = role my $map_connection = { ahead => 0, behind => 0, off => 0, established => 0, pausedsyncs => 0, pausedsynct => 0, startingsyncs => 0, startingsynct => 0, syncsource => 0, synctarget => 0, verifys => 0, verifyt => 0, wfbitmaps => 0, wfbitmapt => 0, wfsyncuuid => 0, syncingall => 0, syncingquick => 0, syncpaused => 0, skippedsyncs => 0, skippedsynct => 0, brokenpipe => 1, connected => 1, connecting => 1, disconnecting => 1, networkfailure => 1, protocolerror => 1, standalone => 1, teardown => 1, timeout => 1, unconnected => 1, wfconnection => 1, wfreportparams => 1, unconfigured => 2 }; $self->{resources} = {}; while ($options{stdout} =~ /^\s*(\d+):(.*?)(?=\n\s*(\d+):|\Z$)/msg) { my ($res_name, $content) = ($1, $2); if (defined($self->{option_results}->{filter_resource_name}) && $self->{option_results}->{filter_resource_name} ne '' && $res_name !~ /$self->{option_results}->{filter_resource_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $res_name . "': no matching filter.", debug => 1); next; } $self->{resources}->{$res_name} = { display => $res_name, role => { display => $res_name, role => '-' }, device => { display => $res_name, disk_status => '-' }, peers => { 0 => { display => 0, role => '-', connection_status => '-', device_replication_status => '-', device_disk_status => '-' } } }; if ($content =~ /cs:(\S+)/ms) { my $cs = lc($1); if ($map_connection->{$cs} == 0) { $self->{resources}->{$res_name}->{peers}->{0}->{device_replication_status} = $cs; } elsif ($map_connection->{$cs} == 1) { $self->{resources}->{$res_name}->{peers}->{0}->{connection_status} = $cs; } elsif ($map_connection->{$cs} == 2) { $self->{resources}->{$res_name}->{role}->{role} = $cs; } } if ($content =~ /(?:ro|st):(.*?)\/(.*?)\s/ms) { $self->{resources}->{$res_name}->{role}->{role} = lc($1); $self->{resources}->{$res_name}->{peers}->{0}->{role} = lc($2); } if ($content =~ /ds:(.*?)\/(.*?)\s/ms) { $self->{resources}->{$res_name}->{device}->{disk_status} = lc($1); $self->{resources}->{$res_name}->{peers}->{0}->{device_disk_status} = lc($2); } if ($content =~ /ld:(\S+)/ms) { $self->{resources}->{$res_name}->{device}->{disk_status} = lc($1); } if ($content =~ /dw:(\d+).*?dr:(\d+)/ms) { $self->{resources}->{$res_name}->{device}->{data_written} = $1 * 1024; $self->{resources}->{$res_name}->{device}->{data_read} = $2 * 1024; } if ($content =~ /ns:(\d+).*?nr:(\d+)/ms) { $self->{resources}->{$res_name}->{peers}->{0}->{traffic_out} = $1 * 1024 * 8; $self->{resources}->{$res_name}->{peers}->{0}->{traffic_in} = $2 * 1024 * 8; } } } sub drbdsetup_events2 { my ($self, %options) = @_; #exists resource name:drbd1 role:Secondary suspended:no write-ordering:flush #exists connection name:drbd1 peer-node-id:0 conn-name:central-2004 connection:Connected role:Primary congested:no ap-in-flight:0 rs-in-flight:0 #exists connection name:drbd1 peer-node-id:1 conn-name:poller-2004-1 connection:Connected role:Secondary congested:no ap-in-flight:0 rs-in-flight:0 #exists device name:drbd1 volume:0 minor:1 disk:UpToDate client:no quorum:yes size:765868 read:0 written:765868 al-writes:0 bm-writes:0 upper-pending:0 lower-pending:0 al-suspended:no blocked:no #exists peer-device name:drbd1 peer-node-id:0 conn-name:central-2004 volume:0 replication:Established peer-disk:UpToDate peer-client:no resync-suspended:no received:765868 sent:0 out-of-sync:0 pending:0 unacked:0 #exists peer-device name:drbd1 peer-node-id:1 conn-name:poller-2004-1 volume:0 replication:Established peer-disk:UpToDate peer-client:no resync-suspended:no received:0 sent:0 out-of-sync:0 pending:0 unacked:0 #exists - $self->{resources} = {}; foreach my $line (split /\n/, $options{stdout}) { next if ($line !~ /^exists\s+(?:resource|connection|device|peer-device)\s+name:(\S+)/); my $res_name = $1; if (defined($self->{option_results}->{filter_resource_name}) && $self->{option_results}->{filter_resource_name} ne '' && $res_name !~ /$self->{option_results}->{filter_resource_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $res_name . "': no matching filter.", debug => 1); next; } if ($line =~ /^exists\s+resource\s+.*?role:(\S+)/) { $self->{resources}->{ $res_name } = { display => $res_name, role => { display => $res_name, role => $1 }, device => { display => $res_name }, peers => {} }; } elsif ($line =~ /^exists\s+connection.*?conn-name:(\S+)\s+connection:(\S+)\s+role:(\S+)/) { $self->{resources}->{ $res_name }->{peers}->{ $1 } = { display => $1 } if (!defined($self->{resources}->{ $res_name }->{peers}->{ $1 })); $self->{resources}->{ $res_name }->{peers}->{ $1 }->{connection_status} = $2; $self->{resources}->{ $res_name }->{peers}->{ $1 }->{role} = $3; } elsif ($line =~ /^exists\s+device.*?disk:(\S+).*?read:(\d+)\s+written:(\d+)/) { $self->{resources}->{ $res_name }->{device}->{disk_status} = $1; $self->{resources}->{ $res_name }->{device}->{data_read} = $2 * 1024; $self->{resources}->{ $res_name }->{device}->{data_written} = $3 * 1024; } elsif ($line =~ /^exists\s+peer-device.*?conn-name:(\S+).*?replication:(\S+).*?peer-disk:(\S+).*?received:(\d+)\s+sent:(\d+)/) { $self->{resources}->{ $res_name }->{peers}->{ $1 } = { display => $1 } if (!defined($self->{resources}->{ $res_name }->{peers}->{ $1 })); $self->{resources}->{ $res_name }->{peers}->{ $1 }->{device_replication_status} = $2; $self->{resources}->{ $res_name }->{peers}->{ $1 }->{device_disk_status} = $3; $self->{resources}->{ $res_name }->{peers}->{ $1 }->{traffic_in} = $4 * 1024 * 8; $self->{resources}->{ $res_name }->{peers}->{ $1 }->{traffic_out} = $5 * 1024 * 8; } } } sub manage_selection { my ($self, %options) = @_; my ($command, $command_path, $command_options) = ('drbdsetup', '/usr/sbin', 'events2 --now --statistics all 2>&1'); if (defined($self->{option_results}->{legacy_proc})) { ($command, $command_path, $command_options) = ('cat', undef, '/proc/drbd'); } my ($stdout) = $options{custom}->execute_command( command => $command, command_path => $command_path, command_options => $command_options ); if (defined($self->{option_results}->{legacy_proc})) { $self->legacy_proc(stdout => $stdout); } else { $self->drbdsetup_events2(stdout => $stdout); } $self->{global} = { resources_total => scalar(keys %{$self->{resources}}) }; $self->{cache_name} = 'cache_linux_local_' . $options{custom}->get_identifier() . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_resource_name}) ? md5_hex($self->{option_results}->{filter_resource_name}) : md5_hex('all')); } 1; __END__ =head1 MODE Check DRBD resources. Command used: /usr/sbin/drbdsetup events2 --now --statistics all 2>&1 Legacy used: cat /proc/drbd =over 8 =item B<--filter-resource-name> Filter resource name (Can be a regexp). =item B<--legacy-proc> Use legacy proc file. =item B<--unknown-*> B<--warning-*> B<--critical-*> Available threshold options =over 4 resources-total data-read data-written peer-traffic-in peer-traffic-out role: =over 4 [unknown] %{role} =~ /unknown/i [critical] %{role} =~ /unconfigured/i =back disk-status: =over 4 [unknown] %{disk_status} =~ /dunknown/i [warning] %{disk_status} =~ /attaching|detaching|negotiating/i [critical] %{disk_status} =~ /outdated|inconsistent|failed|diskless/i =back peer-role: =over 4 [unknown] %{role} =~ /unknown/i [critical] %{role} =~ /unconfigured/i =back peer-connection-status: =over 4 [warning] %{connection_status} =~ /^(?:connecting|disconnecting|standalone|teardown)$/i [critical] %{connection_status} =~ /^(?:brokenpipe|networkfailure|protocolerror|timeout|unconnected|wfconnection|wfreportparams)$/i =back peer-device-replication-status: =over 4 [warning] %{device_replication_status} =~ /^(?:ahead|off|startingsyncs|startingsynct|syncsource|synctarget|verifys|verifyt|wfsyncuuid|syncingall|syncingquick)$/i [critical] %{device_replication_status} =~ /^(?:behind|pausedsyncs|pausedsynct|wfbitmaps|wfbitmapt|syncpaused|skippedsyncs|skippedsynct)$/i =back peer-device-disk-status: =over 4 [unknown] %{device_disk_status} =~ /dunknown/i [warning] %{device_disk_status} =~ /^(?:attaching|detaching|diskless|failed|inconsistent|negotiating|outdated)$/i =back =back =back =cut centreon-plugins-20220113/apps/drbd/local/plugin.pm000066400000000000000000000025371417000230700220470ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::drbd::local::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} = { 'resources' => 'apps::drbd::local::mode::resources' }; $self->{custom_modes}->{cli} = 'centreon::plugins::script_custom::cli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check drbd through local commands (the plugin can use SSH). Tested: DRBD 9.x with drbd-utils 9.13.x =cut centreon-plugins-20220113/apps/dynamics/000077500000000000000000000000001417000230700200065ustar00rootroot00000000000000centreon-plugins-20220113/apps/dynamics/ax/000077500000000000000000000000001417000230700204165ustar00rootroot00000000000000centreon-plugins-20220113/apps/dynamics/ax/mode/000077500000000000000000000000001417000230700213425ustar00rootroot00000000000000centreon-plugins-20220113/apps/dynamics/ax/mode/ediorder.pm000066400000000000000000000132561417000230700235040ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::dynamics::ax::mode::ediorder; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_global_output { my ($self, %options) = @_; return 'Order '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 }} ]; $self->{maps_counters}->{global} = [ { label => 'order-warning', nlabel => 'order.warning.count', set => { key_values => [ { name => '2' } ], output_template => 'warning: %d', perfdatas => [ { template => '%d', min => 0 } ] } }, { label => 'order-critical', nlabel => 'order.critical.count', set => { key_values => [ { name => '3' } ], output_template => 'critical: %d', perfdatas => [ { template => '%d', min => 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 => { 'timeframe:s' => { name => 'timeframe', default => 14400 }, 'filter-module:s' => { name => 'filter_module' }, 'filter-company:s' => { name => 'filter_company' }, 'filter-portname:s' => { name => 'filter_portname' } }); return $self; } sub manage_selection { my ($self, %options) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; my $query = " SELECT [AIFEXCEPTIONMAP].[MESSAGEID], [SYSEXCEPTIONTABLE].[EXCEPTION], [SYSEXCEPTIONTABLE].[DESCRIPTION], [SYSEXCEPTIONTABLE].[MODULE], convert(char(19), [SYSEXCEPTIONTABLE].[CREATEDDATETIME], 120) CREATEDDATETIME, [AIFEXCEPTIONMAP].[PORTNAME], [AIFMESSAGELOG].[COMPANY] FROM [MicrosoftDynamicsAX].[dbo].[SYSEXCEPTIONTABLE] Inner join [MicrosoftDynamicsAX].[dbo].[AIFEXCEPTIONMAP] on SYSEXCEPTIONTABLE.RECID = AIFEXCEPTIONMAP.EXCEPTIONID Inner join [MicrosoftDynamicsAX].[dbo].[AIFDOCUMENTLOG] on AIFEXCEPTIONMAP.MESSAGEID = AIFDOCUMENTLOG.MESSAGEID Inner join [MicrosoftDynamicsAX].[dbo].[AIFMESSAGELOG] on AIFDOCUMENTLOG.MESSAGEID = AIFMESSAGELOG.MESSAGEID WHERE [SYSEXCEPTIONTABLE].[CREATEDDATETIME] > (DATEADD(SECOND,-" . $self->{option_results}->{timeframe} . ",SYSDATETIME()))"; if(defined($self->{option_results}->{filter_module}) && $self->{option_results}->{filter_module} ne '') { $query = $query . " AND [SYSEXCEPTIONTABLE].[MODULE] LIKE '$self->{option_results}->{filter_module}'"; } if(defined($self->{option_results}->{filter_company}) && $self->{option_results}->{filter_company} ne '') { $query = $query . " AND [AIFMESSAGELOG].[COMPANY] LIKE '$self->{option_results}->{filter_company}'"; } if(defined($self->{option_results}->{filter_portname}) && $self->{option_results}->{filter_portname} ne '') { $query = $query . " AND [AIFEXCEPTIONMAP].[PORTNAME] LIKE '$self->{option_results}->{filter_portname}'"; } $query = $query . " ORDER BY [AIFEXCEPTIONMAP].[MESSAGEID] "; $self->{sql}->connect(); $self->{sql}->query(query => $query ); $self->{global} = { 2 => 0, 3 => 0 }; my $messageId = ''; my $desc_num = 1; while (my $row = $self->{sql}->fetchrow_hashref()) { if ($messageId eq $row->{MESSAGEID}){ $desc_num++; $self->{output}->output_add( long_msg => sprintf(' [description %d: %s]', $desc_num, $row->{DESCRIPTION} ) ); next } $desc_num = 1; $messageId = $row->{MESSAGEID}; $self->{global}->{ $row->{EXCEPTION} }++; $self->{output}->output_add( long_msg => sprintf( 'Exception: %d [company: %s] [module: %s] [date: %s] [portname: %s] [id: %s]', $row->{EXCEPTION}, $row->{COMPANY}, $row->{MODULE}, $row->{CREATEDDATETIME}, $row->{PORTNAME}, $row->{MESSAGEID} ) ); $self->{output}->output_add( long_msg => sprintf( ' [description %d: %s]', $desc_num, $row->{DESCRIPTION} ) ); } } 1; __END__ =head1 MODE Check EDI Orders execptions. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'order-critical', 'order-warning'. =item B<--timeframe> Set the timeframe to query in seconds (Default: 14400). =item B<--filter-module> Filter on module. =item B<--filter-company> Filter on company. =item B<--filter-portname> Filter on portname. =back =cut centreon-plugins-20220113/apps/emc/000077500000000000000000000000001417000230700167435ustar00rootroot00000000000000centreon-plugins-20220113/apps/emc/ppma/000077500000000000000000000000001417000230700177005ustar00rootroot00000000000000centreon-plugins-20220113/apps/emc/ppma/restapi/000077500000000000000000000000001417000230700213475ustar00rootroot00000000000000centreon-plugins-20220113/apps/emc/ppma/restapi/custom/000077500000000000000000000000001417000230700226615ustar00rootroot00000000000000centreon-plugins-20220113/apps/emc/ppma/restapi/custom/api.pm000066400000000000000000000220511417000230700237700ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Authors : Roman Morandell - ivertix # package apps::emc::ppma::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use centreon::plugins::statefile; use JSON::XS; use Digest::MD5 qw(md5_hex); 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'url-path:s' => { name => 'url_path' }, 'api-username:s' => { name => 'api_username' }, 'api-password:s' => { name => 'api_password' }, 'timeout:s' => { name => 'timeout' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); $self->{cache} = centreon::plugins::statefile->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{url_path} = (defined($self->{option_results}->{url_path})) ? $self->{option_results}->{url_path} : '/LicenseReportingApplication/rest/powerpath'; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : ''; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : ''; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 30; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300' ; $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify hostname option.'); $self->{output}->option_exit(); } if ($self->{api_username} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-username option."); $self->{output}->option_exit(); } if ($self->{api_password} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-password option."); $self->{output}->option_exit(); } $self->{cache}->check_options(option_results => $self->{option_results}); return 0; } sub get_connection_infos { my ($self, %options) = @_; return $self->{hostname} . '_' . $self->{http}->get_port(); } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub get_port { my ($self, %options) = @_; return $self->{port}; } sub json_decode { my ($self, %options) = @_; $options{content} =~ s/\r//mg; my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($options{content}); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } return $decoded; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->set_options(%{$self->{option_results}}); } sub clean_session { my ($self, %options) = @_; my $datas = {}; $options{statefile}->write(data => $datas); $self->{cookie_id} = undef; } sub get_session { my ($self, %options) = @_; my $has_cache_file = $options{statefile}->read(statefile => 'emc_ppma_' . md5_hex($self->{option_results}->{hostname}) . '_' . md5_hex($self->{option_results}->{api_username})); my $cookie_id = $options{statefile}->get(name => 'cookie_id'); if ($has_cache_file == 0 || !defined($cookie_id)) { my ($content) = $self->{http}->request( method => 'POST', url_path => '/LicenseReportingApplication/authenticate', post_param => [ 'j_username=' . $self->{api_username}, 'j_password=' . $self->{api_password} ], cookies_file => '', warning_status => '', unknown_status => '', critical_status => '' ); if ($self->{http}->get_code() != 200) { $self->{output}->add_option_msg(short_msg => "Authentication error [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my (@cookies) = $self->{http}->get_first_header(name => 'Set-Cookie'); foreach my $cookie (@cookies) { $cookie_id = $1 if ($cookie =~ /JSESSIONID=(.+?);/); } if (!defined($cookie_id)) { $self->{output}->add_option_msg(short_msg => "Cannot get cookie"); $self->{output}->option_exit(); } $options{statefile}->write(data => { cookie_id => $cookie_id }); } $self->{cookie_id} = $cookie_id; } sub request { my ($self, %options) = @_; my $endpoint = $self->{url_path} . $options{endpoint}; $self->settings(); if (!defined($self->{access_token})) { $self->get_session(statefile => $self->{cache}); } my $content = $self->{http}->request( method => 'GET', url_path => $endpoint, get_param => $options{get_param}, header => [ 'Cookie: JSESSIONID=' . $self->{cookie_id}, 'Content-Type: application/json' ], warning_status => '', unknown_status => '', critical_status => '' ); # Maybe there is an issue with the token. So we retry. if ($self->{http}->get_code() < 200 || $self->{http}->get_code() >= 300) { $self->clean_session(statefile => $self->{cache}); $self->get_session(statefile => $self->{cache}); $content = $self->{http}->request( url_path => $endpoint, get_param => $options{get_param}, header => [ 'Cookie: JSESSIONID=' . $self->{cookie_id}, 'Content-Type: application/json' ], unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status} ); } my $decoded = $self->json_decode(content => $content); if (!defined($decoded)) { $self->{output}->add_option_msg(short_msg => 'Error while retrieving data (add --debug option for detailed message)'); $self->{output}->option_exit(); } return $decoded; } 1; __END__ =head1 NAME PPMA API =head1 SYNOPSIS PPMA api =head1 REST API OPTIONS =over 8 =item B<--hostname> API hostname. =item B<--url-path> API url path (Default: '/LicenseReportingApplication/rest/powerpath') =item B<--port> API port (Default: 443) =item B<--proto> Specify https if needed (Default: 'https') =item B<--api-username> Set API username =item B<--api-password> Set API password =item B<--timeout> Set HTTP timeout =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/emc/ppma/restapi/mode/000077500000000000000000000000001417000230700222735ustar00rootroot00000000000000centreon-plugins-20220113/apps/emc/ppma/restapi/mode/discovery.pm000066400000000000000000000054631417000230700246500ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::emc::ppma::restapi::mode::discovery; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'prettify' => { name => 'prettify' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my $disco_data; my $disco_stats; $disco_stats->{start_time} = time(); my $hosts = $options{custom}->request(endpoint => '/hosts'); foreach my $host (@$hosts) { my $detail = $options{custom}->request(endpoint => '/hosts/' . $host->{id}); my $item = {}; $item->{id} = $host->{id}; $item->{hostname} = $host->{hostname}; $item->{platform} = $detail->{platform}; $item->{ip} = $detail->{ip}; $item->{os_version} = $detail->{osVersion}; $item->{powerpath_version} = $detail->{powerpathVersion}; $item->{state} = $detail->{state}; push @$disco_data, $item; } $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; $disco_stats->{discovered_items} = scalar(@$disco_data); $disco_stats->{results} = $disco_data; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE Resources discovery. =over 8 =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/apps/emc/ppma/restapi/mode/hosts.pm000066400000000000000000000152431417000230700237760ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::emc::ppma::restapi::mode::hosts; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf( 'status: %s', $self->{result_values}->{status} ); } sub host_long_output { my ($self, %options) = @_; return "checking host '" . $options{instance_value}->{name} . "'"; } sub prefix_host_output { my ($self, %options) = @_; return "Host '" . $options{instance_value}->{name} . "' "; } sub prefix_path_output { my ($self, %options) = @_; return 'path '; } sub prefix_volume_output { my ($self, %options) = @_; return 'volume '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'hosts', type => 3, cb_prefix_output => 'prefix_host_output', cb_long_output => 'host_long_output', indent_long_output => ' ', message_multiple => 'All hosts are ok', group => [ { name => 'status', type => 0, skipped_code => { -10 => 1 } }, { name => 'path', type => 0, cb_prefix_output => 'prefix_path_output', skipped_code => { -10 => 1 } }, { name => 'volume', type => 0, cb_prefix_output => 'prefix_volume_output', skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{status} = [ { label => 'status', type => 2, critical_default => '%{status} !~ /powerPathManaged/', set => { key_values => [ { name => 'status' }, { name => 'name' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{path} = [ { label => 'paths-total', nlabel => 'host.paths.total.count', set => { key_values => [ { name => 'total' } ], output_template => 'total: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } }, { label => 'paths-dead', nlabel => 'host.paths.dead.count', set => { key_values => [ { name => 'dead' }, { name => 'total' } ], output_template => 'dead: %s', perfdatas => [ { template => '%s', min => 0, max => 'total', label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{volume} = [ { label => 'volumes-total', nlabel => 'host.volumes.total.count', set => { key_values => [ { name => 'total' } ], output_template => 'total: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } }, { label => 'volumes-dead', nlabel => 'host.volumes.dead.count', set => { key_values => [ { name => 'dead' }, { name => 'total' } ], output_template => 'dead: %s', perfdatas => [ { template => '%s', min => 0, max => 'total', label_extra_instance => 1 } ] } }, { label => 'volumes-degraded', nlabel => 'host.volumes.degraded.count', set => { key_values => [ { name => 'degraded' }, { name => 'total' } ], output_template => 'degraded: %s', perfdatas => [ { template => '%s', min => 0, max => 'total', label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $hosts = $options{custom}->request(endpoint => '/hosts'); $self->{hosts} = {}; foreach my $host (@$hosts) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $host->{hostname} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $host->{hostname} . "': no matching filter.", debug => 1); next; } my $detail = $options{custom}->request(endpoint => '/hosts/' . $host->{id}); $self->{hosts}->{ $host->{hostname} } = { name => $host->{hostname}, status => { name => $host->{hostname}, status => $detail->{state} }, path => { total => $detail->{totalPathCount}, dead => $detail->{deadPathCount} }, volume => { total => $detail->{totalVolumeCount}, dead => $detail->{deadVolumeCount}, degraded => $detail->{degradedVolumeCount} } }; } } 1; __END__ =head1 MODE Check host powerpath informations. =over 8 =item B<--filter-name> Filter hosts by host name (can be a regexp). =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{status}, %{name} =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{status}, %{name} =item B<--critical-status> Set critical threshold for status (Default: '%{status} !~ /powerPathManaged/'). Can used special variables like: %{status}, %{name} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'paths-total', 'paths-dead', 'volumes-total', 'volumes-dead', 'volumes-degraded'. =back =cut centreon-plugins-20220113/apps/emc/ppma/restapi/mode/listhosts.pm000066400000000000000000000043011417000230700246630ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::emc::ppma::restapi::mode::listhosts; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; return $options{custom}->request(endpoint => '/hosts'); } sub run { my ($self, %options) = @_; my $hosts = $self->manage_selection(custom => $options{custom}); foreach my $host (@$hosts) { $self->{output}->output_add(long_msg => join('', map("[$_ = " . $host->{$_} . ']', keys(%$host))) ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List hosts:' ); $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 => ['id', 'hostname']); } sub disco_show { my ($self, %options) = @_; my $hosts = $self->manage_selection(custom => $options{custom}); foreach my $host (@$hosts) { $self->{output}->add_disco_entry( %$host ); } } 1; __END__ =head1 MODE List powerpath hosts. =over 8 =back =cut centreon-plugins-20220113/apps/emc/ppma/restapi/plugin.pm000066400000000000000000000027541417000230700232130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Authors : Roman Morandell - ivertix # package apps::emc::ppma::restapi::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} = '1.0'; $self->{modes} = { 'discovery' => 'apps::emc::ppma::restapi::mode::discovery', 'hosts' => 'apps::emc::ppma::restapi::mode::hosts', 'list-hosts' => 'apps::emc::ppma::restapi::mode::listhosts' }; $self->{custom_modes}->{api} = 'apps::emc::ppma::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check EMC PowerPath Management Appliance using Rest API. =cut centreon-plugins-20220113/apps/ericsson/000077500000000000000000000000001417000230700200245ustar00rootroot00000000000000centreon-plugins-20220113/apps/ericsson/enm/000077500000000000000000000000001417000230700206035ustar00rootroot00000000000000centreon-plugins-20220113/apps/ericsson/enm/api/000077500000000000000000000000001417000230700213545ustar00rootroot00000000000000centreon-plugins-20220113/apps/ericsson/enm/api/custom/000077500000000000000000000000001417000230700226665ustar00rootroot00000000000000centreon-plugins-20220113/apps/ericsson/enm/api/custom/api.pm000066400000000000000000000356651417000230700240140ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::ericsson::enm::api::custom::api; use strict; use warnings; use centreon::plugins::http; use centreon::plugins::statefile; use JSON::XS; use Time::HiRes; use Digest::MD5 qw(md5_hex); 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'api-username:s' => { name => 'api_username' }, 'api-password:s' => { name => 'api_password' }, 'timeout:s' => { name => 'timeout' }, 'cache-use' => { name => 'cache_use' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); $self->{cache_token} = centreon::plugins::statefile->new(%options); $self->{cache} = centreon::plugins::statefile->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 50; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : ''; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : ''; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } if ($self->{api_username} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-username option."); $self->{output}->option_exit(); } if ($self->{api_password} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-password option."); $self->{output}->option_exit(); } # we force to use storable module $self->{option_results}->{statefile_storable} = 1; $self->{cache_token}->check_options(option_results => $self->{option_results}); $self->{cache}->check_options(option_results => $self->{option_results}); return 0; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; } sub settings { my ($self, %options) = @_; return if (defined($self->{settings_done})); $self->build_options_for_httplib(); $self->{http}->set_options(%{$self->{option_results}}); $self->{settings_done} = 1; } sub login { my ($self, %options) = @_; my $has_cache_file = $self->{cache_token}->read(statefile => 'ericsson_enm_' . md5_hex($self->{option_results}->{hostname} . '_' . $self->{api_username})); my $session_id = $self->{cache_token}->get(name => 'session_id'); my $md5_secret_cache = $self->{cache_token}->get(name => 'md5_secret'); my $md5_secret = md5_hex($self->{api_username} . $self->{api_password}); if ($has_cache_file == 0 || !defined($session_id) || (defined($md5_secret_cache) && $md5_secret_cache ne $md5_secret) ) { $self->settings(); my $content = $self->{http}->request( method => 'POST', url_path => '/login', post_param => ['IDToken1=' . $self->{api_username}, 'IDToken2=' . $self->{api_password}], critical_status => '', warning_status => '', unknown_status => '' ); # 401 for failed auth if ($self->{http}->get_code() != 200) { $self->{output}->add_option_msg(short_msg => "Authentication error [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my (@cookies) = $self->{http}->get_first_header(name => 'Set-Cookie'); $session_id = ''; foreach my $cookie (@cookies) { $session_id = $1 if ($cookie =~ /^iPlanetDirectoryPro=(.+?);/); } if (!defined($session_id) || $session_id eq '') { $self->{output}->add_option_msg(short_msg => 'Cannot get session id'); $self->{output}->option_exit(); } my $datas = { updated => time(), session_id => $session_id, md5_secret => $md5_secret }; $self->{cache_token}->write(data => $datas); } return $session_id; } sub clean_session { my ($self, %options) = @_; my $datas = { updated => time() }; $self->{cache_token}->write(data => $datas); $self->{session_id} = undef; } sub credentials { my ($self, %options) = @_; if (!defined($self->{session_id})) { $self->{session_id} = $self->login(); } } sub execute_command { my ($self, %options) = @_; my $response = $self->{http}->request( method => 'POST', url_path => '/server-scripting/services/command', header => [ 'Accept: application/vnd.com.ericsson.oss.scripting+text;VERSION="1"', 'X-Requested-With: XMLHttpRequest', 'Cookie: iPlanetDirectoryPro=' . $self->{session_id} ], form => [ { copyname => 'name', copycontents => 'command' }, { copyname => 'command', copycontents => $options{command} }, { copyname => 'stream_output', copycontents => 'true' }, { copyname => 'requestSequence', copycontents => Time::HiRes::time() } ], critical_status => '', warning_status => '', unknown_status => '' ); # Maybe token is invalid. so we retry if ($self->{http}->get_code() < 200 || $self->{http}->get_code() >= 300) { $self->clean_session(); $self->credentials(); $response = $self->{http}->request( method => 'POST', url_path => '/server-scripting/services/command', header => [ 'Accept: application/vnd.com.ericsson.oss.scripting+text;VERSION="1"', 'X-Requested-With: XMLHttpRequest', 'Cookie: iPlanetDirectoryPro=' . $self->{session_id} ], form => [ { copyname => 'name', copycontents => 'command' }, { copyname => 'command', copycontents => $options{command} }, { copyname => 'stream_output', copycontents => 'true' }, { copyname => 'requestSequence', copycontents => Time::HiRes::time() } ], critical_status => '', warning_status => '', unknown_status => '' ); } if ($self->{http}->get_code() != 201) { $self->{output}->add_option_msg(short_msg => "execute-command issue"); $self->{output}->option_exit(); } return $response; } sub get_command_output { my ($self, %options) = @_; my $decoded; my $elements = []; while (1) { my $response = $self->{http}->request( method => 'GET', url_path => '/server-scripting/services/command/output/' . $options{command_id} . '/stream?', header => [ 'Accept: application/vnd.com.ericsson.oss.scripting.terminal+json;VERSION="3"', 'X-Requested-With: XMLHttpRequest', 'Cookie: iPlanetDirectoryPro=' . $self->{session_id} ], get_param => => ['_wait_milli=1000'], critical_status => '', warning_status => '', unknown_status => '' ); # Maybe token is invalid. so we retry if ($self->{http}->get_code() < 200 || $self->{http}->get_code() >= 300) { $self->clean_session(); $self->credentials(); $response = $self->{http}->request( method => 'GET', url_path => '/server-scripting/services/command/output/' . $options{command_id} . '/stream?', header => [ 'Accept: application/vnd.com.ericsson.oss.scripting.terminal+json;VERSION="3"', 'X-Requested-With: XMLHttpRequest', 'Cookie: iPlanetDirectoryPro=' . $self->{session_id} ], get_param => => ['_wait_milli=1000'], critical_status => '', warning_status => '', unknown_status => '' ); } if ($self->{http}->get_code() < 200 || $self->{http}->get_code() >= 300) { $self->{output}->add_option_msg(short_msg => "get-command-output issue"); $self->{output}->option_exit(); } my $json; eval { $json = JSON::XS->new->utf8->decode($response); }; if ($@) { $self->{output}->add_option_msg(short_msg => 'get-command-output: cannot decode response'); $self->{output}->option_exit(); } #_response_status = FETCHING, COMPLETE if ($json->{_response_status} eq 'COMPLETE') { $decoded = $json; unshift @{$decoded->{output}->{_elements}}, @$elements; last; } else { push @$elements, @{$json->{output}->{_elements}}; } } return $decoded; } sub execute { my ($self, %options) = @_; $self->settings(); $self->credentials(); my $command_id = $self->execute_command(command => $options{command}); return $self->get_command_output(command_id => $command_id); } sub parse_result { my ($self, %options) = @_; my $results = []; foreach my $group (@{$options{result}->{output}->{_elements}}) { foreach my $entry (@{$group->{_elements}}) { my $h = {}; foreach (@{$entry->{_elements}}) { $h->{ $_->{_label}->[0] } = $_->{value}; } push @$results, $h; } } return $results; } sub call_fruState { my ($self, %options) = @_; my $datas = $self->execute( command => 'cmedit get * FieldReplaceableUnit.(administrativeState,availabilityStatus,faultIndicator,hwTestResult,maintenanceIndicator,operationalIndicator,operationalState,specialIndicator,statusIndicator,userLabel) -t' ); return $self->parse_result(result => $datas); } sub call_nodeSyncState { my ($self, %options) = @_; my $datas = $self->execute( command => 'cmedit get * CmFunction.syncStatus -t' ); return $self->parse_result(result => $datas); } sub call_EUtranCellTDD { my ($self, %options) = @_; my $datas = $self->execute( command => 'cmedit get * EUtranCellTDD.(operationalstate,administrativestate,availabilityStatus,userlabel) -t' ); return $self->parse_result(result => $datas); } sub cache_fruState { my ($self, %options) = @_; my $datas = $self->call_fruState(); $self->write_cache_file( statefile => 'fruState', response => $datas ); return $datas; } sub cache_nodeSyncState { my ($self, %options) = @_; my $datas = $self->call_nodeSyncState(); $self->write_cache_file( statefile => 'nodeSyncState', response => $datas ); return $datas; } sub cache_EUtranCellTDD { my ($self, %options) = @_; my $datas = $self->call_EUtranCellTDD(); $self->write_cache_file( statefile => 'EUtranCellTDD', response => $datas ); return $datas; } sub write_cache_file { my ($self, %options) = @_; $self->{cache}->read(statefile => 'cache_ericsson_enm_' . $self->get_hostname() . '_' . $options{statefile}); $self->{cache}->write(data => { update_time => time(), response => $options{response} }); } sub get_cache_file_response { my ($self, %options) = @_; $self->{cache}->read(statefile => 'cache_ericsson_enm_' . $self->get_hostname() . '_' . $options{statefile}); my $response = $self->{cache}->get(name => 'response'); if (!defined($response)) { $self->{output}->add_option_msg(short_msg => 'Cache file missing'); $self->{output}->option_exit(); } return $response; } sub get_fruState { my ($self, %options) = @_; return $self->get_cache_file_response(statefile => 'fruState') if (defined($self->{option_results}->{cache_use})); return $self->call_fruState(); } sub get_nodeSyncState { my ($self, %options) = @_; return $self->get_cache_file_response(statefile => 'nodeSyncState') if (defined($self->{option_results}->{cache_use})); return $self->call_nodeSyncState(); } sub get_EUtranCellTDD { my ($self, %options) = @_; return $self->get_cache_file_response(statefile => 'EUtranCellTDD') if (defined($self->{option_results}->{cache_use})); return $self->call_EUtranCellTDD(); } 1; __END__ =head1 NAME ENM REST API =head1 SYNOPSIS Rest API custom mode =head1 REST API OPTIONS =over 8 =item B<--hostname> ENM hostname (Required) =item B<--port> Port used (Default: 443) =item B<--proto> Specify https if needed (Default: 'https') =item B<--api-username> API username. =item B<--api-password> API password. =item B<--timeout> Set HTTP timeout =item B<--cache-use> Use the cache file (created with cache mode). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/ericsson/enm/api/mode/000077500000000000000000000000001417000230700223005ustar00rootroot00000000000000centreon-plugins-20220113/apps/ericsson/enm/api/mode/cache.pm000066400000000000000000000027711417000230700237100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::ericsson::enm::api::mode::cache; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub manage_selection { my ($self, %options) = @_; $options{custom}->cache_fruState(); $options{custom}->cache_nodeSyncState(); $options{custom}->cache_EUtranCellTDD(); $self->{output}->output_add( severity => 'OK', short_msg => 'Cache files created successfully' ); } 1; __END__ =head1 MODE Create cache files (other modes could use it with --cache-use option). =over 8 =back =cut centreon-plugins-20220113/apps/ericsson/enm/api/mode/discovery.pm000066400000000000000000000061351417000230700246520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::ericsson::enm::api::mode::discovery; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'resource-type:s' => { name => 'resource_type' }, 'prettify' => { name => 'prettify' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{resource_type}) || $self->{option_results}->{resource_type} eq '') { $self->{option_results}->{resource_type} = 'nodes'; } if ($self->{option_results}->{resource_type} !~ /^nodes$/) { $self->{output}->add_option_msg(short_msg => 'unknown resource type'); $self->{output}->option_exit(); } } sub discovery_nodes { my ($self, %options) = @_; my $nodes = $options{custom}->call_nodeSyncState(); my $disco_data = []; foreach (@$nodes) { my $node = {}; $node->{id} = $_->{NodeId}; $node->{sync_status} = $_->{syncStatus}; push @$disco_data, $node; } return $disco_data; } sub run { my ($self, %options) = @_; my $disco_stats; $disco_stats->{start_time} = time(); my $results = $self->discovery_nodes( custom => $options{custom} ); $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; $disco_stats->{discovered_items} = scalar(@$results); $disco_stats->{results} = $results; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE Resources discovery. =over 8 =item B<--resource-type> Choose the type of resources to discover (Can be: 'nodes'). =back =cut centreon-plugins-20220113/apps/ericsson/enm/api/mode/listnodes.pm000066400000000000000000000043001417000230700246370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::ericsson::enm::api::mode::listnodes; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; my $nodes = $options{custom}->call_nodeSyncState(); my $results = []; foreach my $node (@$nodes) { push @$results, { node_id => $node->{NodeId} }; } return $results; } sub run { my ($self, %options) = @_; my $results = $self->manage_selection(%options); foreach (@$results) { $self->{output}->output_add(long_msg => sprintf('[node_id: %s]', $_->{node_id})); } $self->{output}->output_add( severity => 'OK', short_msg => 'List nodes:' ); $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 => ['node_id']); } sub disco_show { my ($self, %options) = @_; my $results = $self->manage_selection(%options); foreach (@$results) { $self->{output}->add_disco_entry(%$_); } } 1; __END__ =head1 MODE List nodes. =over 8 =back =cut centreon-plugins-20220113/apps/ericsson/enm/api/mode/listnodescelltdd.pm000066400000000000000000000075631417000230700262110ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::ericsson::enm::api::mode::listnodescelltdd; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'add-extra-attrs' => { name => 'add_extra_attrs' }, 'filter-node-id:s' => { name => 'filter_node_id' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; my $cells = $options{custom}->call_EUtranCellTDD(); my $results = []; foreach my $cell (@$cells) { next if (defined($self->{option_results}->{filter_node_id}) && $self->{option_results}->{filter_node_id} ne '' && $cell->{NodeId} !~ /$self->{option_results}->{filter_node_id}/); my $attr = { node_id => $cell->{NodeId}, cell_tdd_id => $cell->{EUtranCellTDDId} }; if (defined($self->{option_results}->{add_extra_attrs})) { $attr->{label} = defined($cell->{userLabel}) && $cell->{userLabel} ne 'null' ? $cell->{userLabel} : ''; $attr->{administrative_state} = lc($cell->{administrativeState}); $attr->{availability_status} = $cell->{availabilityStatus} ne 'null' ? lc($cell->{availabilityStatus}) : ''; $attr->{operational_state} = lc($cell->{operationalState}); } push @$results, $attr; } return $results; } sub run { my ($self, %options) = @_; my $results = $self->manage_selection(%options); foreach (@$results) { my $msg = sprintf('[node_id: %s][cell_tdd_id: %s]', $_->{node_id}, $_->{cell_tdd_id}); if (defined($self->{option_results}->{add_extra_attrs})) { $msg .= sprintf( '[label: %s][administrative state: %s][availability status: %s][operational state: %s]', $_->{label}, $_->{administrative_state}, $_->{availability_status}, $_->{operational_state} ) } $self->{output}->output_add(long_msg => $msg); } $self->{output}->output_add( severity => 'OK', short_msg => 'List cells tdd:' ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } sub disco_format { my ($self, %options) = @_; my $attrs = ['node_id', 'cell_tdd_id']; push @$attrs, ('label', 'administrative_state', 'availability_status', 'operational_state') if (defined($self->{option_results}->{add_extra_attrs})); $self->{output}->add_disco_format( elements => $attrs ); } sub disco_show { my ($self, %options) = @_; my $results = $self->manage_selection(%options); foreach (@$results) { $self->{output}->add_disco_entry(%$_); } } 1; __END__ =head1 MODE List nodes cells tdd. =over 8 =item B<--filter-node-id> Filter tdd cells by node id (can be a regexp). =item B<--add-extra-attrs> Display label/administrative_state/availability_status/operational_state. =back =cut centreon-plugins-20220113/apps/ericsson/enm/api/mode/listnodesfru.pm000066400000000000000000000075721417000230700253720ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::ericsson::enm::api::mode::listnodesfru; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'add-extra-attrs' => { name => 'add_extra_attrs' }, 'filter-node-id:s' => { name => 'filter_node_id' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; my $frus = $options{custom}->call_fruState(); my $results = []; foreach my $fru (@$frus) { next if (defined($self->{option_results}->{filter_node_id}) && $self->{option_results}->{filter_node_id} ne '' && $fru->{NodeId} !~ /$self->{option_results}->{filter_node_id}/); my $attr = { node_id => $fru->{NodeId}, fru_id => $fru->{FieldReplaceableUnitId} }; if (defined($self->{option_results}->{add_extra_attrs})) { $attr->{label} = defined($fru->{userLabel}) && $fru->{userLabel} ne 'null' ? $fru->{userLabel} : ''; $attr->{administrative_state} = lc($fru->{administrativeState}); $attr->{availability_status} = $fru->{availabilityStatus} ne 'null' ? lc($fru->{availabilityStatus}) : ''; $attr->{operational_state} = lc($fru->{operationalState}); } push @$results, $attr; } return $results; } sub run { my ($self, %options) = @_; my $results = $self->manage_selection(%options); foreach (@$results) { my $msg = sprintf('[node_id: %s][fru_id: %s]', $_->{node_id}, $_->{fru_id}); if (defined($self->{option_results}->{add_extra_attrs})) { $msg .= sprintf( '[label: %s][administrative state: %s][availability status: %s][operational state: %s]', $_->{label}, $_->{administrative_state}, $_->{availability_status}, $_->{operational_state} ) } $self->{output}->output_add(long_msg => $msg); } $self->{output}->output_add( severity => 'OK', short_msg => 'List field replaceable units:' ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } sub disco_format { my ($self, %options) = @_; my $attrs = ['node_id', 'fru_id']; push @$attrs, ('label', 'administrative_state', 'availability_status', 'operational_state') if (defined($self->{option_results}->{add_extra_attrs})); $self->{output}->add_disco_format( elements => $attrs ); } sub disco_show { my ($self, %options) = @_; my $results = $self->manage_selection(%options); foreach (@$results) { $self->{output}->add_disco_entry(%$_); } } 1; __END__ =head1 MODE List nodes field replaceable units. =over 8 =item B<--filter-node-id> Filter field replaceable units by node id (can be a regexp). =item B<--add-extra-attrs> Display label/administrative_state/availability_status/operational_state. =back =cut centreon-plugins-20220113/apps/ericsson/enm/api/mode/nodes.pm000066400000000000000000000300221417000230700237430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::ericsson::enm::api::mode::nodes; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_fru_status_output { my ($self, %options) = @_; return sprintf( 'operational state: %s, admin state: %s%s', $self->{result_values}->{operational_state}, $self->{result_values}->{administrative_state}, $self->{result_values}->{availability_status} ne 'null' ? ', availability status: ' . $self->{result_values}->{availability_status}: '' ); } sub custom_celltdd_status_output { my ($self, %options) = @_; return sprintf( 'operational state: %s, admin state: %s%s', $self->{result_values}->{operational_state}, $self->{result_values}->{administrative_state}, $self->{result_values}->{availability_status} ne 'null' ? ', availability status: ' . $self->{result_values}->{availability_status}: '' ); } sub prefix_fru_output { my ($self, %options) = @_; return sprintf( "field replaceable unit '%s'%s ", $options{instance}, $options{instance_value}->{label} ne '' ? ' [label: ' . $options{instance_value}->{label} . ']' : '' ); } sub prefix_celltdd_output { my ($self, %options) = @_; return sprintf( "tdd cell '%s'%s ", $options{instance}, $options{instance_value}->{label} ne '' ? ' [label: ' . $options{instance_value}->{label} . ']' : '' ); } sub prefix_global_output { my ($self, %options) = @_; return 'nodes '; } sub node_long_output { my ($self, %options) = @_; return "checking node '" . $options{instance} . "'"; } sub prefix_node_output { my ($self, %options) = @_; return "Node '" . $options{instance} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } }, { name => 'nodes', type => 3, cb_prefix_output => 'prefix_node_output', cb_long_output => 'node_long_output', indent_long_output => ' ', message_multiple => 'All nodes are ok', group => [ { name => 'node_global', type => 0, skipped_code => { -10 => 1 } }, { name => 'fru', display_long => 1, cb_prefix_output => 'prefix_fru_output', message_multiple => 'All field replaceable units are ok', type => 1, skipped_code => { -10 => 1 } }, { name => 'celltdd', display_long => 1, cb_prefix_output => 'prefix_celltdd_output', message_multiple => 'All tdd cells are ok', type => 1, skipped_code => { -10 => 1 } }, ] } ]; $self->{maps_counters}->{global} = [ { label => 'nodes-total', nlabel => 'nodes.total.count', display_ok => 0, set => { key_values => [ { name => 'total' } ], output_template => 'total: %s', perfdatas => [ { template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{node_global} = [ { label => 'node-sync-status', type => 2, critical_default => '%{sync_status} =~ /unsynchronized/i', set => { key_values => [ { name => 'sync_status' }, { name => 'node_id' } ], output_template => 'synchronization status: %s', closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{fru} = [ { label => 'fru-status', type => 2, set => { key_values => [ { name => 'node_id' }, { name => 'fru_id' }, { name => 'label' }, { name => 'administrative_state' }, { name => 'availability_status' }, { name => 'operational_state' } ], closure_custom_output => $self->can('custom_fru_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{celltdd} = [ { label => 'cell-tdd-status', type => 2, set => { key_values => [ { name => 'node_id' }, { name => 'cell_tdd_id' }, { name => 'label' }, { name => 'administrative_state' }, { name => 'availability_status' }, { name => 'operational_state' } ], closure_custom_output => $self->can('custom_celltdd_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-node-id:s' => { name => 'filter_node_id' }, 'exclude-node-id:s' => { name => 'exclude_node_id' }, 'filter-fru-id:s' => { name => 'filter_fru_id' }, 'exclude-fru-id:s' => { name => 'exclude_fru_id' }, 'filter-cell-tdd-id:s' => { name => 'filter_cell_tdd_id' }, 'exclude-cell-tdd-id:s' => { name => 'exclude_cell_tdd_id' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $nodes = $options{custom}->get_nodeSyncState(); $self->{global} = { total => 0 }; $self->{nodes} = {}; foreach my $node (@$nodes) { next if (defined($self->{option_results}->{filter_node_id}) && $self->{option_results}->{filter_node_id} ne '' && $node->{NodeId} !~ /$self->{option_results}->{filter_node_id}/); next if (defined($self->{option_results}->{exclude_node_id}) && $self->{option_results}->{exclude_node_id} ne '' && $node->{NodeId} =~ /$self->{option_results}->{exclude_node_id}/); $self->{global}->{total}++; $self->{nodes}->{ $node->{NodeId} } = { node_global => { node_id => $node->{NodeId}, sync_status => lc($node->{syncStatus}) }, fru => {}, celltdd => {} }; } my $frus = $options{custom}->get_fruState(); foreach my $fru (@$frus) { next if (defined($self->{option_results}->{filter_node_id}) && $self->{option_results}->{filter_node_id} ne '' && $fru->{NodeId} !~ /$self->{option_results}->{filter_node_id}/); next if (defined($self->{option_results}->{exclude_node_id}) && $self->{option_results}->{exclude_node_id} ne '' && $fru->{NodeId} =~ /$self->{option_results}->{exclude_node_id}/); next if (defined($self->{option_results}->{filter_fru_id}) && $self->{option_results}->{filter_fru_id} ne '' && $fru->{FieldReplaceableUnitId} !~ /$self->{option_results}->{filter_fru_id}/); next if (defined($self->{option_results}->{exclude_fru_id}) && $self->{option_results}->{exclude_fru_id} ne '' && $fru->{FieldReplaceableUnitId} =~ /$self->{option_results}->{exclude_fru_id}/); $self->{nodes}->{ $fru->{NodeId} }->{fru}->{ $fru->{FieldReplaceableUnitId} } = { node_id => $fru->{NodeId}, fru_id => $fru->{FieldReplaceableUnitId}, label => defined($fru->{userLabel}) && $fru->{userLabel} ne 'null' ? $fru->{userLabel} : '', administrative_state => lc($fru->{administrativeState}), availability_status => lc($fru->{availabilityStatus}), operational_state => lc($fru->{operationalState}) }; } my $cells = $options{custom}->get_EUtranCellTDD(); foreach my $cell (@$cells) { next if (defined($self->{option_results}->{filter_node_id}) && $self->{option_results}->{filter_node_id} ne '' && $cell->{NodeId} !~ /$self->{option_results}->{filter_node_id}/); next if (defined($self->{option_results}->{exclude_node_id}) && $self->{option_results}->{exclude_node_id} ne '' && $cell->{NodeId} =~ /$self->{option_results}->{exclude_node_id}/); next if (defined($self->{option_results}->{filter_cell_tdd_id}) && $self->{option_results}->{filter_cell_tdd_id} ne '' && $cell->{EUtranCellTDDId} !~ /$self->{option_results}->{filter_cell_tdd_id}/); next if (defined($self->{option_results}->{exclude_cell_tdd_id}) && $self->{option_results}->{exclude_cell_tdd_id} ne '' && $cell->{EUtranCellTDDId} =~ /$self->{option_results}->{exclude_cell_tdd_id}/); $self->{nodes}->{ $cell->{NodeId} }->{celltdd}->{ $cell->{EUtranCellTDDId} } = { node_id => $cell->{NodeId}, cell_tdd_id => $cell->{EUtranCellTDDId}, label => defined($cell->{userLabel}) && $cell->{userLabel} ne 'null' ? $cell->{userLabel} : '', administrative_state => lc($cell->{administrativeState}), availability_status => lc($cell->{availabilityStatus}), operational_state => lc($cell->{operationalState}) }; } } 1; __END__ =head1 MODE Check nodes. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='total' =item B<--filter-node-id> Filter nodes by id (can be a regexp). =item B<--filter-fru-id> Filter field replaceable units by id (can be a regexp). =item B<--filter-cell-tdd-id> Filter tdd cells by id (can be a regexp). =item B<--unknown-node-sync-status> Set unknown threshold for synchronization status. Can used special variables like: %{node_id}, %{sync_status} =item B<--warning-node-sync-status> Set warning threshold for synchronization status. Can used special variables like: %{node_id}, %{sync_status} =item B<--critical-node-sync-status> Set critical threshold for synchronization status (Default: '%{sync_status} =~ /unsynchronized/i'). Can used special variables like: %{node_id}, %{sync_status} =item B<--unknown-fru-status> Set unknown threshold for field replaceable unit status. Can used special variables like: %{node_id}, %{fru_id}, %{label}, %{administrative_state}, %{availability_status}, %{operational_state} =item B<--warning-fru-status> Set warning threshold for field replaceable unit status. Can used special variables like: %{node_id}, %{fru_id}, %{label}, %{administrative_state}, %{availability_status}, %{operational_state} =item B<--critical-fru-status> Set critical threshold for field replaceable unit status. Can used special variables like: %{node_id}, %{fru_id}, %{label}, %{administrative_state}, %{availability_status}, %{operational_state} =item B<--unknown-cell-tdd-status> Set unknown threshold for cell tdd status. Can used special variables like: %{node_id}, %{cell_tdd_id}, %{label}, %{administrative_state}, %{availability_status}, %{operational_state} =item B<--warning-cell-tdd-status> Set warning threshold for cell tdd status. Can used special variables like: %{node_id}, %{cell_tdd_id}, %{label}, %{administrative_state}, %{availability_status}, %{operational_state} =item B<--critical-cell-tdd-status> Set critical threshold for cell tdd status. Can used special variables like: %{node_id}, %{cell_tdd_id}, %{label}, %{administrative_state}, %{availability_status}, %{operational_state} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'nodes-total'. =back =cut centreon-plugins-20220113/apps/ericsson/enm/api/plugin.pm000066400000000000000000000033011417000230700232050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::ericsson::enm::api::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} = '1.0'; $self->{modes} = { 'cache' => 'apps::ericsson::enm::api::mode::cache', 'discovery' => 'apps::ericsson::enm::api::mode::discovery', 'list-nodes' => 'apps::ericsson::enm::api::mode::listnodes', 'list-nodes-celltdd' => 'apps::ericsson::enm::api::mode::listnodescelltdd', 'list-nodes-fru' => 'apps::ericsson::enm::api::mode::listnodesfru', 'nodes' => 'apps::ericsson::enm::api::mode::nodes' }; $self->{custom_modes}->{api} = 'apps::ericsson::enm::api::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Ericsson Network Manager (ENM) using API. =cut centreon-plugins-20220113/apps/github/000077500000000000000000000000001417000230700174615ustar00rootroot00000000000000centreon-plugins-20220113/apps/github/mode/000077500000000000000000000000001417000230700204055ustar00rootroot00000000000000centreon-plugins-20220113/apps/github/mode/commits.pm000066400000000000000000000106561417000230700224260ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::github::mode::commits; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::http; use centreon::plugins::statefile; use JSON; use DateTime; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "hostname:s" => { name => 'hostname', default => 'api.github.com' }, "port:s" => { name => 'port', default => '443'}, "proto:s" => { name => 'proto', default => 'https' }, "timeout:s" => { name => 'timeout' }, "owner:s" => { name => 'owner' }, "repository:s" => { name => 'repository' }, }); $self->{http} = centreon::plugins::http->new(%options); $self->{statefile_value} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{repository})) { $self->{output}->add_option_msg(short_msg => "Please set the repository option"); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{owner})) { $self->{output}->add_option_msg(short_msg => "Please set the owner option"); $self->{output}->option_exit(); } $self->{option_results}->{url_path} = "/repos/" . $self->{option_results}->{owner} . "/" . $self->{option_results}->{repository}."/commits"; $self->{http}->set_options(%{$self->{option_results}}); $self->{statefile_value}->check_options(%options); } sub run { my ($self, %options) = @_; $self->{statefile_value}->read(statefile => 'github_' . $self->{option_results}->{repository} . '_' . $self->{option_results}->{owner} . '_' . $self->{http}->get_port() . '_' . $self->{mode}); my $old_timestamp = $self->{statefile_value}->get(name => 'last_timestamp'); my $new_datas = {}; $new_datas->{last_timestamp} = time(); $self->{statefile_value}->write(data => $new_datas); if (!defined($old_timestamp)) { $self->{output}->output_add(severity => 'OK', short_msg => "Buffer creation..."); $self->{output}->display(); $self->{output}->exit(); } # Change date format from epoch to iso8601 my $old_iso8601 = DateTime->from_epoch(epoch => $old_timestamp)."Z"; my $jsoncontent = $self->{http}->request(get_param => ['per_page=1000', 'since=' . $old_iso8601]); my $json = JSON->new; my $webcontent; eval { $webcontent = $json->decode($jsoncontent); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response"); $self->{output}->option_exit(); } # Number of commits is array length my $nb_commits = @{$webcontent}; $self->{output}->output_add(severity => 'OK', short_msg => sprintf("Number of commits : %d", $nb_commits)); $self->{output}->perfdata_add(label => "commits", value => $nb_commits, min => 0 ); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check GitHub's number of commits for a repository =over 8 =item B<--hostname> IP Addr/FQDN of the GitHub's API (Default: api.github.com) =item B<--port> Port used by GitHub's API (Default: '443') =item B<--proto> Specify https if needed (Default: 'https') =item B<--timeout> Threshold for HTTP timeout (Default: 5) =item B<--owner> Specify GitHub's owner =item B<--repository> Specify GitHub's repository =back =cut centreon-plugins-20220113/apps/github/mode/issues.pm000066400000000000000000000132621417000230700222620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::github::mode::issues; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::http; use JSON; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "hostname:s" => { name => 'hostname', default => 'api.github.com' }, "port:s" => { name => 'port', default => '443'}, "proto:s" => { name => 'proto', default => 'https' }, "timeout:s" => { name => 'timeout' }, "warning:s" => { name => 'warning' }, "critical:s" => { name => 'critical' }, "owner:s" => { name => 'owner' }, "repository:s" => { name => 'repository' }, "label:s" => { name => 'label', default => '' }, }); $self->{http} = centreon::plugins::http->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{repository})) { $self->{output}->add_option_msg(short_msg => "Please set the repository option"); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{owner})) { $self->{output}->add_option_msg(short_msg => "Please set the owner option"); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'warning', value => $self->{option_results}->{warning})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning threshold '" . $self->{option_results}->{warning} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'critical', value => $self->{option_results}->{critical})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical threshold '" . $self->{option_results}->{critical} . "'."); $self->{output}->option_exit(); } $self->{option_results}->{url_path} = "/search/issues?q=state:open+is:issue+repo:" . $self->{option_results}->{owner} . "/" . $self->{option_results}->{repository}; if (defined($self->{option_results}->{label}) && $self->{option_results}->{label} ne '') { $self->{option_results}->{url_path} .= "+label:" . $self->{option_results}->{label}; } $self->{http}->set_options(%{$self->{option_results}}); } sub run { my ($self, %options) = @_; my $jsoncontent = $self->{http}->request(); my $json = JSON->new; my $webcontent; eval { $webcontent = $json->decode($jsoncontent); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response"); $self->{output}->option_exit(); } my $nb_issues = $webcontent->{total_count}; my $exit = $self->{perfdata}->threshold_check(value => $nb_issues, threshold => [ { label => 'critical', exit_litteral => 'critical' }, , { label => 'warning', exit_litteral => 'warning' } ]); if (defined($self->{option_results}->{label}) && $self->{option_results}->{label} ne '') { $self->{output}->output_add(severity => $exit, short_msg => sprintf("%d %s issues are open", $nb_issues, $self->{option_results}->{label})); $self->{output}->perfdata_add(label => $self->{option_results}->{label}, value => $nb_issues, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0 ); } else { $self->{output}->output_add(severity => $exit, short_msg => sprintf("%d issues are open", $nb_issues)); $self->{output}->perfdata_add(label => 'issues', value => $nb_issues, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0 ); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check GitHub's number of issues for a repository =over 8 =item B<--hostname> IP Addr/FQDN of the GitHub's API (Default: api.gitub.com) =item B<--port> Port used by GitHub's API (Default: '443') =item B<--proto> Specify https if needed (Default: 'https') =item B<--timeout> Threshold for HTTP timeout (Default: 5) =item B<--warning> Threshold warning. =item B<--critical> Threshold critical. =item B<--owner> Specify GitHub's owner =item B<--repository> Specify GitHub's repository =item B<--label> Specify label for issues =back =cut centreon-plugins-20220113/apps/github/mode/pullrequests.pm000066400000000000000000000113201417000230700235100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::github::mode::pullrequests; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::http; use JSON; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "hostname:s" => { name => 'hostname', default => 'api.github.com' }, "port:s" => { name => 'port', default => '443' }, "proto:s" => { name => 'proto', default => 'https' }, "timeout:s" => { name => 'timeout' }, "warning:s" => { name => 'warning' }, "critical:s" => { name => 'critical' }, "owner:s" => { name => 'owner' }, "repository:s" => { name => 'repository' }, }); $self->{http} = centreon::plugins::http->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{repository})) { $self->{output}->add_option_msg(short_msg => "Please set the repository option"); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{owner})) { $self->{output}->add_option_msg(short_msg => "Please set the owner option"); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'warning', value => $self->{option_results}->{warning})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning threshold '" . $self->{option_results}->{warning} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'critical', value => $self->{option_results}->{critical})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical threshold '" . $self->{option_results}->{critical} . "'."); $self->{output}->option_exit(); } $self->{option_results}->{url_path} = "/repos/".$self->{option_results}->{owner}."/".$self->{option_results}->{repository}."/pulls"; $self->{option_results}->{get_param} = ['state=open', 'per_page=1000']; $self->{http}->set_options(%{$self->{option_results}}); } sub run { my ($self, %options) = @_; my $jsoncontent = $self->{http}->request(); my $json = JSON->new; my $webcontent; eval { $webcontent = $json->decode($jsoncontent); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response"); $self->{output}->option_exit(); } # Number of pull requests is array length my $nb_pulls = @{$webcontent}; my $exit = $self->{perfdata}->threshold_check(value => $nb_pulls, threshold => [ { label => 'critical', exit_litteral => 'critical' }, , { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit, short_msg => sprintf("%d pull requests are open", $nb_pulls )); $self->{output}->perfdata_add(label => 'pullrequests', value => $nb_pulls, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0 ); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check GitHub's number of pull requests for a repository =over 8 =item B<--hostname> IP Addr/FQDN of the GitHub's API (Default: api.gitub.com) =item B<--port> Port used by GitHub's API (Default: '443') =item B<--proto> Specify https if needed (Default: 'https') =item B<--timeout> Threshold for HTTP timeout (Default: 5) =item B<--warning> Threshold warning. =item B<--critical> Threshold critical. =item B<--owner> Specify GitHub's owner =item B<--repository> Specify GitHub's repository =back =cut centreon-plugins-20220113/apps/github/mode/stats.pm000066400000000000000000000074541417000230700221130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::github::mode::stats; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::http; use JSON; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "hostname:s" => { name => 'hostname', default => 'api.github.com' }, "port:s" => { name => 'port', default => '443'}, "proto:s" => { name => 'proto', default => 'https' }, "timeout:s" => { name => 'timeout' }, "owner:s" => { name => 'owner' }, "repository:s" => { name => 'repository' }, }); $self->{http} = centreon::plugins::http->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{repository})) { $self->{output}->add_option_msg(short_msg => "Please set the repository option"); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{owner})) { $self->{output}->add_option_msg(short_msg => "Please set the owner option"); $self->{output}->option_exit(); } $self->{option_results}->{url_path} = "/repos/" . $self->{option_results}->{owner} . "/" . $self->{option_results}->{repository}; $self->{http}->set_options(%{$self->{option_results}}); } sub run { my ($self, %options) = @_; my $jsoncontent = $self->{http}->request(); my $json = JSON->new; my $webcontent; eval { $webcontent = $json->decode($jsoncontent); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } my $watchers = $webcontent->{subscribers_count}; my $forks = $webcontent->{forks_count}; my $stars = $webcontent->{watchers_count}; $self->{output}->output_add(severity => "OK", short_msg => sprintf("%d forks - %d watchers - %d stars", $forks, $watchers, $stars)); $self->{output}->perfdata_add(label => 'forks', value => $forks, min => 0); $self->{output}->perfdata_add(label => 'watchers', value => $watchers, min => 0); $self->{output}->perfdata_add(label => 'stars', value => $stars, min => 0); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check GitHub's statistics =over 8 =item B<--hostname> IP Addr/FQDN of the GitHub's status website (Default: status.github.com) =item B<--port> Port used by GitHub's status website (Default: '443') =item B<--proto> Specify https if needed (Default: 'https') =item B<--urlpath> Set path to get GitHub's status information (Default: '/repo/:owner/:repository') =item B<--timeout> Threshold for HTTP timeout (Default: 5) =back =cut centreon-plugins-20220113/apps/github/mode/status.pm000066400000000000000000000110051417000230700222630ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::github::mode::status; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::http; use JSON; my $thresholds = { status => [ ['good', 'OK'], ['minor', 'WARNING'], ['major', 'CRITICAL'], ], }; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "hostname:s" => { name => 'hostname', default => 'status.github.com' }, "port:s" => { name => 'port', default => '443'}, "proto:s" => { name => 'proto', default => 'https' }, "urlpath:s" => { name => 'url_path', default => '/api/last-message.json' }, "timeout:s" => { name => 'timeout' }, "threshold-overload:s@" => { name => 'threshold_overload' }, }); $self->{http} = centreon::plugins::http->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); $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) = ('status', $1, $2); 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->{http}->set_options(%{$self->{option_results}}); } 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; } sub run { my ($self, %options) = @_; my $jsoncontent = $self->{http}->request(); my $json = JSON->new; my $webcontent; eval { $webcontent = $json->decode($jsoncontent); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response"); $self->{output}->option_exit(); } my $exit = $self->get_severity(section => 'status', value => $webcontent->{status}); $self->{output}->output_add(severity => $exit, short_msg => sprintf("%s", $webcontent->{body})); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check GitHub's status =over 8 =item B<--hostname> IP Addr/FQDN of the GitHub's status website (Default: status.github.com) =item B<--port> Port used by GitHub's status website (Default: '443') =item B<--proto> Specify https if needed (Default: 'https') =item B<--urlpath> Set path to get GitHub's status information (Default: '/api/last-message.json') =item B<--timeout> Threshold for HTTP timeout (Default: 5) =item B<--threshold-overload> Set to overload default threshold values (syntax: status,regexp) It used before default thresholds (order stays). Example: --threshold-overload='CRITICAL,^(?!(good)$)' =back =cut centreon-plugins-20220113/apps/github/plugin.pm000066400000000000000000000027241417000230700213220ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::github::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} = '0.1'; %{$self->{modes}} = ( 'issues' => 'apps::github::mode::issues', 'commits' => 'apps::github::mode::commits', 'pullrequests' => 'apps::github::mode::pullrequests', 'stats' => 'apps::github::mode::stats', 'status' => 'apps::github::mode::status', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check GitHub status, issues, pullrequests and get commits for metrology. =cut centreon-plugins-20220113/apps/google/000077500000000000000000000000001417000230700174535ustar00rootroot00000000000000centreon-plugins-20220113/apps/google/workspace/000077500000000000000000000000001417000230700214515ustar00rootroot00000000000000centreon-plugins-20220113/apps/google/workspace/custom/000077500000000000000000000000001417000230700227635ustar00rootroot00000000000000centreon-plugins-20220113/apps/google/workspace/custom/api.pm000066400000000000000000000140531417000230700240750ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::google::workspace::custom::api; use strict; use warnings; use centreon::plugins::http; use JSON::XS; 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'timeout:s' => { name => 'timeout' }, 'unknown-http-status:s' => { name => 'unknown_http_status' }, 'warning-http-status:s' => { name => 'warning_http_status' }, 'critical-http-status:s' => { name => 'critical_http_status' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : 'www.google.com'; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 30; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300'; $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; } sub settings { my ($self, %options) = @_; return if (defined($self->{settings_done})); $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->set_options(%{$self->{option_results}}); $self->{settings_done} = 1; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub get_services { my ($self, %options) = @_; my $services = { 'Admin Console' => 1, 'Classic Hangouts' => 1, 'Classroom' => 1, 'Currents' => 1, 'Gmail' => 1, 'Google Calendar' => 1, 'Google Chat' => 1, 'Google Cloud Search' => 1, 'Google Docs' => 1, 'Google Drive' => 1, 'Google Forms' => 1, 'Google Groups' => 1, 'Google Keep' => 1, 'Google Meet' => 1, 'Google Sheets' => 1, 'Google Sites' => 1, 'Google Slides' => 1, 'Google Tasks' => 1, 'Google Vault' => 1, 'Google Voice' => 1, 'Google Workspace Support' => 1 }; return $services; } sub request_api { my ($self, %options) = @_; $self->settings(); my ($content) = $self->{http}->request( url_path => '/appsstatus/dashboard/incidents.json', unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status} ); if (!defined($content) || $content eq '') { $self->{output}->add_option_msg(short_msg => "API returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } return $decoded; } 1; __END__ =head1 NAME Google Workspace Rest API =head1 REST API OPTIONS Google Workspace Rest API =over 8 =item B<--hostname> Hostname (default: 'www.google.com'). =item B<--port> Port used (Default: 443) =item B<--proto> Specify https if needed (Default: 'https') =item B<--timeout> Set timeout in seconds (Default: 10). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/google/workspace/mode/000077500000000000000000000000001417000230700223755ustar00rootroot00000000000000centreon-plugins-20220113/apps/google/workspace/mode/listservices.pm000066400000000000000000000051401417000230700254520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::google::workspace::mode::listservices; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { '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 $results = $options{custom}->get_services(); my $services = {}; foreach my $name (keys %$results) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $name !~ /$self->{option_results}->{filter_name}/); $services->{$name} = $name; } return $services; } sub run { my ($self, %options) = @_; my $services = $self->manage_selection(%options); foreach (sort keys %$services) { $self->{output}->output_add( long_msg => sprintf("[name = %s]", $services->{$_}) ); } $self->{output}->output_add(severity => 'OK', short_msg => 'Google workspace service:'); $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) = @_; my $services = $self->manage_selection(%options); foreach (sort keys %$services) { $self->{output}->add_disco_entry( name => $services->{$_} ); } } 1; __END__ =head1 MODE List Google Gsuite applications. =over 8 =item B<--filter-name> Filter application name (Can be a regexp). =back =cut centreon-plugins-20220113/apps/google/workspace/mode/services.pm000066400000000000000000000124061417000230700245610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::google::workspace::mode::services; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use DateTime; use centreon::plugins::misc; sub custom_status_output { my ($self, %options) = @_; my $msg = 'status is ' . $self->{result_values}->{status}; if ($self->{result_values}->{since} ne '') { $msg .= sprintf( ' [since: %s][message: %s]', $self->{result_values}->{since}, $self->{result_values}->{message}, ); } return $msg; } sub prefix_service_output { my ($self, %options) = @_; return "Service '" . $options{instance_value}->{name} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'services', type => 1, cb_prefix_output => 'prefix_service_output', display_long => 1, cb_long_output => 'long_output', message_multiple => 'All Google workspace services are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'services', nlabel => 'google.workspace.services.count', display_ok => 0, set => { key_values => [ { name => 'total' } ], output_template => '%s Google workspace services', perfdatas => [ { template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{services} = [ { label => 'status', type => 2, warning_default => '%{status} eq "disruption"', critical_default => '%{status} eq "outage"', set => { key_values => [ { name => 'status' }, { name => 'name' }, { name => 'message' }, { name => 'since' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } my $status_mapping = { SERVICE_DISRUPTION => 'disruption', SERVICE_OUTAGE => 'outage', SERVICE_INFORMATION => 'information' }; sub manage_selection { my ($self, %options) = @_; my $services = $options{custom}->get_services(); my $history = $options{custom}->request_api(); $self->{services} = {}; foreach my $name (keys %$services) { next if ( defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $name !~ /$self->{option_results}->{filter_name}/i ); $self->{services}->{lc($name)} = { name => $name, status => 'available', message => '-', since => '' }; } foreach my $entry (@$history) { next if (defined($entry->{end}) && $entry->{end} =~ /^\d+-\d+-\d+T\d+:\d+:\d+(.*)$/); next if (!defined($entry->{begin}) || $entry->{begin} !~ /^(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)(.*)$/); my $dt = DateTime->new( year => $1, month => $2, day => $3, hour => $4, minute => $5, second => $6, time_zone => $7 ); my $diff_time = time() - $dt->epoch(); foreach (@{$entry->{affected_products}}) { next if (!defined($self->{services}->{ lc($_->{title}) })); $self->{services}->{ lc($_->{title}) }->{status} = $status_mapping->{ $entry->{status_impact} }; $self->{services}->{ lc($_->{title}) }->{message} = $entry->{external_desc}; $self->{services}->{ lc($_->{title}) }->{since} = centreon::plugins::misc::change_seconds(value => $diff_time); } } $self->{global} = { total => scalar(keys %{$self->{services}}) }; } 1; __END__ =head1 MODE Check Google workspace service status. =over 8 =item B<--filter-name> Only display the status for a specific servie (Example: --filter-service='gmail') =item B<--warning-status> Set warning threshold for the service status (Default: '%{status} eq "disruption"'). =item B<--critical-status> Set warning threshold for the service status (Default: '%{status} eq "outage"'). =back =cut centreon-plugins-20220113/apps/google/workspace/plugin.pm000066400000000000000000000025561417000230700233150ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::google::workspace::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} = { 'services' => 'apps::google::workspace::mode::services', 'list-services' => 'apps::google::workspace::mode::listservices' }; $self->{custom_modes}->{api} = 'apps::google::workspace::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Google Workspace status. =cut centreon-plugins-20220113/apps/gorgone/000077500000000000000000000000001417000230700176375ustar00rootroot00000000000000centreon-plugins-20220113/apps/gorgone/restapi/000077500000000000000000000000001417000230700213065ustar00rootroot00000000000000centreon-plugins-20220113/apps/gorgone/restapi/custom/000077500000000000000000000000001417000230700226205ustar00rootroot00000000000000centreon-plugins-20220113/apps/gorgone/restapi/custom/api.pm000066400000000000000000000143701417000230700237340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::gorgone::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use JSON::XS; 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 => { 'api-username:s' => { name => 'api_username' }, 'api-password:s' => { name => 'api_password' }, 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'timeout:s' => { name => 'timeout' }, 'unknown-http-status:s' => { name => 'unknown_http_status' }, 'warning-http-status:s' => { name => 'warning_http_status' }, 'critical-http-status:s' => { name => 'critical_http_status' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 8085; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'http'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : ''; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : ''; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300'; $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } if ($self->{api_username} ne '' && $self->{api_password} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-password option."); $self->{output}->option_exit(); } return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; if ($self->{api_username} ne '') { $self->{option_results}->{credentials} = 1; $self->{option_results}->{basic} = 1; $self->{option_results}->{username} = $self->{api_username}; $self->{option_results}->{password} = $self->{api_password}; } } sub settings { my ($self, %options) = @_; return if (defined($self->{settings_done})); $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->set_options(%{$self->{option_results}}); $self->{settings_done} = 1; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub request_api { my ($self, %options) = @_; $self->settings(); my $content = $self->{http}->request( url_path => $options{endpoint}, unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status} ); if (!defined($content) || $content eq '') { $self->{output}->add_option_msg(short_msg => "API returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } return $decoded; } 1; __END__ =head1 NAME Gorgone Rest API =head1 REST API OPTIONS Gorgone Rest API =over 8 =item B<--hostname> Gorgone hostname. =item B<--port> Port used (Default: 8085) =item B<--proto> Specify https if needed (Default: 'http') =item B<--api-username> Gorgone API username. =item B<--api-password> Gorgone API password. =item B<--timeout> Set timeout in seconds (Default: 10). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/gorgone/restapi/mode/000077500000000000000000000000001417000230700222325ustar00rootroot00000000000000centreon-plugins-20220113/apps/gorgone/restapi/mode/events.pm000066400000000000000000000102021417000230700240670ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::gorgone::restapi::mode::events; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); sub prefix_path_output { my ($self, %options) = @_; return "Path '" . $options{instance_value}->{display} . "' "; } sub path_long_output { my ($self, %options) = @_; return "checking path '" . $options{instance_value}->{display} . "'"; } sub prefix_event_output { my ($self, %options) = @_; return "event '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'paths', type => 3, cb_prefix_output => 'prefix_path_output', cb_long_output => 'path_long_output', indent_long_output => ' ', message_multiple => 'All paths are ok', group => [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'events', cb_prefix_output => 'prefix_event_output', message_multiple => 'All events are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'events-total', nlabel => 'path.events.total.count', set => { key_values => [ { name => 'total', diff => 1 } ], output_template => 'total events: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{events} = [ { label => 'event-total', nlabel => 'event.total.count', set => { key_values => [ { name => 'total', diff => 1 } ], output_template => 'total: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $infos = $options{custom}->request_api(endpoint => '/api/internal/information'); $self->{paths} = {}; foreach my $path (('internal', 'external')) { next if (!defined($infos->{data}->{counters}->{$path})); $self->{paths}->{$path} = { display => $path, global => { total => $infos->{data}->{counters}->{$path}->{total} }, events => {} }; foreach my $event (keys %{$infos->{data}->{counters}->{$path}}) { next if ($event eq 'total'); $self->{paths}->{$path}->{events}->{$event} = { display => $event, total => $infos->{data}->{counters}->{$path}->{$event} }; } } $self->{cache_name} = 'gorgone_' . $self->{mode} . '_' . $options{custom}->get_hostname() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check events. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='events-total' =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'events-total', 'event-total'. =back =cut centreon-plugins-20220113/apps/gorgone/restapi/mode/nodes.pm000066400000000000000000000074401417000230700237050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::gorgone::restapi::mode::nodes; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; sub prefix_node_output { my ($self, %options) = @_; return "Node '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'nodes', type => 1, cb_prefix_output => 'prefix_node_output', message_multiple => 'All nodes are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'nodes-total', nlabel => 'nodes.total.count', set => { key_values => [ { name => 'total' } ], output_template => 'total nodes: %s', perfdatas => [ { template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{nodes} = [ { label => 'ping-received-lasttime', nlabel => 'node.ping.received.lasttime.seconds', set => { key_values => [ { name => 'last_ping_recv' }, { name => 'last_ping_recv_human' }, { name => 'display' } ], output_template => 'last ping received: %s', output_use => 'last_ping_recv_human', perfdatas => [ { template => '%d', min => -1, unit => 's', label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-node-id:s' => { name => 'filter_node_id' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $nodes = $options{custom}->request_api(endpoint => '/api/internal/constatus'); $self->{global} = { total => 0 }; $self->{nodes} = {}; foreach my $node_id (keys %{$nodes->{data}}) { if (defined($self->{option_results}->{filter_node_id}) && $self->{option_results}->{filter_node_id} ne '' && $node_id !~ /$self->{option_results}->{filter_node_id}/) { $self->{output}->output_add(long_msg => "skipping node '" . $node_id . "': no matching filter.", debug => 1); next; } my $last_ping_recv = defined($nodes->{data}->{$node_id}->{last_ping_recv}) && $nodes->{data}->{$node_id}->{last_ping_recv} != 0 ? time() - $nodes->{data}->{$node_id}->{last_ping_recv} : -1; $self->{nodes}->{ $node_id } = { display => $node_id, last_ping_recv => $last_ping_recv, last_ping_recv_human => $last_ping_recv != -1 ? centreon::plugins::misc::change_seconds(value => $last_ping_recv) : $last_ping_recv }; $self->{global}->{total}++; } } 1; __END__ =head1 MODE Check nodes. =over 8 =item B<--filter-node-id> Filter nodes (can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'nodes-total', 'ping-received-lasttime' (s). =back =cut centreon-plugins-20220113/apps/gorgone/restapi/plugin.pm000066400000000000000000000025771417000230700231550ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::gorgone::restapi::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} = { 'events' => 'apps::gorgone::restapi::mode::events', 'nodes' => 'apps::gorgone::restapi::mode::nodes' }; $self->{custom_modes}{api} = 'apps::gorgone::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check gorgone using Rest API. https://github.com/centreon/centreon-gorgone =cut centreon-plugins-20220113/apps/grafana/000077500000000000000000000000001417000230700175765ustar00rootroot00000000000000centreon-plugins-20220113/apps/grafana/api/000077500000000000000000000000001417000230700203475ustar00rootroot00000000000000centreon-plugins-20220113/apps/grafana/api/custom/000077500000000000000000000000001417000230700216615ustar00rootroot00000000000000centreon-plugins-20220113/apps/grafana/api/custom/api.pm000066400000000000000000000124061417000230700227730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::grafana::api::custom::api; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::http; use JSON::XS; 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'timeout:s' => { name => 'timeout' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'CUSTOM MODE OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 3000; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'http'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{username} = (defined($self->{option_results}->{username})) ? $self->{option_results}->{username} : undef; $self->{password} = (defined($self->{option_results}->{password})) ? $self->{option_results}->{password} : undef; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --hostname option.'); $self->{output}->option_exit(); } return 0; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub get_port { my ($self, %options) = @_; return $self->{port}; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; if (defined($self->{username}) && $self->{username} ne '') { $self->{option_results}->{credentials} = 1; $self->{option_results}->{basic} = 1; $self->{option_results}->{username} = $self->{username}; $self->{option_results}->{password} = $self->{password}; } } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->set_options(%{$self->{option_results}}); } sub request { my ($self, %options) = @_; $self->settings(); my $content = $self->{http}->request( %options, unknown_status => '%{http_code} < 200 or %{http_code} >= 300', critical_status => '' ); if (!defined($content) || $content eq '') { $self->{output}->add_option_msg(short_msg => "API returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } return $decoded; } sub query { my ($self, %options) = @_; return $self->request(url_path => $options{url_path}); } 1; __END__ =head1 NAME Grafana Rest API =head1 CUSTOM MODE OPTIONS Grafana Rest API =over 8 =item B<--hostname> Remote hostname or IP address. =item B<--port> Port used (Default: 3000) =item B<--proto> Specify https if needed (Default: 'http') =item B<--username> Specify username for authentication =item B<--password> Specify password for authentication =item B<--timeout> Set timeout in seconds (Default: 10). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/grafana/api/mode/000077500000000000000000000000001417000230700212735ustar00rootroot00000000000000centreon-plugins-20220113/apps/grafana/api/mode/health.pm000066400000000000000000000051011417000230700230730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::grafana::api::mode::health; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf( "database state is '%s' [grafana version: %s]", $self->{result_values}->{state}, $self->{result_values}->{version} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'health', type => 0, skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{health} = [ { label => 'status', type => 2, critical_default => '%{state} ne "ok"', set => { key_values => [ { name => 'state' }, { name => 'version' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->query(url_path => '/api/health'); $self->{health} = { state => $result->{database}, version => $result->{version} }; } 1; __END__ =head1 MODE Check health. =over 8 =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{state}, %{version} =item B<--critical-status> Set critical threshold for status (Default: '%{state} ne "ok"'). Can used special variables like: %{state}, %{version} =back =cut centreon-plugins-20220113/apps/grafana/api/plugin.pm000066400000000000000000000024051417000230700222040ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::grafana::api::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} = '1.0'; $self->{modes} = { 'health' => 'apps::grafana::api::mode::health' }; $self->{custom_modes}->{api} = 'apps::grafana::api::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Grafana with API. =cut centreon-plugins-20220113/apps/graylog/000077500000000000000000000000001417000230700176435ustar00rootroot00000000000000centreon-plugins-20220113/apps/graylog/restapi/000077500000000000000000000000001417000230700213125ustar00rootroot00000000000000centreon-plugins-20220113/apps/graylog/restapi/custom/000077500000000000000000000000001417000230700226245ustar00rootroot00000000000000centreon-plugins-20220113/apps/graylog/restapi/custom/api.pm000066400000000000000000000244171417000230700237430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::graylog::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use centreon::plugins::statefile; use JSON::XS; use Digest::MD5 qw(md5_hex); 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 => { 'hostname:s' => { name => 'hostname' }, 'url-path:s' => { name => 'url_path' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'api-username:s' => { name => 'api_username' }, 'api-password:s' => { name => 'api_password' }, 'timeout:s' => { name => 'timeout' }, 'requested-by:s' => { name => 'requested_by' }, 'unknown-http-status:s' => { name => 'unknown_http_status' }, 'warning-http-status:s' => { name => 'warning_http_status' }, 'critical-http-status:s' => { name => 'critical_http_status' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); $self->{cache} = centreon::plugins::statefile->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 9000; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'http'; $self->{url_path} = (defined($self->{option_results}->{url_path})) ? $self->{option_results}->{url_path} : '/api/'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : ''; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : ''; $self->{requested_by} = (defined($self->{option_results}->{requested_by})) ? $self->{option_results}->{requested_by} : 'cli'; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300'; $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify hostname option.'); $self->{output}->option_exit(); } if ($self->{api_username} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --api-username option.'); $self->{output}->option_exit(); } if ($self->{api_password} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --api-password option.'); $self->{output}->option_exit(); } $self->{cache}->check_options(option_results => $self->{option_results}); return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Content-Type', value => 'application/json'); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->add_header(key => 'X-Requested-By', value => $self->{requested_by}); $self->{http}->set_options(%{$self->{option_results}}); } sub get_connection_info { my ($self, %options) = @_; return $self->{hostname} . ":" . $self->{port}; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub get_port { my ($self, %options) = @_; return $self->{port}; } sub json_decode { my ($self, %options) = @_; my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($options{content}); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } return $decoded; } sub clean_session_token { my ($self, %options) = @_; my $datas = {}; $options{statefile}->write(data => $datas); $self->{session_token} = undef; } sub authenticate { my ($self, %options) = @_; my $has_cache_file = $options{statefile}->read(statefile => 'graylog_api_' . md5_hex($self->{option_results}->{hostname}) . '_' . md5_hex($self->{option_results}->{api_username})); my $session_token = $options{statefile}->get(name => 'session_token'); if ($has_cache_file == 0 || !defined($session_token)) { my $json_request = { username => $self->{api_username}, password => $self->{api_password}, host => $self->{hostname} }; my $encoded; eval { $encoded = encode_json($json_request); }; if ($@) { $self->{output}->add_option_msg(short_msg => 'cannot encode json request'); $self->{output}->option_exit(); } my ($content) = $self->{http}->request( method => 'POST', url_path => $self->{url_path} . 'system/sessions/', query_form_post => $encoded, warning_status => '', unknown_status => '', critical_status => '' ); if ($self->{http}->get_code() != 200) { $self->{output}->add_option_msg(short_msg => "login error [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded = $self->json_decode(content => $content); if (!defined($decoded) || !defined($decoded->{session_id})) { $self->{output}->add_option_msg(short_msg => 'error retrieving session_token'); $self->{output}->option_exit(); } $session_token = $decoded->{session_id}; my $datas = { session_token => $session_token }; $options{statefile}->write(data => $datas); } $self->{session_token} = $session_token; } sub query_relative { my ($self, %options) = @_; my $content = $self->request_api( endpoint => 'search/universal/relative', get_param => ['query=' . $options{query}, 'range=' . $options{timeframe}] ); return $content; } sub request_api { my ($self, %options) = @_; $self->settings(); if (!defined($self->{session_token})) { $self->authenticate(statefile => $self->{cache}); } my $content = $self->{http}->request( url_path => $self->{url_path} . $options{endpoint}, get_param => $options{get_param}, username => $self->{session_token}, password => 'session', credentials => 1, basic => 1, warning_status => '', unknown_status => '', critical_status => '' ); if ($self->{http}->get_code() < 200 || $self->{http}->get_code() >= 300) { $self->clean_session_token(statefile => $self->{cache}); $self->authenticate(statefile => $self->{cache}); $content = $self->{http}->request( url_path => $self->{url_path} . $options{endpoint}, get_param => $options{get_param}, username => $self->{session_token}, password => 'session', credentials => 1, basic => 1, unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status} ); } my $decoded = $self->json_decode(content => $content); if (!defined($decoded)) { $self->{output}->add_option_msg(short_msg => 'error while retrieving data (add --debug option for detailed message)'); $self->{output}->option_exit(); } return $decoded; } 1; __END__ =head1 NAME Graylog Rest API =head1 REST API OPTIONS Graylog Rest API =over 8 =item B<--hostname> Graylog hostname. =item B<--url-path> API url path (Default: '/api/') =item B<--port> API port (Default: 9000) =item B<--proto> Specify https if needed (Default: 'http') =item B<--username> Specify username for authentication (Mandatory if --credentials is specified) =item B<--password> Specify password for authentication (Mandatory if --credentials is specified) =item B<--timeout> Set HTTP timeout =item B<--requested-by> Set request HTTP header (Default: 'cli') =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/graylog/restapi/mode/000077500000000000000000000000001417000230700222365ustar00rootroot00000000000000centreon-plugins-20220113/apps/graylog/restapi/mode/notifications.pm000066400000000000000000000105421417000230700254470ustar00rootroot00000000000000# ## Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::graylog::restapi::mode::notifications; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_global_output { my ($self, %options) = @_; return 'System notifications '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'notifications-total', nlabel => 'graylog.system.notifications.total.count', set => { key_values => [ { name => 'total' } ], output_template => 'total: %s', perfdatas => [ { template => '%d', min => 0 } ] } }, { label => 'notifications-normal', nlabel => 'graylog.system.notifications.normal.count', set => { key_values => [ { name => 'normal' } ], output_template => 'normal: %s', perfdatas => [ { template => '%d', min => 0 } ] } }, { label => 'notifications-urgent', nlabel => 'graylog.system.notifications.urgent.count', set => { key_values => [ { name => 'urgent' } ], output_template => 'urgent: %s', perfdatas => [ { template => '%d', min => 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-severity:s' => { name => 'filter_severity' }, 'filter-node:s' => { name => 'filter_node' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->request_api(endpoint => 'system/notifications'); $self->{global} = { normal => 0, urgent => 0 }; foreach my $notification (@{$result->{notifications}}) { next if (defined($self->{option_results}->{filter_severity}) && $self->{option_results}->{filter_severity} ne '' && $notification->{severity} !~ /$self->{option_results}->{filter_severity}/); next if (defined($self->{option_results}->{filter_node}) && $self->{option_results}->{filter_node} ne '' && $notification->{node_id} !~ /$self->{option_results}->{filter_node}/); $self->{global}->{normal}++ if ($notification->{severity} =~ /normal/); $self->{global}->{urgent}++ if ($notification->{severity} =~ /urgent/); } $self->{global}->{total} = $self->{global}->{normal} + $self->{global}->{urgent}; } 1; __END__ =head1 MODE Check Graylog system notifications using Graylog API Example: perl centreon_plugins.pl --plugin=apps::graylog::restapi::plugin --mode=notifications --hostname=10.0.0.1 --api-username='username' --api-password='password' More information on https://docs.graylog.org/en//pages/configuration/rest_api.html =over 8 =item B<--filter-severity> Filter on specific notification severity. Can be 'normal' or 'urgent'. (Default: both severities shown). =item B<--filter-node> Filter notifications by node ID. (Default: all notifications shown). =item B<--warning-notifications-*> Set warning threshold for notifications count (Default: '') where '*' can be 'total', 'normal' or 'urgent'. =item B<--critical-notifications-*> Set critical threshold for notifications count (Default: '') where '*' can be 'total', 'normal' or 'urgent'. =back =cut centreon-plugins-20220113/apps/graylog/restapi/mode/query.pm000066400000000000000000000062621417000230700237470ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::graylog::restapi::mode::query; 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, skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'query-matches', nlabel => 'graylog.query.match.count', set => { key_values => [ { name => 'query_matches' } ], output_template => 'current queue messages: %s', perfdatas => [ { template => '%d', min => 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 => { 'query:s' => { name => 'query' }, 'timeframe:s' => { name => 'timeframe', default => 300 } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{query}) || $self->{option_results}->{query} eq '') { $self->{output}->add_option_msg(short_msg => 'Please set --query option.'); $self->{output}->option_exit(); } if (defined($self->{option_results}->{timeframe}) && $self->{option_results}->{timeframe} eq '') { $self->{output}->add_option_msg(short_msg => 'Please set --timeframe value.'); $self->{output}->option_exit(); } } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->query_relative( query => $self->{option_results}->{query}, timeframe => $self->{option_results}->{timeframe} ); $self->{global} = { query_matches => $result->{total_results} }; } 1; __END__ =head1 MODE Perform Lucene queries against Graylog API Example: perl centreon_plugins.pl --plugin=apps::graylog::restapi::plugin --mode=query --hostname=10.0.0.1 --api-username='username' --api-password='password' --query='my query' More information on https://docs.graylog.org/en//pages/configuration/rest_api.html =over 8 =item B<--query> Set a Lucene query. =item B<--timeframe> Set timeframe in seconds (E.g '300' to check last 5 minutes). =item B<--warning-query-matches> B<--critical-query-matches> Threshold on the number of results. =back =cut centreon-plugins-20220113/apps/graylog/restapi/plugin.pm000066400000000000000000000025541417000230700231540ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::graylog::restapi::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} = { query => 'apps::graylog::restapi::mode::query', notifications => 'apps::graylog::restapi::mode::notifications' }; $self->{custom_modes}->{api} = 'apps::graylog::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Graylogs through HTTP/REST API. =cut centreon-plugins-20220113/apps/haproxy/000077500000000000000000000000001417000230700176715ustar00rootroot00000000000000centreon-plugins-20220113/apps/haproxy/snmp/000077500000000000000000000000001417000230700206465ustar00rootroot00000000000000centreon-plugins-20220113/apps/haproxy/snmp/mode/000077500000000000000000000000001417000230700215725ustar00rootroot00000000000000centreon-plugins-20220113/apps/haproxy/snmp/mode/backendusage.pm000066400000000000000000000222501417000230700245450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::haproxy::snmp::mode::backendusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub prefix_backend_output { my ($self, %options) = @_; return "Backend '" . $options{instance_value}->{display} . "' "; } sub custom_status_output { my ($self, %options) = @_; return sprintf("status : %s", $self->{result_values}->{status}); } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_alBackendStatus'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'backend', type => 1, cb_prefix_output => 'prefix_backend_output', message_multiple => 'All backends are ok' } ]; $self->{maps_counters}->{backend} = [ { label => 'status', type => 2, critical_default => '%{status} !~ /UP/i', set => { key_values => [ { name => 'alBackendStatus' }, { 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 => \&catalog_status_threshold_ng } }, { label => 'current-queue', nlabel => 'backend.queue.current.count', set => { key_values => [ { name => 'alBackendQueueCur' }, { name => 'display' } ], output_template => 'Current queue : %s', perfdatas => [ { label => 'current_queue', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'current-sessions', nlabel => 'backend.sessions.current.count', set => { key_values => [ { name => 'alBackendSessionCur' }, { name => 'display' } ], output_template => 'Current sessions : %s', perfdatas => [ { label => 'current_sessions', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'total-sessions', nlabel => 'backend.sessions.total.count', set => { key_values => [ { name => 'alBackendSessionTotal', diff => 1 }, { name => 'display' } ], output_template => 'Total sessions : %s', perfdatas => [ { label => 'total_connections', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'traffic-in', nlabel => 'backend.traffic.in.bitpersecond', set => { key_values => [ { name => 'alBackendBytesIN', per_second => 1 }, { name => 'display' } ], output_template => 'Traffic In : %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'traffic_in', template => '%.2f', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'traffic-out', nlabel => 'backend.traffic.out.bitpersecond', set => { key_values => [ { name => 'alBackendBytesOUT', per_second => 1 }, { name => 'display' } ], output_template => 'Traffic Out : %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'traffic_out', template => '%.2f', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } my $mapping = { entreprise => { alBackendQueueCur => { oid => '.1.3.6.1.4.1.23263.4.2.1.3.3.1.4' }, alBackendSessionCur => { oid => '.1.3.6.1.4.1.23263.4.2.1.3.3.1.7' }, alBackendSessionTotal => { oid => '.1.3.6.1.4.1.23263.4.2.1.3.3.1.10' }, alBackendBytesIN => { oid => '.1.3.6.1.4.1.23263.4.2.1.3.3.1.12' }, alBackendBytesOUT => { oid => '.1.3.6.1.4.1.23263.4.2.1.3.3.1.13' }, alBackendStatus => { oid => '.1.3.6.1.4.1.23263.4.2.1.3.3.1.20' } }, csv => { alBackendQueueCur => { oid => '.1.3.6.1.4.1.29385.106.1.1.2' }, alBackendSessionCur => { oid => '.1.3.6.1.4.1.29385.106.1.1.4' }, alBackendSessionTotal => { oid => '.1.3.6.1.4.1.29385.106.1.1.7' }, alBackendBytesIN => { oid => '.1.3.6.1.4.1.29385.106.1.1.8' }, alBackendBytesOUT => { oid => '.1.3.6.1.4.1.29385.106.1.1.9' }, alBackendStatus => { oid => '.1.3.6.1.4.1.29385.106.1.1.17' } }, }; my $mapping_name = { csv => '.1.3.6.1.4.1.29385.106.1.1.0', entreprise => '.1.3.6.1.4.1.23263.4.2.1.3.3.1.3', # alBackendName }; 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_multiple_table(oids => [ { oid => $mapping_name->{csv} }, { oid => $mapping_name->{entreprise} } ], nothing_quit => 1); my $branch = 'entreprise'; if (defined($snmp_result->{ $mapping_name->{csv} }) && scalar(keys %{$snmp_result->{ $mapping_name->{csv} }}) > 0) { $branch = 'csv'; } $self->{backend} = {}; foreach my $oid (keys %{$snmp_result->{ $mapping_name->{$branch} }}) { $oid =~ /^$mapping_name->{$branch}\.(.*)$/; my $instance = $1; my $name = $snmp_result->{$mapping_name->{$branch}}->{$oid}; 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 backend '" . $name . "'.", debug => 1); next; } $self->{backend}->{$instance} = { display => $name }; } if (scalar(keys %{$self->{backend}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No backend found."); $self->{output}->option_exit(); } $options{snmp}->load( oids => [ map($_->{oid}, values(%{$mapping->{$branch}})) ], instances => [keys %{$self->{backend}}], instance_regexp => '^(.*)$' ); $snmp_result = $options{snmp}->get_leef(nothing_quit => 1); foreach (keys %{$self->{backend}}) { my $result = $options{snmp}->map_instance(mapping => $mapping->{$branch}, results => $snmp_result, instance => $_); $result->{alBackendBytesIN} *= 8; $result->{alBackendBytesOUT} *= 8; $self->{backend}->{$_} = { %{$self->{backend}->{$_}}, %$result }; } $self->{cache_name} = 'haproxy_' . $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 backend usage. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^total-sessions$' =item B<--filter-name> Filter backend name (can be a regexp). =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 (Default: '%{status} !~ /UP/i'). Can used special variables like: %{status}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'total-sessions', 'current-sessions', 'current-queue', 'traffic-in' (b/s), 'traffic-out' (b/s). =back =cut centreon-plugins-20220113/apps/haproxy/snmp/mode/frontendusage.pm000066400000000000000000000211241417000230700247740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::haproxy::snmp::mode::frontendusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub prefix_frontend_output { my ($self, %options) = @_; return "Frontend '" . $options{instance_value}->{display} . "' "; } sub custom_status_output { my ($self, %options) = @_; return sprintf("status : %s", $self->{result_values}->{status}); } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_alFrontendStatus'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'frontend', type => 1, cb_prefix_output => 'prefix_frontend_output', message_multiple => 'All frontends are ok' } ]; $self->{maps_counters}->{frontend} = [ { label => 'status', type => 2, critical_default => '%{status} !~ /OPEN/i', set => { key_values => [ { name => 'alFrontendStatus' }, { 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 => \&catalog_status_threshold_ng } }, { label => 'current-sessions', nlabel => 'frontend.sessions.current.count', set => { key_values => [ { name => 'alFrontendSessionCur' }, { name => 'display' } ], output_template => 'Current sessions : %s', perfdatas => [ { label => 'current_sessions', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'total-sessions', nlabel => 'frontend.sessions.total.count', set => { key_values => [ { name => 'alFrontendSessionTotal', diff => 1 }, { name => 'display' } ], output_template => 'Total sessions : %s', perfdatas => [ { label => 'total_connections', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'traffic-in', nlabel => 'frontend.traffic.in.bitpersecond', set => { key_values => [ { name => 'alFrontendBytesIN', per_second => 1 }, { name => 'display' } ], output_template => 'Traffic In : %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'traffic_in', template => '%.2f', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'traffic-out', nlabel => 'frontend.traffic.out.bitpersecond', set => { key_values => [ { name => 'alFrontendBytesOUT', per_second => 1 }, { name => 'display' } ], output_template => 'Traffic Out : %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'traffic_out', template => '%.2f', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } my $mapping = { entreprise => { alFrontendSessionCur => { oid => '.1.3.6.1.4.1.23263.4.2.1.3.2.1.4' }, alFrontendSessionTotal => { oid => '.1.3.6.1.4.1.23263.4.2.1.3.2.1.7' }, alFrontendBytesIN => { oid => '.1.3.6.1.4.1.23263.4.2.1.3.2.1.8' }, alFrontendBytesOUT => { oid => '.1.3.6.1.4.1.23263.4.2.1.3.2.1.9' }, alFrontendStatus => { oid => '.1.3.6.1.4.1.23263.4.2.1.3.2.1.13' } }, csv => { alFrontendSessionCur => { oid => '.1.3.6.1.4.1.29385.106.1.0.4' }, alFrontendSessionTotal => { oid => '.1.3.6.1.4.1.29385.106.1.0.7' }, alFrontendBytesIN => { oid => '.1.3.6.1.4.1.29385.106.1.0.8' }, alFrontendBytesOUT => { oid => '.1.3.6.1.4.1.29385.106.1.0.9' }, alFrontendStatus => { oid => '.1.3.6.1.4.1.29385.106.1.0.17' } }, }; my $mapping_name = { csv => '.1.3.6.1.4.1.29385.106.1.0.0', entreprise => '.1.3.6.1.4.1.23263.4.2.1.3.2.1.3' # alFrontendName }; 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_multiple_table(oids => [ { oid => $mapping_name->{csv} }, { oid => $mapping_name->{entreprise} } ], nothing_quit => 1); my $branch = 'entreprise'; if (defined($snmp_result->{ $mapping_name->{csv} }) && scalar(keys %{$snmp_result->{ $mapping_name->{csv} }}) > 0) { $branch = 'csv'; } $self->{frontend} = {}; foreach my $oid (keys %{$snmp_result->{ $mapping_name->{$branch} }}) { $oid =~ /^$mapping_name->{$branch}\.(.*)$/; my $instance = $1; my $name = $snmp_result->{$mapping_name->{$branch}}->{$oid}; 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 frontend '" . $name . "'.", debug => 1); next; } $self->{frontend}->{$instance} = { display => $name }; } if (scalar(keys %{$self->{frontend}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No frontend found."); $self->{output}->option_exit(); } $options{snmp}->load( oids => [ map($_->{oid}, values(%{$mapping->{$branch}})) ], instances => [keys %{$self->{frontend}}], instance_regexp => '^(.*)$' ); $snmp_result = $options{snmp}->get_leef(nothing_quit => 1); foreach (keys %{$self->{frontend}}) { my $result = $options{snmp}->map_instance(mapping => $mapping->{$branch}, results => $snmp_result, instance => $_); $result->{alFrontendBytesIN} *= 8; $result->{alFrontendBytesOUT} *= 8; $self->{frontend}->{$_} = { %{$self->{frontend}->{$_}}, %$result }; } $self->{cache_name} = 'haproxy_' . $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 frontend usage. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^total-connections$' =item B<--filter-name> Filter backend name (can be a regexp). =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 (Default: '%{status} !~ /OPEN/i'). Can used special variables like: %{status}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'total-sessions', 'current-sessions', 'traffic-in' (b/s), 'traffic-out' (b/s). =back =cut centreon-plugins-20220113/apps/haproxy/snmp/plugin.pm000066400000000000000000000024351417000230700225060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::haproxy::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} = { 'backend-usage' => 'apps::haproxy::snmp::mode::backendusage', 'frontend-usage' => 'apps::haproxy::snmp::mode::frontendusage' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check haproxy software in SNMP. =cut centreon-plugins-20220113/apps/hashicorp/000077500000000000000000000000001417000230700201575ustar00rootroot00000000000000centreon-plugins-20220113/apps/hashicorp/vault/000077500000000000000000000000001417000230700213125ustar00rootroot00000000000000centreon-plugins-20220113/apps/hashicorp/vault/restapi/000077500000000000000000000000001417000230700227615ustar00rootroot00000000000000centreon-plugins-20220113/apps/hashicorp/vault/restapi/custom/000077500000000000000000000000001417000230700242735ustar00rootroot00000000000000centreon-plugins-20220113/apps/hashicorp/vault/restapi/custom/api.pm000066400000000000000000000252361417000230700254120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::hashicorp::vault::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use centreon::plugins::statefile; use JSON::XS; use Digest::MD5 qw(md5_hex); 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 => { 'api-version:s' => { name => 'api_version' }, 'critical-http-status:s' => { name => 'critical_http_status' }, 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'warning-http-status:s' => { name => 'warning_http_status' }, 'auth-method:s' => { name => 'auth_method', default => 'token' }, 'auth-settings:s%' => { name => 'auth_settings' }, 'unknown-http-status:s' => { name => 'unknown_http_status' }, 'vault-token:s' => { name => 'vault_token'} }); }; $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); $self->{cache} = centreon::plugins::statefile->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; if ($self->{option_results}->{auth_method} eq 'token' && (!defined($self->{option_results}->{vault_token}) || $self->{option_results}->{vault_token} eq '')) { $self->{output}->add_option_msg(short_msg => "Please set the --vault-token option"); $self->{output}->option_exit(); }; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 8200; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'http'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{auth_method} = lc($self->{option_results}->{auth_method}); $self->{auth_settings} = defined($self->{option_results}->{auth_settings}) && $self->{option_results}->{auth_settings} ne '' ? $self->{option_results}->{auth_settings} : {}; $self->{vault_token} = $self->{option_results}->{vault_token}; $self->{api_version} = (defined($self->{option_results}->{api_version})) ? $self->{option_results}->{api_version} : 'v1'; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300'; $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; $self->{reload_cache_time} = (defined($self->{option_results}->{reload_cache_time})) ? $self->{option_results}->{reload_cache_time} : 180; $self->{cache}->check_options(option_results => $self->{option_results}); if (lc($self->{auth_method}) !~ m/azure|cert|github|ldap|okta|radius|userpass|token/ ) { $self->{output}->add_option_msg(short_msg => "Incorrect or unsupported authentication method set in --auth-method"); $self->{output}->option_exit(); }; return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{basic} = 1; } sub settings { my ($self, %options) = @_; return if (defined($self->{settings_done})); $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); if (defined($self->{option_results}->{auth_method}) && $self->{option_results}->{auth_method} ne 'token') { $self->{vault_token} = $self->get_access_token(statefile => $self->{cache}); }; if (defined($self->{vault_token})) { $self->{http}->add_header(key => 'X-Vault-Token', value => $self->{vault_token}); }; $self->{http}->set_options(%{$self->{option_results}}); $self->{settings_done} = 1; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub get_access_token { my ($self, %options) = @_; my $has_cache_file = $options{statefile}->read(statefile => 'vault_restapi_' . md5_hex($self->{hostname}) . '_' . md5_hex($self->{auth_method})); my $expires_on = $options{statefile}->get(name => 'expires_on'); my $access_token = $options{statefile}->get(name => 'access_token'); if ( $has_cache_file == 0 || !defined($access_token) || (($expires_on - time()) < 10) ) { my $decoded; my $login = $self->parse_auth_method(method => $self->{auth_method}, settings => $self->{auth_settings}); my $post_json = JSON::XS->new->utf8->encode($login); my $url_path = '/' . $self->{api_version} . '/auth/'. $self->{auth_method} . '/login/'; $url_path .= $self->{auth_settings}->{username} if (defined($self->{auth_settings}->{username}) && $self->{auth_method} =~ 'userpass|login') ; my $content = $self->{http}->request( hostname => $self->{hostname}, port => $self->{port}, proto => $self->{proto}, method => 'POST', header => ['Content-type: application/json'], query_form_post => $post_json, url_path => $url_path ); if (!defined($content) || $content eq '') { $self->{output}->add_option_msg(short_msg => "Authentication endpoint returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); }; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->output_add(long_msg => $content, debug => 1); $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); }; if (defined($decoded->{errors}[0])) { $self->{output}->output_add(long_msg => "Error message : " . $decoded->{errors}[0], debug => 1); $self->{output}->add_option_msg(short_msg => "Authentication endpoint returns error code '" . $decoded->{errors}[0] . "' (add --debug option for detailed message)"); $self->{output}->option_exit(); }; $access_token = $decoded->{auth}->{client_token}; my $datas = { last_timestamp => time(), access_token => $decoded->{access_token}, expires_on => time() + 3600 }; $options{statefile}->write(data => $datas); }; return $access_token; } sub parse_auth_method { my ($self, %options) = @_; my $login_settings; my $settings_mapping = { azure => [ 'role', 'jwt' ], cert => [ 'name' ], github => [ 'token' ], ldap => [ 'username', 'password' ], okta => [ 'username', 'password', 'totp' ], radius => [ 'username', 'password' ], userpass => [ 'username', 'password' ] }; foreach (@{$settings_mapping->{$options{method}}}) { if (!defined($options{settings}->{$_})) { $self->{output}->add_option_msg(short_msg => 'Missing authentication setting: ' . $_); $self->{output}->option_exit(); } $login_settings->{$_} = $options{settings}->{$_}; }; return $login_settings; } sub request_api { my ($self, %options) = @_; $self->settings(%options); my ($json, $response); $response = $self->{http}->request( method => 'GET', url_path => '/' . $self->{api_version} . '/sys/' . $options{url_path} ); $self->{output}->output_add(long_msg => $response, debug => 1); eval { $json = JSON::XS->new->utf8->decode($response); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode Vault JSON response: $@"); $self->{output}->option_exit(); }; return $json; } 1; __END__ =head1 NAME HashiCorp Vault Rest API =head1 REST API OPTIONS HashiCorp Vault Rest API =over 8 =item B<--hostname> HashiCorp Vault hostname. =item B<--port> Port used (Default: 8200) =item B<--proto> Specify https if needed (Default: 'http') =item B<--api-version> Specify the Vault API version (Default: 'v1') =item B<--vault-token> Specify the Vault access token (only for the 'token' authentication method) =item B<--auth-method> Specify the Vault authentication method (Default: 'token'). Can be: 'azure', 'cert', 'github', 'ldap', 'okta', 'radius', 'userpass', 'token' If different from 'token' the "--auth-settings" options must be set. =item B<--auth-settings> Specify the Vault authentication specific settings. Syntax: --auth-settings='='.Example for the 'userpass' method: --auth-method='userpass' --auth-settings='username=my_account' --auth-settings='password=my_password' =item B<--timeout> Set timeout in seconds (Default: 10). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/hashicorp/vault/restapi/mode/000077500000000000000000000000001417000230700237055ustar00rootroot00000000000000centreon-plugins-20220113/apps/hashicorp/vault/restapi/mode/health.pm000066400000000000000000000072641417000230700255210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::hashicorp::vault::restapi::mode::health; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'vault_cluster', type => 1, cb_prefix_output => 'custom_prefix_output'}, ]; $self->{maps_counters}->{vault_cluster} = [ { label => 'seal-status', type => 2, critical_default => '%{sealed} ne "unsealed"', set => { key_values => [ { name => 'sealed' } ], output_template => "seal status : %s", closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'init-status', type => 2, critical_default => '%{init} ne "initialized"', set => { key_values => [ { name => 'init' } ], output_template => "init status : %s", closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub custom_prefix_output { my ($self, %options) = @_; return 'Server ' . $options{instance_value}->{cluster_name} . ' '; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub set_options { my ($self, %options) = @_; } sub manage_selection { my ($self, %options) = @_; my $code_param = '?sealedcode=200&uninitcode=200'; # By default API will return error codes if sealed or uninit my $result = $options{custom}->request_api(url_path => 'health' . $code_param); my $cluster_name = defined($result->{cluster_name}) ? $result->{cluster_name} : $self->{option_results}->{hostname}; $self->{vault_cluster}->{$cluster_name} = { cluster_name => $cluster_name, sealed => $result->{sealed} ? 'sealed' : 'unsealed', init => $result->{initialized} ? 'initialized' : 'not initialized', }; } 1; __END__ =head1 MODE Check Hashicorp Vault Health status. Example: perl centreon_plugins.pl --plugin=apps::hashicorp::vault::restapi::plugin --mode=health --hostname=10.0.0.1 --vault-token='s.aBCD123DEF456GHI789JKL012' --verbose More information on'https://www.vaultproject.io/api-docs/system/health'. =over 8 =item B<--warning-seal-status> Set warning threshold for seal status (Default: none). =item B<--critical-seal-status> Set critical threshold for seal status (Default: '%{sealed} ne "unsealed"'). =item B<--warning-init-status> Set warning threshold for initialization status (Default: none). =item B<--critical-init-status> Set critical threshold for initialization status (Default: '%{init} ne "initialized"'). =back =cut centreon-plugins-20220113/apps/hashicorp/vault/restapi/mode/raftstorage.pm000066400000000000000000000122601417000230700265650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::hashicorp::vault::restapi::mode::raftstorage; 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 }, { name => 'boltdb', type => 1, cb_prefix_output => 'prefix_boltdb_output', message_multiple => 'All Bolt Databases are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'commit-time', nlbalel => 'vault.raftstorage.committime.seconds', set => { key_values => [ { name => 'commit_time' } ], output_template => "commit time : %.2fs", perfdatas => [ { template => '%.2f', unit => 'ms', min => 0 } ] } } ]; $self->{maps_counters}->{boltdb} = [ { label => 'spill-time', nlabel => 'vault.raftstorage.spilltime.seconds', set => { key_values => [ { name => 'spill_time' }, { name => 'display' } ], output_template => 'spill time: %.2fms', perfdatas => [ { template => '%d', unit => 'ms', min => 0, cast_int => 1, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'rebalance-time', nlabel => 'vault.raftstorage.rebalance_time.seconds', set => { key_values => [ { name => 'rebalance_time' }, { name => 'display' } ], output_template => 'rebalance time: %.2fms', perfdatas => [ { template => '%d', unit => 'ms', min => 0, cast_int => 1, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'write-time', nlabel => 'vault.raftstorage.write_time.seconds', set => { key_values => [ { name => 'write_time' }, { name => 'display' } ], output_template => 'write time: %.2fms', perfdatas => [ { template => '%d', unit => 'ms', min => 0, cast_int => 1, label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub prefix_boltdb_output { my ($self, %options) = @_; return "Database '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub set_options { my ($self, %options) = @_; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->request_api(url_path => 'metrics'); foreach (@{$result->{Samples}}) { $_->{Name} =~ s/\.|\-/_/g; if (defined($_->{Labels}->{database})) { $_->{Name} =~ s/vault_raft_storage_bolt_//g; $self->{raftstorage}->{boltdb}->{ $_->{Labels}->{database} }->{ $_->{Name} } = { rate => $_->{Rate}, cluster => $_->{Labels}->{cluster} } } else { $self->{raftstorage}->{global}->{ $_->{Name} } = { rate => $_->{Rate}, } } }; $self->{global} = { commit_time => defined($self->{raftstorage}->{global}->{'vault.raft.commitTime'}) ? $self->{global}->{raftstorage}->{'vault.raft.commitTime'}->{rate} : 0 }; foreach my $database (keys %{$self->{raftstorage}->{boltdb}}) { $self->{boltdb}->{$database} = { display => $database, rebalance_time => $self->{raftstorage}->{boltdb}->{$database}->{rebalance_time}, spill_time => $self->{raftstorage}->{boltdb}->{$database}->{spill_time}, write_time => $self->{raftstorage}->{boltdb}->{$database}->{write_time} } }; if (scalar(keys %{$self->{boltdb}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No Bolt DB found."); $self->{output}->option_exit(); }; } 1; __END__ =head1 MODE Check Hashicorp Vault Raft Storage status. Example: perl centreon_plugins.pl --plugin=apps::hashicorp::vault::restapi::plugin --mode=raft-storage --hostname=10.0.0.1 --vault-token='s.aBCD123DEF456GHI789JKL012' --verbose More information on'https://www.vaultproject.io/api-docs/system/health'. =over 8 =item B<--warning-*> Warning threshold where '*' can be: 'commit-time', 'spill-time', 'rebalance-time', 'write-time' =item B<--critical-*> Critical threshold where '*' can be: 'commit-time', 'spill-time', 'rebalance-time', 'write-time' =back =cut centreon-plugins-20220113/apps/hashicorp/vault/restapi/plugin.pm000066400000000000000000000026151417000230700246210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::hashicorp::vault::restapi::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} = '1.0'; $self->{modes} = { 'health' => 'apps::hashicorp::vault::restapi::mode::health', 'raft-storage' => 'apps::hashicorp::vault::restapi::mode::raftstorage' }; $self->{custom_modes}->{api} = 'apps::hashicorp::vault::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check HashiCorp Vault using RestAPI. =cutcentreon-plugins-20220113/apps/hddtemp/000077500000000000000000000000001417000230700176245ustar00rootroot00000000000000centreon-plugins-20220113/apps/hddtemp/custom/000077500000000000000000000000001417000230700211365ustar00rootroot00000000000000centreon-plugins-20220113/apps/hddtemp/custom/cli.pm000066400000000000000000000210441417000230700222440ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::hddtemp::custom::cli; use strict; use warnings; use centreon::plugins::ssh; 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 => { 'hostname:s' => { name => 'hostname' }, 'timeout:s' => { name => 'timeout', default => 45 }, 'command-drives:s' => { name => 'command_drives' }, 'command-path-drives:s' => { name => 'command_path_drives' }, 'command-options-drives:s' => { name => 'command_options_drives' }, 'command-hddtemp:s' => { name => 'command_hddtemp' }, 'command-path-hddtemp:s' => { name => 'command_path_hddtemp' }, 'command-options-hddtemp:s' => { name => 'command_options_hddtemp' }, 'sudo:s' => { name => 'sudo' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'CLI OPTIONS', once => 1); $self->{output} = $options{output}; $self->{ssh} = centreon::plugins::ssh->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; if (defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '') { $self->{ssh}->check_options(option_results => $self->{option_results}); } return 0; } sub list_drives { my ($self, %options) = @_; my $stdout; if (defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '') { ($stdout) = $self->{ssh}->execute( hostname => $self->{option_results}->{hostname}, command => defined($self->{option_results}->{command_drives}) && $self->{option_results}->{command_drives} ne '' ? $self->{option_results}->{command_drives} : 'lsblk', command_path => $self->{option_results}->{command_path_drives}, command_options => defined($self->{option_results}->{command_options_drives}) && $self->{option_results}->{command_options_drives} ne '' ? $self->{option_results}->{command_options_drives} : '-I 8 -d -o NAME -p -n', timeout => $self->{option_results}->{timeout} ); } else { ($stdout) = centreon::plugins::misc::execute( output => $self->{output}, options => { timeout => $self->{option_results}->{timeout} }, command => defined($self->{option_results}->{command_drives}) && $self->{option_results}->{command_drives} ne '' ? $self->{option_results}->{command_drives} : 'lsblk', command_path => $self->{option_results}->{command_path_drives}, command_options => defined($self->{option_results}->{command_options_drives}) && $self->{option_results}->{command_options_drives} ne '' ? $self->{option_results}->{command_options_drives} : '-I 8 -d -o NAME -p -n' ); } $self->{output}->output_add(long_msg => "command response: $stdout", debug => 1); my $drives = {}; $drives->{$_} = {} foreach (split /\n/, $stdout); return $drives; } sub get_drives_information { my ($self, %options) = @_; my $drives = $self->list_drives(); my $cmd_options = '-u C ' . join(' ', keys %$drives); my ($stdout, $exit_code); if (defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '') { ($stdout, $exit_code) = $self->{ssh}->execute( hostname => $self->{option_results}->{hostname}, sudo => $self->{option_results}->{sudo}, command => defined($self->{option_results}->{command_hddtemp}) && $self->{option_results}->{command_hddtemp} ne '' ? $self->{option_results}->{command_hddtemp} : 'hddtemp', command_path => $self->{option_results}->{command_path_hddtemp}, command_options => defined($self->{option_results}->{command_options_hddtemp}) && $self->{option_results}->{command_options_hddtemp} ne '' ? $self->{option_results}->{command_options_hddtemp} : $cmd_options, timeout => $self->{option_results}->{timeout}, no_quit => 1 ); } else { ($stdout, $exit_code) = centreon::plugins::misc::execute( output => $self->{output}, options => { timeout => $self->{option_results}->{timeout} }, sudo => $self->{option_results}->{sudo}, command => defined($self->{option_results}->{command_hddtemp}) && $self->{option_results}->{command_hddtemp} ne '' ? $self->{option_results}->{command_hddtemp} : 'hddtemp', command_path => $self->{option_results}->{command_path_hddtemp}, command_options => defined($self->{option_results}->{command_options_hddtemp}) && $self->{option_results}->{command_options_hddtemp} ne '' ? $self->{option_results}->{command_options_hddtemp} : $cmd_options . ' 2> /dev/null', no_quit => 1, ); } # exit values can be: 0/1. Need root permissions. if ($exit_code != 0 && $exit_code != 1) { $self->{output}->add_option_msg(short_msg => sprintf('command execution error [exit code: %s]', $exit_code)); $self->{output}->option_exit(); } # OK: # /dev/sda: SanDisk ...: 32 C # ERROR: # message on stderr. So if we don't catch stderr and we have nothing, surely error. for example: # /dev/sda: open: Permission denied # UNKNOWN: # /dev/sda: SanDisk ...: no sensor # SLEEP: # /dev/sda: SanDisk ...: drive is sleeping # NOSENSOR: # /dev/sda: SanDisk ...: drive supported, but it doesn't have a temperature sensor # NOT_APPLICABLE: # /dev/sda: SanDisk ...: misc message foreach my $name (keys %$drives) { if ($stdout =~ /^$name:.*?:\s+(\d+).*?C/m) { $drives->{$name}->{status} = 'ok'; $drives->{$name}->{temperature_unit} = 'C'; $drives->{$name}->{temperature} = $1; } elsif ($stdout =~ /^$name:.*?:\s+(.*)$/m) { my $message = $1; $drives->{$name}->{status} = 'notApplicable'; $drives->{$name}->{status} = 'unknown' if ($message =~ /no sensor/i); $drives->{$name}->{status} = 'driveSleep' if ($message =~ /drive is sleeping/i); $drives->{$name}->{status} = 'noSensor' if ($message =~ /drive supported, but it doesn't have a temperature sensor/i); } else { $drives->{$name}->{status} = 'error'; } } return $drives; } 1; __END__ =head1 NAME ssh =head1 SYNOPSIS my ssh =head1 CLI OPTIONS =over 8 =item B<--hostname> Hostname to query (ssh mode). =item B<--timeout> Timeout in seconds for the command (Default: 45). =item You can override command for drives listing. By default, we use 'lsblk -I 8 -d -o NAME -p -n': =over 16 =item B<--command-drives> Command to get information. Used it you have output in a file. =item B<--command-path-drives> Command path. =item B<--command-options-drives> Command options. =back =item You can override command hddtemp used. By default, we use 'hddtemp -u C /dev/sda /dev/sdb ...' built with the result of drives command: =over 16 =item B<--command-hddtemp> Command to get information. Used it you have output in a file. =item B<--command-path-hddtemp> Command path. =item B<--command-options-hddtemp> Command options. =item B<--sudo> Sudo hddtemp command. =back =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/hddtemp/custom/tcp.pm000066400000000000000000000105761417000230700222730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::hddtemp::custom::tcp; use base qw(centreon::plugins::mode); use strict; use warnings; use IO::Socket; 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'timeout:s' => { name => 'timeout' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'CUSTOM TCP OPTIONS', once => 1); $self->{output} = $options{output}; return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) && $self->{option_results}->{port} =~ /(\d+)/ ? $1 : 7634; $self->{timeout} = (defined($self->{option_results}->{timeout})) && $self->{option_results}->{timeout} =~ /(\d+)/ ? $1 : 30; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --hostname option.'); $self->{output}->option_exit(); } return 0; } sub get_hddtemp_drives { my ($self, %options) = @_; my $socket = new IO::Socket::INET( Proto => 'tcp', PeerAddr => $self->{hostname}, PeerPort => $self->{port}, Timeout => $self->{timeout} ); if (!defined($socket)) { $self->{output}->add_option_msg(short_msg => "could not connect: $@"); $self->{output}->option_exit(); } my $line; eval { local $SIG{ALRM} = sub { die 'Timeout'; }; alarm($self->{timeout}); $line = <$socket>; alarm(0); }; $socket->shutdown(2); if ($@) { $self->{output}->add_option_msg(short_msg => 'cannot get informations: ' . $@); $self->{output}->option_exit(); } return $line; } sub list_drives { my ($self, %options) = @_; my $line = $self->get_hddtemp_drives(); my $drives = {}; while ($line =~ /\|(.*?)\|(.*?)\|(.*?)\|(.*?)\|/msg) { $drives->{$1} = {}; } return $drives; } sub get_drives_information { my ($self, %options) = @_; my $line = $self->get_hddtemp_drives(); #|/dev/sda|SanDisk ....|33|C| #|/dev/sda|Scan .... |NA|*| my $mapping_errors = { NA => 'notApplicable', UNK => 'unknown', NOS => 'noSensor', SLP => 'driveSleep', ERR => 'error' }; my $drives = {}; while ($line =~ /\|(.*?)\|(.*?)\|(.*?)\|(.*?)\|/msg) { my ($name, $value, $unit) = ($1, $3, $4); if ($value =~ /\d+/) { $drives->{$name} = { temperature => $value, temperature_unit => $unit, status => 'ok' }; } else { $drives->{$name} = { status => $mapping_errors->{$value} }; } } return $drives; } 1; __END__ =head1 NAME Hddtemp =head1 CUSTOM TCP OPTIONS Hddtemp tcp =over 8 =item B<--hostname> Hostname or IP address. =item B<--port> Port used (Default: 7634) =item B<--timeout> Set timeout in seconds (Default: 30). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/hddtemp/mode/000077500000000000000000000000001417000230700205505ustar00rootroot00000000000000centreon-plugins-20220113/apps/hddtemp/mode/listdrives.pm000066400000000000000000000041631417000230700233020ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::hddtemp::mode::listdrives; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; return $options{custom}->list_drives(); } sub run { my ($self, %options) = @_; my $drives = $self->manage_selection(%options); foreach (sort keys %$drives) { $self->{output}->output_add(long_msg => sprintf( '[name = %s]', $_ ) ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List drives:' ); $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) = @_; my $drives = $self->manage_selection(%options); foreach (sort keys %$drives) { $self->{output}->add_disco_entry(name => $_); } } 1; __END__ =head1 MODE List queues. =over 8 =back =cut centreon-plugins-20220113/apps/hddtemp/mode/temperatures.pm000066400000000000000000000117231417000230700236320ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::hddtemp::mode::temperatures; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); sub custom_status_output { my ($self, %options) = @_; return sprintf( 'status: %s', $self->{result_values}->{status}, ); } sub custom_temperature_output { my ($self, %options) = @_; return sprintf('temperature: %s %s', $self->{result_values}->{temperature}, $self->{result_values}->{temperature_unit} ); } sub custom_temperature_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => 'drive.temperature.' . ($self->{result_values}->{temperature_unit} eq 'C' ? 'celsius' : 'fahrenheit'), instances => $self->{result_values}->{display}, unit => $self->{result_values}->{temperature_unit}, value => $self->{result_values}->{temperature}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}), ); } sub prefix_drive_output { my ($self, %options) = @_; return "Drive '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'drives', type => 1, cb_prefix_output => 'prefix_drive_output', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{drives} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'display' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } }, { label => 'temperature', set => { key_values => [ { name => 'temperature' }, { name => 'temperature_unit' }, { name => 'display' } ], closure_custom_output => $self->can('custom_temperature_output'), closure_custom_perfdata => $self->can('custom_temperature_perfdata') } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'unknown-status:s' => { name => 'unknown_status', default => '' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{status} !~ /ok/i' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['unknown_status', 'warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->get_drives_information(); $self->{drives} = {}; foreach (keys %$results) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $_ !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping drive '" . $_ . "': no matching filter.", debug => 1); next; } $self->{drives}->{$_} = { display => $_, %{$results->{$_}} }; } } 1; __END__ =head1 MODE Check drive temperatures. =over 8 =item B<--filter-name> Filter drive name (Can use regexp). =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{status}, %{display} =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 (Default: '%{status} !~ /ok/i'). Can used special variables like: %{status}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'temperature'. =back =cut centreon-plugins-20220113/apps/hddtemp/plugin.pm000066400000000000000000000030421417000230700214570ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::hddtemp::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} = '1.0'; %{$self->{modes}} = ( 'list-drives' => 'apps::hddtemp::mode::listdrives', 'temperatures' => 'apps::hddtemp::mode::temperatures' ); $self->{custom_modes}{tcp} = 'apps::hddtemp::custom::tcp'; $self->{custom_modes}{cli} = 'apps::hddtemp::custom::cli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check drives temperature with hddtemp. Two custom modes availables: 'tcp' (remotely with hddtemp in daemon mode) 'command' (with hddtemp command. you can execute locally or through ssh). =cut centreon-plugins-20220113/apps/ibm/000077500000000000000000000000001417000230700167465ustar00rootroot00000000000000centreon-plugins-20220113/apps/ibm/tsamp/000077500000000000000000000000001417000230700200725ustar00rootroot00000000000000centreon-plugins-20220113/apps/ibm/tsamp/local/000077500000000000000000000000001417000230700211645ustar00rootroot00000000000000centreon-plugins-20220113/apps/ibm/tsamp/local/mode/000077500000000000000000000000001417000230700221105ustar00rootroot00000000000000centreon-plugins-20220113/apps/ibm/tsamp/local/mode/listresourcegroups.pm000066400000000000000000000051121417000230700264300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::ibm::tsamp::local::mode::listresourcegroups; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; my ($stdout) = $options{custom}->execute_command( command => 'lssam', command_options => '-nocolor' ); my $rg = []; while ($stdout =~ /^(\S.*)\s+IBM.ResourceGroup:(.*?)\s+.*?Nominal=(.*)\s*$/mig) { my ($name, $opState, $nominalState) = ($2, lc($1), lc($3)); push @$rg, { name => $name, state => $opState, nominal => $nominalState }; } return $rg; } sub run { my ($self, %options) = @_; my $rg = $self->manage_selection(%options); foreach (@$rg) { $self->{output}->output_add( long_msg => sprintf( "[name: %s][state: %s][nominal: %s]", $_->{name}, $_->{state}, $_->{nominal} ) ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List resource groups:' ); $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', 'nominal']); } sub disco_show { my ($self, %options) = @_; my $rg = $self->manage_selection(%options); foreach (@$rg) { $self->{output}->add_disco_entry(%$_); } } 1; __END__ =head1 MODE List resource groups. =over 8 =back =cut centreon-plugins-20220113/apps/ibm/tsamp/local/mode/resourcegroups.pm000066400000000000000000000140471417000230700255430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::ibm::tsamp::local::mode::resourcegroups; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf( 'operational state: %s [nominal: %s]', $self->{result_values}->{opState}, $self->{result_values}->{nominalState} ); } sub prefix_rg_output { my ($self, %options) = @_; return "Resource group '" . $options{instance} . "' "; } sub prefix_global_output { my ($self, %options) = @_; return 'Number of resource groups '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }, { name => 'rg', type => 1, cb_prefix_output => 'prefix_rg_output', message_multiple => 'All resource groups are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = []; foreach ('unknown', 'offline', 'online', 'failed_offline', 'stuck_online', 'pending_online', 'pending_offline', 'ineligible') { my ($label, $output) = ($_, $_); $label =~ s/_/-/g; $output =~ s/_/ /g; push @{$self->{maps_counters}->{global}}, { label => 'total-' . $label, display_ok => 0, nlabel => 'resource_groups.' . $_ . '.count', set => { key_values => [ { name => $_ } ], output_template => $output . ': %s', perfdatas => [ { template => '%s', min => 0 } ] } }; } $self->{maps_counters}->{rg} = [ { label => 'status', type => 2, unknown_default => '%{opState} =~ /unknown/i', warning_default => '%{opState} =~ /pending/i', critical_default => '%{opState} =~ /failed offline|stuck online/i || %{opState} ne %{nominalState}', set => { key_values => [ { name => 'opState' }, { name => 'nominalState' }, { name => 'name' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-rg-name:s' => { name => 'filter_rg_name' }, 'exclude-rg-name:s' => { name => 'exclude_rg_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my ($stdout) = $options{custom}->execute_command( command => 'lssam', command_options => '-nocolor' ); $self->{global} = { unknown => 0, offline => 0, online => 0, failed_offline => 0, stuck_online => 0, pending_online => 0, pending_offline => 0, ineligible => 0 }; $self->{rg} = {}; while ($stdout =~ /^(\S.*)\s+IBM.ResourceGroup:(.*?)\s+.*?Nominal=(.*)\s*$/mig) { my ($name, $opState, $nominalState) = ($2, lc($1), lc($3)); if (defined($self->{option_results}->{filter_rg_name}) && $self->{option_results}->{filter_rg_name} ne '' && $name !~ /$self->{option_results}->{filter_rg_name}/) { $self->{output}->output_add(long_msg => "skipping resource group '" . $name . "': no matching filter.", debug => 1); next; } if (defined($self->{option_results}->{exclude_rg_name}) && $self->{option_results}->{exclude_rg_name} ne '' && $name =~ /$self->{option_results}->{exclude_rg_name}/) { $self->{output}->output_add(long_msg => "skipping resource group '" . $name . "': no matching filter.", debug => 1); next; } $self->{rg}->{$name} = { name => $name, opState => $opState, nominalState => $nominalState }; $opState =~ s/\s+/_/g; $self->{global}->{$opState}++; } } 1; __END__ =head1 MODE Check resource groups. Command used: lssam -nocolor =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='total' =item B<--filter-rg-name> Filter resource groups by name (can be a regexp). =item B<--exclude-rg-name> Exclude resource groups by name (can be a regexp). =item B<--unknown-status> Set unknown threshold for status (Default: '%{opState} =~ /unknown/i'). Can used special variables like: %{opState}, %{nominalState}, %{name} =item B<--warning-status> Set warning threshold for status (Default: '%{opState} =~ /pending/i'). Can used special variables like: %{opState}, %{nominalState}, %{name} =item B<--critical-status> Set critical threshold for status (Default: '%{opState} =~ /failed offline|stuck online/i || %{opState} ne %{nominalState}'). Can used special variables like: %{opState}, %{nominalState}, %{name} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'total-unknown', 'total-offline', 'total-online', 'total-failed-offline', 'total-stuck-online', 'total-pending-online', 'total-pending-offline', 'total-ineligible'. =back =cut centreon-plugins-20220113/apps/ibm/tsamp/local/plugin.pm000066400000000000000000000026151417000230700230240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::ibm::tsamp::local::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->{modes} = { 'resource-groups' => 'apps::ibm::tsamp::local::mode::resourcegroups', 'list-resource-groups' => 'apps::ibm::tsamp::local::mode::listresourcegroups' }; $self->{custom_modes}->{cli} = 'centreon::plugins::script_custom::cli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check IBM Tivoli System Automation for Multiplatforms (TSAMP). =cut centreon-plugins-20220113/apps/inin/000077500000000000000000000000001417000230700171345ustar00rootroot00000000000000centreon-plugins-20220113/apps/inin/ig/000077500000000000000000000000001417000230700175335ustar00rootroot00000000000000centreon-plugins-20220113/apps/inin/ig/snmp/000077500000000000000000000000001417000230700205105ustar00rootroot00000000000000centreon-plugins-20220113/apps/inin/ig/snmp/mode/000077500000000000000000000000001417000230700214345ustar00rootroot00000000000000centreon-plugins-20220113/apps/inin/ig/snmp/mode/spanusage.pm000066400000000000000000000132231417000230700237610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::inin::ig::snmp::mode::spanusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); 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} . '_i3IgSpanInfoSpanState'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'span', type => 1, cb_prefix_output => 'prefix_span_output', message_multiple => 'All spans are ok' } ]; $self->{maps_counters}->{span} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'i3IgSpanInfoSpanState' }, { 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 => \&catalog_status_threshold, } }, { label => 'active-channels', set => { key_values => [ { name => 'i3IgSpanInfoActiveChannels' }, { name => 'display' } ], output_template => 'Current Active Channels : %s', perfdatas => [ { label => 'active_channels', value => 'i3IgSpanInfoActiveChannels', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $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 => '%{status} !~ /closed|ready/i' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub prefix_span_output { my ($self, %options) = @_; return "Span '" . $options{instance_value}->{display} . "' "; } my %map_state = (0 => 'closed', 1 => 'ready', 2 => 'alarm', 3 => 'error'); my $mapping = { i3IgSpanInfoSpanId => { oid => '.1.3.6.1.4.1.2793.4.2.3.1.3' }, i3IgSpanInfoActiveChannels => { oid => '.1.3.6.1.4.1.2793.4.2.3.1.5' }, i3IgSpanInfoSpanState => { oid => '.1.3.6.1.4.1.2793.4.2.3.1.6', map => \%map_state }, }; my $oid_i3IgSpanInfoTableEntry = '.1.3.6.1.4.1.2793.4.2.3.1'; sub manage_selection { my ($self, %options) = @_; $self->{span} = {}; my $snmp_result = $options{snmp}->get_table(oid => $oid_i3IgSpanInfoTableEntry, nothing_quit => 1); foreach my $oid (keys %{$snmp_result}) { next if ($oid !~ /^$mapping->{i3IgSpanInfoSpanState}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $result->{i3IgSpanInfoSpanId} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{i3IgSpanInfoSpanId} . "': no matching filter.", debug => 1); next; } $self->{span}->{$instance} = { display => $result->{i3IgSpanInfoSpanId}, %$result }; } if (scalar(keys %{$self->{span}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No span found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check span usage. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^status$' =item B<--filter-name> Filter span name (can be a regexp). =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 (Default: '%{status} !~ /closed|ready/i'). Can used special variables like: %{status}, %{display} =item B<--warning-*> Threshold warning. Can be: 'active-channels'. =item B<--critical-*> Threshold critical. Can be: 'active-channels'. =back =cut centreon-plugins-20220113/apps/inin/ig/snmp/mode/stats.pm000066400000000000000000000120651417000230700231340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::inin::ig::snmp::mode::stats; 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 => ' - ' }, { name => 'cg', type => 1, cb_prefix_output => 'prefix_cg_output', message_multiple => 'All channel groups are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'sip-active-calls', set => { key_values => [ { name => 'SipActiveCallsCount' } ], output_template => 'SIP Current Active Calls : %s', perfdatas => [ { label => 'sip_active_calls', value => 'SipActiveCallsCount', template => '%d', min => 0 }, ], } }, { label => 'tdm-active-calls', set => { key_values => [ { name => 'TdmActiveCallsCount' } ], output_template => 'TDM Current Active Calls : %s', perfdatas => [ { label => 'tdm_active_calls', value => 'TdmActiveCallsCount', template => '%d', min => 0 }, ], } }, ]; $self->{maps_counters}->{cg} = [ { label => 'channel-group-active-calls', set => { key_values => [ { name => 'i3IgChannelGroupActiveCallsCount' }, { name => 'display' } ], output_template => 'Current Active Calls : %s', perfdatas => [ { label => 'channel_group_active_calls', value => 'i3IgChannelGroupActiveCallsCount', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, }); return $self; } sub prefix_cg_output { my ($self, %options) = @_; return "Channel group '" . $options{instance_value}->{display} . "' "; } my $mapping = { i3IgChannelGroupName => { oid => '.1.3.6.1.4.1.2793.4.2.13.1.2' }, i3IgChannelGroupActiveCallsCount => { oid => '.1.3.6.1.4.1.2793.4.2.13.1.3' }, }; my $oid_i3IgInfo = '.1.3.6.1.4.1.2793.4.2'; my $oid_i3IgSipActiveCallsCount = '.1.3.6.1.4.1.2793.4.2.4'; my $oid_i3IgTdmActiveCallsCount = '.1.3.6.1.4.1.2793.4.2.7'; sub manage_selection { my ($self, %options) = @_; $self->{cg} = {}; my $snmp_result = $options{snmp}->get_table(oid => $oid_i3IgInfo, start => $oid_i3IgSipActiveCallsCount, nothing_quit => 1); foreach my $oid (keys %{$snmp_result}) { next if ($oid !~ /^$mapping->{i3IgChannelGroupActiveCallsCount}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $result->{i3IgChannelGroupName} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{i3IgSpanInfoSpanId} . "': no matching filter.", debug => 1); next; } $self->{cg}->{$instance} = { display => $result->{i3IgChannelGroupName}, %$result }; } $self->{global} = { SipActiveCallsCount => $snmp_result->{$oid_i3IgSipActiveCallsCount . '.0'}, TdmActiveCallsCount => $snmp_result->{$oid_i3IgTdmActiveCallsCount . '.0'}, }; } 1; __END__ =head1 MODE Check statistics. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^sip-active-calls$' =item B<--filter-name> Filter channel group name (can be a regexp). =item B<--warning-*> Threshold warning. Can be: 'sip-active-calls', 'tdm-active-calls', 'channel-group-active-calls'. =item B<--critical-*> Threshold critical. Can be: 'sip-active-calls', 'tdm-active-calls', 'channel-group-active-calls'. =back =cut centreon-plugins-20220113/apps/inin/ig/snmp/plugin.pm000066400000000000000000000024611417000230700223470ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::inin::ig::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}} = ( 'span-usage' => 'apps::inin::ig::snmp::mode::spanusage', 'stats' => 'apps::inin::ig::snmp::mode::stats', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Interactive Intelligence Interaction Gateway in SNMP. =cut centreon-plugins-20220113/apps/inin/mediaserver/000077500000000000000000000000001417000230700214425ustar00rootroot00000000000000centreon-plugins-20220113/apps/inin/mediaserver/snmp/000077500000000000000000000000001417000230700224175ustar00rootroot00000000000000centreon-plugins-20220113/apps/inin/mediaserver/snmp/mode/000077500000000000000000000000001417000230700233435ustar00rootroot00000000000000centreon-plugins-20220113/apps/inin/mediaserver/snmp/mode/audioengineusage.pm000066400000000000000000000110101417000230700272060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::inin::mediaserver::snmp::mode::audioengineusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'engine', type => 1, cb_prefix_output => 'prefix_engine_output', message_multiple => 'All audio engines are ok' } ]; $self->{maps_counters}->{engine} = [ { label => 'avg-load', set => { key_values => [ { name => 'i3MsAudioEngineAverageLoad' }, { name => 'display' } ], output_template => 'Average Load : %s', perfdatas => [ { label => 'load_avg', value => 'i3MsAudioEngineAverageLoad', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'elem-count', set => { key_values => [ { name => 'i3MsAudioEngineElementCount' }, { name => 'display' } ], output_template => 'Total active graph elements : %s', perfdatas => [ { label => 'elem_count', value => 'i3MsAudioEngineElementCount', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-location:s" => { name => 'filter_location' }, }); return $self; } sub prefix_engine_output { my ($self, %options) = @_; return "Audio Engine '" . $options{instance_value}->{display} . "' "; } my $mapping = { i3MsAudioEngineLocation => { oid => '.1.3.6.1.4.1.2793.8227.2.1.1.4' }, i3MsAudioEngineAverageLoad => { oid => '.1.3.6.1.4.1.2793.8227.2.1.1.6' }, i3MsAudioEngineElementCount => { oid => '.1.3.6.1.4.1.2793.8227.2.1.1.8' }, }; my $oid_i3MsAudioEngineInfoTableEntry = '.1.3.6.1.4.1.2793.8227.2.1.1'; sub manage_selection { my ($self, %options) = @_; $self->{engine} = {}; my $snmp_result = $options{snmp}->get_table(oid => $oid_i3MsAudioEngineInfoTableEntry, nothing_quit => 1); foreach my $oid (keys %{$snmp_result}) { next if ($oid !~ /^$mapping->{i3MsAudioEngineLocation}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); if (defined($self->{option_results}->{filter_location}) && $self->{option_results}->{filter_location} ne '' && $result->{i3MsAudioEngineLocation} !~ /$self->{option_results}->{filter_location}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{i3MsAudioEngineLocation} . "': no matching filter.", debug => 1); next; } $self->{engine}->{$instance} = { display => $result->{i3MsAudioEngineLocation}, %$result }; } if (scalar(keys %{$self->{engine}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No audio engine found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check audio engine usage. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^elem-count$' =item B<--filter-location> Filter location name (can be a regexp). =item B<--warning-*> Threshold warning. Can be: 'elem-count', 'avg-load'. =item B<--critical-*> Threshold critical. Can be: 'elem-count', 'avg-load'. =back =cut centreon-plugins-20220113/apps/inin/mediaserver/snmp/mode/cmdsrvusage.pm000066400000000000000000000244451417000230700262350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::inin::mediaserver::snmp::mode::cmdsrvusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); 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} . '_i3MsCmdSrvStatus'}; $self->{result_values}->{accept_sessions} = $options{new_datas}->{$self->{instance} . '_i3MsCmdSrvAcceptSessions'}; $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($self->{instance_mode}->{option_results}->{free})) { $label = 'free'; $value_perf = $self->{result_values}->{free}; } my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } $self->{output}->perfdata_add( label => $label, unit => 'B', instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, 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} ); } sub custom_usage_threshold { my ($self, %options) = @_; my ($exit, $threshold_value); $threshold_value = $self->{result_values}->{used}; $threshold_value = $self->{result_values}->{free} if (defined($self->{instance_mode}->{option_results}->{free})); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; $threshold_value = $self->{result_values}->{prct_free} if (defined($self->{instance_mode}->{option_results}->{free})); } $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel}, 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("Disk 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}->{free} = $options{new_datas}->{$self->{instance} . '_free'}; $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 => 'cmd', type => 1, cb_prefix_output => 'prefix_cmd_output', message_multiple => 'All command servers are ok' } ]; $self->{maps_counters}->{cmd} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'i3MsCmdSrvStatus' }, { name => 'i3MsCmdSrvAcceptSessions' }, { 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 => \&catalog_status_threshold, } }, { label => 'usage', set => { key_values => [ { name => 'display' }, { name => 'free' }, { 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'), } }, { label => 'resource-count', set => { key_values => [ { name => 'i3MsCmdSrvResourceCount' }, { name => 'display' } ], output_template => 'Resource Count : %s', perfdatas => [ { label => 'resource_count', value => 'i3MsCmdSrvResourceCount', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-client:s" => { name => 'filter_client' }, "warning-status:s" => { name => 'warning_status', default => '' }, "critical-status:s" => { name => 'critical_status', default => '%{status} !~ /^ready/i' }, "units:s" => { name => 'units', default => '%' }, "free" => { name => 'free' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub prefix_cmd_output { my ($self, %options) = @_; return "Command Server '" . $options{instance_value}->{display} . "' "; } my %map_status = (1 => 'unknown', 1 => 'ready', 2 => 'notready', 3 => 'error'); my %map_truth = (1 => 'true', 2 => 'false'); my $mapping = { i3MsCmdSrvAcceptSessions => { oid => '.1.3.6.1.4.1.2793.8227.2.2.1.8', map => \%map_truth }, i3MsCmdSrvStatus => { oid => '.1.3.6.1.4.1.2793.8227.2.2.1.2', map => \%map_status }, i3MsCmdSrvClient => { oid => '.1.3.6.1.4.1.2793.8227.2.2.1.6' }, i3MsCmdSrvResourceCount => { oid => '.1.3.6.1.4.1.2793.8227.2.2.1.9' }, i3MsCmdSrvRecFreeDiskSpace => { oid => '.1.3.6.1.4.1.2793.8227.2.2.1.12' }, i3MsCmdSrvRecTotalDiskSpace => { oid => '.1.3.6.1.4.1.2793.8227.2.2.1.13' }, }; my $oid_i3MsCommandServerInfoTableEntry = '.1.3.6.1.4.1.2793.8227.2.2.1'; sub manage_selection { my ($self, %options) = @_; $self->{cmd} = {}; my $snmp_result = $options{snmp}->get_table(oid => $oid_i3MsCommandServerInfoTableEntry, nothing_quit => 1); foreach my $oid (keys %{$snmp_result}) { next if ($oid !~ /^$mapping->{i3MsCmdSrvStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); if (defined($self->{option_results}->{filter_client}) && $self->{option_results}->{filter_client} ne '' && $result->{i3MsCmdSrvClient} !~ /$self->{option_results}->{filter_client}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{i3MsCmdSrvClient} . "': no matching filter.", debug => 1); next; } $self->{cmd}->{$instance} = { display => $result->{i3MsCmdSrvClient}, total => $result->{i3MsCmdSrvRecTotalDiskSpace} * 1024 * 1024, free => $result->{i3MsCmdSrvRecFreeDiskSpace} * 1024 * 1024, %$result }; } if (scalar(keys %{$self->{cmd}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No command server found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check command servers usage. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^status$' =item B<--filter-client> Filter client name (can be a regexp). =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{accept_sessions}, %{status}, %{display} =item B<--critical-status> Set critical threshold for status (Default: '%{status} !~ /^ready/i'). Can used special variables like: %{accept_sessions}, %{status}, %{display} =item B<--warning-*> Threshold warning. Can be: 'usage', 'resource-count'. =item B<--critical-*> Threshold critical. Can be: 'usage', 'resource-count'. =item B<--units> Units of thresholds (Default: '%') ('%', 'B'). =item B<--free> Thresholds are on free space left. =back =cut centreon-plugins-20220113/apps/inin/mediaserver/snmp/mode/component.pm000066400000000000000000000076541417000230700257170ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::inin::mediaserver::snmp::mode::component; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { device => [ ['unknown', 'UNKNOWN'], ['up', 'OK'], ['down', 'CRITICAL'], ['congested', 'WARNING'], ['restarting', 'OK'], ['quiescing', 'OK'], ['testing', 'OK'], ], }; $self->{components_path} = 'apps::inin::mediaserver::snmp::mode::components'; $self->{components_module} = ['device']; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_absent => 1, no_performance => 1, no_load_components => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); } 1; =head1 MODE Check hardware devices. =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'device'. =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='device,WARNING,restarting' =back =cut package apps::inin::mediaserver::snmp::mode::components::device; use strict; use warnings; my %map_status = (1 => 'unknown', 2 => 'up', 3 => 'down', 4 => 'congested', 5 => 'restarting', 6 => 'quiescing', 7 => 'testing' ); my $mapping = { i3MsGeneralInfoOperStatus => { oid => '.1.3.6.1.4.1.2793.8227.1.2', map => \%map_status }, }; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping->{i3MsGeneralInfoOperStatus}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking devices"); $self->{components}->{device} = {name => 'devices', total => 0, skip => 0}; return if ($self->check_filter(section => 'device')); my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$mapping->{i3MsGeneralInfoOperStatus}->{oid}}, instance => '0'); return if (!defined($result->{i3MsGeneralInfoOperStatus})); $self->{components}->{device}->{total}++; $self->{output}->output_add(long_msg => sprintf("device status is '%s' [instance = %s]", $result->{i3MsGeneralInfoOperStatus}, '0')); my $exit = $self->get_severity(section => 'device', value => $result->{i3MsGeneralInfoOperStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Device status is '%s'", $result->{i3MsGeneralInfoOperStatus})); } } 1; centreon-plugins-20220113/apps/inin/mediaserver/snmp/mode/diskusage.pm000066400000000000000000000163551417000230700256720ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::inin::mediaserver::snmp::mode::diskusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'disktracelog', type => 0 }, { name => 'diskhttpcache', type => 0 }, ]; $self->{maps_counters}->{disktracelog} = [ { label => 'tracelog-usage', set => { key_values => [ { name => 'free' }, { name => 'total' }, { name => 'display' } ], 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'), } }, ]; $self->{maps_counters}->{diskhttpcache} = [ { label => 'httpcache-usage', set => { key_values => [ { name => 'free' }, { name => 'total' }, { name => 'display' } ], 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 custom_usage_perfdata { my ($self, %options) = @_; my $label = 'used_' . $self->{result_values}->{display}; my $value_perf = $self->{result_values}->{used}; if (defined($self->{instance_mode}->{option_results}->{free})) { $label = 'free_' . $self->{result_values}->{display}; $value_perf = $self->{result_values}->{free}; } my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } $self->{output}->perfdata_add(label => $label, 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($self->{instance_mode}->{option_results}->{free})); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; $threshold_value = $self->{result_values}->{prct_free} if (defined($self->{instance_mode}->{option_results}->{free})); } $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{label}, exit_litteral => 'warning' } ]); return $exit; } sub custom_usage_output { my ($self, %options) = @_; my ($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("Disk '%s' Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", $self->{result_values}->{display}, $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}->{free} = $options{new_datas}->{$self->{instance} . '_free'}; $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 new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "units:s" => { name => 'units', default => '%' }, "free" => { name => 'free' }, }); return $self; } sub manage_selection { my ($self, %options) = @_; my $oid_i3MsGeneralInfoTracelogFreeDiskSpace = '.1.3.6.1.4.1.2793.8227.1.12.0'; # MiB my $oid_i3MsGeneralInfoTracelogTotalDiskSpace = '.1.3.6.1.4.1.2793.8227.1.13.0'; # MiB my $oid_i3MsGeneralInfoHttpCacheFreeDiskSpace = '.1.3.6.1.4.1.2793.8227.1.15.0'; # MiB my $oid_i3MsGeneralInfoHttpCacheTotalDiskSpace = '.1.3.6.1.4.1.2793.8227.1.16.0'; # MiB my $snmp_result = $options{snmp}->get_leef(oids => [ $oid_i3MsGeneralInfoTracelogFreeDiskSpace, $oid_i3MsGeneralInfoTracelogTotalDiskSpace, $oid_i3MsGeneralInfoHttpCacheFreeDiskSpace, $oid_i3MsGeneralInfoHttpCacheTotalDiskSpace ], nothing_quit => 1); $self->{disktracelog} = { free => $snmp_result->{$oid_i3MsGeneralInfoTracelogFreeDiskSpace} * 1024 * 1024, total => $snmp_result->{$oid_i3MsGeneralInfoTracelogTotalDiskSpace} * 1024 * 1024, display => 'tracelog' }; $self->{diskhttpcache} = { free => $snmp_result->{$oid_i3MsGeneralInfoHttpCacheFreeDiskSpace} * 1024 * 1024, total => $snmp_result->{$oid_i3MsGeneralInfoHttpCacheTotalDiskSpace} * 1024 * 1024, display => 'httpcache' }; } 1; __END__ =head1 MODE Check disk usages. =over 8 =item B<--warning-*> Threshold warning. Can be: 'httpcache-usage', 'tracelog-usage'. =item B<--critical-*> Threshold critical. Can be: 'httpcache-usage', 'tracelog-usage'. =item B<--units> Default is '%', can be 'B' =item B<--free> Thresholds are on free space left. =back =cut centreon-plugins-20220113/apps/inin/mediaserver/snmp/mode/memoryusage.pm000066400000000000000000000044341417000230700262430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::inin::mediaserver::snmp::mode::memoryusage; 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 => 'usage', set => { key_values => [ { name => 'used' } ], output_template => 'Memory Used : %s %s', output_change_bytes => 1, perfdatas => [ { label => 'used', value => 'used', template => '%s', unit => 'B', min => 0 }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $oid_i3MsGeneralInfoMemoryUsage = '.1.3.6.1.4.1.2793.8227.1.10.0'; my $snmp_result = $options{snmp}->get_leef(oids => [ $oid_i3MsGeneralInfoMemoryUsage ], nothing_quit => 1); $self->{global} = { used => $snmp_result->{$oid_i3MsGeneralInfoMemoryUsage} }; } 1; __END__ =head1 MODE Check memory. =over 8 =item B<--warning-*> Threshold warning. Can be: 'usage' (B). =item B<--critical-*> Threshold critical. Can be: 'usage' (B). =back =cut centreon-plugins-20220113/apps/inin/mediaserver/snmp/plugin.pm000066400000000000000000000031401417000230700242510ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::inin::mediaserver::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}} = ( 'audioengine-usage' => 'apps::inin::mediaserver::snmp::mode::audioengineusage', 'cmdsrv-usage' => 'apps::inin::mediaserver::snmp::mode::cmdsrvusage', 'component' => 'apps::inin::mediaserver::snmp::mode::component', 'disk-usage' => 'apps::inin::mediaserver::snmp::mode::diskusage', 'memory-usage' => 'apps::inin::mediaserver::snmp::mode::memoryusage', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Interactive Intelligence Media Server in SNMP. =cut centreon-plugins-20220113/apps/java/000077500000000000000000000000001417000230700171205ustar00rootroot00000000000000centreon-plugins-20220113/apps/java/awa/000077500000000000000000000000001417000230700176705ustar00rootroot00000000000000centreon-plugins-20220113/apps/java/awa/jmx/000077500000000000000000000000001417000230700204665ustar00rootroot00000000000000centreon-plugins-20220113/apps/java/awa/jmx/mode/000077500000000000000000000000001417000230700214125ustar00rootroot00000000000000centreon-plugins-20220113/apps/java/awa/jmx/mode/agent.pm000066400000000000000000000142101417000230700230440ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::java::awa::jmx::mode::agent; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use DateTime; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = 'active : ' . $self->{result_values}->{active} . ' [IpAddress: ' . $self->{result_values}->{ipaddress} . ' ]' . '[LastCheck: ' . centreon::plugins::misc::change_seconds(value => $self->{result_values}->{since}) . ']'; return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{since} = $options{new_datas}->{$self->{instance} . '_since'}; $self->{result_values}->{ipaddress} = $options{new_datas}->{$self->{instance} . '_ipaddress'}; $self->{result_values}->{active} = $options{new_datas}->{$self->{instance} . '_active'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'agent', type => 1, cb_prefix_output => 'prefix_agent_output', message_multiple => 'All agents are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{agent} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'active' }, { name => 'ipaddress' }, { name => 'since' }, { 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 => \&catalog_status_threshold, } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $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 => '' }, "timezone:s" => { name => 'timezone' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); $self->{option_results}->{timezone} = 'GMT' if (!defined($self->{option_results}->{timezone}) || $self->{option_results}->{timezone} eq ''); } sub prefix_agent_output { my ($self, %options) = @_; return "Agent '" . $options{instance_value}->{display} . "' "; } sub manage_selection { my ($self, %options) = @_; $self->{app} = {}; $self->{request} = [ { mbean => 'Automic:name=*,side=Agents,type=*', attributes => [ { name => 'LastCheck' }, { name => 'IpAddress' }, { name => 'Active' }, { name => 'Name' } ] }, ]; my $result = $options{custom}->get_attributes(request => $self->{request}, nothing_quit => 1); my $tz = centreon::plugins::misc::set_timezone(name => $self->{option_results}->{timezone}); foreach my $mbean (keys %{$result}) { $mbean =~ /name=(.*?)(,|$)/i; my $name = $1; $mbean =~ /type=(.*?)(,|$)/i; my $display = $1 . '.' . $name; if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $display !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $display . "': no matching filter.", debug => 1); next; } my $agent_infos = { display => $display, ipaddress => $result->{$mbean}->{IpAddress}, active => $result->{$mbean}->{Active} ? 'yes' : 'no', }; if ($result->{$mbean}->{LastCheck} =~ /^\s*(\d+)-(\d+)-(\d+)\s+(\d+):(\d+):(\d+)/) { my $dt = DateTime->new( year => $1, month => $2, day => $3, hour => $4, minute => $5, second => $6, %$tz ); $agent_infos->{since} = time() - $dt->epoch; } elsif ($result->{$mbean}->{LastCheck} =~ /^\s*00:00:00/) { $agent_infos->{since} = 0; } else { next; } $self->{agent}->{$display} = $agent_infos; } if (scalar(keys %{$self->{agent}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No agent found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check agent status. =over 8 =item B<--filter-name> Filter agent name (can be a regexp). =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{since}, %{display}, %{ipaddress}, %{active} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{since}, %{display}, %{ipaddress}, %{active} =item B<--timezone> Timezone options (the date from the equipment overload that option). Default is 'GMT'. =back =cut centreon-plugins-20220113/apps/java/awa/jmx/mode/listagents.pm000066400000000000000000000101171417000230700241250ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::java::awa::jmx::mode::listagents; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "filter-type:s" => { name => 'filter_type' }, }); $self->{agents} = {}; return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{request} = [ { mbean => 'Automic:name=*,side=Agents,type=*', attributes => [ { name => 'IpAddress' }, { name => 'Active' }, { name => 'Name' } ] }, ]; my $result = $options{custom}->get_attributes(request => $self->{request}, nothing_quit => 1); foreach my $mbean (keys %{$result}) { $mbean =~ /name=(.*?)(,|$)/i; my $name = $1; $mbean =~ /type=(.*?)(,|$)/i; my $type = $1; 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; } if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' && $type !~ /$self->{option_results}->{filter_type}/) { $self->{output}->output_add(long_msg => "skipping '" . $name . "': no matching filter.", debug => 1); next; } $self->{agents}->{$name . '.' . $type} = { name => $name, type => $type, ipaddress => $result->{$mbean}->{IpAddress}, active => $result->{$mbean}->{Active} ? 'yes' : 'no', }; } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $instance (sort keys %{$self->{agents}}) { $self->{output}->output_add(long_msg => '[name = ' . $self->{agents}->{$instance}->{name} . "]" . " [type = '" . $self->{agents}->{$instance}->{type} . "']" . " [ipaddress = '" . $self->{agents}->{$instance}->{ipaddress} . "']" . " [active = '" . $self->{agents}->{$instance}->{active} . "']" ); } $self->{output}->output_add(severity => 'OK', short_msg => 'List agents:'); $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', 'type', 'ipaddress', 'active']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $instance (sort keys %{$self->{agents}}) { $self->{output}->add_disco_entry( %{$self->{agents}->{$instance}} ); } } 1; __END__ =head1 MODE List agents. =over 8 =item B<--filter-name> Filter by agent name (can be a regexp). =item B<--filter-type> Filter by type (can be a regexp). =back =cut centreon-plugins-20220113/apps/java/awa/jmx/mode/listqueues.pm000066400000000000000000000076161417000230700241650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::java::awa::jmx::mode::listqueues; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "filter-type:s" => { name => 'filter_type' }, }); $self->{queues} = {}; return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{request} = [ { mbean => 'Automic:name=*,side=Queues,type=*', attributes => [ { name => 'Status' }, { name => 'Name' } ] }, ]; my $result = $options{custom}->get_attributes(request => $self->{request}, nothing_quit => 1); foreach my $mbean (keys %{$result}) { $mbean =~ /name=(.*?)(,|$)/i; my $name = $1; $mbean =~ /type=(.*?)(,|$)/i; my $type = $1; 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; } if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' && $type !~ /$self->{option_results}->{filter_type}/) { $self->{output}->output_add(long_msg => "skipping '" . $name . "': no matching filter.", debug => 1); next; } $self->{queues}->{$name . '.' . $type} = { name => $name, type => $type, status => $result->{$mbean}->{Status}, }; } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $instance (sort keys %{$self->{queues}}) { $self->{output}->output_add(long_msg => '[name = ' . $self->{queues}->{$instance}->{name} . "]" . " [type = '" . $self->{queues}->{$instance}->{type} . "']" . " [status = '" . $self->{queues}->{$instance}->{status} . "']" ); } $self->{output}->output_add(severity => 'OK', short_msg => 'List queues:'); $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', 'type', 'status']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $instance (sort keys %{$self->{queues}}) { $self->{output}->add_disco_entry( %{$self->{queues}->{$instance}} ); } } 1; __END__ =head1 MODE List queues. =over 8 =item B<--filter-name> Filter by queue name (can be a regexp). =item B<--filter-type> Filter by type (can be a regexp). =back =cut centreon-plugins-20220113/apps/java/awa/jmx/mode/listservers.pm000066400000000000000000000104371417000230700243420ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::java::awa::jmx::mode::listservers; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "filter-type:s" => { name => 'filter_type' }, }); $self->{servers} = {}; return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{request} = [ { mbean => 'Automic:name=*,side=Servers,type=*', attributes => [ { name => 'NetArea' }, { name => 'IpAddress' }, { name => 'Active' }, { name => 'Name' } ] }, ]; my $result = $options{custom}->get_attributes(request => $self->{request}, nothing_quit => 1); foreach my $mbean (keys %{$result}) { $mbean =~ /name=(.*?)(,|$)/i; my $name = $1; $mbean =~ /type=(.*?)(,|$)/i; my $type = $1; 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; } if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' && $type !~ /$self->{option_results}->{filter_type}/) { $self->{output}->output_add(long_msg => "skipping '" . $name . "': no matching filter.", debug => 1); next; } $self->{servers}->{$name . '.' . $type} = { name => $name, type => $type, ipaddress => $result->{$mbean}->{IpAddress}, active => $result->{$mbean}->{Active} ? 'yes' : 'no', netarea => $result->{$mbean}->{NetArea}, }; } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $instance (sort keys %{$self->{servers}}) { $self->{output}->output_add(long_msg => '[name = ' . $self->{servers}->{$instance}->{name} . "]" . " [type = '" . $self->{servers}->{$instance}->{type} . "']" . " [ipaddress = '" . $self->{servers}->{$instance}->{ipaddress} . "']" . " [active = '" . $self->{servers}->{$instance}->{active} . "']" . " [netarea = '" . $self->{servers}->{$instance}->{netarea} . "']" ); } $self->{output}->output_add(severity => 'OK', short_msg => 'List 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', 'type', 'ipaddress', 'active', 'netarea']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $instance (sort keys %{$self->{servers}}) { $self->{output}->add_disco_entry( %{$self->{servers}->{$instance}} ); } } 1; __END__ =head1 MODE List servers. =over 8 =item B<--filter-name> Filter by server name (can be a regexp). =item B<--filter-type> Filter by type (can be a regexp). =back =cut centreon-plugins-20220113/apps/java/awa/jmx/mode/queue.pm000066400000000000000000000110171417000230700230740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::java::awa::jmx::mode::queue; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); 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} . '_status'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'queue', type => 1, cb_prefix_output => 'prefix_queue_output', message_multiple => 'All queues are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{queue} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { 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 => \&catalog_status_threshold, } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $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 => '%{status} !~ /GREEN/i' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub prefix_queue_output { my ($self, %options) = @_; return "Queue '" . $options{instance_value}->{display} . "' "; } sub manage_selection { my ($self, %options) = @_; $self->{app} = {}; $self->{request} = [ { mbean => 'Automic:name=*,side=Queues,type=*', attributes => [ { name => 'Status' }, { name => 'Name' } ] }, ]; my $result = $options{custom}->get_attributes(request => $self->{request}, nothing_quit => 1); foreach my $mbean (keys %{$result}) { $mbean =~ /name=(.*?)(,|$)/i; my $name = $1; $mbean =~ /type=(.*?)(,|$)/i; my $display = $1 . '.' . $name; if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $display !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $display . "': no matching filter.", debug => 1); next; } $self->{queue}->{$display} = { display => $display, status => $result->{$mbean}->{Status}, }; } if (scalar(keys %{$self->{queue}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No queue found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check queue status. =over 8 =item B<--filter-name> Filter queue name (can be a regexp). =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{display}, %{status} =item B<--critical-status> Set critical threshold for status (Default: '%{status} !~ /GREEN/i'). Can used special variables like: %{display}, %{status} =back =cut centreon-plugins-20220113/apps/java/awa/jmx/mode/server.pm000066400000000000000000000115711417000230700232630ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::java::awa::jmx::mode::server; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = 'active : ' . $self->{result_values}->{active} . ' [IpAddress: ' . $self->{result_values}->{ipaddress} . ' ]'; return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{ipaddress} = $options{new_datas}->{$self->{instance} . '_ipaddress'}; $self->{result_values}->{active} = $options{new_datas}->{$self->{instance} . '_active'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'server', type => 1, cb_prefix_output => 'prefix_server_output', message_multiple => 'All servers are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{server} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'active' }, { name => 'ipaddress' }, { 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 => \&catalog_status_threshold, } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $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); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub prefix_server_output { my ($self, %options) = @_; return "Server '" . $options{instance_value}->{display} . "' "; } sub manage_selection { my ($self, %options) = @_; $self->{app} = {}; $self->{request} = [ { mbean => 'Automic:name=*,side=Servers,type=*', attributes => [ { name => 'NetArea' }, { name => 'IpAddress' }, { name => 'Active' }, { name => 'Name' } ] }, ]; my $result = $options{custom}->get_attributes(request => $self->{request}, nothing_quit => 1); foreach my $mbean (keys %{$result}) { $mbean =~ /name=(.*?)(,|$)/i; my $name = $1; $mbean =~ /type=(.*?)(,|$)/i; my $display = $1 . '.' . $name; if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $display !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $display . "': no matching filter.", debug => 1); next; } $self->{server}->{$display} = { display => $display, ipaddress => $result->{$mbean}->{IpAddress}, active => $result->{$mbean}->{Active} ? 'yes' : 'no', }; } if (scalar(keys %{$self->{server}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No server found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check server status. =over 8 =item B<--filter-name> Filter server name (can be a regexp). =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{display}, %{ipaddress}, %{active} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{display}, %{ipaddress}, %{active} =back =cut centreon-plugins-20220113/apps/java/awa/jmx/plugin.pm000066400000000000000000000032611417000230700223240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::java::awa::jmx::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}} = ( 'agent' => 'apps::java::awa::jmx::mode::agent', 'list-agents' => 'apps::java::awa::jmx::mode::listagents', 'list-queues' => 'apps::java::awa::jmx::mode::listqueues', 'list-servers' => 'apps::java::awa::jmx::mode::listservers', 'queue' => 'apps::java::awa::jmx::mode::queue', 'server' => 'apps::java::awa::jmx::mode::server', ); $self->{custom_modes}{jolokia} = 'centreon::common::protocols::jmx::custom::jolokia'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Automic Workload Automation (Awa) in JMX. Need Jolokia agent. =cut centreon-plugins-20220113/apps/java/hibernate/000077500000000000000000000000001417000230700210615ustar00rootroot00000000000000centreon-plugins-20220113/apps/java/hibernate/jmx/000077500000000000000000000000001417000230700216575ustar00rootroot00000000000000centreon-plugins-20220113/apps/java/hibernate/jmx/mode/000077500000000000000000000000001417000230700226035ustar00rootroot00000000000000centreon-plugins-20220113/apps/java/hibernate/jmx/mode/stats.pm000066400000000000000000000155701417000230700243070ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::java::hibernate::jmx::mode::stats; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use Digest::MD5 qw(md5_hex); sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'app', type => 1, cb_prefix_output => 'prefix_app_output', message_multiple => 'All hibernate applications are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{app} = [ { label => 'connect-count', set => { key_values => [ { name => 'connect', diff => 1 }, { name => 'display' } ], output_template => 'Connect Count : %s', perfdatas => [ { label => 'connect_count', value => 'connect', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'close-count', set => { key_values => [ { name => 'close', diff => 1 }, { name => 'display' } ], output_template => 'Close Count : %s', perfdatas => [ { label => 'close_count', value => 'close', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'query-count', set => { key_values => [ { name => 'query', diff => 1 }, { name => 'display' } ], output_template => 'Query Count : %s', perfdatas => [ { label => 'query_count', value => 'query', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'insert-count', set => { key_values => [ { name => 'insert', diff => 1 }, { name => 'display' } ], output_template => 'Insert Count : %s', perfdatas => [ { label => 'insert_count', value => 'insert', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'update-count', set => { key_values => [ { name => 'update', diff => 1 }, { name => 'display' } ], output_template => 'Update Count : %s', perfdatas => [ { label => 'update_count', value => 'update', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, }); return $self; } sub prefix_app_output { my ($self, %options) = @_; return "Application '" . $options{instance_value}->{display} . "' "; } sub manage_selection { my ($self, %options) = @_; $self->{app} = {}; $self->{request} = [ { mbean => 'Hibernate:Application=*,type=statistics', attributes => [ { name => 'SessionCloseCount' }, { name => 'ConnectCount' }, { name => 'EntityInsertCount' }, { name => 'CollectionUpdateCount' }, { name => 'QueryExecutionCount' }, { name => 'StatisticsEnabled' } ] }, { mbean => 'Hibernate:type=statistics', attributes => [ { name => 'SessionCloseCount' }, { name => 'ConnectCount' }, { name => 'EntityInsertCount' }, { name => 'CollectionUpdateCount' }, { name => 'QueryExecutionCount' }, { name => 'StatisticsEnabled' } ] }, ]; my $result = $options{custom}->get_attributes(request => $self->{request}, nothing_quit => 1); foreach my $mbean (keys %{$result}) { $mbean =~ /Application=(.*?),/; my $app = defined($1) ? $1 : 'global'; if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $app !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $app . "': no matching filter.", debug => 1); next; } if (!$result->{$mbean}->{StatisticsEnabled}) { $self->{output}->output_add(long_msg => "skipping '" . $app . "': statistics is disabled.", debug => 1); next; } $self->{app}->{$app} = { display => $app, close => $result->{$mbean}->{SessionCloseCount}, connect => $result->{$mbean}->{ConnectCount}, insert => $result->{$mbean}->{EntityInsertCount}, query => $result->{$mbean}->{QueryExecutionCount}, update => $result->{$mbean}->{CollectionUpdateCount}, }; } if (scalar(keys %{$self->{app}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No application found (or staistics is disabled)."); $self->{output}->option_exit(); } $self->{cache_name} = "hibernate_" . $self->{mode} . '_' . md5_hex($options{custom}->get_connection_info()) . '_' . (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 hibernate statistics. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^connect-count$' =item B<--filter-name> Filter application name (can be a regexp). =item B<--warning-*> Threshold warning. Can be: 'connect-count', 'query-count', 'insert-count', 'update-count' 'close-count'. =item B<--critical-*> Threshold critical. Can be: 'connect-count', 'query-count', 'insert-count', 'update-count' 'close-count'. =back =cut centreon-plugins-20220113/apps/java/hibernate/jmx/plugin.pm000066400000000000000000000024771417000230700235250ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::java::hibernate::jmx::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}} = ( 'stats' => 'apps::java::hibernate::jmx::mode::stats', ); $self->{custom_modes}{jolokia} = 'centreon::common::protocols::jmx::custom::jolokia'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Hibernate in JMX. Need Jolokia agent. =cut centreon-plugins-20220113/apps/java/jboss/000077500000000000000000000000001417000230700202405ustar00rootroot00000000000000centreon-plugins-20220113/apps/java/jboss/jmx/000077500000000000000000000000001417000230700210365ustar00rootroot00000000000000centreon-plugins-20220113/apps/java/jboss/jmx/mode/000077500000000000000000000000001417000230700217625ustar00rootroot00000000000000centreon-plugins-20220113/apps/java/jboss/jmx/mode/datasourceusage.pm000066400000000000000000000141611417000230700255020ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::java::jboss::jmx::mode::datasourceusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); sub prefix_ds_output { my ($self, %options) = @_; return "Datasource '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'datasource', type => 1, cb_prefix_output => 'prefix_ds_output', message_multiple => 'All datasources are ok' } ]; $self->{maps_counters}->{datasource} = [ { label => 'active-con', nlabel => 'datasource.connections.active.count', set => { key_values => [ { name => 'ActiveCount' } ], output_template => 'current active connections: %s', perfdatas => [ { label => 'active_con', template => '%s', min => 0, label_extra_instance => 1 } ] } }, { label => 'available-con', nlabel => 'datasource.connections.available.count', set => { key_values => [ { name => 'AvailableCount' } ], output_template => 'current available connections: %s', perfdatas => [ { label => 'available_con', template => '%s', min => 0, label_extra_instance => 1 } ] } }, { label => 'in-use-con', nlabel => 'datasource.connections.inuse.count', set => { key_values => [ { name => 'InUseCount' } ], output_template => 'current in use connections: %s', perfdatas => [ { label => 'in_use_con', template => '%s', min => 0, label_extra_instance => 1 } ] } }, { label => 'created-con', nlabel => 'datasource.connections.created.count', set => { key_values => [ { name => 'CreatedCount', diff => 1 } ], output_template => 'created connections: %s', perfdatas => [ { label => 'created_con', template => '%s', min => 0, label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, }); return $self; } sub manage_selection { my ($self, %options) = @_; # 'jboss.as|jboss.as.expr' my $request = [ { mbean => 'jboss.jca:name=*,service=ManagedConnectionPool', attributes => [ { name => 'AvailableConnectionCount' }, { name => 'ConnectionCount' }, { name => 'ConnectionCreatedCount' }, { name => 'InUseConnectionCount' } ] }, { mbean => 'jboss.as*:data-source=*,statistics=pool,subsystem=datasources', attributes => [ { name => 'AvailableCount' }, { name => 'ActiveCount' }, { name => 'CreatedCount' }, { name => 'InUseCount' } ] }, { mbean => 'jboss.as*:xa-data-source=*,statistics=pool,subsystem=datasources', attributes => [ { name => 'AvailableCount' }, { name => 'ActiveCount' }, { name => 'CreatedCount' }, { name => 'InUseCount' } ] } ]; my $result = $options{custom}->get_attributes(request => $request, nothing_quit => 1); $self->{datasource} = {}; foreach my $key (keys %$result) { $key =~ /(?:[:,])(?:name|data-source|xa-data-source)=(.*?)(?:,|$)/; my $ds_name = $1; $ds_name =~ s/^"(.*)"$/$1/; if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $ds_name !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $ds_name . "': no matching filter.", debug => 1); next; } $self->{datasource}->{$ds_name} = { display => $ds_name, AvailableCount => defined($result->{$key}->{AvailableConnectionCount}) ? $result->{$key}->{AvailableConnectionCount} : $result->{$key}->{AvailableCount}, ActiveCount => defined($result->{$key}->{ConnectionCount}) ? $result->{$key}->{ConnectionCount} : $result->{$key}->{ActiveCount}, CreatedCount => defined($result->{$key}->{ConnectionCreatedCount}) ? $result->{$key}->{ConnectionCreatedCount} : $result->{$key}->{CreatedCount}, InUseCount => defined($result->{$key}->{InUseConnectionCount}) ? $result->{$key}->{InUseConnectionCount} : $result->{$key}->{InUseCount} }; } $self->{cache_name} = 'jboss_' . $self->{mode} . '_' . md5_hex($options{custom}->get_connection_info()) . '_' . (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 data sources usage. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='num-active' =item B<--filter-name> Filter datasource name (can be a regexp). =item B<--warning-*> Threshold warning. Can be: 'active-con', 'available-con', 'created-con', 'in-use-con'. =item B<--critical-*> Threshold critical. Can be: 'active-con', 'available-con', 'created-con', 'in-use-con'. =back =cut centreon-plugins-20220113/apps/java/jboss/jmx/mode/listdatasources.pm000066400000000000000000000064701417000230700255400ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::java::jboss::jmx::mode::listdatasources; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { '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 $request = [ { mbean => 'jboss.jca:name=*,service=ManagedConnectionPool', attributes => [ { name => 'ConnectionCount' } ] }, { mbean => 'jboss.as*:data-source=*,statistics=pool,subsystem=datasources', attributes => [ { name => 'ActiveCount' } ] }, { mbean => 'jboss.as*:xa-data-source=*,statistics=pool,subsystem=datasources', attributes => [ { name => 'ActiveCount' } ] } ]; my $result = $options{custom}->get_attributes(request => $request); my $ds = {}; foreach my $mbean (keys %{$result}) { $mbean =~ /(?:[:,])(?:data-source|name|xa-data-source)=(.*?)(?:,|$)/; my $name = $1; $name =~ s/^"(.*)"$/$1/; 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; } $ds->{$name} = { name => $name }; } return $ds; } sub run { my ($self, %options) = @_; my $ds = $self->manage_selection(%options); foreach my $instance (sort keys %$ds) { $self->{output}->output_add(long_msg => '[name = ' . $self->{ds}->{$instance}->{name} . "]"); } $self->{output}->output_add( severity => 'OK', short_msg => 'List data sources:' ); $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) = @_; my $ds = $self->manage_selection(%options); foreach my $instance (sort keys %$ds) { $self->{output}->add_disco_entry( %{$self->{ds}->{$instance}} ); } } 1; __END__ =head1 MODE List data sources. =over 8 =item B<--filter-name> Filter by name (can be a regexp). =back =cut centreon-plugins-20220113/apps/java/jboss/jmx/plugin.pm000066400000000000000000000032661417000230700227010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::java::jboss::jmx::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} = { 'class-count' => 'centreon::common::jvm::mode::classcount', 'datasource-usage' => 'apps::java::jboss::jmx::mode::datasourceusage', 'list-datasources' => 'apps::java::jboss::jmx::mode::listdatasources', 'memory' => 'centreon::common::jvm::mode::memory', 'memory-detailed' => 'centreon::common::jvm::mode::memorydetailed', 'threads' => 'centreon::common::jvm::mode::threads' }; $self->{custom_modes}->{jolokia} = 'centreon::common::protocols::jmx::custom::jolokia'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Jboss in JMX. Need Jolokia agent. =cut centreon-plugins-20220113/apps/java/jvm/000077500000000000000000000000001417000230700177145ustar00rootroot00000000000000centreon-plugins-20220113/apps/java/jvm/actuator/000077500000000000000000000000001417000230700215365ustar00rootroot00000000000000centreon-plugins-20220113/apps/java/jvm/actuator/mode/000077500000000000000000000000001417000230700224625ustar00rootroot00000000000000centreon-plugins-20220113/apps/java/jvm/actuator/mode/classcount.pm000066400000000000000000000060111417000230700251740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::java::jvm::actuator::mode::classcount; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); sub prefix_global_output { my ($self, %options) = @_; return 'Class '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'current', nlabel => 'class.loaded.current.count', set => { key_values => [ { name => 'current' } ], output_template => 'current: %d', perfdatas => [ { template => '%d', min => 0 } ] } }, { label => 'unloaded', nlabel => 'class.unloaded.count', set => { key_values => [ { name => 'unloaded', diff => 1 } ], output_template => 'unloaded: %d', perfdatas => [ { template => '%d', min => 0 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->request_api(endpoint => '/metrics/jvm.classes.unloaded'); $self->{global} = { unloaded => $result->{measurements}->[0]->{value} }; $result = $options{custom}->request_api(endpoint => '/metrics/jvm.classes.loaded'); $self->{global}->{current} = $result->{measurements}->[0]->{value}; $self->{cache_name} = 'jvm_actuactor_' . $self->{mode} . '_' . $options{custom}->get_connection_infos() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check java class loading. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='current' =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'unloaded', 'current'. =back =cut centreon-plugins-20220113/apps/java/jvm/actuator/mode/cpuload.pm000066400000000000000000000056461417000230700244620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::java::jvm::actuator::mode::cpuload; 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 => ' - ', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'system', nlabel => 'system.cpu.load.percentage', set => { key_values => [ { name => 'system_load' } ], output_template => 'system cpu load: %.2f%%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%' } ] } }, { label => 'process', nlabel => 'process.cpu.load.percentage', set => { key_values => [ { name => 'process_load' } ], output_template => 'process cpu load: %.2f%%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->request_api(endpoint => '/metrics/system.cpu.usage'); $self->{global} = { system_load => $result->{measurements}->[0]->{value} }; $result = $options{custom}->request_api(endpoint => '/metrics/process.cpu.usage'); $self->{global}->{process_load} = $result->{measurements}->[0]->{value}; } 1; __END__ =head1 MODE Check JVM SystemCpuLoad and ProcessCpuLoad (From 0 to 1 where 1 means 100% of CPU ressources are in use, here we * by 100 for convenience). WARN : Probably not work for java -version < 7. =over 8 =item B<--warning-system> Threshold warning of System cpuload =item B<--critical-system> Threshold critical of System cpuload =item B<--warning-process> Threshold warning of Process cpuload =item B<--critical-process> Threshold critical of Process cpuload =back =cut centreon-plugins-20220113/apps/java/jvm/actuator/mode/fdusage.pm000066400000000000000000000074331417000230700244450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::java::jvm::actuator::mode::fdusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_usage_output { my ($self, %options) = @_; return sprintf( "File descriptor usage total: %s used: %s (%.2f%%) free: %s (%.2f%%)", $self->{result_values}->{total}, $self->{result_values}->{used}, $self->{result_values}->{prct_used}, $self->{result_values}->{free}, $self->{result_values}->{prct_free} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 } ]; $self->{maps_counters}->{global} = [ { label => 'usage', nlabel => 'fd.opened.usage.count', set => { key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', cast_int => 1 }, ] } }, { label => 'usage-free', display_ok => 0, nlabel => 'fd.opened.free.count', set => { key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', cast_int => 1 } ] } }, { label => 'usage-prct', display_ok => 0, nlabel => 'fd.opened.usage.percentage', set => { key_values => [ { name => 'prct_used' }, { name => 'used' }, { name => 'free' }, { name => 'prct_free' }, { name => 'total' } ], output_template => 'Used : %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->request_api(endpoint => '/metrics/process.files.open'); $self->{global} = { used => $result->{measurements}->[0]->{value} }; $result = $options{custom}->request_api(endpoint => '/metrics/process.files.max'); $self->{global}->{total} = $result->{measurements}->[0]->{value}; $self->{global}->{free} = $self->{global}->{total} - $self->{global}->{used}; $self->{global}->{prct_used} = $self->{global}->{used} / $self->{global}->{total} * 100; $self->{global}->{prct_free} = 100 - $self->{global}->{prct_used}; } 1; __END__ =head1 MODE Check number/percentage of file descriptors. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'usage', 'usage-free', 'usage-prct' (%). =back =cut centreon-plugins-20220113/apps/java/jvm/actuator/mode/loadaverage.pm000066400000000000000000000043211417000230700252720ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::java::jvm::actuator::mode::loadaverage; 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 } ]; $self->{maps_counters}->{global} = [ { label => 'load1', nlabel => 'system.load.1m.count', set => { key_values => [ { name => 'load' } ], output_template => 'System load average: %.2f (1m)', perfdatas => [ { template => '%.2f', min => 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 => {}); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->request_api(endpoint => '/metrics/system.load.average.1m'); if ($result->{measurements}->[0]->{value} == -1) { $self->{output}->add_option_msg(short_msg => 'System load average is not set'); $self->{output}->option_exit(); } $self->{global} = { load => $result->{measurements}->[0]->{value} }; } 1; __END__ =head1 MODE Check system load average. =over 8 =item B<--warning-load1> Warning threshold for loadaverage =item B<--critical-load1> Critical threshold for loadaverage =back =cut centreon-plugins-20220113/apps/java/jvm/actuator/mode/memory.pm000066400000000000000000000157671417000230700243500ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::java::jvm::actuator::mode::memory; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_usage_perfdata { my ($self, %options) = @_; my $use_th = 1; $use_th = 0 if ($self->{instance_mode}->{option_results}->{units} eq '%' && $self->{result_values}->{max} <= 0); my $value_perf = $self->{result_values}->{used}; my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%' && $self->{result_values}->{max} > 0) { $total_options{total} = $self->{result_values}->{max}; $total_options{cast_int} = 1; } $self->{output}->perfdata_add( nlabel => $self->{nlabel}, unit => 'B', value => $value_perf, warning => $use_th == 1 ? $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, %total_options) : undef, critical => $use_th == 1 ? $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, %total_options) : undef, min => 0, max => $self->{result_values}->{max} > 0 ? $self->{result_values}->{max} : undef ); } sub custom_usage_threshold { my ($self, %options) = @_; # Cannot use percent without total return 'ok' if ($self->{result_values}->{max} <= 0 && $self->{instance_mode}->{option_results}->{units} eq '%'); my ($exit, $threshold_value); $threshold_value = $self->{result_values}->{used}; if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; } $exit = $self->{perfdata}->threshold_check( value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_usage_output { my ($self, %options) = @_; my $msg; my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); if ($self->{result_values}->{max} > 0) { my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{max}); my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{max} - $self->{result_values}->{used}); $msg = sprintf( "%s Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", $self->{result_values}->{label}, $total_size_value . " " . $total_size_unit, $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}, $total_free_value . " " . $total_free_unit, 100 - $self->{result_values}->{prct_used} ); } else { $msg = sprintf( "%s Used: %s", $self->{result_values}->{label}, $total_used_value . " " . $total_used_unit ); } return $msg; } sub custom_usage_calc { my ($self, %options) = @_; $self->{result_values}->{label} = $options{new_datas}->{$self->{label} . '_label'}; $self->{result_values}->{max} = $options{new_datas}->{$self->{instance} . '_max'}; $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_used'}; if ($self->{result_values}->{max} > 0) { $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{max}; } return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'heap', type => 0 }, { name => 'nonheap', type => 0 } ]; $self->{maps_counters}->{heap} = [ { label => 'heap', nlabel => 'memory.heap.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'max' }, { name => 'label' } ], 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') } }, ]; $self->{maps_counters}->{nonheap} = [ { label => 'nonheap', nlabel => 'memory.nonheap.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'max' }, { name => 'label' } ], 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, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'units:s' => { name => 'units', default => '%' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->request_api(endpoint => '/metrics/jvm.memory.max', get_param => ['tag=area:heap']); $self->{heap} = { label => 'HeapMemory', max => $result->{measurements}->[0]->{value} }; $result = $options{custom}->request_api(endpoint => '/metrics/jvm.memory.used', get_param => ['tag=area:heap']); $self->{heap}->{used} = $result->{measurements}->[0]->{value}; $result = $options{custom}->request_api(endpoint => '/metrics/jvm.memory.max', get_param => ['tag=area:nonheap']); $self->{nonheap} = { label => 'NonHeapMemoryUsage', max => $result->{measurements}->[0]->{value} }; $result = $options{custom}->request_api(endpoint => '/metrics/jvm.memory.used', get_param => ['tag=area:nonheap']); $self->{nonheap}->{used} = $result->{measurements}->[0]->{value}; } 1; __END__ =head1 MODE Check Java Heap and NonHeap memory usage. =over 8 =item B<--warning-heap> Threshold warning of Heap memory usage =item B<--critical-heap> Threshold critical of Heap memory usage =item B<--warning-nonheap> Threshold warning of NonHeap memory usage =item B<--critical-nonheap> Threshold critical of NonHeap memory usage =item B<--units> Units of thresholds (Default: '%') ('%', 'B'). =back =cut centreon-plugins-20220113/apps/java/jvm/actuator/mode/memorydetailed.pm000066400000000000000000000250561417000230700260340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::java::jvm::actuator::mode::memorydetailed; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my %mapping_memory = ( 'Eden Space' => 'eden', 'Par Eden Space' => 'eden', 'PS Eden Space' => 'eden', 'Survivor Space' => 'survivor', 'Par Survivor Space' => 'survivor', 'PS Survivor Space' => 'survivor', 'CMS Perm Gen' => 'permanent', 'PS Perm Gen' => 'permanent', 'Perm Gen' => 'permanent', 'Metaspace' => 'permanent', 'JIT data cache' => 'permanent', 'Code Cache' => 'code', 'JIT Code Cache' => 'code', 'CMS Old Gen' => 'tenured', 'PS Old Gen' => 'tenured', 'Tenured Gen' => 'tenured' ); sub custom_usage_perfdata { my ($self, %options) = @_; my $use_th = 1; $use_th = 0 if ($self->{instance_mode}->{option_results}->{units} eq '%' && $self->{result_values}->{max} <= 0); my $value_perf = $self->{result_values}->{used}; my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%' && $self->{result_values}->{max} > 0) { $total_options{total} = $self->{result_values}->{max}; $total_options{cast_int} = 1; } $self->{output}->perfdata_add( nlabel => $self->{nlabel}, unit => 'B', value => $value_perf, warning => $use_th == 1 ? $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, %total_options) : undef, critical => $use_th == 1 ? $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, %total_options) : undef, min => 0, max => $self->{result_values}->{max} > 0 ? $self->{result_values}->{max} : undef ); } sub custom_usage_threshold { my ($self, %options) = @_; # Cannot use percent without total return 'ok' if ($self->{result_values}->{max} <= 0 && $self->{instance_mode}->{option_results}->{units} eq '%'); my ($exit, $threshold_value); $threshold_value = $self->{result_values}->{used}; if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; } $exit = $self->{perfdata}->threshold_check( value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_usage_output { my ($self, %options) = @_; my $msg; my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); if ($self->{result_values}->{max} > 0) { my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{max}); my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{max} - $self->{result_values}->{used}); $msg = sprintf( "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, 100 - $self->{result_values}->{prct_used} ); } else { $msg = sprintf("Used: %s", $total_used_value . " " . $total_used_unit); } return $msg; } sub custom_usage_calc { my ($self, %options) = @_; if ($mapping_memory{$options{new_datas}->{$self->{instance} . '_display'}} ne $self->{label}) { return -12; } $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{max} = $options{new_datas}->{$self->{instance} . '_max'}; $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_used'}; if ($self->{result_values}->{max} > 0) { $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{max}; } return 0; } sub prefix_mem_output { my ($self, %options) = @_; return "Memory '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'mem', type => 1, cb_prefix_output => 'prefix_mem_output', message_multiple => 'All memories within bounds', skipped_code => { -12 => 1 } } ]; $self->{maps_counters}->{mem} = [ { label => 'eden', nlabel => 'memory.eden.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'max' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_output => $self->can('custom_usage_output'), closure_custom_threshold_check => $self->can('custom_usage_threshold'), closure_custom_perfdata => $self->can('custom_usage_perfdata') } }, { label => 'tenured', nlabel => 'memory.tenured.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'max' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_output => $self->can('custom_usage_output'), closure_custom_threshold_check => $self->can('custom_usage_threshold'), closure_custom_perfdata => $self->can('custom_usage_perfdata') } }, { label => 'survivor', nlabel => 'memory.survivor.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'max' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_output => $self->can('custom_usage_output'), closure_custom_threshold_check => $self->can('custom_usage_threshold'), closure_custom_perfdata => $self->can('custom_usage_perfdata') } }, { label => 'permanent', nlabel => 'memory.permanent.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'max' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_output => $self->can('custom_usage_output'), closure_custom_threshold_check => $self->can('custom_usage_threshold'), closure_custom_perfdata => $self->can('custom_usage_perfdata') } }, { label => 'code', nlabel => 'memory.code.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'max' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_output => $self->can('custom_usage_output'), closure_custom_threshold_check => $self->can('custom_usage_threshold'), closure_custom_perfdata => $self->can('custom_usage_perfdata') } } ]; } 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 => { 'units:s' => { name => 'units', default => '%' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->request_api(endpoint => '/metrics/jvm.memory.max'); foreach (@{$result->{availableTags}}) { next if ($_->{tag} ne 'id'); foreach my $name (@{$_->{values}}) { if (!defined($mapping_memory{$name})) { $self->{output}->output_add(long_msg => "unknown memory: " . $name, debug => 1); next; } my $max = $options{custom}->request_api(endpoint => '/metrics/jvm.memory.max', get_param => ['tag=id:' . $name]); my $used = $options{custom}->request_api(endpoint => '/metrics/jvm.memory.used', get_param => ['tag=id:' . $name]); $self->{mem}->{$name} = { display => $name, max => $max->{measurements}->[0]->{value}, used => $used->{measurements}->[0]->{value} }; } } } 1; __END__ =head1 MODE Check JVM Memory Pools : Eden Space (heap) (-eden) : The pool from which memory is initially allocated for most objects. Survivor Space (heap) (-survivor) : The pool containing objects that have survived the garbage collection of the Eden space. Tenured Generation (heap) (-tenured) : The pool containing objects that have existed for some time in the survivor space. Permanent Generation (non-heap) (-permanent) : The pool containing all the reflective data of the virtual machine itself, such as class and method objects. Code Cache (non-heap) (-code) : The HotSpot Java VM also includes a code cache, containing memory that is used for compilation and storage of native code. =over 8 =item B<--warning-eden> Threshold warning of Heap 'Eden Space' memory usage =item B<--critical-eden> Threshold critical of Heap 'Survivor Space' memory usage =item B<--warning-tenured> Threshold warning of Heap 'Tenured Generation' memory usage =item B<--critical-tenured> Threshold critical of Heap 'Tenured Generation' memory usage =item B<--warning-survivor> Threshold warning of Heap 'Survivor Space' memory usage =item B<--critical-survivor> Threshold critical of Heap 'Survivor Space' memory usage =item B<--warning-permanent> Threshold warning of NonHeap 'Permanent Generation' memory usage =item B<--critical-permanent> Threshold critical of NonHeap 'Permanent Generation' memory usage =item B<--warning-code> Threshold warning of NonHeap 'Code Cache' memory usage =item B<--critical-code> Threshold critical of NonHeap 'Code Cache' memory usage =item B<--units> Units of thresholds (Default: '%') ('%', 'B'). =back =cut centreon-plugins-20220113/apps/java/jvm/actuator/mode/threads.pm000066400000000000000000000052151417000230700244550ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::java::jvm::actuator::mode::threads; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); sub prefix_global_output { my ($self, %options) = @_; return 'Threads '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'active', nlabel => 'threads.active.count', set => { key_values => [ { name => 'active' } ], output_template => 'active: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'daemon', nlabel => 'threads.daemon.count', set => { key_values => [ { name => 'daemon' } ], output_template => 'daemon: %s', perfdatas => [ { template => '%s', min => 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 => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->request_api(endpoint => '/metrics/jvm.threads.live'); $self->{global} = { active => $result->{measurements}->[0]->{value} }; $result = $options{custom}->request_api(endpoint => '/metrics/jvm.threads.daemon'); $self->{global}->{daemon} = $result->{measurements}->[0]->{value}; } 1; __END__ =head1 MODE Check threads. =over 8 =item B<--warning-*> Threshold warning. Can be: 'active', 'daemon'. =item B<--critical-*> Threshold critical. Can be: 'active', 'daemon'. =back =cut centreon-plugins-20220113/apps/java/jvm/actuator/plugin.pm000066400000000000000000000036071417000230700234000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::java::jvm::actuator::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} = { 'class-count' => 'apps::java::jvm::actuator::mode::classcount', 'cpu-load' => 'apps::java::jvm::actuator::mode::cpuload', 'fd-usage' => 'apps::java::jvm::actuator::mode::fdusage', 'load-average' => 'apps::java::jvm::actuator::mode::loadaverage', 'memory' => 'apps::java::jvm::actuator::mode::memory', 'memory-detailed' => 'apps::java::jvm::actuator::mode::memorydetailed', 'threads' => 'apps::java::jvm::actuator::mode::threads' }; $self->{custom_modes}->{standard} = 'centreon::common::protocols::actuator::custom::standard'; $self->{custom_modes}->{centreonmap} = 'centreon::common::protocols::actuator::custom::centreonmap'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Java Virtual Machine with Actuator in HTTP. =cut centreon-plugins-20220113/apps/java/jvm/jmx/000077500000000000000000000000001417000230700205125ustar00rootroot00000000000000centreon-plugins-20220113/apps/java/jvm/jmx/plugin.pm000066400000000000000000000034761417000230700223600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::java::jvm::jmx::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} = { 'class-count' => 'centreon::common::jvm::mode::classcount', 'cpu-load' => 'centreon::common::jvm::mode::cpuload', 'fd-usage' => 'centreon::common::jvm::mode::fdusage', 'gc-usage' => 'centreon::common::jvm::mode::gcusage', 'load-average' => 'centreon::common::jvm::mode::loadaverage', 'memory' => 'centreon::common::jvm::mode::memory', 'memory-detailed' => 'centreon::common::jvm::mode::memorydetailed', 'threads' => 'centreon::common::jvm::mode::threads' }; $self->{custom_modes}->{jolokia} = 'centreon::common::protocols::jmx::custom::jolokia'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Java Virtual Machine JMX. Need Jolokia agent. =cut centreon-plugins-20220113/apps/java/kafka/000077500000000000000000000000001417000230700201755ustar00rootroot00000000000000centreon-plugins-20220113/apps/java/kafka/jmx/000077500000000000000000000000001417000230700207735ustar00rootroot00000000000000centreon-plugins-20220113/apps/java/kafka/jmx/mode/000077500000000000000000000000001417000230700217175ustar00rootroot00000000000000centreon-plugins-20220113/apps/java/kafka/jmx/mode/globalstats.pm000066400000000000000000000175741417000230700246120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::java::kafka::jmx::mode::globalstats; 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 => 'global', type => 0, skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ { label => 'leader-count', set => { key_values => [ { name => 'leader_count' } ], output_template => 'Leaders : %s', perfdatas => [ { label => 'leader_count', template => '%s', min => 0 }, ], } }, { label => 'active-controller-count', set => { key_values => [ { name => 'active_controller_count' } ], output_template => 'Active Controllers : %s', perfdatas => [ { label => 'active_controller_count', template => '%s', min => 0 }, ], } }, { label => 'partition-count', set => { key_values => [ { name => 'partition_count' } ], output_template => 'Partitions : %s', perfdatas => [ { label => 'partition_count', template => '%s', min => 0 }, ], } }, { label => 'offline-partitions-count', set => { key_values => [ { name => 'offline_partitions_count' } ], output_template => 'Offline partitions : %s', perfdatas => [ { label => 'offline_partitions_count', template => '%s', min => 0 }, ], } }, { label => 'under-replicated-partitions', set => { key_values => [ { name => 'under_replicated_partitions' } ], output_template => 'Under replicated partitions : %s', perfdatas => [ { label => 'under_replicated_partitions', template => '%s', min => 0 }, ], } }, { label => 'unclean-leader-elections', set => { key_values => [ { name => 'unclean_leader_elections', diff => 1 } ], output_template => 'Number of unclean leader elections : %s', perfdatas => [ { label => 'unclean_leader_elections', template => '%s', min => 0 }, ], } }, { label => 'traffic-in', set => { key_values => [ { name => 'traffic_in', per_second => 1 } ], output_template => 'Traffic In : %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'traffic_in', template => '%.2f', min => 0, unit => 'b/s' }, ], } }, { label => 'traffic-out', set => { key_values => [ { name => 'traffic_out', per_second => 1 } ], output_template => 'Traffic Out : %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'traffic_out', template => '%.2f', min => 0, unit => 'b/s' }, ], } }, { label => 'total-fetch-requests', set => { key_values => [ { name => 'total_fetch_requests', diff => 1 } ], output_template => 'Number of total fetch requests : %s', perfdatas => [ { label => 'total_fetch_requests', template => '%s', min => 0 }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{request} = [ { mbean => 'kafka.server:name=UnderReplicatedPartitions,type=ReplicaManager', attributes => [ { name => 'Value' } ] }, { mbean => 'kafka.server:name=PartitionCount,type=ReplicaManager', attributes => [ { name => 'Value' } ] }, { mbean => 'kafka.server:name=LeaderCount,type=ReplicaManager', attributes => [ { name => 'Value' } ] }, { mbean => 'kafka.controller:name=OfflinePartitionsCount,type=KafkaController', attributes => [ { name => 'Value' } ] }, { mbean => 'kafka.controller:name=ActiveControllerCount,type=KafkaController', attributes => [ { name => 'Value' } ] }, { mbean => 'kafka.controller:name=UncleanLeaderElectionsPerSec,type=ControllerStats', attributes => [ { name => 'Count' } ] }, { mbean => 'kafka.server:name=BytesInPerSec,type=BrokerTopicMetrics', attributes => [ { name => 'Count' } ] }, { mbean => 'kafka.server:name=BytesOutPerSec,type=BrokerTopicMetrics', attributes => [ { name => 'Count' } ] }, { mbean => 'kafka.server:name=TotalFetchRequestsPerSec,type=BrokerTopicMetrics', attributes => [ { name => 'Count' } ] }, ]; my $result = $options{custom}->get_attributes(request => $self->{request}, nothing_quit => 1); $self->{global} = { under_replicated_partitions => $result->{'kafka.server:name=UnderReplicatedPartitions,type=ReplicaManager'}->{Value}, offline_partitions_count => $result->{'kafka.controller:name=OfflinePartitionsCount,type=KafkaController'}->{Value}, partition_count => $result->{'kafka.server:name=PartitionCount,type=ReplicaManager'}->{Value}, leader_count => $result->{'kafka.server:name=LeaderCount,type=ReplicaManager'}->{Value}, active_controller_count => $result->{'kafka.controller:name=ActiveControllerCount,type=KafkaController'}->{Value}, unclean_leader_elections => $result->{'kafka.controller:name=UncleanLeaderElectionsPerSec,type=ControllerStats'}->{Count}, traffic_in => $result->{'kafka.server:name=BytesInPerSec,type=BrokerTopicMetrics'}->{Count} * 8, traffic_out => $result->{'kafka.server:name=BytesOutPerSec,type=BrokerTopicMetrics'}->{Count} * 8, total_fetch_requests => $result->{'kafka.server:name=TotalFetchRequestsPerSec,type=BrokerTopicMetrics'}->{Count}, }; $self->{cache_name} = "kafka_" . $self->{mode} . '_' . md5_hex($options{custom}->get_connection_info()) . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check kafka global statistics. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^traffic-in$' =item B<--warning-*> Threshold warning. Can be: 'under-replicated-partitions', 'offline-partitions-count', 'partition-count', 'leader-count', 'active-controller-count', 'unclean-leader-elections', 'traffic-in', 'traffic-out', 'total-fetch-requests'. =item B<--critical-*> Threshold critical. Can be: 'under-replicated-partitions', 'offline-partitions-count', 'partition-count', 'leader-count', 'active-controller-count', 'unclean-leader-elections', 'traffic-in', 'traffic-out', 'total-fetch-requests'. =back =cut centreon-plugins-20220113/apps/java/kafka/jmx/plugin.pm000066400000000000000000000025001417000230700226240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::java::kafka::jmx::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}} = ( 'global-stats' => 'apps::java::kafka::jmx::mode::globalstats', ); $self->{custom_modes}{jolokia} = 'centreon::common::protocols::jmx::custom::jolokia'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Kafka in JMX. Need Jolokia agent. =cut centreon-plugins-20220113/apps/java/peoplesoft/000077500000000000000000000000001417000230700213005ustar00rootroot00000000000000centreon-plugins-20220113/apps/java/peoplesoft/jmx/000077500000000000000000000000001417000230700220765ustar00rootroot00000000000000centreon-plugins-20220113/apps/java/peoplesoft/jmx/mode/000077500000000000000000000000001417000230700230225ustar00rootroot00000000000000centreon-plugins-20220113/apps/java/peoplesoft/jmx/mode/queuelength.pm000066400000000000000000000065251417000230700257160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::java::peoplesoft::jmx::mode::queuelength; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "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) = @_; $self->{connector} = $options{custom}; my $mbean = "com.bea:Name=weblogic.kernel.Default,Server=PIA,Type=ExecuteQueue"; $self->{request} = [ { mbean => $mbean, attributes => [ { name => 'QueueLength' } ] }, ]; my $result = $self->{connector}->get_attributes(request => $self->{request}, nothing_quit => 1); my $exit = $self->{perfdata}->threshold_check(value => $result->{$mbean}->{QueueLength}, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->perfdata_add(label => 'queue', value => $result->{$mbean}->{QueueLength}, 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, short_msg => sprintf("Queue Length : %s", $result->{$mbean}->{QueueLength})); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check queue length. =over 8 =item B<--warning> Threshold warning =item B<--critical> Threshold critical =back =cut centreon-plugins-20220113/apps/java/peoplesoft/jmx/mode/sessions.pm000066400000000000000000000066601417000230700252360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::java::peoplesoft::jmx::mode::sessions; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "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) = @_; $self->{connector} = $options{custom}; my $mbean = "com.bea:ApplicationRuntime=peoplesoft,Name=PIA_,ServerRuntime=PIA,Type=WebAppComponentRuntime"; $self->{request} = [ { mbean => $mbean, attributes => [ { name => 'OpenSessionsCurrentCount' } ] }, ]; my $result = $self->{connector}->get_attributes(request => $self->{request}, nothing_quit => 1); my $exit = $self->{perfdata}->threshold_check(value => $result->{$mbean}->{OpenSessionsCurrentCount}, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->perfdata_add(label => 'sessions', value => $result->{$mbean}->{OpenSessionsCurrentCount}, 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, short_msg => sprintf("Sessions Count : %s", $result->{$mbean}->{OpenSessionsCurrentCount})); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check current open sessions. =over 8 =item B<--warning> Threshold warning =item B<--critical> Threshold critical =back =cut centreon-plugins-20220113/apps/java/peoplesoft/jmx/plugin.pm000066400000000000000000000026361417000230700237410ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::java::peoplesoft::jmx::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}} = ( 'queue-length' => 'apps::java::peoplesoft::jmx::mode::queuelength', 'sessions' => 'apps::java::peoplesoft::jmx::mode::sessions', ); $self->{custom_modes}{jolokia} = 'centreon::common::protocols::jmx::custom::jolokia'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check PeopleSoft in JMX. Need Jolokia agent. =cut centreon-plugins-20220113/apps/java/solr/000077500000000000000000000000001417000230700200775ustar00rootroot00000000000000centreon-plugins-20220113/apps/java/solr/jmx/000077500000000000000000000000001417000230700206755ustar00rootroot00000000000000centreon-plugins-20220113/apps/java/solr/jmx/mode/000077500000000000000000000000001417000230700216215ustar00rootroot00000000000000centreon-plugins-20220113/apps/java/solr/jmx/mode/cacheusage.pm000066400000000000000000000141001417000230700242430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::java::solr::jmx::mode::cacheusage; 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 => 'solrcache', type => 1, cb_prefix_output => 'prefix_cache_output', message_multiple => 'All caches are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{solrcache} = [ { label => 'evictions-count', set => { key_values => [ { name => 'cumulative_evictions', diff => 1 }, { name => 'display' } ], output_template => 'Evictions Count : %s', perfdatas => [ { label => 'evictions_count', value => 'cumulative_evictions', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'lookups-count', set => { key_values => [ { name => 'cumulative_lookups', diff => 1 }, { name => 'display' } ], output_template => 'Lookups Count : %s', perfdatas => [ { label => 'lookups_count', value => 'cumulative_lookups', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'inserts-count', set => { key_values => [ { name => 'cumulative_inserts', diff => 1 }, { name => 'display' } ], output_template => 'Inserts Count : %s', perfdatas => [ { label => 'inserts_count', value => 'cumulative_inserts', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'hits-count', set => { key_values => [ { name => 'cumulative_hits', diff => 1 }, { name => 'display' } ], output_template => 'Hits Count : %s', perfdatas => [ { label => 'hits_count', value => 'cumulative_hits', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, }); return $self; } sub prefix_cache_output { my ($self, %options) = @_; return "Cache '" . $options{instance_value}->{display} . "' "; } sub manage_selection { my ($self, %options) = @_; $self->{solrcache} = {}; $self->{request} = [ { mbean => 'solr/*:id=*,type=documentCache', attributes => [ { name => 'cumulative_evictions' }, { name => 'cumulative_lookups' }, { name => 'cumulative_inserts' }, { name => 'cumulative_hits' } ] }, { mbean => 'solr/*:id=*,type=filterCache', attributes => [ { name => 'cumulative_evictions' }, { name => 'cumulative_lookups' }, { name => 'cumulative_inserts' }, { name => 'cumulative_hits' } ] }, { mbean => 'solr/*:id=*,type=queryResultCache', attributes => [ { name => 'cumulative_evictions' }, { name => 'cumulative_lookups' }, { name => 'cumulative_inserts' }, { name => 'cumulative_hits' } ] }, ]; my $result = $options{custom}->get_attributes(request => $self->{request}, nothing_quit => 1); foreach my $mbean (keys %{$result}) { $mbean =~ /solr\/(.*?):.*?,type=(.*?)(?:,|$)/; my $cache = $1 . '.' . $2; if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $cache !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $cache . "': no matching filter.", debug => 1); next; } $self->{solrcache}->{$cache} = { display => $cache, %{$result->{$mbean}}, }; } if (scalar(keys %{$self->{solrcache}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No cache found."); $self->{output}->option_exit(); } $self->{cache_name} = "solr_" . $self->{mode} . '_' . md5_hex($options{custom}->get_connection_info()) . '_' . (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 cache usage. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^evictions-count$' =item B<--filter-name> Filter cache name (can be a regexp). =item B<--warning-*> Threshold warning. Can be: 'evictions-count', 'lookups-count', 'inserts-count', 'hits-count'. =item B<--critical-*> Threshold critical. Can be: 'evictions-count', 'lookups-count', 'inserts-count', 'hits-count'. =back =cut centreon-plugins-20220113/apps/java/solr/jmx/mode/requesthandlerusage.pm000066400000000000000000000137171417000230700262430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::java::solr::jmx::mode::requesthandlerusage; 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 => 'rh', type => 1, cb_prefix_output => 'prefix_rh_output', message_multiple => 'All request handlers are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{rh} = [ { label => '15min-rate-requests', set => { key_values => [ { name => '15minRateRequestsPerSecond' }, { name => 'display' } ], output_template => '15min Rate Requests : %.7f/s', perfdatas => [ { label => '15min_rate_requests', value => '15minRateRequestsPerSecond', template => '%.7f', min => 0, unit => '/s', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'avg-requests', set => { key_values => [ { name => 'avgRequestsPerSecond' }, { name => 'display' } ], output_template => 'Average Requests : %.7f/s', perfdatas => [ { label => 'avg_requests', value => 'avgRequestsPerSecond', template => '%.7f', min => 0, unit => '/s', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'avg-time', set => { key_values => [ { name => 'avgTimePerRequest' }, { name => 'display' } ], output_template => 'Average Time Per Request : %.3f ms', perfdatas => [ { label => 'avg_time', value => 'avgTimePerRequest', template => '%.3f', min => 0, unit => 'ms', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'requests-count', set => { key_values => [ { name => 'requests', diff => 1 }, { name => 'display' } ], output_template => 'Requests Count : %s', perfdatas => [ { label => 'requests_count', value => 'requests', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name', default => '(/select|/update)$' } }); return $self; } sub prefix_rh_output { my ($self, %options) = @_; return "Request Handler '" . $options{instance_value}->{display} . "' "; } sub manage_selection { my ($self, %options) = @_; $self->{rh} = {}; $self->{request} = [ { mbean => 'solr/*:id=org.apache.solr.handler.component.SearchHandler,type=*', attributes => [ { name => '15minRateRequestsPerSecond' }, { name => 'avgTimePerRequest' }, { name => 'avgRequestsPerSecond' }, { name => 'requests' } ] }, { mbean => 'solr/*:id=org.apache.solr.handler.UpdateRequestHandler,type=*', attributes => [ { name => '15minRateRequestsPerSecond' }, { name => 'avgTimePerRequest' }, { name => 'avgRequestsPerSecond' }, { name => 'requests' } ] }, ]; my $result = $options{custom}->get_attributes(request => $self->{request}, nothing_quit => 1); foreach my $mbean (keys %{$result}) { $mbean =~ /solr\/(.*?):id=.*?\.(.*?)Handler,type=(.*?)(?:,|$)/; my $rhname = $1 . '.' . $2 . '.' . $3; if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $rhname !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $rhname . "': no matching filter.", debug => 1); next; } $self->{rh}->{$rhname} = { display => $rhname, %{$result->{$mbean}}, }; } if (scalar(keys %{$self->{rh}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No request handler found."); $self->{output}->option_exit(); } $self->{cache_name} = "solr_" . $self->{mode} . '_' . md5_hex($options{custom}->get_connection_info()) . '_' . (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 request handler usage. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^requests-count$' =item B<--filter-name> Filter request handler name (can be a regexp). Default: '(/select|/update)$'. =item B<--warning-*> Threshold warning. Can be: 'requests-count', 'avg-requests', 'avg-time', '15min-rate-requests'. =item B<--critical-*> Threshold critical. Can be: 'requests-count', 'avg-requests', 'avg-time', '15min-rate-requests'. =back =cut centreon-plugins-20220113/apps/java/solr/jmx/plugin.pm000066400000000000000000000026401417000230700225330ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::java::solr::jmx::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}} = ( 'cache-usage' => 'apps::java::solr::jmx::mode::cacheusage', 'request-handler-usage' => 'apps::java::solr::jmx::mode::requesthandlerusage', ); $self->{custom_modes}{jolokia} = 'centreon::common::protocols::jmx::custom::jolokia'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Solr in JMX. Need Jolokia agent. =cut centreon-plugins-20220113/apps/java/weblogic/000077500000000000000000000000001417000230700207135ustar00rootroot00000000000000centreon-plugins-20220113/apps/java/weblogic/jmx/000077500000000000000000000000001417000230700215115ustar00rootroot00000000000000centreon-plugins-20220113/apps/java/weblogic/jmx/mode/000077500000000000000000000000001417000230700224355ustar00rootroot00000000000000centreon-plugins-20220113/apps/java/weblogic/jmx/mode/workmanager.pm000066400000000000000000000226541417000230700253210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::java::weblogic::jmx::mode::workmanager; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); sub custom_threshold_output { my ($self, %options) = @_; return $self->{instance_mode}->get_severity(section => 'health', value => $self->{result_values}->{health_state}); } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{health_state} = $options{new_datas}->{$self->{instance} . '_health_state'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'wm', type => 1, cb_prefix_output => 'prefix_wm_output', message_multiple => 'All WorkerManagers are ok' } ]; $self->{maps_counters}->{wm} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'health_state' } ], closure_custom_calc => $self->can('custom_status_calc'), output_template => 'State : %s', output_error_template => 'State : %s', output_use => 'health_state', closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => $self->can('custom_threshold_output'), } }, { label => 'request-completed', set => { key_values => [ { name => 'completed', diff => 1 }, { name => 'display' } ], output_template => 'Requests completed : %s', perfdatas => [ { label => 'request_completed', value => 'completed', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'request-pending', set => { key_values => [ { name => 'pending' }, { name => 'display' } ], output_template => 'Requests pending : %s', perfdatas => [ { label => 'request_pending', value => 'pending', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'thread-stuck', set => { key_values => [ { name => 'stuck' }, { name => 'display' } ], output_template => 'Threads stuck : %s', perfdatas => [ { label => 'thread_stuck', value => 'stuck', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub prefix_wm_output { my ($self, %options) = @_; return "WorkerManager '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { "filter-application:s" => { name => 'filter_application' }, "filter-name:s" => { name => 'filter_name' }, "filter-runtime:s" => { name => 'filter_runtime' }, "threshold-overload:s@" => { name => 'threshold_overload' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $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}; } } my $thresholds = { health => [ ['HEALTH_OK', 'OK'], ['HEALTH_WARNING', 'WARNING'], ['HEALTH_CRITICAL', 'CRITICAL'], ['HEALTH_FAILED', 'CRITICAL'], ['HEALTH_OVERLOADED', 'CRITICAL'], ['LOW_MEMORY_REASON', 'CRITICAL'], ], }; 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; } my %map_state = ( 0 => 'HEALTH_OK', 1 => 'HEALTH_WARNING', 2 => 'HEALTH_CRITICAL', 3 => 'HEALTH_FAILED', 4 => 'HEALTH_OVERLOADED', 5 => 'LOW_MEMORY_REASON', ); sub manage_selection { my ($self, %options) = @_; my $request = [ { mbean => 'com.bea:ApplicationRuntime=*,Name=*,ServerRuntime=*,Type=WorkManagerRuntime', attributes => [ { name => 'HealthState' }, { name => 'StuckThreadCount' }, { name => 'CompletedRequests' }, { name => 'PendingRequests' } ] } ]; my $result = $options{custom}->get_attributes(request => $request, nothing_quit => 1); $self->{wm} = {}; foreach my $mbean (keys %{$result}) { next if ($mbean !~ /ApplicationRuntime=(.*?),Name=(.*?),ServerRuntime=(.*?),/); my ($app, $name, $runtime) = ($1, $2, $3); my $health_state = defined($map_state{$result->{$mbean}->{HealthState}->{state}}) ? $map_state{$result->{$mbean}->{HealthState}->{state}} : 'unknown'; if (defined($self->{option_results}->{filter_application}) && $self->{option_results}->{filter_application} ne '' && $app !~ /$self->{option_results}->{filter_application}/) { $self->{output}->output_add(long_msg => "skipping '" . $app . "': no matching filter application."); next; } 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 name."); next; } if (defined($self->{option_results}->{filter_runtime}) && $self->{option_results}->{filter_runtime} ne '' && $runtime !~ /$self->{option_results}->{filter_runtime}/) { $self->{output}->output_add(long_msg => "skipping '" . $runtime . "': no matching filter runtime."); next; } $self->{wm}->{$app . '/' . $name . '/' . $runtime} = { health_state => $health_state, display => $app . '/' . $name . '/' . $runtime, completed => $result->{$mbean}->{CompletedRequests}, pending => $result->{$mbean}->{PendingRequests}, stuck => $result->{$mbean}->{StuckThreadCount} }; } if (scalar(keys %{$self->{wm}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No entry found."); $self->{output}->option_exit(); } $self->{cache_name} = "weblogic_" . $self->{mode} . '_' . md5_hex($self->{connector}->{url}) . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_application}) ? md5_hex($self->{option_results}->{filter_application}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_runtime}) ? md5_hex($self->{option_results}->{filter_runtime}) : md5_hex('all')); } 1; __END__ =head1 MODE Check WebLogic WorkManagers. =over 8 =item B<--warning-*> Threshold warning. Can be: 'thread-stuck', 'request-completed', 'request-pending'. =item B<--critical-*> Threshold critical. Can be: 'thread-stuck', 'request-completed', 'request-pending'. =item B<--filter-application> Filter by application runtime. =item B<--filter-name> Filter by name (regexp can be used). =item B<--filter-runtime> Filter by server runtime. =item B<--threshold-overload> Set to overload default threshold values (syntax: section,status,regexp) It used before default thresholds (order stays). Example: --threshold-overload='health,CRITICAL,^(?!(HEALTH_OK)$)' =back =cut centreon-plugins-20220113/apps/java/weblogic/jmx/plugin.pm000066400000000000000000000031561417000230700233520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::java::weblogic::jmx::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}} = ( 'class-count' => 'centreon::common::jvm::mode::classcount', 'memory' => 'centreon::common::jvm::mode::memory', 'memory-detailed' => 'centreon::common::jvm::mode::memorydetailed', 'threads' => 'centreon::common::jvm::mode::threads', 'work-manager' => 'apps::java::weblogic::jmx::mode::workmanager', ); $self->{custom_modes}{jolokia} = 'centreon::common::protocols::jmx::custom::jolokia'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check WebLogic in JMX. Need Jolokia agent. =cut centreon-plugins-20220113/apps/java/zookeeper/000077500000000000000000000000001417000230700211235ustar00rootroot00000000000000centreon-plugins-20220113/apps/java/zookeeper/jmx/000077500000000000000000000000001417000230700217215ustar00rootroot00000000000000centreon-plugins-20220113/apps/java/zookeeper/jmx/mode/000077500000000000000000000000001417000230700226455ustar00rootroot00000000000000centreon-plugins-20220113/apps/java/zookeeper/jmx/mode/stats.pm000066400000000000000000000137721417000230700243530ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::java::zookeeper::jmx::mode::stats; 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 => 'zk', type => 1, cb_prefix_output => 'prefix_zk_output', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{zk} = [ { label => 'avg-request-latency', set => { key_values => [ { name => 'AvgRequestLatency' } ], output_template => 'Avg Request Latency : %s ms', perfdatas => [ { label => 'avg_request_latency', value => 'AvgRequestLatency', template => '%s', min => 0, unit => 'ms' }, ], } }, { label => 'max-request-latency', set => { key_values => [ { name => 'MaxRequestLatency' } ], output_template => 'Max Request Latency : %s ms', perfdatas => [ { label => 'max_request_latency', value => 'MaxRequestLatency', template => '%s', min => 0, unit => 'ms' }, ], } }, { label => 'outstanding-requests', set => { key_values => [ { name => 'OutstandingRequests' } ], output_template => 'Outstanding Requests : %s', perfdatas => [ { label => 'outstanding_requests', value => 'OutstandingRequests', template => '%s', min => 0 }, ], } }, { label => 'packets-received', set => { key_values => [ { name => 'PacketsReceived', diff => 1 } ], output_template => 'Packets Received : %s', perfdatas => [ { label => 'packets_received', value => 'PacketsReceived', template => '%s', min => 0 }, ], } }, { label => 'packets-sent', set => { key_values => [ { name => 'PacketsSent', diff => 1 } ], output_template => 'Packets Sent : %s', perfdatas => [ { label => 'packets_sent', value => 'PacketsSent', template => '%s', min => 0 }, ], } }, { label => 'num-connections', set => { key_values => [ { name => 'NumAliveConnections' } ], output_template => 'Num Alive Connections : %s', perfdatas => [ { label => 'num_connections', value => 'NumAliveConnections', template => '%s', min => 0 }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub prefix_zk_output { my ($self, %options) = @_; return "Zookeeper '" . $options{instance_value}->{display} . "' "; } sub manage_selection { my ($self, %options) = @_; $self->{zk} = {}; $self->{request} = [ { mbean => 'org.apache.ZooKeeperService:name0=*,name1=*,name2=Leader', attributes => [ { name => 'AvgRequestLatency' }, { name => 'MaxRequestLatency' }, { name => 'OutstandingRequests' }, { name => 'PacketsReceived' }, { name => 'PacketsSent' }, { name => 'NumAliveConnections' } ] }, { mbean => 'org.apache.ZooKeeperService:name0=*,name1=*,name2=Follower', attributes => [ { name => 'AvgRequestLatency' }, { name => 'MaxRequestLatency' }, { name => 'OutstandingRequests' }, { name => 'PacketsReceived' }, { name => 'PacketsSent' }, { name => 'NumAliveConnections' } ] }, ]; my $result = $options{custom}->get_attributes(request => $self->{request}, nothing_quit => 1); foreach my $mbean (keys %{$result}) { next if ($mbean !~ /name2=(.*?)(?:,|$)/); my $type = $1; $self->{zk}->{$type} = { display => $type, %{$result->{$mbean}}, }; } if (scalar(keys %{$self->{zk}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No zookeeper found."); $self->{output}->option_exit(); } $self->{cache_name} = "zookeeper_" . $self->{mode} . '_' . md5_hex($options{custom}->get_connection_info()) . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check hibernate statistics. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^avg-request-latency$' =item B<--warning-*> Threshold warning. Can be: 'avg-request-latency', 'max-request-latency', 'outstanding-requests', 'packets-received' 'packets-sent', 'num-connections'. =item B<--critical-*> Threshold critical. Can be: 'avg-request-latency', 'max-request-latency', 'outstanding-requests', 'packets-received' 'packets-sent', 'num-connections'. =back =cut centreon-plugins-20220113/apps/java/zookeeper/jmx/plugin.pm000066400000000000000000000024771417000230700235670ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::java::zookeeper::jmx::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}} = ( 'stats' => 'apps::java::zookeeper::jmx::mode::stats', ); $self->{custom_modes}{jolokia} = 'centreon::common::protocols::jmx::custom::jolokia'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Zookeeper in JMX. Need Jolokia agent. =cut centreon-plugins-20220113/apps/jenkins/000077500000000000000000000000001417000230700176405ustar00rootroot00000000000000centreon-plugins-20220113/apps/jenkins/mode/000077500000000000000000000000001417000230700205645ustar00rootroot00000000000000centreon-plugins-20220113/apps/jenkins/mode/jobstate.pm000066400000000000000000000136771417000230700227530ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::jenkins::mode::jobstate; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::http; use centreon::plugins::statefile; use JSON; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "hostname:s" => { name => 'hostname' }, "port:s" => { name => 'port' }, "proto:s" => { name => 'proto' }, "urlpath:s" => { name => 'url_path' }, "timeout:s" => { name => 'timeout' }, "credentials" => { name => 'credentials' }, "basic" => { name => 'basic' }, "username:s" => { name => 'username' }, "password:s" => { name => 'password' }, "jobname:s" => { name => 'jobname' }, "warning:s" => { name => 'warning' }, "critical:s" => { name => 'critical' }, "checkstyle" => { name => 'checkstyle' }, }); $self->{http} = centreon::plugins::http->new(%options); 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}->{jobname})) { $self->{output}->add_option_msg(short_msg => "Please set the jobname option"); $self->{output}->option_exit(); } $self->{option_results}->{url_path} = $self->{option_results}->{url_path} . "/job/" . $self->{option_results}->{jobname} . "/api/json"; $self->{http}->set_options(%{$self->{option_results}}); } sub run { my ($self, %options) = @_; my $jsoncontent = $self->{http}->request(); my $json = JSON->new; my $webcontent; eval { $webcontent = $json->decode($jsoncontent); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response"); $self->{output}->option_exit(); } my $description_tendency = $webcontent->{healthReport}->[0]->{description}; my $score_tendency = $webcontent->{healthReport}->[0]->{score}; my ($description_violations, $number_violations); my $exit1 = $self->{perfdata}->threshold_check(value => $score_tendency, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit1, short_msg => sprintf("%s", $description_tendency)); $self->{output}->perfdata_add(label => 'score_tendency', value => sprintf("%d", $score_tendency), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0, ); if (defined($self->{option_results}->{checkstyle})) { if (defined($webcontent->{healthReport}->[1]->{description})) { my $description_violations; my $number_violations; $description_violations = $webcontent->{healthReport}->[1]->{description}; if ( $description_violations =~ /^.+?([0-9]+)$/ ) { $number_violations = $1; } $self->{output}->add_option_msg(short_msg => sprintf("%s", $description_violations)); $self->{output}->perfdata_add(label => 'number_violations', value => sprintf("%d", $number_violations), min => 0, ); } } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check Jenkins specific job tendency (score) and checkstyle violation =over 8 =item B<--hostname> IP Addr/FQDN of the Jenkins host =item B<--port> Port used by Jenkins API =item B<--proto> Specify https if needed (Default: 'http') =item B<--urlpath> Set path to get Jenkins information =item B<--credentials> Required to use username/password authentication method =item B<--basic> Specify this option if you access API over basic authentication and don't want a '401 UNAUTHORIZED' error to be logged on your webserver. Specify this option if you access API over hidden basic authentication or you'll get a '404 NOT FOUND' error. (Use with --credentials) =item B<--username> Specify username for API authentification =item B<--password> Specify password for API authentification =item B<--timeout> Threshold for HTTP timeout (Default: 5) =item B<--warning> Warning Threshold for tendency score =item B<--critical> Critical Threshold for tendency score =item B<--checkstyle> Add checkstyle's violation output and perfdata =back =cut centreon-plugins-20220113/apps/jenkins/plugin.pm000066400000000000000000000023131417000230700214730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::jenkins::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} = '0.1'; %{$self->{modes}} = ( 'job-state' => 'apps::jenkins::mode::jobstate', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Jenkins through its JSON API =cut centreon-plugins-20220113/apps/jive/000077500000000000000000000000001417000230700171345ustar00rootroot00000000000000centreon-plugins-20220113/apps/jive/sql/000077500000000000000000000000001417000230700177335ustar00rootroot00000000000000centreon-plugins-20220113/apps/jive/sql/mode/000077500000000000000000000000001417000230700206575ustar00rootroot00000000000000centreon-plugins-20220113/apps/jive/sql/mode/etljobstatus.pm000066400000000000000000000117411417000230700237440ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::jive::sql::mode::etljobstatus; use base qw(centreon::plugins::mode); use strict; use warnings; my $thresholds = { status => [ ['^1$', 'OK'], ['^3$', 'CRITICAL'], ], }; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "retention:s" => { name => 'retention', default => 1 }, "threshold-overload:s@" => { name => 'threshold_overload' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); $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) = ('status', $1, $2); 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}; } } sub run { my ($self, %options) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); my $retention = $self->{option_results}->{retention}; # CURRENT_TIMESTAMP should be compatible with the jive databases: Oracle, MS SQL, MySQL, Postgres. # INTERVAL also. my $query = q{SELECT etl_job_id, state, start_ts, end_ts FROM jivedw_etl_job WHERE start_ts > CURRENT_TIMESTAMP - INTERVAL '} . $retention . q{' DAY}; $self->{sql}->query(query => $query); my $job_etl_problems = {}; my $total_problems = 0; while ((my $row = $self->{sql}->fetchrow_hashref())) { my $exit = $self->get_severity(section => 'status', value => $row->{state}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(long_msg => sprintf("%s: job '%i' state is %s [start_time: %s]", $exit, $row->{etl_job_id}, $row->{state}, $row->{start_ts})); $job_etl_problems->{$exit} = 0 if (!defined($job_etl_problems->{$exit})); $job_etl_problems->{$exit}++; $total_problems++; } } $self->{output}->output_add(severity => 'OK', short_msg => 'no job etl problems'); foreach (keys %{$job_etl_problems}) { $self->{output}->output_add(severity => $_, short_msg => sprintf("job etl had %i problems during the last %i days", $job_etl_problems->{$_}, $self->{option_results}->{retention})); } $self->{output}->perfdata_add(label => 'job_etl_problems', value => $total_problems, min => 0); $self->{output}->display(); $self->{output}->exit(); } 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__ =head1 MODE Check jive ETL job status. Please use with dyn-mode option. =over 8 =item B<--retention> Retention in days (default : 1). =item B<--threshold-overload> Set to overload default threshold values (syntax: status,regexp) It used before default thresholds (order stays). Example: --threshold-overload='CRITICAL,^(?!(1)$)' =back =cut centreon-plugins-20220113/apps/jmeter/000077500000000000000000000000001417000230700174655ustar00rootroot00000000000000centreon-plugins-20220113/apps/jmeter/mode/000077500000000000000000000000001417000230700204115ustar00rootroot00000000000000centreon-plugins-20220113/apps/jmeter/mode/scenario.pm000066400000000000000000000230241417000230700225530ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package 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; $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|/testResults/sample'); 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 centreon-plugins-20220113/apps/jmeter/plugin.pm000066400000000000000000000022621417000230700213230ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package 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 centreon-plugins-20220113/apps/keepalived/000077500000000000000000000000001417000230700203105ustar00rootroot00000000000000centreon-plugins-20220113/apps/keepalived/snmp/000077500000000000000000000000001417000230700212655ustar00rootroot00000000000000centreon-plugins-20220113/apps/keepalived/snmp/mode/000077500000000000000000000000001417000230700222115ustar00rootroot00000000000000centreon-plugins-20220113/apps/keepalived/snmp/mode/vrrpstatus.pm000066400000000000000000000133251417000230700250100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::keepalived::snmp::mode::vrrpstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("state : %s [last state : %s, wanted state : '%s']", $self->{result_values}->{instanceState}, $self->{result_values}->{instanceStateLast}, $self->{result_values}->{instanceWantedState}); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{instanceWantedState} = $options{new_datas}->{$self->{instance} . '_instance_wanted_state'}; $self->{result_values}->{instanceStateLast} = $options{old_datas}->{$self->{instance} . '_instance_state'}; $self->{result_values}->{instanceState} = $options{new_datas}->{$self->{instance} . '_instance_state'}; $self->{result_values}->{instancePrimaryInterface} = $options{new_datas}->{$self->{instance} . '_instance_primary_interface'}; if (!defined($options{old_datas}->{$self->{instance} . '_instance_state'})) { $self->{error_msg} = "buffer creation"; return -2; } return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'vrrp', type => 1, cb_prefix_output => 'prefix_vrrp_output', message_multiple => 'All VRRP instances are ok' }, ]; $self->{maps_counters}->{vrrp} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'instance_primary_interface' }, { name => 'instance_wanted_state' }, { name => 'instance_state' } ], 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 => \&catalog_status_threshold, } }, ]; } sub prefix_vrrp_output { my ($self, %options) = @_; return "VRRP '" . $options{instance_value}->{instance_primary_interface} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{instanceState} ne %{instanceWantedState} or %{instanceState} ne %{instanceStateLast}' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } my %map_instance_state = (0 => 'init', 1 => 'backup', 2 => 'master', 3 => 'fault', 4 => 'unknown'); my %map_instance_wanted_state = (0 => 'init', 1 => 'backup', 2 => 'master', 3 => 'fault', 4 => 'unknown'); my $mapping = { vrrpInstanceState => { oid => '.1.3.6.1.4.1.9586.100.5.2.3.1.4', map => \%map_instance_state }, vrrpInstanceWantedState => { oid => '.1.3.6.1.4.1.9586.100.5.2.3.1.6', map => \%map_instance_wanted_state }, vrrpInstancePrimaryInterface => { oid => '.1.3.6.1.4.1.9586.100.5.2.3.1.10' }, }; my $oid_vrrpInstanceEntry = '.1.3.6.1.4.1.9586.100.5.2.3.1'; sub manage_selection { my ($self, %options) = @_; $self->{vrrp} = {}; my $snmp_result = $options{snmp}->get_table( oid => $oid_vrrpInstanceEntry, end => $mapping->{vrrpInstancePrimaryInterface}->{oid}, nothing_quit => 1 ); foreach my $oid (keys %{$snmp_result}) { next if ($oid !~ /^$mapping->{vrrpInstanceState}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); $self->{vrrp}->{$instance} = { instance_primary_interface => $result->{vrrpInstancePrimaryInterface}, instance_wanted_state => $result->{vrrpInstanceWantedState}, instance_state => $result->{vrrpInstanceState}, }; } $self->{cache_name} = "keepalived_" . $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')); } 1; __END__ =head1 MODE Check VRRP instances status. =over 8 =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{instanceWantedState}, %{instanceStateLast}, %{instanceState}, %{instancePrimaryInterface} =item B<--critical-status> Set critical threshold for status (Default: '%{instanceState} ne %{instanceWantedState} or %{instanceState} ne %{instanceStateLast}'). Can used special variables like: %{instanceWantedState}, %{instanceStateLast}, %{instanceState}, %{instancePrimaryInterface} =back =cut centreon-plugins-20220113/apps/keepalived/snmp/plugin.pm000066400000000000000000000023261417000230700231240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::keepalived::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}} = ( 'vrrp-status' => 'apps::keepalived::snmp::mode::vrrpstatus', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Keepalived in SNMP. =cut centreon-plugins-20220113/apps/kingdee/000077500000000000000000000000001417000230700176055ustar00rootroot00000000000000centreon-plugins-20220113/apps/kingdee/eas/000077500000000000000000000000001417000230700203555ustar00rootroot00000000000000centreon-plugins-20220113/apps/kingdee/eas/custom/000077500000000000000000000000001417000230700216675ustar00rootroot00000000000000centreon-plugins-20220113/apps/kingdee/eas/custom/api.pm000066400000000000000000000107501417000230700230010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::kingdee::eas::custom::api; use strict; use warnings; use centreon::plugins::http; 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 => { 'hostname:s@' => { name => 'hostname' }, 'proto:s@' => { name => 'proto' }, 'port:s@' => { name => 'port' }, 'username:s@' => { name => 'username' }, 'password:s@' => { name => 'password' }, 'timeout:s@' => { name => 'timeout' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? shift(@{$self->{option_results}->{hostname}}) : undef; $self->{username} = (defined($self->{option_results}->{username})) ? shift(@{$self->{option_results}->{username}}) : ''; $self->{password} = (defined($self->{option_results}->{password})) ? shift(@{$self->{option_results}->{password}}) : ''; $self->{proto} = (defined($self->{option_results}->{proto})) ? shift(@{$self->{option_results}->{proto}}) : 'http'; $self->{port} = (defined($self->{option_results}->{port})) ? shift(@{$self->{option_results}->{port}}) : 80; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? shift(@{$self->{option_results}->{timeout}}) : 10; if (!defined($self->{hostname})) { $self->{output}->add_option_msg(short_msg => 'Need to specify hostname option.'); $self->{output}->option_exit(); } if (!defined($self->{hostname}) || scalar(@{$self->{option_results}->{hostname}}) == 0) { return 0; } return 1; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{credentials} = 1; $self->{option_results}->{basic} = 1; $self->{option_results}->{username} = $self->{username}; $self->{option_results}->{password} = $self->{password}; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub get_port { my ($self, %options) = @_; return $self->{port}; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->set_options(%{$self->{option_results}}); } sub request { my ($self, %options) = @_; $self->settings(); my $content = $self->{http}->request(url_path => $options{path}); $content =~ s/^\s|\s+$//g; return $content; } 1; __END__ =head1 NAME KINGDEE REST API =head1 SYNOPSIS KINGDEE Rest API custom mode =head1 REST API OPTIONS =over 8 =item B<--hostname> Kingdee hostname. =item B<--proto> Specify https if needed. =item B<--username> Kingdee username. =item B<--password> Kingdee password. =item B<--timeout> Set HTTP timeout in seconds (Default: '10'). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/kingdee/eas/mode/000077500000000000000000000000001417000230700213015ustar00rootroot00000000000000centreon-plugins-20220113/apps/kingdee/eas/mode/activeusers.pm000066400000000000000000000072241417000230700242010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Author : CHEN JUN , aladdin.china@gmail.com package apps::kingdee::eas::mode::activeusers; 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, skipped_code => { -10 => 1 } }, { name => 'global_time', type => 0, cb_prefix_output => 'prefix_time_output', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ { label => 'users-active-total', nlabel => 'system.users.active.total.count', set => { key_values => [ { name => 'total' } ], output_template => 'total users active: %s', perfdatas => [ { value => 'total', template => '%s', min => 0 }, ], } } ]; $self->{maps_counters}->{global_time} = []; foreach (('1m', '5m', '15m', '30m', '1h', '3h', '8h')) { push @{$self->{maps_counters}->{global_time}}, { label => 'users-active-' . $_, nlabel => 'system.users.active.' . $_ . '.count', set => { key_values => [ { name => 'users_' . $_ } ], output_template => '%s (' . $_ . ')', perfdatas => [ { value => 'users_' . $_ , template => '%s', min => 0 }, ], } }; } } sub prefix_time_output { my ($self, %options) = @_; return 'active users: '; } 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 => { 'urlpath:s' => { name => 'url_path', default => "/easportal/tools/nagios/checkactiveusers.jsp" }, }); return $self; } sub manage_selection { my ($self, %options) = @_; my $webcontent = $options{custom}->request(path => $self->{option_results}->{url_path}); if ($webcontent !~ /.*ActiveUsers_1m=.*/i) { $self->{output}->add_option_msg(short_msg => 'cannot find eas actvie users info.'); $self->{output}->option_exit(); } # ActiveUsers_1m=0 ActiveUsers_5m=0 ActiveUsers_15m=0 ActiveUsers_30m=0 ActiveUsers_1h=0 ActiveUsers_3h=0 ActiveUsers_8h=0 TotalUsers=0 $self->{global} = {}; $self->{global}->{total} = $1 if ($webcontent =~ /TotalUsers=(\d+)/mi); $self->{global_time} = {}; while ($webcontent =~ /activeusers_(\S+?)=(\d+)/mig) { $self->{global_time}->{'users_' . $1} = $2; } } 1; __END__ =head1 MODE Check eas active users info. =over 8 =item B<--urlpath> Set path to get status page. (Default: '/easportal/tools/nagios/checkclassloading.jsp') =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'sers-active-total', 'users-active-1m', 'users-active-5m', 'users-active-15m', 'users-active-30m', 'users-active-1h', 'users-active-3h', 'users-active-8h'. =back =cut centreon-plugins-20220113/apps/kingdee/eas/mode/classloading.pm000066400000000000000000000065161417000230700243120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Author : CHEN JUN , aladdin.china@gmail.com package apps::kingdee::eas::mode::classloading; 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 => 'global', type => 0 }, ]; $self->{maps_counters}->{global} = [ { label => 'class-loaded', nlabel => 'java.class.loaded.count', set => { key_values => [ { name => 'loadedclass' } ], output_template => 'class loaded: %s', perfdatas => [ { value => 'loadedclass', template => '%s', min => 0 }, ], } }, { label => 'class-unloaded', nlabel => 'java.class.unloaded.count', set => { key_values => [ { name => 'unloadedclass', diff => 1 } ], output_template => 'class unloaded: %s', perfdatas => [ { value => 'unloadedclass', template => '%s', min => 0 }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'urlpath:s' => { name => 'url_path', default => "/easportal/tools/nagios/checkclassloading.jsp" }, }); return $self; } sub manage_selection { my ($self, %options) = @_; my $webcontent = $options{custom}->request(path => $self->{option_results}->{url_path}); if ($webcontent !~ /(LoadedClassCount|UnloadedClassCount)/i) { $self->{output}->add_option_msg(short_msg => 'cannot find classloading status.'); $self->{output}->option_exit(); } $self->{global} = { loadedclass => 0, unloadedclass => 0 }; $self->{global}->{loadedclass} = $1 if ($webcontent =~ /LoadedClassCount=\s*(\d+)/mi); $self->{global}->{unloadedclass} = $1 if ($webcontent =~ /UnloadedClassCount=\s*(\d+)/mi); $self->{cache_name} = 'kingdee_' . $self->{mode} . '_' . $options{custom}->get_hostname() . '_' . $options{custom}->get_port() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check EAS application classLoading status. =over 8 =item B<--urlpath> Set path to get status page. (Default: '/easportal/tools/nagios/checkclassloading.jsp') =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'class-loaded', 'class-unloaded'. =back =cut centreon-plugins-20220113/apps/kingdee/eas/mode/datasource.pm000066400000000000000000000201251417000230700237710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Author : CHEN JUN , aladdin.china@gmail.com package apps::kingdee::eas::mode::datasource; 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 => 'datasource', type => 1, cb_prefix_output => 'prefix_datasource_output', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{datasource} = [ { label => 'pool-size-initial', nlabel => 'datasource.pool.size.initial.count', display_ok => 0, set => { key_values => [ { name => 'init_pool_size' } ], output_template => 'pool initial size: %s', perfdatas => [ { value => 'init_pool_size', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, { label => 'pool-size-max', nlabel => 'datasource.pool.size.max.count', display_ok => 0, set => { key_values => [ { name => 'max_pool_size' } ], output_template => 'pool max size: %s', perfdatas => [ { value => 'max_pool_size', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, { label => 'idle-timeout', nlabel => 'datasource.idle.timeout.count', display_ok => 0, set => { key_values => [ { name => 'idle_timeout' } ], output_template => 'idle timeout: %s', perfdatas => [ { value => 'idle_timeout', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, { label => 'connections-active', nlabel => 'datasource.connections.active.count', set => { key_values => [ { name => 'active_conn_count' } ], output_template => 'connections active: %s', perfdatas => [ { value => 'active_conn_count', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, { label => 'connections-current', nlabel => 'datasource.connections.current.count', display_ok => 0, set => { key_values => [ { name => 'cur_conn_count' } ], output_template => 'connections current: %s', perfdatas => [ { value => 'cur_conn_count', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, { label => 'connections-max', nlabel => 'datasource.connections.max.count', display_ok => 0, set => { key_values => [ { name => 'max_conn_count' } ], output_template => 'connections max: %s', perfdatas => [ { value => 'max_conn_count', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, { label => 'connections-created', nlabel => 'datasource.connections.created.count', display_ok => 0, set => { key_values => [ { name => 'create_count', diff => 1 } ], output_template => 'connections created: %s', perfdatas => [ { value => 'create_count', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, { label => 'connections-closed', nlabel => 'datasource.connections.closed.count', display_ok => 0, set => { key_values => [ { name => 'close_count', diff => 1 } ], output_template => 'connections closed: %s', perfdatas => [ { value => 'close_count', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, ]; } sub prefix_datasource_output { my ($self, %options) = @_; return "Datasource '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'urlpath:s' => { name => 'url_path', default => "/easportal/tools/nagios/checkdatasources.jsp" }, 'datasource:s' => { name => 'datasource' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{datasource}) || $self->{option_results}->{datasource} eq "") { $self->{output}->add_option_msg(short_msg => "Missing datasource name."); $self->{output}->option_exit(); } $self->{option_results}->{url_path} .= "?ds=" . $self->{option_results}->{datasource}; } sub manage_selection { my ($self, %options) = @_; my $webcontent = $options{custom}->request(path => $self->{option_results}->{url_path}); if ($webcontent !~ /^Name=/i) { $self->{output}->add_option_msg(short_msg => "Cannot find datasource '" . $self->{option_results}->{datasource} . "' status."); $self->{output}->option_exit(); } $self->{datasource}->{$self->{option_results}->{datasource}} = { display => $self->{option_results}->{datasource} }; $self->{datasource}->{$self->{option_results}->{datasource}}->{init_pool_size} = $1 if ($webcontent =~ /InitialPoolSize=(\d+)\s/i); $self->{datasource}->{$self->{option_results}->{datasource}}->{max_pool_size} = $1 if ($webcontent =~ /MaxPoolSize=(\d+)\s/i); $self->{datasource}->{$self->{option_results}->{datasource}}->{idle_timeout} = $1 if ($webcontent =~ /IdleTimeout=(\d+)\s/i); $self->{datasource}->{$self->{option_results}->{datasource}}->{cur_conn_count} = $1 if ($webcontent =~ /CurrentConnectionCount=(\d+)\s/i); $self->{datasource}->{$self->{option_results}->{datasource}}->{cur_avail_conn_count} = $1 if ($webcontent =~ /CurrentAvailableConnectionCount=(\d+)\s/i); $self->{datasource}->{$self->{option_results}->{datasource}}->{max_conn_count} = $1 if ($webcontent =~ /MaxConnectionCount=(\d+)\s/i); $self->{datasource}->{$self->{option_results}->{datasource}}->{create_count} = $1 if ($webcontent =~ /CreateCount=(\d+)\s/i); $self->{datasource}->{$self->{option_results}->{datasource}}->{close_count} = $1 if ($webcontent =~ /CloseCount=(\d+)\s/i); $self->{datasource}->{$self->{option_results}->{datasource}}->{active_conn_count} = $self->{datasource}->{$self->{option_results}->{datasource}}->{cur_conn_count} - $self->{datasource}->{$self->{option_results}->{datasource}}->{cur_avail_conn_count}; $self->{cache_name} = 'kingdee_' . $self->{mode} . '_' . $options{custom}->get_hostname() . '_' . $options{custom}->get_port() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{datasource}) ? md5_hex($self->{option_results}->{datasource}) : md5_hex('all')); } 1; __END__ =head1 MODE Check EAS application datasource status. =over 8 =item B<--urlpath> Specify path to get status page. (Default: '/easportal/tools/nagios/checkdatasources.jsp') =item B<--datasource> Specify the datasource name. =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'pool-size-initial', 'pool-size-max', 'idle-timeout', 'connections-active', 'connections-current', 'connections-max', 'connections-created', 'connections-closed'. =back =cut centreon-plugins-20220113/apps/kingdee/eas/mode/handlers.pm000066400000000000000000000270371417000230700234500ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Author : CHEN JUN , aladdin.china@gmail.com package apps::kingdee::eas::mode::handlers; 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 => 'handlers', type => 1, cb_prefix_output => 'prefix_handler_output', message_multiple => 'All handlers are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{handlers} = [ { label => 'threads-max', nlabel => 'handler.threads.max.count', display_ok => 0, set => { key_values => [ { name => 'maxthreads' } ], output_template => 'threads max: %s', perfdatas => [ { value => 'maxthreads', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, { label => 'threads-spare-min', nlabel => 'handler.threads.spare.min.count', display_ok => 0, set => { key_values => [ { name => 'minsparethreads' } ], output_template => 'threads spare min: %s', perfdatas => [ { value => 'minsparethreads', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, { label => 'threads-spare-max', nlabel => 'handler.threads.spare.max.count', display_ok => 0, set => { key_values => [ { name => 'maxsparethreads' } ], output_template => 'threads spare max: %s', perfdatas => [ { value => 'maxsparethreads', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, { label => 'queue-size-max', nlabel => 'handler.queue.size.max.count', display_ok => 0, set => { key_values => [ { name => 'maxqueuesize' } ], output_template => 'max queue size: %s', perfdatas => [ { value => 'maxqueuesize', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, { label => 'idle-timeout', nlabel => 'handler.idle.timeout.count', display_ok => 0, set => { key_values => [ { name => 'idle_timeout' } ], output_template => 'idle timeout: %s', perfdatas => [ { value => 'idle_timeout', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, { label => 'threads-processed', nlabel => 'handler.threads.processed.count', display_ok => 0, set => { key_values => [ { name => 'processedcount', diff => 1 } ], output_template => 'threads processed: %s', perfdatas => [ { value => 'processedcount', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, { label => 'threads-current', nlabel => 'handler.threads.current.count', set => { key_values => [ { name => 'currentthreadcount' } ], output_template => 'threads current: %s', perfdatas => [ { value => 'currentthreadcount', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, { label => 'threads-current', nlabel => 'handler.threads.current.count', set => { key_values => [ { name => 'currentthreadcount' } ], output_template => 'threads current: %s', perfdatas => [ { value => 'currentthreadcount', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, { label => 'threads-available', nlabel => 'handler.threads.available.count', set => { key_values => [ { name => 'availablethreadcount' } ], output_template => 'threads available: %s', perfdatas => [ { value => 'availablethreadcount', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, { label => 'threads-busy', nlabel => 'handler.threads.busy.count', set => { key_values => [ { name => 'busythreadcount' } ], output_template => 'threads busy: %s', perfdatas => [ { value => 'busythreadcount', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, { label => 'threads-available-max', nlabel => 'handler.threads.available.max.count', display_ok => 0, set => { key_values => [ { name => 'maxavailablethreadcount' } ], output_template => 'threads available max: %s', perfdatas => [ { value => 'maxavailablethreadcount', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, { label => 'threads-busy-max', nlabel => 'handler.threads.busy.max.count', display_ok => 0, set => { key_values => [ { name => 'maxbusythreadcount' } ], output_template => 'threads busy max: %s', perfdatas => [ { value => 'maxbusythreadcount', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, { label => 'threads-processedtime-max', nlabel => 'handler.threads.processedtime.max.milliseconds', display_ok => 0, set => { key_values => [ { name => 'maxprocessedtime' } ], output_template => 'threads processed time max: %s ms', perfdatas => [ { value => 'maxprocessedtime', template => '%s', min => 0, unit => 'ms', label_extra_instance => 1 }, ], } }, { label => 'threads-created', nlabel => 'handler.threads.created.count', display_ok => 0, set => { key_values => [ { name => 'createcount' } ], output_template => 'threads created: %s', perfdatas => [ { value => 'createcount', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, { label => 'threads-destroyed', nlabel => 'handler.threads.destroyed.count', display_ok => 0, set => { key_values => [ { name => 'destroycount' } ], output_template => 'threads destroyed: %s', perfdatas => [ { value => 'destroycount', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, ]; } sub prefix_handler_output { my ($self, %options) = @_; return "Handler '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options( arguments => { 'urlpath-httphandler:s' => { name => 'url_path_httphandler', default => "/easportal/tools/nagios/checkhttphandler.jsp" }, 'urlpath-muxhandler:s' => { name => 'url_path_muxhandler', default => "/easportal/tools/nagios/checkmuxhandler.jsp" }, 'filter-handler:s' => { name => 'filter_handler' }, }); return $self; } sub manager_handler { my ($self, %options) = @_; if (defined($self->{option_results}->{filter_handler}) && $self->{option_results}->{filter_handler} ne "" && $options{name} !~ /$self->{option_results}->{filter_handler}/ ) { return undef; } my $webcontent = $options{custom}->request(path => $self->{option_results}->{'url_path_' . $options{name} . 'handler'}); if ($webcontent !~ /MaxThreads=\d+/i) { $self->{output}->add_option_msg(short_msg => 'Cannot find ' . $options{name} . 'handler status in response'); $self->{output}->option_exit(); } $self->{handlers}->{$options{name}} = { display => $options{name} }; $self->{handlers}->{$options{name}}->{maxthreads} = $1 if ($webcontent =~ /MaxThreads=(\d+)/mi); $self->{handlers}->{$options{name}}->{minsparethreads} = $1 if $webcontent =~ /MinSpareThreads=(\d+)/mi ; $self->{handlers}->{$options{name}}->{maxsparethreads} = $1 if $webcontent =~ /MaxSpareThreads=(\d+)/mi ; $self->{handlers}->{$options{name}}->{maxqueuesize} = $1 if $webcontent =~ /MaxQueueSize=(\d+)/mi ; $self->{handlers}->{$options{name}}->{idle_timeout} = $1 if $webcontent =~ /IdleTimeout=(\d+)/mi ; $self->{handlers}->{$options{name}}->{processedcount} = $1 if $webcontent =~ /ProcessedCount=(\d+)/mi ; $self->{handlers}->{$options{name}}->{currentthreadcount} = $1 if $webcontent =~ /CurrentThreadCount=(\d+)/mi ; $self->{handlers}->{$options{name}}->{availablethreadcount} = $1 if $webcontent =~ /AvailableThreadCount=(\d+)/mi ; $self->{handlers}->{$options{name}}->{busythreadcount} = $1 if $webcontent =~ /BusyThreadCount=(\d+)/mi ; $self->{handlers}->{$options{name}}->{maxavailablethreadcount} = $1 if $webcontent =~ /MaxAvailableThreadCount=(\d+)/mi ; $self->{handlers}->{$options{name}}->{maxbusythreadcount} = $1 if $webcontent =~ /MaxBusyThreadCount=(\d+)/mi ; $self->{handlers}->{$options{name}}->{maxprocessedtime} = $1 if $webcontent =~ /MaxProcessedTime=(\d+)/mi ; $self->{handlers}->{$options{name}}->{createcount} = $1 if $webcontent =~ /CreateCount=(\d+)/mi ; $self->{handlers}->{$options{name}}->{destroycount} = $1 if $webcontent =~ /DestroyCount=(\d+)/mi ; } sub manage_selection { my ($self, %options) = @_; $self->{handlers} = {}; $self->manager_handler(custom => $options{custom}, name => 'http'); $self->manager_handler(custom => $options{custom}, name => 'mux'); $self->{cache_name} = 'kingdee_' . $self->{mode} . '_' . $options{custom}->get_hostname() . '_' . $options{custom}->get_port() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_handler}) ? md5_hex($self->{option_results}->{filter_handler}) : md5_hex('all')); } 1; __END__ =head1 MODE Check EAS instance handlers (http and mux). =over 8 =item B<--urlpath-httphandler> Set path to get status page. (Default: '/easportal/tools/nagios/checkhttphandler.jsp') =item B<--urlpath-muxhandler> Set path to get status page. (Default: '/easportal/tools/nagios/checkmuxhandler.jsp') =item B<--filter-handler> Handler filter (can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'threads-max', 'threads-spare-min', 'threads-spare-max', 'queue-size-max' 'idle-timeout', 'threads-processed', 'threads-current', 'threads-current', 'threads-available', 'threads-busy', 'threads-available-max', 'threads-busy-max', 'threads-processedtime-max', 'threads-created', 'threads-destroyed'. =back =cut centreon-plugins-20220113/apps/kingdee/eas/mode/ibmjvmgc.pm000066400000000000000000000065611417000230700234450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Author : CHEN JUN , aladdin.china@gmail.com package apps::kingdee::eas::mode::ibmjvmgc; 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, skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ { label => 'collection', nlabel => 'gc.collection.count', set => { key_values => [ { name => 'collection_count', diff => 1 } ], output_template => 'gc collection count: %s', perfdatas => [ { value => 'collection_count', template => '%s', min => 0 }, ], } }, { label => 'collection-time', nlabel => 'gc.collection.time.milliseconds', set => { key_values => [ { name => 'collection_time', diff => 1 } ], output_template => 'gc collection time: %s ms', perfdatas => [ { value => 'collection_time', template => '%s', min => 0, unit => 'ms' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'urlpath:s' => { name => 'url_path', default => "/easportal/tools/nagios/checkgc_j9gen.jsp" }, }); return $self; } sub manage_selection { my ($self, %options) = @_; my $webcontent = $options{custom}->request(path => $self->{option_results}->{url_path}); if ($webcontent !~ /CollectionCount=\d+/mi) { $self->{output}->add_option_msg(short_msg => 'Cannot find ibm jdk j9 gc status'); $self->{output}->option_exit(); } my ($collectioncount, $collectiontime) = (0, 0); $self->{global} = {}; if ($webcontent =~ /CollectionCount=(\d+)\sCollectionTime=(\d+)/mi) { $self->{global}->{collection_count} = $1; $self->{global}->{collection_time} = $2; } $self->{cache_name} = 'kingdee_' . $self->{mode} . '_' . $options{custom}->get_hostname() . '_' . $options{custom}->get_port() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check EAS application jvm gc status. =over 8 =item B<--urlpath> Set path to get status page. (Default: '/easportal/tools/nagios/checkgc_j9.jsp') =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'collection', 'collection-time'. =back =cut centreon-plugins-20220113/apps/kingdee/eas/mode/javaruntime.pm000066400000000000000000000062611417000230700241710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Author : CHEN JUN , aladdin.china@gmail.com package apps::kingdee::eas::mode::javaruntime; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use POSIX; use centreon::plugins::misc; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, ]; $self->{maps_counters}->{global} = [ { label => 'uptime', nlabel => 'java.uptime.milliseconds', set => { key_values => [ { name => 'uptime' }, { name => 'uptime_date' } ], output_template => 'java uptime: %s', output_use => 'uptime_date', perfdatas => [ { value => 'uptime', template => '%s', unit => 'ms' }, ], } }, ]; } 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 => { 'urlpath:s' => { name => 'url_path', default => "/easportal/tools/nagios/checkjavaruntime.jsp" }, }); return $self; } sub manage_selection { my ($self, %options) = @_; my $webcontent = $options{custom}->request(path => $self->{option_results}->{url_path}); if ($webcontent !~ /VmName=/mi) { $self->{output}->add_option_msg(short_msg => 'Cannot find java runtime status.'); $self->{output}->option_exit(); } my ($vmname, $specversion, $vmversion, $vendor, $uptime); $vmname = $1 if ($webcontent =~ /VmName=\'(.*?)\'/i); $specversion = $1 if ($webcontent =~ /SpecVersion=([\d\.]+)/i); $vmversion = $1 if ($webcontent =~ /VmVersion=(.*?)\s/i); $vendor = $1 if ($webcontent =~ /VmVendor=\'(.*?)\'/i); $uptime = $1 if ($webcontent =~ /Uptime=(\d*)/i); #unit:ms $self->{output}->output_add( long_msg => sprintf( '%s %s (build %s), %s', $vmname, $specversion, $vmversion, $vendor ) ); $self->{global} = { uptime => $uptime, uptime_date => centreon::plugins::misc::change_seconds(value => floor($uptime / 1000), start => 'd') }; } 1; __END__ =head1 MODE Check EAS application java runtime status. =over 8 =item B<--urlpath> Set path to get status page. (Default: '/easportal/tools/nagios/checkjavaruntime.jsp') =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'uptime'. =back =cut centreon-plugins-20220113/apps/kingdee/eas/mode/memory.pm000066400000000000000000000071141417000230700231520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Author : CHEN JUN , aladdin.china@gmail.com package apps::kingdee::eas::mode::memory; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'heap', cb_prefix_output => 'prefix_memory_output', type => 0 }, { name => 'nonheap', cb_prefix_output => 'prefix_memory_output', type => 0 }, ]; foreach (('heap', 'nonheap')) { $self->{maps_counters}->{$_} = []; foreach my $def ((['init', 0], ['max', 0], ['used', 1], ['commited', 1])) { push @{$self->{maps_counters}->{$_}}, { label => 'memory-' . $_ . '-' . $def->[0], nlabel => 'java.memory.' . $_ . '.' . $def->[0] . '.count', display_ok => $def->[1], set => { key_values => [ { name => $def->[0] } ], output_template => $def->[0] . ': %s', perfdatas => [ { value => $def->[0] , template => '%s', min => 0 }, ], } }; } } } sub prefix_memory_output { my ($self, %options) = @_; return "Memory '" . $options{instance_value}->{display} . "' "; } 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 => { 'urlpath:s' => { name => 'url_path', default => "/easportal/tools/nagios/checkmemory.jsp" }, }); return $self; } sub manage_selection { my ($self, %options) = @_; my $webcontent = $options{custom}->request(path => $self->{option_results}->{url_path}); if ($webcontent !~ /^(Type=HeapMemoryUsage|Type=NonHeapMemoryUsage)/mi) { $self->{output}->add_option_msg(short_msg => 'Cannot find heap or nonheap memory usage status.'); $self->{output}->option_exit(); } if ($webcontent =~ /^Type=HeapMemoryUsage\sinit=(\d+)\smax=(\d+)\sused=(\d+)\scommitted=(\d+)/mi) { $self->{heap} = { init => $1, max => $2, used => $3, commited => $4 }; } if ($webcontent =~ /^Type=NonHeapMemoryUsage\sinit=(\d+)\smax=(-{0,1}\d+)\sused=(\d+)\scommitted=(\d+)/mi) { $self->{nonheap} = { init => $1, max => $2, used => $3, commited => $4 }; } } 1; __END__ =head1 MODE Check EAS instance heap & nonheap memory usage. =over 8 =item B<--urlpath> Set path to get status page. (Default: '/easportal/tools/nagios/checkmemory.jsp') =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'memory-heap-init', 'memory-heap-max', 'memory-heap-used', 'memory-heap-commited', 'memory-nonheap-init', 'memory-nonheap-max', 'memory-nonheap-used', 'memory-nonheap-commited'. =back =cut centreon-plugins-20220113/apps/kingdee/eas/mode/oraclejvmgc.pm000066400000000000000000000103641417000230700241370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Author : CHEN JUN , aladdin.china@gmail.com package apps::kingdee::eas::mode::oraclejvmgc; 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 => 'global', cb_prefix_output => 'prefix_global_output', type => 0 }, ]; $self->{maps_counters}->{global} = [ { label => 'gc-minor', nlabel => 'java.gc.minor.count', set => { key_values => [ { name => 'minor_gc_count', diff => 1 } ], output_template => 'minor count: %s', perfdatas => [ { value => 'minor_gc_count', template => '%s', min => 0 }, ], } }, { label => 'gc-minor-time', nlabel => 'java.gc.minor.time.milliseconds', set => { key_values => [ { name => 'minor_gc_time', diff => 1 } ], output_template => 'minor time: %s ms', perfdatas => [ { value => 'minor_gc_time', template => '%s', min => 0, unit => 'ms' }, ], } }, { label => 'gc-full', nlabel => 'java.gc.full.count', set => { key_values => [ { name => 'full_gc_count', diff => 1 } ], output_template => 'full count: %s', perfdatas => [ { value => 'full_gc_count', template => '%s', min => 0 }, ], } }, { label => 'gc-full-time', nlabel => 'java.gc.full.time.milliseconds', set => { key_values => [ { name => 'full_gc_time', diff => 1 } ], output_template => 'full time: %s ms', perfdatas => [ { value => 'full_gc_time', template => '%s', min => 0, unit => 'ms' }, ], } }, ]; } sub prefix_global_output { my ($self, %options) = @_; return 'garbage collector '; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'urlpath:s' => { name => 'url_path', default => "/easportal/tools/nagios/checkgc_ps.jsp" }, }); return $self; } sub manage_selection { my ($self, %options) = @_; my $webcontent = $options{custom}->request(path => $self->{option_results}->{url_path}); if ($webcontent !~ /MinorGCCount=(\d+)/mi) { $self->{output}->add_option_msg(short_msg => 'cannot find jvm gc status.'); $self->{output}->option_exit(); } $self->{global} = { minor_gc_count => 0 }; $self->{global}->{minor_gc_time} = $1 if ($webcontent =~ /MinorGCTime=\s*(\d+)/mi); $self->{global}->{full_gc_count} = $1 if ($webcontent =~ /FullGCCount=\s*(\d+)/mi); $self->{global}->{full_gc_time} = $1 if ($webcontent =~ /FullGCTime=\s*(\d+)/mi); $self->{cache_name} = 'kingdee_' . $self->{mode} . '_' . $options{custom}->get_hostname() . '_' . $options{custom}->get_port() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check EAS application jvm gc status. =over 8 =item B<--urlpath> Set path to get status page. (Default: '/easportal/tools/nagios/checkgc_ps.jsp') =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'gc-minor', 'gc-minor-time', 'gc-full', 'gc-full-time'. =back =cut centreon-plugins-20220113/apps/kingdee/eas/mode/oracleksqltemptable.pm000066400000000000000000000066351417000230700257070ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Author : CHEN JUN , aladdin.china@gmail.com package apps::kingdee::eas::mode::oracleksqltemptable; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'datasource', type => 1, cb_prefix_output => 'prefix_datasource_output', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{datasource} = [ { label => 'table-ksqltemp', nlabel => 'datasource.table.ksqltemp.count', set => { key_values => [ { name => 'ksqltemp_count' } ], output_template => 'ksqltemp table: %s', perfdatas => [ { value => 'ksqltemp_count', template => '%s', min => 0, label_extra_instance => 1 }, ], } } ]; } sub prefix_datasource_output { my ($self, %options) = @_; return "Datasource '" . $options{instance_value}->{display} . "' "; } 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 => { 'urlpath:s' => { name => 'url_path', default => "/easportal/tools/nagios/checkoraclevt.jsp" }, 'datasource:s' => { name => 'datasource' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{datasource}) || $self->{option_results}->{datasource} eq "") { $self->{output}->add_option_msg(short_msg => "Missing datasource name."); $self->{output}->option_exit(); } $self->{option_results}->{url_path} .= "?ds=" . $self->{option_results}->{datasource}; } sub manage_selection { my ($self, %options) = @_; my $webcontent = $options{custom}->request(path => $self->{option_results}->{url_path}); if ($webcontent !~ /^COUNT.*?=\d+/i) { $self->{output}->add_option_msg(short_msg => 'Cannot find ksql temptable status.'); $self->{output}->option_exit(); } $self->{datasource}->{$self->{option_results}->{datasource}} = { display => $self->{option_results}->{datasource} }; $self->{datasource}->{$self->{option_results}->{datasource}}->{ksqltemp_count} = $1 if ($webcontent =~ /^COUNT.*?=(\d+)/i); } 1; __END__ =head1 MODE Check ksql temp table count for specify datasource. =over 8 =item B<--urlpath> Set path to get status page. (Default: '/easportal/tools/nagios/checkoraclevt.jsp') =item B<--datasource> Specify the datasource name. =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'table-ksqltemp'. =back =cut centreon-plugins-20220113/apps/kingdee/eas/mode/oraclerecyclebin.pm000066400000000000000000000067031417000230700251520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Author : CHEN JUN , aladdin.china@gmail.com package apps::kingdee::eas::mode::oraclerecyclebin; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'datasource', type => 1, cb_prefix_output => 'prefix_datasource_output', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{datasource} = [ { label => 'table-recyclebin', nlabel => 'datasource.table.recyclebin.count', set => { key_values => [ { name => 'recyclebin_count' } ], output_template => 'recyclebin table: %s', perfdatas => [ { value => 'recyclebin_count', template => '%s', min => 0, label_extra_instance => 1 }, ], } } ]; } sub prefix_datasource_output { my ($self, %options) = @_; return "Datasource '" . $options{instance_value}->{display} . "' "; } 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 => { 'urlpath:s' => { name => 'url_path', default => "/easportal/tools/nagios/checkoraclerecyclebin.jsp" }, 'datasource:s' => { name => 'datasource' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{datasource}) || $self->{option_results}->{datasource} eq "") { $self->{output}->add_option_msg(short_msg => "Missing datasource name."); $self->{output}->option_exit(); } $self->{option_results}->{url_path} .= "?ds=" . $self->{option_results}->{datasource}; } sub manage_selection { my ($self, %options) = @_; my $webcontent = $options{custom}->request(path => $self->{option_results}->{url_path}); if ($webcontent !~ /^COUNT.*?=\d+/i) { $self->{output}->add_option_msg(short_msg => 'Cannot find oracle recyclebin status.'); $self->{output}->option_exit(); } $self->{datasource}->{$self->{option_results}->{datasource}} = { display => $self->{option_results}->{datasource} }; $self->{datasource}->{$self->{option_results}->{datasource}}->{recyclebin_count} = $1 if ($webcontent =~ /^COUNT.*?=(\d+)/i); } 1; __END__ =head1 MODE Check oracle recyclebin table count for specify datasource. =over 8 =item B<--urlpath> Set path to get status page. (Default: '/easportal/tools/nagios/checkoraclerecyclebin.jsp') =item B<--datasource> Specify the datasource name. =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'table-recyclebin'. =back =cut centreon-plugins-20220113/apps/kingdee/eas/mode/oracleredolog.pm000066400000000000000000000107501417000230700244630ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure 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 # limitations under the License. # # Author : CHEN JUN , aladdin.china@gmail.com package apps::kingdee::eas::mode::oracleredolog; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'datasource', type => 1, cb_prefix_output => 'prefix_datasource_output', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{datasource} = [ { label => 'oracle-redolog-inactive', nlabel => 'datasource.oracle.redolog.inactive.count', set => { key_values => [ { name => 'inactive' } ], output_template => 'inactive: %s', perfdatas => [ { value => 'inactive', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, { label => 'oracle-redolog-active', nlabel => 'datasource.oracle.redolog.active.count', set => { key_values => [ { name => 'active' } ], output_template => 'active: %s', perfdatas => [ { value => 'active', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, { label => 'oracle-redolog-current', nlabel => 'datasource.oracle.redolog.current.count', set => { key_values => [ { name => 'current' } ], output_template => 'current: %s', perfdatas => [ { value => 'current', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, ]; } sub prefix_datasource_output { my ($self, %options) = @_; return "Datasource '" . $options{instance_value}->{display} . "' oracle redolog "; } 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 => { 'urlpath:s' => { name => 'url_path', default => "/easportal/tools/nagios/checkoracleredolog.jsp" }, 'datasource:s' => { name => 'datasource' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{datasource}) || $self->{option_results}->{datasource} eq "") { $self->{output}->add_option_msg(short_msg => "Missing datasource name."); $self->{output}->option_exit(); } $self->{option_results}->{url_path} .= "?ds=" . $self->{option_results}->{datasource}; } sub manage_selection { my ($self, %options) = @_; my $webcontent = $options{custom}->request(path => $self->{option_results}->{url_path}); if ($webcontent !~ /^STATUS=CURRENT/mi) { $self->{output}->add_option_msg(short_msg => 'Cannot find oracle redolog status.'); $self->{output}->option_exit(); } $self->{datasource}->{$self->{option_results}->{datasource}} = { display => $self->{option_results}->{datasource} }; $self->{datasource}->{$self->{option_results}->{datasource}}->{active} = $1 if ($webcontent =~ /^STATUS=ACTIVE\sCOUNT=(\d+)/mi); $self->{datasource}->{$self->{option_results}->{datasource}}->{inactive} = $1 if ($webcontent =~ /^STATUS=INACTIVE\sCOUNT=(\d+)/mi); $self->{datasource}->{$self->{option_results}->{datasource}}->{current} = $1 if ($webcontent =~ /^STATUS=CURRENT\sCOUNT=(\d+)/mi); } 1; __END__ =head1 MODE Check oracle redolog status. =over 8 =item B<--urlpath> Set path to get status page. (Default: '/easportal/tools/nagios/checkoracleredolog.jsp') =item B<--datasource> Specify the datasource name. =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'oracle-redolog-inactive', 'oracle-redolog-'active', 'oracle-redolog-current'. =back =cut centreon-plugins-20220113/apps/kingdee/eas/mode/oraclesession.pm000066400000000000000000000142041417000230700245110ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure 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 # limitations under the License. # # Author : CHEN JUN , aladdin.china@gmail.com package apps::kingdee::eas::mode::oraclesession; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'datasource', type => 1, cb_prefix_output => 'prefix_datasource_output', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{datasource} = [ { label => 'oracle-sessions-active', nlabel => 'datasource.oracle.sessions.active.count', set => { key_values => [ { name => 'active' } ], output_template => 'sessions active: %s', perfdatas => [ { value => 'active', template => '%s', min => 0, max => 'total', label_extra_instance => 1 }, ], } }, { label => 'oracle-sessions-inactive', nlabel => 'datasource.oracle.sessions.inactive.count', set => { key_values => [ { name => 'inactive' } ], output_template => 'sessions inactive: %s', perfdatas => [ { value => 'inactive', template => '%s', min => 0, max => 'total', label_extra_instance => 1 }, ], } }, ]; foreach ( ('other', 'queueing', 'network', 'administrative', 'configuration', 'commit', 'application', 'concurrency', 'scheduler', 'idle', 'userio', 'systemio') ) { push @{$self->{maps_counters}->{datasource}}, { label => 'oracle-waitclass-' . $_, nlabel => 'datasource.oracle.waitclass.' . $_ . '.count', display_ok => 0, set => { key_values => [ { name => $_ } ], output_template => 'wait class ' . $_ . ': %s', perfdatas => [ { value => $_ , template => '%s', min => 0, label_extra_instance => 1 }, ], } }; } } sub prefix_datasource_output { my ($self, %options) = @_; return "Datasource '" . $options{instance_value}->{display} . "' oracle "; } 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 => { 'urlpath:s' => { name => 'url_path', default => "/easportal/tools/nagios/checkoraclesession.jsp" }, 'datasource:s' => { name => 'datasource' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{datasource}) || $self->{option_results}->{datasource} eq "") { $self->{output}->add_option_msg(short_msg => "Missing datasource name."); $self->{output}->option_exit(); } $self->{option_results}->{url_path} .= "?ds=" . $self->{option_results}->{datasource}; } sub manage_selection { my ($self, %options) = @_; my $webcontent = $options{custom}->request(path => $self->{option_results}->{url_path} . '&groupby=status'); if ($webcontent !~ /^STATUS=ACTIVE/mi) { $self->{output}->add_option_msg(short_msg => 'Cannot find oracle session info.'); $self->{output}->option_exit(); } $self->{datasource}->{$self->{option_results}->{datasource}} = { display => $self->{option_results}->{datasource} }; $self->{datasource}->{$self->{option_results}->{datasource}}->{active} = $1 if ($webcontent =~ /^STATUS=ACTIVE\sCOUNT=(\d+)/mi); $self->{datasource}->{$self->{option_results}->{datasource}}->{inactive} = $1 if ($webcontent =~ /^STATUS=INACTIVE\sCOUNT=(\d+)/mi); $self->{datasource}->{$self->{option_results}->{datasource}}->{total} = $self->{datasource}->{$self->{option_results}->{datasource}}->{active} + $self->{datasource}->{$self->{option_results}->{datasource}}->{inactive}; $webcontent = $options{custom}->request(path => $self->{option_results}->{url_path} . '&groupby=wait_class&status=ACTIVE'); if ($webcontent !~ /^WAIT_CLASS=.*?COUNT=\d+/mi) { $self->{output}->add_option_msg(short_msg => 'Cannot find oracle session info.'); $self->{output}->option_exit(); } foreach ( ('other', 'queueing', 'network', 'administrative', 'configuration', 'commit', 'application', 'concurrency', 'scheduler', 'idle') ) { $self->{datasource}->{$self->{option_results}->{datasource}}->{$_} = $1 if ($webcontent =~ /^WAIT_CLASS=$_\sCOUNT=(\d+)/mi); } $self->{datasource}->{$self->{option_results}->{datasource}}->{systemio} = $1 if ($webcontent =~ /^WAIT_CLASS='System\s+I\/O'\sCOUNT=(\d+)/mi); $self->{datasource}->{$self->{option_results}->{datasource}}->{userio} = $1 if ($webcontent =~ /^WAIT_CLASS='User\s+I\/O'\sCOUNT=(\d+)/mi); } 1; __END__ =head1 MODE Check oracle database session status. =over 8 =item B<--urlpath> Set path to get status page. (Default: '/easportal/tools/nagios/checkoraclesession.jsp') =item B<--datasource> Specify the datasource name. =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'oracle-sessions-active', 'oracle-sessions-inactive', 'oracle-waitclass-other', 'oracle-waitclass-queueing', 'oracle-waitclass-network', 'oracle-waitclass-administrative', 'oracle-waitclass-configuration', 'oracle-waitclass-commit', 'oracle-waitclass-application', 'oracle-waitclass-concurrency', 'oracle-waitclass-scheduler', 'oracle-waitclass-idle', 'oracle-waitclass-userio', 'oracle-waitclass-systemio'. =back =cut centreon-plugins-20220113/apps/kingdee/eas/mode/oracletable.pm000066400000000000000000000106011417000230700241120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Author : CHEN JUN , aladdin.china@gmail.com package apps::kingdee::eas::mode::oracletable; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'datasource', type => 1, cb_prefix_output => 'prefix_datasource_output', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{datasource} = [ { label => 'table-rows', nlabel => 'datasource.table.rows.count', set => { key_values => [ { name => 'num_rows' } ], output_template => 'number of rows: %s', perfdatas => [ { value => 'num_rows', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, { label => 'table-actual-rows', nlabel => 'datasource.table.actual.rows.count', set => { key_values => [ { name => 'actual_num_rows' } ], output_template => 'number of actual rows: %s', perfdatas => [ { value => 'actual_num_rows', template => '%s', min => 0, label_extra_instance => 1 }, ], } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'urlpath:s' => { name => 'url_path', default => "/easportal/tools/nagios/checkoracletable.jsp" }, 'datasource:s' => { name => 'datasource' }, 'tablename:s' => { name => 'tablename' , default => 'T_GL_VOUCHER' }, 'actualrows:s' => { name => 'actualrows', default => 'false' }, }); return $self; } sub prefix_datasource_output { my ($self, %options) = @_; return "Datasource table '" . $options{instance_value}->{display} . "' "; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{datasource}) || $self->{option_results}->{datasource} eq "") { $self->{output}->add_option_msg(short_msg => 'Missing datasource name.'); $self->{output}->option_exit(); } $self->{option_results}->{url_path} .= "?ds=" . $self->{option_results}->{datasource} . "\&tablename=" . $self->{option_results}->{tablename} . "\&actual=" . $self->{option_results}->{actualrows}; } sub manage_selection { my ($self, %options) = @_; my $webcontent = $options{custom}->request(path => $self->{option_results}->{url_path}); if ($webcontent !~ /^TABLE_NAME=\w+/i) { $self->{output}->add_option_msg(short_msg => 'cannot find oracle table status'); $self->{output}->option_exit(); } my $name = $self->{option_results}->{datasource} . ':' . $self->{option_results}->{tablename}; $self->{datasource}->{$name} = { display => $name }; $self->{datasource}->{$name}->{num_rows} = $1 if ($webcontent =~ /NUM_ROWS=(\d+)/mi); $self->{datasource}->{$name}->{actual_num_rows} = $1 if ($webcontent =~ /ACTUAL_NUM_ROWS=(\d+)/mi); } 1; __END__ =head1 MODE Check oracle table info for specify datasource. =over 8 =item B<--urlpath> Set path to get status page. (Default: '/easportal/tools/nagios/checkoracletable.jsp') =item B<--datasource> Specify the datasource name. =item B<--tablename> Specify the table name , MUST BE uppercase. =item B<--actualrows> Specify whether check actual rows of table or not , true or false. MAY have performance problem for large table if specify true. =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'table-rows', 'table-actual-rows'. =back =cut centreon-plugins-20220113/apps/kingdee/eas/mode/oracleversion.pm000066400000000000000000000046471417000230700245250ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure 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 # limitations under the License. # # Author : CHEN JUN , aladdin.china@gmail.com package apps::kingdee::eas::mode::oracleversion; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'urlpath:s' => { name => 'url_path', default => "/easportal/tools/nagios/checkoracleversion.jsp" }, 'datasource:s' => { name => 'datasource' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{datasource}) || $self->{option_results}->{datasource} eq "") { $self->{output}->add_option_msg(short_msg => "Missing datasource name."); $self->{output}->option_exit(); } $self->{option_results}->{url_path} .= "?ds=" . $self->{option_results}->{datasource}; } sub run { my ($self, %options) = @_; my $webcontent = $options{custom}->request(path => $self->{option_results}->{url_path}); if ($webcontent !~ /^BANNER=/i) { $self->{output}->add_option_msg(short_msg => 'Cannot find oracle version info.'); $self->{output}->option_exit(); } my $banner = ''; $banner = $1 if ($webcontent =~ /^BANNER=\'(.*?)\'/i); $self->{output}->output_add(severity => "ok", short_msg => $banner); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check oracle database version. =over 8 =item B<--urlpath> Set path to get status page. (Default: '/easportal/tools/nagios/checkoracleversion.jsp') =item B<--datasource> Specify the datasource name. =back =cut centreon-plugins-20220113/apps/kingdee/eas/mode/ormrpc.pm000066400000000000000000000157771417000230700231620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Author : CHEN JUN , aladdin.china@gmail.com package apps::kingdee::eas::mode::ormrpc; 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 => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ { label => 'threads-active', nlabel => 'ormrpc.threads.active.count', set => { key_values => [ { name => 'active_thread_count' } ], output_template => 'threads active: %s', perfdatas => [ { value => 'active_thread_count', template => '%s', min => 0 }, ], } }, { label => 'stubs', nlabel => 'ormrpc.stubs.count', display_ok => 0, set => { key_values => [ { name => 'stub_count' } ], output_template => 'stubs: %s', perfdatas => [ { value => 'stub_count', template => '%s', min => 0 }, ], } }, { label => 'proxies', nlabel => 'ormrpc.proxies.count', display_ok => 0, set => { key_values => [ { name => 'proxy_count' } ], output_template => 'proxies: %s', perfdatas => [ { value => 'proxy_count', template => '%s', min => 0 }, ], } }, { label => 'sessions-client', nlabel => 'ormrpc.sessions.client.count', set => { key_values => [ { name => 'client_session_count' } ], output_template => 'sessions client: %s', perfdatas => [ { value => 'client_session_count', template => '%s', min => 0 }, ], } }, { label => 'sessions-server', nlabel => 'ormrpc.sessions.server.count', set => { key_values => [ { name => 'server_session_count' } ], output_template => 'sessions server: %s', perfdatas => [ { value => 'server_session_count', template => '%s', min => 0 }, ], } }, { label => 'clients-invoke-perminute', nlabel => 'ormrpc.clients.invoked.countperminute', display_ok => 0, set => { key_values => [ { name => 'client_invoke_count_per_minute' } ], output_template => 'clients invoke: %s/m', perfdatas => [ { value => 'client_invoke_count_per_minute', template => '%s', min => 0, unit => '/m' }, ], } }, { label => 'processed-service-perminute', nlabel => 'ormrpc.processed.service.countperminute', display_ok => 0, set => { key_values => [ { name => 'processed_service_count_per_minute' } ], output_template => 'processed service: %s/m', perfdatas => [ { value => 'processed_service_count_per_minute', template => '%s', min => 0, unit => '/m' }, ], } }, { label => 'clients-invoked', nlabel => 'ormrpc.clients.invoked.count', display_ok => 0, set => { key_values => [ { name => 'client_invoke_count', diff => 1 } ], output_template => 'clients invoked: %s', perfdatas => [ { value => 'client_invoke_count', template => '%s', min => 0 }, ], } }, { label => 'processed-service', nlabel => 'ormrpc.processed.service.count', display_ok => 0, set => { key_values => [ { name => 'processed_service_count', diff => 1 } ], output_template => 'processed service: %s', perfdatas => [ { value => 'processed_service_count', template => '%s', min => 0 }, ], } }, ]; } sub prefix_global_output { my ($self, %options) = @_; return 'orm rpc '; } sub new { my ( $class, %options ) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options( arguments => { 'urlpath:s' => { name => 'url_path', default => "/easportal/tools/nagios/checkrpc.jsp" }, }); return $self; } sub manage_selection { my ($self, %options) = @_; my $webcontent = $options{custom}->request(path => $self->{option_results}->{url_path}); if ($webcontent !~ /ActiveThreadCount=\d+/i) { $self->{output}->add_option_msg(short_msg => 'Cannot find ormrpc status'); $self->{output}->option_exit(); } $self->{global} = {}; $self->{global}->{active_thread_count} = $1 if ($webcontent =~ /ActiveThreadCount=(\d+)/mi); $self->{global}->{stub_count} = $1 if ($webcontent =~ /StubCount=(\d+)/mi); $self->{global}->{proxy_count} = $1 if ($webcontent =~ /ProxyCount=(\d+)/mi); $self->{global}->{client_session_count} = $1 if ($webcontent =~ /ClientSessionCount=(\d+)/mi); $self->{global}->{server_session_count} = $1 if ($webcontent =~ /ServerSessionCount=(\d+)/mi); $self->{global}->{client_invoke_count_per_minute} = $1 if ($webcontent =~ /ClientInvokeCountPerMinute=(\d+)/mi); $self->{global}->{processed_service_count_per_minute} = $1 if ($webcontent =~ /ProcessedServiceCountPerMinute=(\d+)/mi); $self->{global}->{client_invoke_count} = $1 if ($webcontent =~ /ClientInvokeCount=(\d+)/mi); $self->{global}->{processed_service_count} = $1 if ($webcontent =~ /ProcessedServiceCount=(\d+)/mi); $self->{cache_name} = 'kingdee_' . $self->{mode} . '_' . $options{custom}->get_hostname() . '_' . $options{custom}->get_port() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check EAS instance orm rpc status. =over 8 =item B<--urlpath> Set path to get status page. (Default: '/easportal/tools/nagios/checkrpc.jsp') =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'threads-active', 'stubs', 'proxies', 'sessions-client', 'sessions-server', 'clients-invoke-perminute', 'processed-service-perminute', 'clients-invoked', 'processed-service'. =back =cut centreon-plugins-20220113/apps/kingdee/eas/mode/transaction.pm000066400000000000000000000144621417000230700241730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Author : CHEN JUN , aladdin.china@gmail.com package apps::kingdee::eas::mode::transaction; 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 => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ { label => 'active', nlabel => 'transactions.active.count', set => { key_values => [ { name => 'active_count' } ], output_template => 'active: %s', perfdatas => [ { value => 'active_count', template => '%s', min => 0 }, ], } }, { label => 'timedout', nlabel => 'transactions.timedout.count', display_ok => 0, set => { key_values => [ { name => 'timedout_count' } ], output_template => 'timed out: %s', perfdatas => [ { value => 'timedout_count', template => '%s', min => 0 }, ], } }, { label => 'committed', nlabel => 'transactions.committed.count', set => { key_values => [ { name => 'committed_count', diff => 1 } ], output_template => 'committed: %s', perfdatas => [ { value => 'committed_count', template => '%s', min => 0 }, ], } }, { label => 'rolledback', nlabel => 'transactions.rolledback.count', set => { key_values => [ { name => 'rolledback_count', diff => 1 } ], output_template => 'rolledback: %s', perfdatas => [ { value => 'rolledback_count', template => '%s', min => 0 }, ], } }, { label => 'created', nlabel => 'transactions.created.count', set => { key_values => [ { name => 'transaction_count', diff => 1 } ], output_template => 'created: %s', perfdatas => [ { value => 'transaction_count', template => '%s', min => 0 }, ], } }, { label => 'time-total', nlabel => 'transactions.time.total.milliseconds', set => { key_values => [ { name => 'total_transaction_time', diff => 1 } ], output_template => 'total time: %s ms', perfdatas => [ { value => 'total_transaction_time', template => '%s', min => 0, unit => 'ms' }, ], } }, { label => 'time-max', nlabel => 'transactions.time.max.milliseconds', display_ok => 0, set => { key_values => [ { name => 'max_transaction_time', diff => 1 } ], output_template => 'max time: %s ms', perfdatas => [ { value => 'max_transaction_time', template => '%s', min => 0, unit => 'ms' }, ], } }, { label => 'timeout-default', nlabel => 'transactions.timeout.default.count', display_ok => 0, set => { key_values => [ { name => 'default_timeout' } ], output_template => 'default timeout: %s', perfdatas => [ { value => 'default_timeout', template => '%s', min => 0 }, ], } }, ]; } sub prefix_global_output { my ($self, %options) = @_; return 'transactions '; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'urlpath:s' => { name => 'url_path', default => "/easportal/tools/nagios/checktransaction.jsp" }, }); return $self; } sub manage_selection { my ($self, %options) = @_; my $webcontent = $options{custom}->request(path => $self->{option_results}->{url_path}); if ($webcontent !~ /TransactionCount=\d+/i) { $self->{output}->add_option_msg(short_msg => 'Cannot find transaction status.'); $self->{output}->option_exit(); } $self->{global} = {}; $self->{global}->{transaction_count} = $1 if ($webcontent =~ /TransactionCount=(\d+)\s/i); $self->{global}->{total_transaction_time} = $1 if ($webcontent =~ /TotalTransactionTime=(\d+)\s/i); $self->{global}->{committed_count} = $1 if ($webcontent =~ /CommittedCount=(\d+)\s/i); $self->{global}->{rolledback_count} = $1 if ($webcontent =~ /RolledbackCount=(\d+)\s/i); $self->{global}->{active_count} = $1 if ($webcontent =~ /ActiveCount=(\d+)\s/i); $self->{global}->{max_transaction_time} = $1 if ($webcontent =~ /MaxTransactionTime=(\d+)\s/i); $self->{global}->{default_timeout} = $1 if ($webcontent =~ /DefaultTimeout=(\d+)\s/i); $self->{global}->{timedout_count} = $1 if ($webcontent =~ /TimedOutCount=(\d+)\s/i); $self->{cache_name} = 'kingdee_' . $self->{mode} . '_' . $options{custom}->get_hostname() . '_' . $options{custom}->get_port() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check EAS application EJB transaction status. =over 8 =item B<--urlpath> Set path to get status page. (Default: '/easportal/tools/nagios/checktransaction.jsp') =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'active', 'timedout', 'committed', 'rolledback', 'created', 'time-total', 'time-max', 'timeout-default'. =back =cut centreon-plugins-20220113/apps/kingdee/eas/plugin.pm000066400000000000000000000045721417000230700222210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::kingdee::eas::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} = '1.0'; %{$self->{modes}} = ( 'classloading' => 'apps::kingdee::eas::mode::classloading', 'memory' => 'apps::kingdee::eas::mode::memory', 'javaruntime' => 'apps::kingdee::eas::mode::javaruntime', 'datasource' => 'apps::kingdee::eas::mode::datasource', 'handlers' => 'apps::kingdee::eas::mode::handlers', 'transaction' => 'apps::kingdee::eas::mode::transaction', 'oraclejvmgc' => 'apps::kingdee::eas::mode::oraclejvmgc', 'ibmjvmgc' => 'apps::kingdee::eas::mode::ibmjvmgc', 'ormrpc' => 'apps::kingdee::eas::mode::ormrpc', 'activeusers' => 'apps::kingdee::eas::mode::activeusers', 'oracleversion' => 'apps::kingdee::eas::mode::oracleversion', 'oraclesession' => 'apps::kingdee::eas::mode::oraclesession', 'oracletable' => 'apps::kingdee::eas::mode::oracletable', 'oraclerecyclebin' => 'apps::kingdee::eas::mode::oraclerecyclebin', 'oracleksqltemptable' => 'apps::kingdee::eas::mode::oracleksqltemptable', 'oracleredolog' => 'apps::kingdee::eas::mode::oracleredolog' ); $self->{custom_modes}{api} = 'apps::kingdee::eas::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Kingdee EAS Application & DB Server Status . =cut centreon-plugins-20220113/apps/lmsensors/000077500000000000000000000000001417000230700202245ustar00rootroot00000000000000centreon-plugins-20220113/apps/lmsensors/snmp/000077500000000000000000000000001417000230700212015ustar00rootroot00000000000000centreon-plugins-20220113/apps/lmsensors/snmp/mode/000077500000000000000000000000001417000230700221255ustar00rootroot00000000000000centreon-plugins-20220113/apps/lmsensors/snmp/mode/components/000077500000000000000000000000001417000230700243125ustar00rootroot00000000000000centreon-plugins-20220113/apps/lmsensors/snmp/mode/components/fan.pm000066400000000000000000000057441417000230700254260ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::lmsensors::snmp::mode::components::fan; use strict; use warnings; my $mapping = { lmFanSensorsDevice => { oid => '.1.3.6.1.4.1.2021.13.16.3.1.2' }, lmFanSensorsValue => { oid => '.1.3.6.1.4.1.2021.13.16.3.1.3' }, }; my $oid_lmFanSensorsEntry = '.1.3.6.1.4.1.2021.13.16.3.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_lmFanSensorsEntry }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking fans"); $self->{components}->{fan} = {name => 'fans', total => 0, skip => 0}; return if ($self->check_filter(section => 'fan')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_lmFanSensorsEntry}})) { next if ($oid !~ /^$mapping->{lmFanSensorsValue}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_lmFanSensorsEntry}, instance => $instance); next if ($self->check_filter(section => 'fan', instance => $instance, name => $result->{lmFanSensorsDevice})); $self->{components}->{fan}->{total}++; $self->{output}->output_add(long_msg => sprintf("fan '%s' speed is %s rpm [instance = %s]", $result->{lmFanSensorsDevice}, $result->{lmFanSensorsValue}, $instance, )); my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'fan', instance => $instance, name => $result->{lmFanSensorsDevice}, value => $result->{lmFanSensorsValue}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Fan '%s' speed is %s rpm", $result->{lmFanSensorsDevice}, $result->{lmFanSensorsValue})); } $self->{output}->perfdata_add( label => 'fan', unit => 'rpm', nlabel => 'sensor.fan.speed.rpm', instances => $result->{lmFanSensorsDevice}, value => $result->{lmFanSensorsValue}, warning => $warn, critical => $crit, min => 0, ); } } 1; centreon-plugins-20220113/apps/lmsensors/snmp/mode/components/misc.pm000066400000000000000000000057451417000230700256160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::lmsensors::snmp::mode::components::misc; use strict; use warnings; my $mapping = { lmMiscSensorsDevice => { oid => '.1.3.6.1.4.1.2021.13.16.5.1.2' }, lmMiscSensorsValue => { oid => '.1.3.6.1.4.1.2021.13.16.5.1.3' }, }; my $oid_lmMiscSensorsEntry = '.1.3.6.1.4.1.2021.13.16.5.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_lmMiscSensorsEntry }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking misc"); $self->{components}->{misc} = {name => 'misc', total => 0, skip => 0}; return if ($self->check_filter(section => 'misc')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_lmMiscSensorsEntry}})) { next if ($oid !~ /^$mapping->{lmMiscSensorsValue}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_lmMiscSensorsEntry}, instance => $instance); next if ($self->check_filter(section => 'misc', instance => $instance, name => $result->{lmMiscSensorsDevice})); $self->{components}->{misc}->{total}++; $self->{output}->output_add(long_msg => sprintf("misc '%s' values is %s [instance = %s]", $result->{lmMiscSensorsDevice}, $result->{lmMiscSensorsValue}, $instance, )); my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'misc', instance => $instance, name => $result->{lmMiscSensorsDevice}, value => $result->{lmMiscSensorsValue}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Misc '%s' value is %s", $result->{lmMiscSensorsDevice}, $result->{lmMiscSensorsValue})); } $self->{output}->perfdata_add( label => 'misc',, nlabel => 'sensor.misc.current', instances => $result->{lmMiscSensorsDevice}, value => $result->{lmMiscSensorsValue}, warning => $warn, critical => $crit, min => 0, ); } } 1; centreon-plugins-20220113/apps/lmsensors/snmp/mode/components/temperature.pm000066400000000000000000000061271417000230700272130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::lmsensors::snmp::mode::components::temperature; use strict; use warnings; my $mapping = { lmTempSensorsDevice => { oid => '.1.3.6.1.4.1.2021.13.16.2.1.2' }, lmTempSensorsValue => { oid => '.1.3.6.1.4.1.2021.13.16.2.1.3' }, }; my $oid_lmTempSensorsEntry = '.1.3.6.1.4.1.2021.13.16.2.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_lmTempSensorsEntry }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking temperatures"); $self->{components}->{temperature} = {name => 'temperatures', total => 0, skip => 0}; return if ($self->check_filter(section => 'temperature')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_lmTempSensorsEntry}})) { next if ($oid !~ /^$mapping->{lmTempSensorsValue}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_lmTempSensorsEntry}, instance => $instance); next if ($self->check_filter(section => 'temperature', instance => $instance, name => $result->{lmTempSensorsDevice})); $self->{components}->{temperature}->{total}++; $result->{lmTempSensorsValue} /= 1000; $self->{output}->output_add(long_msg => sprintf("temperature '%s' is %s C [instance = %s]", $result->{lmTempSensorsDevice}, $result->{lmTempSensorsValue}, $instance, )); my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $instance, name => $result->{lmTempSensorsDevice}, value => $result->{lmTempSensorsValue}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Temperature '%s' is %s C", $result->{lmTempSensorsDevice}, $result->{lmTempSensorsValue})); } $self->{output}->perfdata_add( label => 'temperature', unit => 'C', nlabel => 'sensor.temperature.celsius', instances => $result->{lmTempSensorsDevice}, value => $result->{lmTempSensorsValue}, warning => $warn, critical => $crit, ); } } 1; centreon-plugins-20220113/apps/lmsensors/snmp/mode/components/voltage.pm000066400000000000000000000060441417000230700263150ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::lmsensors::snmp::mode::components::voltage; use strict; use warnings; my $mapping = { lmVoltSensorsDevice => { oid => '.1.3.6.1.4.1.2021.13.16.4.1.2' }, lmVoltSensorsValue => { oid => '.1.3.6.1.4.1.2021.13.16.4.1.3' }, }; my $oid_lmVoltSensorsEntry = '.1.3.6.1.4.1.2021.13.16.4.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_lmVoltSensorsEntry }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking voltages"); $self->{components}->{voltage} = {name => 'voltages', total => 0, skip => 0}; return if ($self->check_filter(section => 'voltage')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_lmVoltSensorsEntry}})) { next if ($oid !~ /^$mapping->{lmVoltSensorsValue}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_lmVoltSensorsEntry}, instance => $instance); next if ($self->check_filter(section => 'voltage', instance => $instance, name => $result->{lmVoltSensorsDevice})); $self->{components}->{voltage}->{total}++; $result->{lmVoltSensorsValue} /= 1000; $self->{output}->output_add(long_msg => sprintf("voltage '%s' is %s V [instance = %s]", $result->{lmVoltSensorsDevice}, $result->{lmVoltSensorsValue}, $instance, )); my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'voltage', instance => $instance, name => $result->{lmVoltSensorsDevice}, value => $result->{lmVoltSensorsValue}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Voltage '%s' is %s V", $result->{lmVoltSensorsDevice}, $result->{lmVoltSensorsValue})); } $self->{output}->perfdata_add( label => 'voltage', unit => 'V', nlabel => 'sensor.voltage.volt', instances => $result->{lmVoltSensorsDevice}, value => $result->{lmVoltSensorsValue}, warning => $warn, critical => $crit, ); } } 1; centreon-plugins-20220113/apps/lmsensors/snmp/mode/sensors.pm000066400000000000000000000046671417000230700241740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::lmsensors::snmp::mode::sensors; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^(temperature|fan|voltage|misc)$'; $self->{cb_hook1} = 'get_version'; # before the loads $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { }; $self->{components_path} = 'apps::lmsensors::snmp::mode::components'; $self->{components_module} = ['fan', 'temperature', 'voltage', 'misc']; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $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, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } 1; __END__ =head1 MODE Check components. =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'fan', 'voltage', 'temperature', 'misc'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=fan --filter=power) Can also exclude specific instance: --filter=power,3.3 =item B<--no-component> Return an error if no compenents are checked. If total (with skipped) is 0. (Default: 'critical' returns). =item B<--warning> Set warning threshold (syntax: type,instance,threshold) Example: --warning='temperature,.*,20' =item B<--critical> Set critical threshold (syntax: type,instance,threshold) Example: --critical='temperature,1,25' =back =cut centreon-plugins-20220113/apps/lmsensors/snmp/plugin.pm000066400000000000000000000023171417000230700230400ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::lmsensors::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}} = ( 'sensors' => 'apps::lmsensors::snmp::mode::sensors', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check with SNMP LM-Sensors =cut centreon-plugins-20220113/apps/lotus/000077500000000000000000000000001417000230700173455ustar00rootroot00000000000000centreon-plugins-20220113/apps/lotus/snmp/000077500000000000000000000000001417000230700203225ustar00rootroot00000000000000centreon-plugins-20220113/apps/lotus/snmp/mode/000077500000000000000000000000001417000230700212465ustar00rootroot00000000000000centreon-plugins-20220113/apps/lotus/snmp/mode/mailstate.pm000066400000000000000000000130011417000230700235620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::lotus::snmp::mode::mailstate; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning-waiting:s" => { name => 'warning_waiting', }, "critical-waiting:s" => { name => 'critical_waiting', }, "warning-dead:s" => { name => 'warning_dead', }, "critical-dead:s" => { name => 'critical_dead', }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (($self->{perfdata}->threshold_validate(label => 'warning-waiting', value => $self->{option_results}->{warning_waiting})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning-waiting threshold '" . $self->{option_results}->{warning_waiting} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'critical-waiting', value => $self->{option_results}->{critical_waiting})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical-waiting threshold '" . $self->{option_results}->{critical_waiting} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'warning-dead', value => $self->{option_results}->{warning_dead})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning-dead threshold '" . $self->{option_results}->{warning_dead} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'critical-dead', value => $self->{option_results}->{critical_dead})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical-dead threshold '" . $self->{option_results}->{critical_dead} . "'."); $self->{output}->option_exit(); } } sub run { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; my $oid_lnDeadMail = '.1.3.6.1.4.1.334.72.1.1.4.1.0'; # my $oid_DeliveredMail = '.1.3.6.1.4.1.334.72.1.1.4.2.0'; # my $oid_TransferredMail = '.1.3.6.1.4.1.334.72.1.1.4.5.0'; my $oid_lnWaitingMail = '.1.3.6.1.4.1.334.72.1.1.4.6.0'; my $results = $self->{snmp}->get_leef(oids => [$oid_lnDeadMail, $oid_lnWaitingMail], nothing_quit => 1); # my $delivered = $self->{snmp}->get_leef(oid => $oid_DeliveredMail, nothing_quit => 1); # my $transferred = $self->{snmp}->get_leef(oid => $oid_TransferredMail, nothing_quit => 1); my $exit1 = $self->{perfdata}->threshold_check(value => $results->{$oid_lnDeadMail}, threshold => [ { label => 'critical-dead', 'exit_litteral' => 'critical' }, { label => 'warning-dead', exit_litteral => 'warning' } ]); my $exit2 = $self->{perfdata}->threshold_check(value => $results->{$oid_lnWaitingMail}, threshold => [ { label => 'critical-waiting', 'exit_litteral' => 'critical' }, { label => 'warning-waiting', exit_litteral => 'warning' } ]); my $exit_code = $self->{output}->get_most_critical(status => [ $exit1, $exit2 ]); $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("Number of dead mail: %d Number of waiting mail: %d", $results->{$oid_lnDeadMail}, $results->{$oid_lnWaitingMail})); $self->{output}->perfdata_add(label => 'dead', unit => 'mail', value => $results->{$oid_lnDeadMail}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-dead'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-dead'), ); $self->{output}->perfdata_add(label => 'waiting', unit => 'mail', value => $results->{$oid_lnWaitingMail}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-waiting'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-waiting'), ); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check the number of dead and wainting mail on the lotus server (NOTES-MIB.mib) =over 8 =item B<--warning-dead> Threshold warning in percent. =item B<--critical-dead> Threshold critical in percent. =item B<--warning-waiting> Threshold warning in percent. =item B<--critical-waiting> Threshold critical in percent. =back =cut centreon-plugins-20220113/apps/lotus/snmp/mode/mailtime.pm000066400000000000000000000077611417000230700234200ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::lotus::snmp::mode::mailtime; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "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) = @_; $self->{snmp} = $options{snmp}; my $oid_lnAverageMailDeliverTime = '.1.3.6.1.4.1.334.72.1.1.4.9.0'; my $oid_lnMaximumMailDeliverTime = '.1.3.6.1.4.1.334.72.1.1.4.12.0'; my $oid_lnMinimumMailDeliverTime = '.1.3.6.1.4.1.334.72.1.1.4.15.0'; my $results = $self->{snmp}->get_leef(oids => [$oid_lnMinimumMailDeliverTime, $oid_lnMaximumMailDeliverTime, $oid_lnAverageMailDeliverTime], nothing_quit => 1); my $exit_code = $self->{perfdata}->threshold_check(value => $results->{$oid_lnAverageMailDeliverTime}, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("Average seconds to deliver mail: %.2f (Min : %.2f) (Max : %.2f)", $results->{$oid_lnAverageMailDeliverTime}, $results->{$oid_lnMinimumMailDeliverTime}, $results->{$oid_lnMaximumMailDeliverTime})); $self->{output}->perfdata_add(label => 'avgTime', unit => 's', value => $results->{$oid_lnAverageMailDeliverTime}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical')); $self->{output}->perfdata_add(label => 'minTime', unit => 's', value => $results->{$oid_lnMinimumMailDeliverTime}); $self->{output}->perfdata_add(label => 'maxTime', unit => 's', value => $results->{$oid_lnMaximumMailDeliverTime}); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check the mail average delivery time (print min and max for info)(NOTES-MIB.mib) =over 8 =item B<--warning> Threshold warning in seconds. =item B<--critical> Threshold critical in seconds. =back =cut centreon-plugins-20220113/apps/lotus/snmp/mode/serveravailability.pm000066400000000000000000000066051417000230700255140ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::lotus::snmp::mode::serveravailability; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "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) = @_; $self->{snmp} = $options{snmp}; my $oid_lnServerAvailabilityIndex = '.1.3.6.1.4.1.334.72.1.1.6.3.19.0'; my $availability = $self->{snmp}->get_leef(oids => [$oid_lnServerAvailabilityIndex], nothing_quit => 1); my $exit_code = $self->{perfdata}->threshold_check(value => $availability->{$oid_lnServerAvailabilityIndex}, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("Lotus Note Server Ressources Availability is %.2f%%", $availability->{$oid_lnServerAvailabilityIndex})); $self->{output}->perfdata_add(label => 'availability', unit => '%', value => $availability->{$oid_lnServerAvailabilityIndex}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0, max => 100); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check the mail server global availability percentage (NOTES-MIB.mib) =over 8 =item B<--warning> Threshold warning in percent. =item B<--critical> Threshold critical in percent. =back =cut centreon-plugins-20220113/apps/lotus/snmp/mode/servertransactions.pm000066400000000000000000000066701417000230700255540ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::lotus::snmp::mode::servertransactions; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "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) = @_; $self->{snmp} = $options{snmp}; my $oid_lnServerTransPerMin = '.1.3.6.1.4.1.334.72.1.1.6.3.2.0'; my $transactions = $self->{snmp}->get_leef(oids => [$oid_lnServerTransPerMin], nothing_quit => 1); my $exit_code = $self->{perfdata}->threshold_check(value => $transactions->{$oid_lnServerTransPerMin}, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("%d transactions/minutes (average)", $transactions->{$oid_lnServerTransPerMin})); $self->{output}->perfdata_add(label => 'srv_transactions', unit => 'tr', value => $transactions->{$oid_lnServerTransPerMin}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), ); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check the avg number of transactions per minute since the server was started (NOTES-MIB.mib) =over 8 =item B<--warning> Threshold warning in number of transactions per minutes. =item B<--critical> Threshold critical in number of transactions per minute. =back =cut centreon-plugins-20220113/apps/lotus/snmp/mode/usersessions.pm000066400000000000000000000064161417000230700243600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::lotus::snmp::mode::usersessions; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "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) = @_; $self->{snmp} = $options{snmp}; my $oid_lnServerUsers = '.1.3.6.1.4.1.334.72.1.1.6.3.6.0'; my $users = $self->{snmp}->get_leef(oids => [$oid_lnServerUsers], nothing_quit => 1); my $exit_code = $self->{perfdata}->threshold_check(value => $users->{$oid_lnServerUsers}, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("Number of open users sessions: %d", $users->{$oid_lnServerUsers})); $self->{output}->perfdata_add(label => 'users', unit => 'users', value => $users->{$oid_lnServerUsers}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), ); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check the number of user connections (NOTES-MIB.mib) =over 8 =item B<--warning> Threshold warning in users. =item B<--critical> Threshold critical in users. =back =cut centreon-plugins-20220113/apps/lotus/snmp/plugin.pm000066400000000000000000000030141417000230700221540ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::lotus::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}} = ( 'mail-state' => 'apps::lotus::snmp::mode::mailstate', 'mail-time' => 'apps::lotus::snmp::mode::mailtime', 'server-availability' => 'apps::lotus::snmp::mode::serveravailability', 'server-transactions' => 'apps::lotus::snmp::mode::servertransactions', 'user-sessions' => 'apps::lotus::snmp::mode::usersessions', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check IBM Lotus Mail Server in SNMP. =cut centreon-plugins-20220113/apps/lync/000077500000000000000000000000001417000230700171445ustar00rootroot00000000000000centreon-plugins-20220113/apps/lync/2013/000077500000000000000000000000001417000230700175315ustar00rootroot00000000000000centreon-plugins-20220113/apps/lync/2013/mssql/000077500000000000000000000000001417000230700206705ustar00rootroot00000000000000centreon-plugins-20220113/apps/lync/2013/mssql/mode/000077500000000000000000000000001417000230700216145ustar00rootroot00000000000000centreon-plugins-20220113/apps/lync/2013/mssql/mode/lyncusers.pm000066400000000000000000000062201417000230700242010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::lync::2013::mssql::mode::lyncusers; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_user_output { my ($self, %options) = @_; return "'Frontend' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'users', type => 0, cb_prefix_output => 'prefix_user_output' } ]; $self->{maps_counters}->{users} = [ { label => 'total', nlabel => 'users.total.count', set => { key_values => [ { name => 'total' } ], output_template => '%d total users', perfdatas => [ { label => 'total_users', template => '%d', unit => 'users', min => 0 } ] } }, { label => 'unique', nlabel => 'users.unique.count', set => { key_values => [ { name => 'unique' } ], output_template => '%d unique users', perfdatas => [ { label => 'unique_users', template => '%d', unit => 'users', min => 0 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); $options{sql}->query(query => q{ Select count(*) as totalonline, count(distinct UserAtHost) as totalunique From rtcdyn.dbo.RegistrarEndpoint RE Inner Join rtc.dbo.Resource R on R.ResourceId = RE.OwnerId Inner Join rtcdyn.dbo.Registrar Reg on Reg.RegistrarId = RE.PrimaryRegistrarClusterId }); my ($total_online, $total_unique) = $options{sql}->fetchrow_array(); $self->{users} = { total => $total_online, unique => $total_unique }; } 1; __END__ =head1 MODE Check Lync Users Total and Unique. Query your RTCLocal Lync Frontend Dabatase (Get instance port in SQL Server configuration if dynamic mode) =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). =item B<--warning-*> Set warning threshold for number of user. Can be : 'total', 'unique' =item B<--critical-*> Set critical threshold for number of user. Can be : 'total', 'unique' =back =cut centreon-plugins-20220113/apps/microsoft/000077500000000000000000000000001417000230700202045ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/activedirectory/000077500000000000000000000000001417000230700234045ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/activedirectory/local/000077500000000000000000000000001417000230700244765ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/activedirectory/local/conf/000077500000000000000000000000001417000230700254235ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/activedirectory/local/conf/dcdiag.xml000066400000000000000000000007771417000230700273730ustar00rootroot00000000000000 Starting test.*?:\s+(.*?)\n.*?(passed|warning|failed) passed warning failed D.*?marrage du test.*?:\s+(.*?)\n.*?(a r.*?ussi|a .*?chou.|warning) a r.*?ussi warning a .*?chou. centreon-plugins-20220113/apps/microsoft/activedirectory/local/mode/000077500000000000000000000000001417000230700254225ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/activedirectory/local/mode/dcdiag.pm000066400000000000000000000167241417000230700272050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::activedirectory::local::mode::dcdiag; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::misc; use File::Basename; use XML::Simple; use Win32; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'config:s' => { name => 'config' }, 'language:s' => { name => 'language', default => 'en' }, 'dfsr' => { name => 'dfsr' }, 'noeventlog' => { name => 'noeventlog' }, 'nomachineaccount' => { name => 'nomachineaccount' }, 'timeout:s' => { name => 'timeout', default => 30 } }); $self->{os_is2003} = 0; $self->{os_is2008} = 0; $self->{os_is2012} = 0; $self->{os_is2016} = 0; return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub check_version { my ($self, %options) = @_; our ($ver_string, $ver_major, $ver_minor, $ver_build, $ver_id) = Win32::GetOSVersion(); #"Operating system is " . "$ver_string - ($ver_id.$ver_major.$ver_minor.$ver_build)\n"; # 5.1, 5.2 => XP/2003 # 6.0, 6.1 => Vista/7/2008 # 6.2, 6.3 => 2012 # 10.0 => 2016, 2019 if ($ver_major == 5 && ($ver_minor == 1 || $ver_minor == 2)) { $self->{os_is2003} = 1; } elsif ($ver_major == 6 && ($ver_minor == 0 || $ver_minor == 1)) { $self->{os_is2008} = 1; } elsif ($ver_major == 6 && ($ver_minor == 2 || $ver_minor == 3)) { $self->{os_is2012} = 1; } elsif ($ver_major == 10 && $ver_minor == 0) { $self->{os_is2016} = 1; } else { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => 'OS version ' . $ver_major . '.' . $ver_minor . ' not managed.' ); return 1; } return 0; } sub read_config { my ($self, %options) = @_; my $content_file = <<'END_FILE'; Starting test.*?:\s+(.*?)\n.*?(passed|warning|failed) passed warning failed D.*?marrage du test.*?:\s+(.*?)\n.*?(a r.*?ussi|a .*?chou.|warning) a r.*?ussi warning a .*?chou. END_FILE if (defined($self->{option_results}->{config}) && $self->{option_results}->{config} ne '') { $content_file = do { local $/ = undef; if (!open my $fh, "<", $self->{option_results}->{config}) { $self->{output}->add_option_msg(short_msg => "Could not open file $self->{option_results}->{config} : $!"); $self->{output}->option_exit(); } <$fh>; }; } my $content; eval { $content = XMLin($content_file, ForceArray => ['dcdiag'], KeyAttr => ['language']); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode xml response: $@"); $self->{output}->option_exit(); } if (!defined($content->{dcdiag}->{$self->{option_results}->{language}})) { $self->{output}->add_option_msg(short_msg => "Cannot find language '$self->{option_results}->{language}' in config file"); $self->{output}->option_exit(); } return $content->{dcdiag}->{ $self->{option_results}->{language} }; } sub dcdiag { my ($self, %options) = @_; my $dcdiag_cmd = 'dcdiag /test:services /test:replications /test:advertising /test:fsmocheck /test:ridmanager'; $dcdiag_cmd .= ' /test:machineaccount' if (!defined($self->{option_results}->{nomachineaccount})); $dcdiag_cmd .= ' /test:frssysvol' if ($self->{os_is2003} == 1); $dcdiag_cmd .= ' /test:sysvolcheck' if ($self->{os_is2008} == 1 || $self->{os_is2012} == 1 || $self->{os_is2016} == 1); if (!defined($self->{option_results}->{noeventlog})) { $dcdiag_cmd .= ' /test:frsevent /test:kccevent' if ($self->{os_is2003} == 1); $dcdiag_cmd .= ' /test:frsevent /test:kccevent' if (($self->{os_is2008} == 1 || $self->{os_is2012} == 1 || $self->{os_is2016} == 1) && !defined($self->{option_results}->{dfsr})); $dcdiag_cmd .= ' /test:dfsrevent /test:kccevent' if (($self->{os_is2008} == 1 || $self->{os_is2012} == 1 || $self->{os_is2016} == 1) && defined($self->{option_results}->{dfsr})); } my ($stdout) = centreon::plugins::misc::windows_execute( output => $self->{output}, timeout => $self->{option_results}->{timeout}, command => $dcdiag_cmd, command_path => undef, command_options => undef ); my $match = 0; while ($stdout =~ /$options{config}->{messages}->{global}/imsg) { my ($test_name, $pattern) = ($1, lc($2)); if ($pattern =~ /$options{config}->{messages}->{ok}/i) { $match = 1; $self->{output}->output_add( severity => 'OK', short_msg => $test_name ); } elsif ($pattern =~ /$options{config}->{messages}->{critical}/i) { $match = 1; $self->{output}->output_add( severity => 'CRITICAL', short_msg => 'test ' . $test_name ); } elsif ($pattern =~ /$options{config}->{messages}->{warning}/i) { $match = 1; $self->{output}->output_add( severity => 'WARNING', short_msg => 'test ' . $test_name ); } } if ($match == 0) { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => 'Cannot match output test (maybe you need to set the good language)' ); return 1; } return 0; } sub run { my ($self, %options) = @_; my $config = $self->read_config(); if ($self->check_version() == 0) { $self->dcdiag(config => $config); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check Windows Active Directory Health (use 'dcdiag' command). =over 8 =item B<--config> command can be localized by using a configuration file. This parameter can be used to specify an alternative location for the configuration file =item B<--language> Set the language used in config file (default: 'en'). =item B<--dfsr> Specifies that SysVol replication uses DFS instead of FRS (Windows 2008 or later) =item B<--noeventlog> Don't run the dc tests kccevent, frsevent and dfsrevent =item B<--nomachineaccount> Don't run the dc tests machineaccount =item B<--timeout> Set timeout time for command execution (Default: 30 sec) =back =cut centreon-plugins-20220113/apps/microsoft/activedirectory/local/mode/dfsrbacklog.pm000066400000000000000000000112311417000230700302370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::activedirectory::local::mode::dfsrbacklog; 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 } ]; $self->{maps_counters}->{global} = [ { label => 'backlog', nlabel => 'backlog.file.count', set => { key_values => [ { name => 'backlog' } ], output_template => 'Backlog File Count : %s', perfdatas => [ { label => 'backlog', template => '%s', min => 0 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'sending-member:s' => { name => 'sending_member' }, 'receiving-member:s' => { name => 'receiving_member' }, 'replication-group:s' => { name => 'replication_group' }, 'replicated-folder:s' => { name => 'replicated_folder' }, 'timeout:s' => { name => 'timeout', default => 30 } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{option_results}->{command} = 'dfsrdiag'; $self->{option_results}->{command_options} = 'backlog '; if (!defined($self->{option_results}->{sending_member}) || $self->{option_results}->{sending_member} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify sending-member option.'); $self->{output}->option_exit(); } $self->{option_results}->{command_options} .= '/SendingMember:"' . $self->{option_results}->{sending_member} . '" '; if (defined($self->{option_results}->{receiving_member}) && $self->{option_results}->{receiving_member} ne '') { $self->{option_results}->{command_options} .= '/ReceivingMember:"' . $self->{option_results}->{receiving_member} . '" '; } if (!defined($self->{option_results}->{replication_group}) || $self->{option_results}->{replication_group} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify replication-group option.'); $self->{output}->option_exit(); } $self->{option_results}->{command_options} .= '/RGName:"' . $self->{option_results}->{replication_group} . '" '; if (!defined($self->{option_results}->{replicated_folder}) || $self->{option_results}->{replicated_folder} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify replicated-folder option.'); $self->{output}->option_exit(); } $self->{option_results}->{command_options} .= '/RFName:"' . $self->{option_results}->{replicated_folder} . '" '; } sub manage_selection { my ($self, %options) = @_; my ($stdout) = centreon::plugins::misc::execute( output => $self->{output}, options => $self->{option_results}, command => $self->{option_results}->{command}, command_path => $self->{option_results}->{command_path}, command_options => $self->{option_results}->{command_options} ); my $backlog = 0; my $pattern = 'Backlog\s+File\s+Count\s*:\s+(\d+)'; $backlog = $1 if ($stdout =~ /$pattern/si); $self->{global} = { backlog => $backlog }; } 1; __END__ =head1 MODE Check dfsr backlog. =over 8 =item B<--sending-member> Name of the member that is sending the replication data. (Mandatory) =item B<--receiving-member> Name of the member that is receiving the replication data. (NOT Mandatory) =item B<--replication-group> Name for the replication group. (Mandatory) =item B<--replicated-folder> Name name for the replicated folder. (Mandatory) =item B<--timeout> Timeout in seconds for the command (Default: 30). =item B<--warning-backlog> Threshold warning. =item B<--critical-backlog> Threshold critical. =back =cut centreon-plugins-20220113/apps/microsoft/activedirectory/local/mode/netdom.pm000066400000000000000000000063451417000230700272560ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::activedirectory::local::mode::netdom; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::misc; use Win32; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'domain:s' => { name => 'domain' }, 'workstation:s' => { name => 'workstation' }, 'timeout:s' => { name => 'timeout', default => 30 } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub netdom { my ($self, %options) = @_; my $netdom_cmd = 'netdom verify '; $netdom_cmd .= ' /Domain:' . $self->{option_results}->{domain} if (defined($self->{option_results}->{domain}) && $self->{option_results}->{domain} ne ''); if (defined($self->{option_results}->{workstation})) { $netdom_cmd .= ' ' . $self->{option_results}->{workstation}; } else { $netdom_cmd .= ' ' . Win32::NodeName(); } my ($stdout, $exit_code) = centreon::plugins::misc::windows_execute(output => $self->{output}, timeout => $self->{option_results}->{timeout}, command => $netdom_cmd, command_path => undef, command_options => undef, no_quit => 1); $self->{output}->output_add(severity => 'OK', short_msg => 'Secure channel has been verified.'); if ($exit_code != 0) { $self->{output}->output_add(long_msg => $stdout); $self->{output}->output_add(severity => 'CRITICAL', short_msg => 'Secure channel had a problem (see additional info).'); } } sub run { my ($self, %options) = @_; $self->netdom(); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check the secure connection between a workstation and a domain controller (use 'netdom' command). =over 8 =item B<--workstation> Set the name of the workstation (Default: current hostname) =item B<--domain> Set the name of the domain (Default: current domain of the workstation) =item B<--timeout> Set timeout time for command execution (Default: 30 sec) =back =cut centreon-plugins-20220113/apps/microsoft/activedirectory/local/plugin.pm000066400000000000000000000026511417000230700263360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::activedirectory::local::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} = '0.1'; $self->{modes} = { 'dcdiag' => 'apps::microsoft::activedirectory::local::mode::dcdiag', 'dfsr-backlog' => 'apps::microsoft::activedirectory::local::mode::dfsrbacklog', 'netdom' => 'apps::microsoft::activedirectory::local::mode::netdom' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Windows ActiveDirectory locally. =cut centreon-plugins-20220113/apps/microsoft/activedirectory/wsman/000077500000000000000000000000001417000230700245315ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/activedirectory/wsman/conf/000077500000000000000000000000001417000230700254565ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/activedirectory/wsman/conf/dcdiag.xml000066400000000000000000000003521417000230700274130ustar00rootroot00000000000000 passed test\s+(.*) warning test\s+(.*) failed test\s+(.*) centreon-plugins-20220113/apps/microsoft/activedirectory/wsman/mode/000077500000000000000000000000001417000230700254555ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/activedirectory/wsman/mode/dcdiag.pm000066400000000000000000000204201417000230700272240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::activedirectory::wsman::mode::dcdiag; use base qw(centreon::plugins::mode); use strict; use warnings; use File::Basename; use XML::LibXML; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "config:s" => { name => 'config' }, "language:s" => { name => 'language', default => 'en' }, "dfsr" => { name => 'dfsr' }, "noeventlog" => { name => 'noeventlog' } }); $self->{os_is2003} = 0; $self->{os_is2008} = 0; $self->{os_is2012} = 0; $self->{msg} = {ok => undef, warning => undef, critical => undef}; return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (defined($self->{option_results}->{config})) { $self->{config_file} = $self->{option_results}->{config}; } else { $self->{config_file} = dirname(__FILE__) . '/../conf/dcdiag.xml'; } } sub check_version { my ($self, %options) = @_; $self->{result} = $self->{wsman}->execute_winshell_commands(commands => [{label => 'os_version', value => 'ver' }], keep_open => 1); if ($self->{result}->{os_version}->{exit_code} != 0) { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => 'Problem execution to get OS version (use verbose for more details)'); $self->{output}->output_add(long_msg => 'stderr: ' . $self->{result}->{os_version}->{stderr}) if (defined($self->{result}->{os_version}->{stderr})); $self->{output}->output_add(long_msg => 'stdout: ' . $self->{result}->{os_version}->{stdout}) if (defined($self->{result}->{os_version}->{stdout})); return 1; } if ($self->{result}->{os_version}->{stdout} !~ /(\d+\.\d+\.\d+)/) { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => 'Cannot find OS version in output'); return 1; } # 5.1, 5.2 => XP/2003 # 6.0, 6.1 => Vista/7/2008 # 6.2, 6.3 => 2012 my $os_version = $1; if ($os_version =~ /^(5\.1\.|5\.2\.)/) { $self->{os_is2003} = 1; } elsif ($os_version =~ /^(6\.0\.|6\.1\.)/) { $self->{os_is2008} = 1; } elsif ($os_version =~ /^(6\.2\.|6\.3\.)/) { $self->{os_is2012} = 1; } else { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => 'OS version ' . $os_version . ' not managed.'); return 1; } return 0; } sub load_xml { my ($self, %options) = @_; # Load XML File my $parser = XML::LibXML->new(); my $doc = $parser->parse_file($self->{config_file}); my $nodes = $doc->getElementsByTagName('dcdiag'); if ($nodes->size() == 0) { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => 'Cannot find a node in XML Config file'); return 1; } my $language_found = 0; foreach my $node ($nodes->get_nodelist()) { if ($node->getAttribute('language') eq $self->{option_results}->{language}) { $language_found = 1; my $messages_node = $node->getElementsByTagName('messages'); foreach my $node2 ($messages_node->get_nodelist()) { foreach my $element_msg ($node2->getChildrenByTagName('*')) { $self->{msg}->{$element_msg->nodeName} = $element_msg->textContent if (exists($self->{msg}->{$element_msg->nodeName})); } } last; } } if ($language_found == 0) { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => "Cannot found language '" . $self->{option_results}->{language} . "' in XML Config file"); return 1; } foreach my $label (keys %{$self->{msg}}) { if (!defined($self->{msg}->{$label})) { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => "Message '" . $label . "' for language '" . $self->{option_results}->{language} . "' not defined in XML Config file"); return 1; } } return 0; } sub dcdiag { my ($self, %options) = @_; my $dcdiag_cmd = 'dcdiag /test:services /test:replications /test:advertising /test:fsmocheck /test:ridmanager /test:machineaccount'; $dcdiag_cmd .= ' /test:frssysvol' if ($self->{os_is2003} == 1); $dcdiag_cmd .= ' /test:sysvolcheck' if ($self->{os_is2008} == 1 || $self->{os_is2012} == 1); if (!defined($self->{option_results}->{noeventlog})) { $dcdiag_cmd .= ' /test:frsevent /test:kccevent' if ($self->{os_is2003} == 1); $dcdiag_cmd .= ' /test:frsevent /test:kccevent' if (($self->{os_is2008} == 1 || $self->{os_is2012} == 1) && !defined($self->{option_results}->{dfsr})); $dcdiag_cmd .= ' /test:dfsrevent /test:kccevent' if (($self->{os_is2008} == 1 || $self->{os_is2012} == 1) && defined($self->{option_results}->{dfsr})); } $self->{result} = $self->{wsman}->execute_winshell_commands(commands => [{label => 'dcdiag', value => $dcdiag_cmd }]); if ($self->{result}->{dcdiag}->{exit_code} != 0) { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => 'Problem execution of dcdiag (use verbose for more details)'); $self->{output}->output_add(long_msg => 'stderr: ' . $self->{result}->{dcdiag}->{stderr}) if (defined($self->{result}->{dcdiag}->{stderr})); $self->{output}->output_add(long_msg => 'stdout: ' . $self->{result}->{dcdiag}->{stdout}) if (defined($self->{result}->{dcdiag}->{stdout})); return 1; } my $match = 0; foreach my $line (split /\n/, $self->{result}->{os_version}->{stdout}) { if ($line =~ /$self->{msg}->{ok}/) { $match = 1; $self->{output}->output_add(severity => 'OK', short_msg => $1); } elsif ($line =~ /$self->{msg}->{critical}/) { $match = 1; $self->{output}->output_add(severity => 'CRITICAL', short_msg => 'test ' . $1); } elsif ($line =~ /$self->{msg}->{warning}/) { $match = 1; $self->{output}->output_add(severity => 'WARNING', short_msg => 'test ' . $1); } } if ($match == 0) { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => 'Cannot match output test (maybe you need to set the good language)'); return 1; } return 0; } sub run { my ($self, %options) = @_; # $options{wsman} = wsman object $self->{wsman} = $options{wsman}; if ($self->load_xml() == 0 && $self->check_version() == 0) { $self->dcdiag(); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check Windows Active Directory Health (use 'dcdiag' command). =over 8 =item B<--config> command can be localized by using a configuration file. This parameter can be used to specify an alternative location for the configuration file =item B<--language> Set the language used in config file (default: 'en'). =item B<--dfsr> Specifies that SysVol replication uses DFS instead of FRS (Windows 2008 or later) =item B<--noeventlog> Don't run the dc tests kccevent, frsevent and dfsrevent =back =cut centreon-plugins-20220113/apps/microsoft/activedirectory/wsman/plugin.pm000066400000000000000000000024341417000230700263700ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::activedirectory::wsman::plugin; use strict; use warnings; use base qw(centreon::plugins::script_wsman); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $self->{version} = '0.1'; %{$self->{modes}} = ( 'dcdiag' => 'apps::microsoft::activedirectory::wsman::mode::dcdiag', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Windows ActiveDirectory through "WinRM" (ws-management protocol). =cut centreon-plugins-20220113/apps/microsoft/dhcp/000077500000000000000000000000001417000230700211225ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/dhcp/snmp/000077500000000000000000000000001417000230700220775ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/dhcp/snmp/mode/000077500000000000000000000000001417000230700230235ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/dhcp/snmp/mode/listsubnets.pm000066400000000000000000000063241417000230700257450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::dhcp::snmp::mode::listsubnets; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } my $mapping = { address => { oid => '.1.3.6.1.4.1.311.1.3.2.1.1.1' }, # subnetAdd used => { oid => '.1.3.6.1.4.1.311.1.3.2.1.1.2' }, # noAddInUse free => { oid => '.1.3.6.1.4.1.311.1.3.2.1.1.3' }, # noAddFree pending_offers => { oid => '.1.3.6.1.4.1.311.1.3.2.1.1.4' } # noPendingOffers }; my $oid_scope_table = '.1.3.6.1.4.1.311.1.3.2.1.1'; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_table(oid => $oid_scope_table); my $results = {}; foreach (keys %$snmp_result) { next if (! /^$mapping->{address}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $1); my $status = 'enabled'; if ($result->{free} == 0 && $result->{used} == 0 && $result->{pending_offers} == 0) { $status = 'disabled'; } $results->{$instance} = { address => $result->{address}, status => $status }; } return $results; } sub run { my ($self, %options) = @_; my $results = $self->manage_selection(snmp => $options{snmp}); foreach (sort keys %$results) { $self->{output}->output_add(long_msg => sprintf( '[address: %s][status: %s]', $results->{$_}->{address}, $results->{$_}->{status} ) ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List subnets:' ); $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 => ['address', 'status']); } sub disco_show { my ($self, %options) = @_; my $results = $self->manage_selection(snmp => $options{snmp}); foreach (sort keys %$results) { $self->{output}->add_disco_entry(%{$results->{$_}}); } } 1; __END__ =head1 MODE List dhcp subnets. =over 8 =back =cut centreon-plugins-20220113/apps/microsoft/dhcp/snmp/mode/subnets.pm000066400000000000000000000170111417000230700250440ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::dhcp::snmp::mode::subnets; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf( 'status: %s', $self->{result_values}->{status} ); } sub custom_usage_output { my ($self, %options) = @_; return sprintf( 'addresses usage total: %s used: %s (%.2f%%) free: %s (%.2f%%)', $self->{result_values}->{total}, $self->{result_values}->{used}, $self->{result_values}->{prct_used}, $self->{result_values}->{free}, $self->{result_values}->{prct_free} ); } sub prefix_subnet_output { my ($self, %options) = @_; return sprintf( "Subnet '%s' ", $options{instance_value}->{name} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'subnets', type => 1, cb_prefix_output => 'prefix_subnet_output', message_multiple => 'All subnets are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{subnets} = [ { label => 'status', type => 2, set => { key_values => [ { name => 'status' }, { name => 'name' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'addresses-usage', nlabel => 'subnet.addresses.usage.count', set => { key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', cast_int => 1, label_extra_instance => 1 } ] } }, { label => 'addresses-usage-free', nlabel => 'subnet.addresses.free.count', display_ok => 0, set => { key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', cast_int => 1, label_extra_instance => 1 } ] } }, { label => 'addresses-usage-prct', nlabel => 'subnet.addresses.usage.percentage', display_ok => 0, set => { key_values => [ { name => 'prct_used' }, { name => 'used' }, { name => 'free' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 } ] } }, { label => 'pending-offers', nlabel => 'subnet.pending.offers.count', set => { key_values => [ { name => 'pending_offers' } ], output_template => 'pending offers: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-subnet-address:s' => { name => 'filter_subnet_address' } }); return $self; } my $mapping = { used => { oid => '.1.3.6.1.4.1.311.1.3.2.1.1.2' }, # noAddInUse free => { oid => '.1.3.6.1.4.1.311.1.3.2.1.1.3' }, # noAddFree pending_offers => { oid => '.1.3.6.1.4.1.311.1.3.2.1.1.4' } # noPendingOffers }; my $oid_subnetAdd = '.1.3.6.1.4.1.311.1.3.2.1.1.1'; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_table( oid => $oid_subnetAdd, nothing_quit => 1 ); $self->{subnets} = {}; foreach (keys %$snmp_result) { /^$oid_subnetAdd\.(.*)$/; my $instance = $1; if (defined($self->{option_results}->{filter_subnet_address}) && $self->{option_results}->{filter_subnet_address} ne '' && $snmp_result->{$_} !~ /$self->{option_results}->{filter_subnet_address}/) { $self->{output}->output_add(long_msg => "skipping '" . $snmp_result->{$_} . "': no matching 'org' filter.", debug => 1); next; } $self->{subnets}->{$instance} = { name => $snmp_result->{$_} }; } if (scalar(keys %{$self->{subnets}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No subnets found."); $self->{output}->option_exit(); } $options{snmp}->load( oids => [ map($_->{oid}, values(%$mapping)) ], instances => [keys %{$self->{subnets}}], instance_regexp => '^(.*)$' ); $snmp_result = $options{snmp}->get_leef(nothing_quit => 1); foreach (keys %{$self->{subnets}}) { my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $_); $self->{subnets}->{$_}->{status} = 'enabled'; if ($result->{free} == 0 && $result->{used} == 0 && $result->{pending_offers} == 0) { $self->{subnets}->{$_}->{status} = 'disabled'; next; } $self->{subnets}->{$_}->{pending_offers} = $result->{pending_offers}; $self->{subnets}->{$_}->{free} = $result->{free}; $self->{subnets}->{$_}->{used} = $result->{used}; $self->{subnets}->{$_}->{total} = $result->{used} + $result->{free}; $self->{subnets}->{$_}->{prct_used} = $result->{used} * 100 / ($result->{used} + $result->{free}); $self->{subnets}->{$_}->{prct_free} = $result->{free} * 100 / ($result->{used} + $result->{free}); } } 1; __END__ =head1 MODE Check dhcp subnets. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='pending' =item B<--filter-subnet-address> Filter subnets by address (can be a regexp). =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{status}, %{name} =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{status}, %{name} =item B<--critical-status> Set critical threshold for status. Can used special variables like: %{status}, %{name} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'addresses-usage', 'addresses-usage-free', 'addresses-usage-prct', 'pending-offers'. =back =cut centreon-plugins-20220113/apps/microsoft/dhcp/snmp/plugin.pm000066400000000000000000000024511417000230700237350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::dhcp::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} = { 'list-subnets' => 'apps::microsoft::dhcp::snmp::mode::listsubnets', 'subnets' => 'apps::microsoft::dhcp::snmp::mode::subnets' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft DHCP in SNMP. =cut centreon-plugins-20220113/apps/microsoft/exchange/000077500000000000000000000000001417000230700217665ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/exchange/local/000077500000000000000000000000001417000230700230605ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/exchange/local/mode/000077500000000000000000000000001417000230700240045ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/exchange/local/mode/activesyncmailbox.pm000066400000000000000000000145251417000230700300750ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::exchange::local::mode::activesyncmailbox; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::misc; use centreon::common::powershell::exchange::activesyncmailbox; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'remote-host:s' => { name => 'remote_host' }, 'remote-user:s' => { name => 'remote_user' }, 'remote-password:s' => { name => 'remote_password' }, 'no-ps' => { name => 'no_ps' }, 'timeout:s' => { name => 'timeout', default => 50 }, 'command:s' => { name => 'command', default => 'powershell.exe' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '-InputFormat none -NoLogo -EncodedCommand' }, 'ps-exec-only' => { name => 'ps_exec_only' }, 'ps-display' => { name => 'ps_display' }, 'warning:s' => { name => 'warning' }, 'critical:s' => { name => 'critical', default => '%{result} !~ /Success/i' }, 'mailbox:s' => { name => 'mailbox' }, 'password:s' => { name => 'password' }, 'no-trust-ssl' => { name => 'no_trust_ssl' }, }); return $self; } sub change_macros { my ($self, %options) = @_; foreach (('warning', 'critical')) { if (defined($self->{option_results}->{$_})) { $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$values->{$1}/g; } } } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{mailbox}) || $self->{option_results}->{mailbox} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify '--mailbox' option."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{password}) || $self->{option_results}->{password} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify '--password' option."); $self->{output}->option_exit(); } $self->change_macros(); } sub run { my ($self, %options) = @_; if (!defined($self->{option_results}->{no_ps})) { my $ps = centreon::common::powershell::exchange::activesyncmailbox::get_powershell( remote_host => $self->{option_results}->{remote_host}, remote_user => $self->{option_results}->{remote_user}, remote_password => $self->{option_results}->{remote_password}, mailbox => $self->{option_results}->{mailbox}, password => $self->{option_results}->{password}, no_trust_ssl => $self->{option_results}->{no_trust_ssl} ); if (defined($self->{option_results}->{ps_display})) { $self->{output}->output_add( severity => 'OK', short_msg => $ps ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{option_results}->{command_options} .= " " . centreon::plugins::misc::powershell_encoded($ps); } my ($stdout) = centreon::plugins::misc::windows_execute( output => $self->{output}, timeout => $self->{option_results}->{timeout}, command => $self->{option_results}->{command}, command_path => $self->{option_results}->{command_path}, command_options => $self->{option_results}->{command_options} ); if (defined($self->{option_results}->{ps_exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } centreon::common::powershell::exchange::activesyncmailbox::check($self, stdout => $stdout, mailbox => $self->{option_results}->{mailbox}); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check activesync to a mailbox. =over 8 =item B<--remote-host> Open a session to the remote-host (fully qualified host name). --remote-user and --remote-password are optional =item B<--remote-user> Open a session to the remote-host with authentication. This also needs --remote-host and --remote-password. =item B<--remote-password> Open a session to the remote-host with authentication. This also needs --remote-user and --remote-host. =item B<--timeout> Set timeout time for command execution (Default: 50 sec) =item B<--no-ps> Don't encode powershell. To be used with --command and 'type' command. =item B<--command> Command to get information (Default: 'powershell.exe'). Can be changed if you have output in a file. To be used with --no-ps option!!! =item B<--command-path> Command path (Default: none). =item B<--command-options> Command options (Default: '-InputFormat none -NoLogo -EncodedCommand'). =item B<--ps-display> Display powershell script. =item B<--ps-exec-only> Print powershell output. =item B<--warning> Set warning threshold. Can used special variables like: %{result}, %{scenario} =item B<--critical> Set critical threshold (Default: '%{result} !~ /Success/i'). Can used special variables like: %{result}, %{scenario} =item B<--mailbox> Set the mailbox to check (Required). =item B<--password> Set the password for the mailbox (Required). =item B<--no-trust-ssl> By default, SSL certificate validy is not checked. =back =cut centreon-plugins-20220113/apps/microsoft/exchange/local/mode/databases.pm000066400000000000000000000403771417000230700263040ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::exchange::local::mode::databases; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use centreon::common::powershell::exchange::databases; use apps::microsoft::exchange::local::mode::resources::types qw($copystatus_contentindexstate $mapi_result); use JSON::XS; sub custom_mailflow_latency_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel}, unit => 's', instances => [$self->{result_values}->{server}, $self->{result_values}->{database}], value => sprintf('%.3f', $self->{result_values}->{mailflow_latency}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}) ); } sub custom_space_size_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel}, unit => 'B', instances => [$self->{result_values}->{server}, $self->{result_values}->{database}], value => $self->{result_values}->{size}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}) ); } sub custom_space_available_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel}, unit => 'B', instances => [$self->{result_values}->{server}, $self->{result_values}->{database}], value => $self->{result_values}->{asize}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}) ); } sub custom_mapi_output { my ($self, %options) = @_; return 'mapi test connectivity is ' . $self->{result_values}->{mapi_result}; } sub custom_mailflow_output { my ($self, %options) = @_; return 'mapi test result is ' . $self->{result_values}->{mailflow_result}; } sub custom_copystatus_output { my ($self, %options) = @_; return sprintf( "copystatus state is %s [error: %s]", $self->{result_values}->{copystatus_indexstate}, $self->{result_values}->{copystatus_content_index_error_message} ); } sub custom_status_output { my ($self, %options) = @_; return sprintf( '%s mounted', $self->{result_values}->{mounted} == 0 ? 'not' : 'is' ); } sub database_long_output { my ($self, %options) = @_; return "checking database '" . $options{instance_value}->{database} . "' server '" . $options{instance_value}->{server} . "'"; } sub prefix_database_output { my ($self, %options) = @_; return "Database '" . $options{instance_value}->{database} . "' server '" . $options{instance_value}->{server} . "'"; } sub prefix_mailflow_output { my ($self, %options) = @_; return 'mailflow '; } sub prefix_global_output { my ($self, %options) = @_; return 'Databases '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } }, { name => 'databases', type => 3, cb_prefix_output => 'prefix_database_output', cb_long_output => 'database_long_output', indent_long_output => ' ', message_multiple => 'All databases are ok', group => [ { name => 'db_global', type => 0, skipped_code => { -10 => 1 } }, { name => 'space', type => 0, skipped_code => { -10 => 1 } }, { name => 'mapi', type => 0, skipped_code => { -10 => 1 } }, { name => 'mailflow', type => 0, cb_prefix_output => 'prefix_mailflow_output', skipped_code => { -10 => 1 } }, { name => 'copystatus', type => 0, skipped_code => { -10 => 1 } }, ] } ]; $self->{maps_counters}->{global} = [ { label => 'databases-space-size', nlabel => 'databases.space.size.bytes', set => { key_values => [ { name => 'size' } ], output_template => 'space size: %s %s', output_change_bytes => 1, perfdatas => [ { template => '%d', unit => 'B', min => 0 } ] } }, { label => 'databases-space-available', nlabel => 'databases.space.available.bytes', set => { key_values => [ { name => 'asize' } ], output_template => 'space available: %s %s', output_change_bytes => 1, perfdatas => [ { template => '%d', unit => 'B', min => 0 } ] } } ]; $self->{maps_counters}->{db_global} = [ { label => 'status', type => 2, critical_default => '%{mounted} == 0', set => { key_values => [ { name => 'mounted' }, { name => 'database' }, { name => 'server' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{space} = [ { label => 'database-space-size', nlabel => 'database.space.size.bytes', set => { key_values => [ { name => 'size' }, { name => 'database' }, { name => 'server' } ], output_template => 'space size: %s %s', output_change_bytes => 1, closure_custom_perfdata => $self->can('custom_space_size_perfdata') } }, { label => 'database-space-available', nlabel => 'database.space.available.bytes', set => { key_values => [ { name => 'asize' }, { name => 'database' }, { name => 'server' } ], output_template => 'space available: %s %s', output_change_bytes => 1, closure_custom_perfdata => $self->can('custom_space_asize_perfdata') } } ]; $self->{maps_counters}->{mapi} = [ { label => 'mapi', type => 2, critical_default => '%{mapi_result} !~ /Success/i', set => { key_values => [ { name => 'mapi_result' }, { name => 'database' }, { name => 'server' } ], closure_custom_output => $self->can('custom_mapi_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{mailflow} = [ { label => 'mailflow', type => 2, critical_default => '%{mailflow_result} !~ /Success/i', set => { key_values => [ { name => 'mailflow_result' }, { name => 'database' }, { name => 'server' } ], closure_custom_output => $self->can('custom_mailflow_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'mailflow-latency', nlabel => 'database.mailflow.latency.seconds', display_ok => 0, set => { key_values => [ { name => 'mailflow_latency' }, { name => 'database' }, { name => 'server' } ], output_template => 'latency: %.3f %%', closure_custom_perfdata => $self->can('custom_mailflow_latency_perfdata') } } ]; $self->{maps_counters}->{copystatus} = [ { label => 'copystatus', type => 2, critical_default => '%{copystatus_indexstate} !~ /Healthy/i', set => { key_values => [ { name => 'copystatus_indexstate' }, { name => 'copystatus_content_index_error_message' }, { name => 'database' }, { name => 'server' } ], closure_custom_output => $self->can('custom_copystatus_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'remote-host:s' => { name => 'remote_host' }, 'remote-user:s' => { name => 'remote_user' }, 'remote-password:s' => { name => 'remote_password' }, 'no-ps' => { name => 'no_ps' }, 'no-mailflow' => { name => 'no_mailflow' }, 'no-mapi' => { name => 'no_mapi' }, 'no-copystatus' => { name => 'no_copystatus' }, 'timeout:s' => { name => 'timeout', default => 50 }, 'command:s' => { name => 'command', default => 'powershell.exe' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '-InputFormat none -NoLogo -EncodedCommand' }, 'ps-exec-only' => { name => 'ps_exec_only' }, 'ps-display' => { name => 'ps_display' }, 'ps-server-filter:s' => { name => 'ps_server_filter' }, 'ps-database-filter:s' => { name => 'ps_database_filter' }, 'ps-database-test-filter:s' => { name => 'ps_database_test_filter' } }); return $self; } sub manage_selection { my ($self, %options) = @_; if (!defined($self->{option_results}->{no_ps})) { my $ps = centreon::common::powershell::exchange::databases::get_powershell( remote_host => $self->{option_results}->{remote_host}, remote_user => $self->{option_results}->{remote_user}, remote_password => $self->{option_results}->{remote_password}, no_mailflow => $self->{option_results}->{no_mailflow}, no_mapi => $self->{option_results}->{no_mapi}, no_copystatus => $self->{option_results}->{no_copystatus}, filter_server => $self->{option_results}->{ps_server_filter}, filter_database => $self->{option_results}->{ps_database_filter}, filter_database_test => $self->{option_results}->{ps_database_test_filter} ); if (defined($self->{option_results}->{ps_display})) { $self->{output}->output_add( severity => 'OK', short_msg => $ps ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{option_results}->{command_options} .= " " . centreon::plugins::misc::powershell_encoded($ps); } my ($stdout) = centreon::plugins::misc::windows_execute( output => $self->{output}, timeout => $self->{option_results}->{timeout}, command => $self->{option_results}->{command}, command_path => $self->{option_results}->{command_path}, command_options => $self->{option_results}->{command_options} ); if (defined($self->{option_results}->{ps_exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } my $decoded; eval { $decoded = JSON::XS->new->decode($stdout); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } $self->{global} = { size => 0, asize => 0 }; $self->{databases} = {}; foreach my $db (@$decoded) { $db->{mounted} = $db->{mounted} =~ /True|1/i ? 1 : 0; $db->{copystatus_indexstate} = $copystatus_contentindexstate->{ $db->{copystatus_indexstate} } if (defined($db->{copystatus_indexstate})); $db->{mapi_result} = $mapi_result->{ $db->{mapi_result} } if (defined($db->{mapi_result})); $self->{databases}->{ $db->{database} . ':' . $db->{server} } = { database => $db->{database}, server => $db->{server}, db_global => $db, space => $db, mapi => $db, mailflow => $db, copystatus => $db }; $self->{global}->{size} += $db->{size}; $self->{global}->{asize} += $db->{asize}; } } 1; __END__ =head1 MODE Check: Exchange Databases are Mounted, Mapi/Mailflow Connectivity to all databases are working and CopyStatus. =over 8 =item B<--remote-host> Open a session to the remote-host (fully qualified host name). --remote-user and --remote-password are optional =item B<--remote-user> Open a session to the remote-host with authentication. This also needs --remote-host and --remote-password. =item B<--remote-password> Open a session to the remote-host with authentication. This also needs --remote-user and --remote-host. =item B<--no-mailflow> Don't check mailflow connectivity. =item B<--no-mapi> Don't check mapi connectivity. =item B<--no-copystatus> Don't check copy status. =item B<--timeout> Set timeout time for command execution (Default: 50 sec) =item B<--no-ps> Don't encode powershell. To be used with --command and 'type' command. =item B<--command> Command to get information (Default: 'powershell.exe'). Can be changed if you have output in a file. To be used with --no-ps option!!! =item B<--command-path> Command path (Default: none). =item B<--command-options> Command options (Default: '-InputFormat none -NoLogo -EncodedCommand'). =item B<--ps-exec-only> Print powershell output. =item B<--ps-display> Display powershell script. =item B<--ps-server-filter> Filter mailboxes by database server name (regexp can be used. In Powershell). =item B<--ps-database-filter> Filter database (only wilcard '*' can be used. In Powershell). =item B<--ps-database-test-filter> Skip mapi/mailflow test (regexp can be used. In Powershell). =item B<--warning-status> Set warning threshold. Can used special variables like: %{mounted}, %{database}, %{server} =item B<--critical-status> Set critical threshold (Default: '%{mounted} == 0'). Can used special variables like: %{mounted}, %{database}, %{server} =item B<--warning-mapi> Set warning threshold. Can used special variables like: %{mapi_result}, %{database}, %{server} =item B<--critical-mapi> Set critical threshold (Default: '%{mapi_result} !~ /Success/i'). Can used special variables like: %{mapi_result}, %{database}, %{server} =item B<--warning-mailflow> Set warning threshold. Can used special variables like: %{mailflow_result}, %{database}, %{server} =item B<--critical-mailflow> Set critical threshold (Default: '%{mailflow_result} !~ /Success/i'). Can used special variables like: %{mailflow_result}, %{database}, %{server} =item B<--warning-copystatus> Set warning threshold. Can used special variables like: %{mailflow_result}, %{database}, %{server} =item B<--critical-copystatus> Set critical threshold (Default: '%{contentindexstate} !~ /Healthy/i'). Can used special variables like: %{copystatus_indexstate}, %{database}, %{server} =back =cut centreon-plugins-20220113/apps/microsoft/exchange/local/mode/imapmailbox.pm000066400000000000000000000141461417000230700266520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::exchange::local::mode::imapmailbox; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::misc; use centreon::common::powershell::exchange::imapmailbox; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'remote-host:s' => { name => 'remote_host' }, 'remote-user:s' => { name => 'remote_user' }, 'remote-password:s' => { name => 'remote_password' }, 'no-ps' => { name => 'no_ps' }, 'timeout:s' => { name => 'timeout', default => 50 }, 'command:s' => { name => 'command', default => 'powershell.exe' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '-InputFormat none -NoLogo -EncodedCommand' }, 'ps-exec-only' => { name => 'ps_exec_only' }, 'ps-display' => { name => 'ps_display' }, 'warning:s' => { name => 'warning' }, 'critical:s' => { name => 'critical', default => '%{result} !~ /Success/i' }, 'mailbox:s' => { name => 'mailbox' }, 'password:s' => { name => 'password' } }); return $self; } sub change_macros { my ($self, %options) = @_; foreach (('warning', 'critical')) { if (defined($self->{option_results}->{$_})) { $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$values->{$1}/g; } } } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{mailbox}) || $self->{option_results}->{mailbox} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify '--mailbox' option."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{password}) || $self->{option_results}->{password} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify '--password' option."); $self->{output}->option_exit(); } $self->change_macros(); } sub run { my ($self, %options) = @_; if (!defined($self->{option_results}->{no_ps})) { my $ps = centreon::common::powershell::exchange::imapmailbox::get_powershell( remote_host => $self->{option_results}->{remote_host}, remote_user => $self->{option_results}->{remote_user}, remote_password => $self->{option_results}->{remote_password}, mailbox => $self->{option_results}->{mailbox}, password => $self->{option_results}->{password} ); if (defined($self->{option_results}->{ps_display})) { $self->{output}->output_add( severity => 'OK', short_msg => $ps ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{option_results}->{command_options} .= " " . centreon::plugins::misc::powershell_encoded($ps); } my ($stdout) = centreon::plugins::misc::windows_execute( output => $self->{output}, timeout => $self->{option_results}->{timeout}, command => $self->{option_results}->{command}, command_path => $self->{option_results}->{command_path}, command_options => $self->{option_results}->{command_options} ); if (defined($self->{option_results}->{ps_exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } centreon::common::powershell::exchange::imapmailbox::check($self, stdout => $stdout, mailbox => $self->{option_results}->{mailbox}); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check imap to a mailbox. =over 8 =item B<--remote-host> Open a session to the remote-host (fully qualified host name). --remote-user and --remote-password are optional =item B<--remote-user> Open a session to the remote-host with authentication. This also needs --remote-host and --remote-password. =item B<--remote-password> Open a session to the remote-host with authentication. This also needs --remote-user and --remote-host. =item B<--timeout> Set timeout time for command execution (Default: 50 sec) =item B<--no-ps> Don't encode powershell. To be used with --command and 'type' command. =item B<--command> Command to get information (Default: 'powershell.exe'). Can be changed if you have output in a file. To be used with --no-ps option!!! =item B<--command-path> Command path (Default: none). =item B<--command-options> Command options (Default: '-InputFormat none -NoLogo -EncodedCommand'). =item B<--ps-display> Display powershell script. =item B<--ps-exec-only> Print powershell output. =item B<--warning> Set warning threshold. Can used special variables like: %{result}, %{scenario} =item B<--critical> Set critical threshold (Default: '%{result} !~ /Success/i'). Can used special variables like: %{result}, %{scenario} =item B<--mailbox> Set the mailbox to check (Required). =item B<--password> Set the password for the mailbox (Required). =back =cut centreon-plugins-20220113/apps/microsoft/exchange/local/mode/listdatabases.pm000066400000000000000000000155551417000230700272000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::exchange::local::mode::listdatabases; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::misc; use centreon::common::powershell::exchange::listdatabases; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'remote-host:s' => { name => 'remote_host' }, 'remote-user:s' => { name => 'remote_user' }, 'remote-password:s' => { name => 'remote_password' }, 'no-ps' => { name => 'no_ps' }, 'timeout:s' => { name => 'timeout', default => 50 }, 'command:s' => { name => 'command', default => 'powershell.exe' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '-InputFormat none -NoLogo -EncodedCommand' }, 'ps-exec-only' => { name => 'ps_exec_only' }, 'ps-display' => { name => 'ps_display' }, 'ps-database-filter:s' => { name => 'ps_database_filter' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; my $decoded; eval { $decoded = JSON::XS->new->decode($options{stdout}); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } return $decoded; } sub run { my ($self, %options) = @_; if (!defined($self->{option_results}->{no_ps})) { my $ps = centreon::common::powershell::exchange::listdatabases::get_powershell( remote_host => $self->{option_results}->{remote_host}, remote_user => $self->{option_results}->{remote_user}, remote_password => $self->{option_results}->{remote_password}, filter_database => $self->{option_results}->{ps_database_filter} ); if (defined($self->{option_results}->{ps_display})) { $self->{output}->output_add( severity => 'OK', short_msg => $ps ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{option_results}->{command_options} .= " " . centreon::plugins::misc::powershell_encoded($ps); } my ($stdout) = centreon::plugins::misc::execute( output => $self->{output}, options => $self->{option_results}, command => $self->{option_results}->{command}, command_path => $self->{option_results}->{command_path}, command_options => $self->{option_results}->{command_options} ); if (defined($self->{option_results}->{ps_exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); } else { $self->{output}->output_add( severity => 'OK', short_msg => 'List databases:' ); my $decoded = $self->manage_selection(stdout => $stdout); foreach my $db (@$decoded) { $self->{output}->output_add( long_msg => sprintf( "[name: %s][server: %s][mounted: %s]", $db->{name}, $db->{server}, $db->{mounted} =~ /True|1/i ? 'true' : 'false' ) ); } } $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', 'server', 'mounted']); } sub disco_show { my ($self, %options) = @_; if (!defined($self->{option_results}->{no_ps})) { my $ps = centreon::common::powershell::exchange::listdatabases::get_powershell( remote_host => $self->{option_results}->{remote_host}, remote_user => $self->{option_results}->{remote_user}, remote_password => $self->{option_results}->{remote_password}, filter_database => $self->{option_results}->{ps_database_filter} ); $self->{option_results}->{command_options} .= " " . centreon::plugins::misc::powershell_encoded($ps); } my ($stdout) = centreon::plugins::misc::execute( output => $self->{output}, options => $self->{option_results}, command => $self->{option_results}->{command}, command_path => $self->{option_results}->{command_path}, command_options => $self->{option_results}->{command_options} ); my $decoded = $self->manage_selection(stdout => $stdout); foreach my $db (@$decoded) { $self->{output}->add_disco_entry( name => $db->{name}, server => $db->{server}, mounted => $db->{mounted} =~ /True|1/i ? 'true' : 'false' ); } } 1; __END__ =head1 MODE List Exchange databases. =over 8 =item B<--remote-host> Open a session to the remote-host (fully qualified host name). --remote-user and --remote-password are optional =item B<--remote-user> Open a session to the remote-host with authentication. This also needs --remote-host and --remote-password. =item B<--remote-password> Open a session to the remote-host with authentication. This also needs --remote-user and --remote-host. =item B<--timeout> Set timeout time for command execution (Default: 50 sec) =item B<--no-ps> Don't encode powershell. To be used with --command and 'type' command. =item B<--command> Command to get information (Default: 'powershell.exe'). Can be changed if you have output in a file. To be used with --no-ps option!!! =item B<--command-path> Command path (Default: none). =item B<--command-options> Command options (Default: '-InputFormat none -NoLogo -EncodedCommand'). =item B<--ps-display> Display powershell script. =item B<--ps-exec-only> Print powershell output. =item B<--ps-database-filter> Filter database (only wilcard '*' can be used. In Powershell). =back =cut centreon-plugins-20220113/apps/microsoft/exchange/local/mode/mailboxes.pm000066400000000000000000000224431417000230700263320ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::exchange::local::mode::mailboxes; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::common::powershell::exchange::mailboxes; use JSON::XS; sub prefix_users_output { my ($self, %options) = @_; return 'Users mailbox '; } sub prefix_folders_output { my ($self, %options) = @_; return 'Public folders mailbox '; } sub prefix_database_output { my ($self, %options) = @_; return "Database '" . $options{instance_value}->{name} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'users', type => 0, cb_prefix_output => 'prefix_users_output', skipped_code => { -10 => 1 } }, { name => 'publicfolders', type => 0, cb_prefix_output => 'prefix_folders_output', skipped_code => { -10 => 1 } }, { name => 'databases', type => 1, cb_prefix_output => 'prefix_database_output', message_multiple => 'All databases are ok' } ]; foreach (('users', 'publicfolders')) { $self->{maps_counters}->{$_} = [ { label => $_ . '-soft-limit', nlabel => 'mailboxes.' . $_ . '.soft.limit.count', set => { key_values => [ { name => 'soft_limit' } ], output_template => 'over soft limit: %s', perfdatas => [ { template => '%d', min => 0 } ] } }, { label => $_ . '-hard-limit', nlabel => 'mailboxes.' . $_ . '.hard.limit.count', set => { key_values => [ { name => 'hard_limit' } ], output_template => 'over hard limit: %s', perfdatas => [ { template => '%d', min => 0 } ] } }, { label => $_ . '-quota-unlimited', nlabel => 'mailboxes.' . $_ . '.quota.unlimited.count', set => { key_values => [ { name => 'unlimited' } ], output_template => 'unlimited quota: %s', perfdatas => [ { template => '%d', min => 0 } ] } }, { label => $_ . '-total', nlabel => 'mailboxes.' . $_ . '.total.count', set => { key_values => [ { name => 'total' } ], output_template => 'total: %s', perfdatas => [ { template => '%d', min => 0 } ] } } ]; } $self->{maps_counters}->{databases} = [ { label => 'database-mailboxes-total', nlabel => 'database.mailboxes.total.count', set => { key_values => [ { name => 'mailboxes' } ], output_template => 'total mailboxes: %s', perfdatas => [ { template => '%d', min => 0, label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'remote-host:s' => { name => 'remote_host' }, 'remote-user:s' => { name => 'remote_user' }, 'remote-password:s' => { name => 'remote_password' }, 'no-ps' => { name => 'no_ps' }, 'timeout:s' => { name => 'timeout', default => 50 }, 'command:s' => { name => 'command', default => 'powershell.exe' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '-InputFormat none -NoLogo -EncodedCommand' }, 'ps-exec-only' => { name => 'ps_exec_only' }, 'ps-display' => { name => 'ps_display' }, 'ps-server:s' => { name => 'ps_server' }, 'ps-database:s' => { name => 'ps_database' }, 'ps-match-database:s' => { name => 'ps_match_database' }, 'ps-match-server:s' => { name => 'ps_match_server' } }); return $self; } sub manage_selection { my ($self, %options) = @_; if (!defined($self->{option_results}->{no_ps})) { my $ps = centreon::common::powershell::exchange::mailboxes::get_powershell( remote_host => $self->{option_results}->{remote_host}, remote_user => $self->{option_results}->{remote_user}, remote_password => $self->{option_results}->{remote_password}, ps_server => $self->{option_results}->{ps_server}, ps_database => $self->{option_results}->{ps_database}, ps_match_database => $self->{option_results}->{ps_match_database}, ps_match_server => $self->{option_results}->{ps_match_server} ); if (defined($self->{option_results}->{ps_display})) { $self->{output}->output_add( severity => 'OK', short_msg => $ps ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{option_results}->{command_options} .= " " . centreon::plugins::misc::powershell_encoded($ps); } my ($stdout) = centreon::plugins::misc::execute( output => $self->{output}, options => { timeout => $self->{option_results}->{timeout} }, command => $self->{option_results}->{command}, command_path => $self->{option_results}->{command_path}, command_options => $self->{option_results}->{command_options} ); if (defined($self->{option_results}->{ps_exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } my $decoded; eval { $decoded = JSON::XS->new->decode($stdout); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } $self->{users} = { total => $decoded->{users}->{total}, soft_limit => $decoded->{users}->{warning_quota}, hard_limit => $decoded->{users}->{over_quota}, unlimited => $decoded->{users}->{unlimited} }; $self->{publicfolders} = { total => $decoded->{public_folders}->{total}, soft_limit => $decoded->{public_folders}->{warning_quota}, hard_limit => $decoded->{public_folders}->{over_quota}, unlimited => $decoded->{public_folders}->{unlimited} }; $self->{databases} = {}; foreach my $name (keys %{$decoded->{group_by_databases}}) { $self->{databases}->{$name} = { name => $name, mailboxes => $decoded->{group_by_databases}->{$name} }; } } 1; __END__ =head1 MODE Check mailboxes (quota and user mailboxes by database). =over 8 =item B<--remote-host> Open a session to the remote-host (fully qualified host name). --remote-user and --remote-password are optional =item B<--remote-user> Open a session to the remote-host with authentication. This also needs --remote-host and --remote-password. =item B<--remote-password> Open a session to the remote-host with authentication. This also needs --remote-user and --remote-host. =item B<--timeout> Set timeout time for command execution (Default: 50 sec) =item B<--no-ps> Don't encode powershell. To be used with --command and 'type' command. =item B<--command> Command to get information (Default: 'powershell.exe'). Can be changed if you have output in a file. To be used with --no-ps option!!! =item B<--command-path> Command path (Default: none). =item B<--command-options> Command options (Default: '-InputFormat none -NoLogo -EncodedCommand'). =item B<--ps-exec-only> Print powershell output. =item B<--ps-display> Display powershell script. =item B<--ps-match-server> Filter mailboxes by server name (regexp can be used. In Powershell). =item B<--ps-match-database> Filter mailboxes by database name (regexp can be used. In Powershell). =item B<--ps-server> Select mailboxes by an uniq server name (In Powershell). =item B<--ps-database> Select mailboxes by an uniq database name (In Powershell). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'users-soft-limit', 'users-hard-limit', 'users-quota-unlimited', 'users-total', 'publicfolders-soft-limit', 'publicfolders-hard-limit', 'publicfolders-quota-unlimited', 'publicfolders-total' 'database-mailboxes-total'. =back =cut centreon-plugins-20220113/apps/microsoft/exchange/local/mode/mapimailbox.pm000066400000000000000000000132541417000230700266510ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::exchange::local::mode::mapimailbox; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::misc; use centreon::common::powershell::exchange::mapimailbox; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'remote-host:s' => { name => 'remote_host' }, 'remote-user:s' => { name => 'remote_user' }, 'remote-password:s' => { name => 'remote_password' }, 'no-ps' => { name => 'no_ps' }, 'timeout:s' => { name => 'timeout', default => 50 }, 'command:s' => { name => 'command', default => 'powershell.exe' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '-InputFormat none -NoLogo -EncodedCommand' }, 'ps-exec-only' => { name => 'ps_exec_only' }, 'ps-display' => { name => 'ps_display' }, 'warning:s' => { name => 'warning' }, 'critical:s' => { name => 'critical', default => '%{result} !~ /Success/i' }, 'mailbox:s' => { name => 'mailbox' } }); return $self; } sub change_macros { my ($self, %options) = @_; foreach (('warning', 'critical')) { if (defined($self->{option_results}->{$_})) { $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$values->{$1}/g; } } } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{mailbox}) || $self->{option_results}->{mailbox} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify '--mailbox' option."); $self->{output}->option_exit(); } $self->change_macros(); } sub run { my ($self, %options) = @_; if (!defined($self->{option_results}->{no_ps})) { my $ps = centreon::common::powershell::exchange::mapimailbox::get_powershell( remote_host => $self->{option_results}->{remote_host}, remote_user => $self->{option_results}->{remote_user}, remote_password => $self->{option_results}->{remote_password}, mailbox => $self->{option_results}->{mailbox} ); if (defined($self->{option_results}->{ps_display})) { $self->{output}->output_add( severity => 'OK', short_msg => $ps ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{option_results}->{command_options} .= " " . centreon::plugins::misc::powershell_encoded($ps); } my ($stdout) = centreon::plugins::misc::windows_execute( output => $self->{output}, timeout => $self->{option_results}->{timeout}, command => $self->{option_results}->{command}, command_path => $self->{option_results}->{command_path}, command_options => $self->{option_results}->{command_options} ); if (defined($self->{option_results}->{ps_exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } centreon::common::powershell::exchange::mapimailbox::check($self, stdout => $stdout, mailbox => $self->{option_results}->{mailbox}); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check mapi connection to a mailbox. =over 8 =item B<--remote-host> Open a session to the remote-host (fully qualified host name). --remote-user and --remote-password are optional =item B<--remote-user> Open a session to the remote-host with authentication. This also needs --remote-host and --remote-password. =item B<--remote-password> Open a session to the remote-host with authentication. This also needs --remote-user and --remote-host. =item B<--timeout> Set timeout time for command execution (Default: 50 sec) =item B<--no-ps> Don't encode powershell. To be used with --command and 'type' command. =item B<--command> Command to get information (Default: 'powershell.exe'). Can be changed if you have output in a file. To be used with --no-ps option!!! =item B<--command-path> Command path (Default: none). =item B<--command-options> Command options (Default: '-InputFormat none -NoLogo -EncodedCommand'). =item B<--ps-display> Display powershell script. =item B<--ps-exec-only> Print powershell output. =item B<--warning> Set warning threshold. Can used special variables like: %{result}, %{scenario} =item B<--critical> Set critical threshold (Default: '%{result} !~ /Success/i'). Can used special variables like: %{result}, %{scenario} =item B<--mailbox> Set the mailbox to check (Required). =back =cut centreon-plugins-20220113/apps/microsoft/exchange/local/mode/outlookwebservices.pm000066400000000000000000000136321417000230700303050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::exchange::local::mode::outlookwebservices; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::misc; use centreon::common::powershell::exchange::outlookwebservices; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'remote-host:s' => { name => 'remote_host' }, 'remote-user:s' => { name => 'remote_user' }, 'remote-password:s' => { name => 'remote_password' }, 'no-ps' => { name => 'no_ps' }, 'timeout:s' => { name => 'timeout', default => 50 }, 'command:s' => { name => 'command', default => 'powershell.exe' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '-InputFormat none -NoLogo -EncodedCommand' }, 'ps-exec-only' => { name => 'ps_exec_only' }, 'ps-display' => { name => 'ps_display' }, 'warning:s' => { name => 'warning', }, 'critical:s' => { name => 'critical', default => '%{type} !~ /Success|Information/i' }, 'mailbox:s' => { name => 'mailbox' }, 'password:s' => { name => 'password' } }); return $self; } sub change_macros { my ($self, %options) = @_; foreach (('warning', 'critical')) { if (defined($self->{option_results}->{$_})) { $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$values->{$1}/g; } } } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{mailbox}) || $self->{option_results}->{mailbox} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify '--mailbox' option."); $self->{output}->option_exit(); } $self->change_macros(); } sub run { my ($self, %options) = @_; if (!defined($self->{option_results}->{no_ps})) { my $ps = centreon::common::powershell::exchange::outlookwebservices::get_powershell( remote_host => $self->{option_results}->{remote_host}, remote_user => $self->{option_results}->{remote_user}, remote_password => $self->{option_results}->{remote_password}, mailbox => $self->{option_results}->{mailbox}, password => $self->{option_results}->{password} ); if (defined($self->{option_results}->{ps_display})) { $self->{output}->output_add( severity => 'OK', short_msg => $ps ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{option_results}->{command_options} .= " " . centreon::plugins::misc::powershell_encoded($ps); } my ($stdout) = centreon::plugins::misc::windows_execute( output => $self->{output}, timeout => $self->{option_results}->{timeout}, command => $self->{option_results}->{command}, command_path => $self->{option_results}->{command_path}, command_options => $self->{option_results}->{command_options} ); if (defined($self->{option_results}->{ps_exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } centreon::common::powershell::exchange::outlookwebservices::check($self, stdout => $stdout, mailbox => $self->{option_results}->{mailbox}); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check outlook autodiscovery webservices. =over 8 =item B<--remote-host> Open a session to the remote-host (fully qualified host name). --remote-user and --remote-password are optional =item B<--remote-user> Open a session to the remote-host with authentication. This also needs --remote-host and --remote-password. =item B<--remote-password> Open a session to the remote-host with authentication. This also needs --remote-user and --remote-host. =item B<--timeout> Set timeout time for command execution (Default: 50 sec) =item B<--no-ps> Don't encode powershell. To be used with --command and 'type' command. =item B<--command> Command to get information (Default: 'powershell.exe'). Can be changed if you have output in a file. To be used with --no-ps option!!! =item B<--command-path> Command path (Default: none). =item B<--command-options> Command options (Default: '-InputFormat none -NoLogo -EncodedCommand'). =item B<--ps-display> Display powershell script. =item B<--ps-exec-only> Print powershell output. =item B<--warning> Set warning threshold. Can used special variables like: %{type}, %{id}, %{message} =item B<--critical> Set critical threshold (Default: '%{type} !~ /Success|Information/i'). Can used special variables like: %{type}, %{id}, %{message} =item B<--mailbox> Set the mailbox to check (Required). =item B<--password> Set the password for the mailbox. =back =cut centreon-plugins-20220113/apps/microsoft/exchange/local/mode/owamailbox.pm000066400000000000000000000152231417000230700265070ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::exchange::local::mode::owamailbox; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::misc; use centreon::common::powershell::exchange::owamailbox; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'remote-host:s' => { name => 'remote_host' }, 'remote-user:s' => { name => 'remote_user' }, 'remote-password:s' => { name => 'remote_password' }, 'no-ps' => { name => 'no_ps' }, 'timeout:s' => { name => 'timeout', default => 50 }, 'command:s' => { name => 'command', default => 'powershell.exe' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '-InputFormat none -NoLogo -EncodedCommand' }, 'ps-exec-only' => { name => 'ps_exec_only' }, 'ps-display' => { name => 'ps_display' }, 'warning:s' => { name => 'warning' }, 'critical:s' => { name => 'critical', default => '%{result} !~ /Success/i' }, 'url:s' => { name => 'url' }, 'mailbox:s' => { name => 'mailbox' }, 'password:s' => { name => 'password' }, 'no-trust-ssl' => { name => 'no_trust_ssl' } }); return $self; } sub change_macros { my ($self, %options) = @_; foreach (('warning', 'critical')) { if (defined($self->{option_results}->{$_})) { $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$values->{$1}/g; } } } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{url}) || $self->{option_results}->{url} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify '--url' option."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{mailbox}) || $self->{option_results}->{mailbox} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify '--mailbox' option."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{password}) || $self->{option_results}->{password} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify '--password' option."); $self->{output}->option_exit(); } $self->change_macros(); } sub run { my ($self, %options) = @_; if (!defined($self->{option_results}->{no_ps})) { my $ps = centreon::common::powershell::exchange::owamailbox::get_powershell( remote_host => $self->{option_results}->{remote_host}, remote_user => $self->{option_results}->{remote_user}, remote_password => $self->{option_results}->{remote_password}, url => $self->{option_results}->{url}, mailbox => $self->{option_results}->{mailbox}, password => $self->{option_results}->{password}, no_trust_ssl => $self->{option_results}->{no_trust_ssl} ); if (defined($self->{option_results}->{ps_display})) { $self->{output}->output_add( severity => 'OK', short_msg => $ps ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{option_results}->{command_options} .= " " . centreon::plugins::misc::powershell_encoded($ps); } my ($stdout) = centreon::plugins::misc::windows_execute( output => $self->{output}, timeout => $self->{option_results}->{timeout}, command => $self->{option_results}->{command}, command_path => $self->{option_results}->{command_path}, command_options => $self->{option_results}->{command_options} ); if (defined($self->{option_results}->{ps_exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } centreon::common::powershell::exchange::owamailbox::check($self, stdout => $stdout, mailbox => $self->{option_results}->{mailbox}); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check OWA connection to a mailbox. =over 8 =item B<--remote-host> Open a session to the remote-host (fully qualified host name). --remote-user and --remote-password are optional =item B<--remote-user> Open a session to the remote-host with authentication. This also needs --remote-host and --remote-password. =item B<--remote-password> Open a session to the remote-host with authentication. This also needs --remote-user and --remote-host. =item B<--timeout> Set timeout time for command execution (Default: 50 sec) =item B<--no-ps> Don't encode powershell. To be used with --command and 'type' command. =item B<--command> Command to get information (Default: 'powershell.exe'). Can be changed if you have output in a file. To be used with --no-ps option!!! =item B<--command-path> Command path (Default: none). =item B<--command-options> Command options (Default: '-InputFormat none -NoLogo -EncodedCommand'). =item B<--ps-display> Display powershell script. =item B<--ps-exec-only> Print powershell output. =item B<--warning> Set warning threshold. Can used special variables like: %{result}, %{scenario} =item B<--critical> Set critical threshold (Default: '%{result} !~ /Success/i'). Can used special variables like: %{result}, %{scenario} =item B<--url> Set the OWA Url (Required). =item B<--mailbox> Set the mailbox to check (Required). =item B<--password> Set the password for the mailbox (Required). =item B<--no-trust-ssl> By default, SSL certificate validy is not checked. =back =cut centreon-plugins-20220113/apps/microsoft/exchange/local/mode/queues.pm000066400000000000000000000176531417000230700256650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::exchange::local::mode::queues; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use centreon::common::powershell::exchange::queues; use apps::microsoft::exchange::local::mode::resources::types qw($queue_status $queue_delivery_type); use JSON::XS; sub custom_status_output { my ($self, %options) = @_; return sprintf( 'status: %s [last error: %s] [delivery type: %s] [identity: %s] [message count: %s]', $self->{result_values}->{status}, $self->{result_values}->{last_error}, $self->{result_values}->{delivery_type}, $self->{result_values}->{identity}, $self->{result_values}->{message_count} ); } sub prefix_queue_output { my ($self, %options) = @_; return "Queue '" . $options{instance_value}->{nexthopdomain} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'queues', type => 1, cb_prefix_output => 'prefix_queue_output', message_multiple => 'All queues are ok', skipped_code => { -11 => 1 } } ]; $self->{maps_counters}->{queues} = [ { label => 'status', type => 2, critical_default => '%{status} !~ /Ready|Active/i', set => { key_values => [ { name => 'nexthopdomain' }, { name => 'identity' }, { name => 'is_valid' }, { name => 'isvalid' }, { name => 'delivery_type' }, { name => 'deliverytype' }, { name => 'message_count' }, { name => 'messagecount' }, { name => 'status' }, { name => 'last_error' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'remote-host:s' => { name => 'remote_host' }, 'remote-user:s' => { name => 'remote_user' }, 'remote-password:s' => { name => 'remote_password' }, 'no-ps' => { name => 'no_ps' }, 'timeout:s' => { name => 'timeout', default => 50 }, 'command:s' => { name => 'command', default => 'powershell.exe' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '-InputFormat none -NoLogo -EncodedCommand' }, 'ps-exec-only' => { name => 'ps_exec_only' }, 'ps-display' => { name => 'ps_display' } }); return $self; } sub manage_selection { my ($self, %options) = @_; if (!defined($self->{option_results}->{no_ps})) { my $ps = centreon::common::powershell::exchange::queues::get_powershell( remote_host => $self->{option_results}->{remote_host}, remote_user => $self->{option_results}->{remote_user}, remote_password => $self->{option_results}->{remote_password} ); if (defined($self->{option_results}->{ps_display})) { $self->{output}->output_add( severity => 'OK', short_msg => $ps ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{option_results}->{command_options} .= " " . centreon::plugins::misc::powershell_encoded($ps); } my ($stdout) = centreon::plugins::misc::windows_execute( output => $self->{output}, timeout => $self->{option_results}->{timeout}, command => $self->{option_results}->{command}, command_path => $self->{option_results}->{command_path}, command_options => $self->{option_results}->{command_options} ); if (defined($self->{option_results}->{ps_exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } my $decoded; eval { $decoded = JSON::XS->new->decode($stdout); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } my $perfdatas_queues = {}; $self->{queues} = {}; foreach my $queue (@$decoded) { $queue->{is_valid} = $queue->{is_valid} =~ /True|1/i ? 1 : 0; $queue->{status} = $queue_status->{ $queue->{status} } if (defined($queue->{status})); $queue->{delivery_type} = $queue_delivery_type->{ $queue->{delivery_type} } if (defined($queue->{delivery_type})); $self->{queues}->{ $queue->{identity} } = { %$queue, deliverytype => $queue->{delivery_type}, isvalid => $queue->{is_valid}, messagecount => $queue->{message_count} }; if ($queue->{message_count} =~ /^(\d+)/) { my $num = $1; my $identity = $queue->{identity}; $identity = $1 if ($queue->{identity} =~ /^(.*\/)[0-9]+$/); $perfdatas_queues->{$identity} = 0 if (!defined($perfdatas_queues->{$identity})); $perfdatas_queues->{$identity} += $num; } } foreach (keys %$perfdatas_queues) { $self->{output}->perfdata_add( nlabel => 'queue.length.count', instances => $_, value => $perfdatas_queues->{$_}, min => 0 ); } } 1; __END__ =head1 MODE Check queues status. =over 8 =item B<--remote-host> Open a session to the remote-host (fully qualified host name). --remote-user and --remote-password are optional =item B<--remote-user> Open a session to the remote-host with authentication. This also needs --remote-host and --remote-password. =item B<--remote-password> Open a session to the remote-host with authentication. This also needs --remote-user and --remote-host. =item B<--timeout> Set timeout time for command execution (Default: 50 sec) =item B<--no-ps> Don't encode powershell. To be used with --command and 'type' command. =item B<--command> Command to get information (Default: 'powershell.exe'). Can be changed if you have output in a file. To be used with --no-ps option!!! =item B<--command-path> Command path (Default: none). =item B<--command-options> Command options (Default: '-InputFormat none -NoLogo -EncodedCommand'). =item B<--ps-display> Display powershell script. =item B<--ps-exec-only> Print powershell output. =item B<--warning-status> Set warning threshold. Can used special variables like: %{status}, %{identity}, %{is_valid}, %{delivery_type}, %{message_count} =item B<--critical-status> Set critical threshold (Default: '%{status} !~ /Ready|Active/i'). Can used special variables like: %{status}, %{identity}, %{is_valid}, %{delivery_type}, %{message_count} =back =cut centreon-plugins-20220113/apps/microsoft/exchange/local/mode/replicationhealth.pm000066400000000000000000000124351417000230700300460ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::exchange::local::mode::replicationhealth; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::misc; use centreon::common::powershell::exchange::replicationhealth; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'remote-host:s' => { name => 'remote_host', }, 'remote-user:s' => { name => 'remote_user', }, 'remote-password:s' => { name => 'remote_password', }, 'no-ps' => { name => 'no_ps', }, 'timeout:s' => { name => 'timeout', default => 50 }, 'command:s' => { name => 'command', default => 'powershell.exe' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '-InputFormat none -NoLogo -EncodedCommand' }, 'ps-exec-only' => { name => 'ps_exec_only', }, 'ps-display' => { name => 'ps_display' }, 'warning:s' => { name => 'warning', }, 'critical:s' => { name => 'critical', default => '%{result} !~ /Passed/i' } }); return $self; } sub change_macros { my ($self, %options) = @_; foreach (('warning', 'critical')) { if (defined($self->{option_results}->{$_})) { $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$values->{$1}/g; } } } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); $self->change_macros(); } sub run { my ($self, %options) = @_; if (!defined($self->{option_results}->{no_ps})) { my $ps = centreon::common::powershell::exchange::replicationhealth::get_powershell( remote_host => $self->{option_results}->{remote_host}, remote_user => $self->{option_results}->{remote_user}, remote_password => $self->{option_results}->{remote_password} ); if (defined($self->{option_results}->{ps_display})) { $self->{output}->output_add( severity => 'OK', short_msg => $ps ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{option_results}->{command_options} .= " " . centreon::plugins::misc::powershell_encoded($ps); } my ($stdout) = centreon::plugins::misc::windows_execute( output => $self->{output}, timeout => $self->{option_results}->{timeout}, command => $self->{option_results}->{command}, command_path => $self->{option_results}->{command_path}, command_options => $self->{option_results}->{command_options} ); if (defined($self->{option_results}->{ps_exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } centreon::common::powershell::exchange::replicationhealth::check($self, stdout => $stdout); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check replication health. =over 8 =item B<--remote-host> Open a session to the remote-host (fully qualified host name). --remote-user and --remote-password are optional =item B<--remote-user> Open a session to the remote-host with authentication. This also needs --remote-host and --remote-password. =item B<--remote-password> Open a session to the remote-host with authentication. This also needs --remote-user and --remote-host. =item B<--timeout> Set timeout time for command execution (Default: 50 sec) =item B<--no-ps> Don't encode powershell. To be used with --command and 'type' command. =item B<--command> Command to get information (Default: 'powershell.exe'). Can be changed if you have output in a file. To be used with --no-ps option!!! =item B<--command-path> Command path (Default: none). =item B<--command-options> Command options (Default: '-InputFormat none -NoLogo -EncodedCommand'). =item B<--ps-display> Display powershell script. =item B<--ps-exec-only> Print powershell output. =item B<--warning> Set warning threshold. Can used special variables like: %{result}, %{server}, %{isvalid}, %{check} =item B<--critical> Set critical threshold (Default: '%{result} !~ /Passed/i'). Can used special variables like: %{result}, %{server}, %{isvalid}, %{check} =back =cut centreon-plugins-20220113/apps/microsoft/exchange/local/mode/resources/000077500000000000000000000000001417000230700260165ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/exchange/local/mode/resources/types.pm000066400000000000000000000047751417000230700275350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::exchange::local::mode::resources::types; use strict; use warnings; use Exporter; our $queue_status; our $queue_delivery_type; our $copystatus_contentindexstate; our $mapi_result; our @ISA = qw(Exporter); our @EXPORT_OK = qw( $queue_status $queue_delivery_type $copystatus_contentindexstate $mapi_result ); $queue_status = { 0 => 'None', 1 => 'Active', 2 => 'Ready', 3 => 'Retry', 4 => 'Suspended', 5 => 'Connecting', 6 => 'Throttled' }; $queue_delivery_type = { 0 => 'Undefined', 1 => 'DnsConnectorDelivery', 2 => 'MapiDelivery', 3 => 'NonSmtpGatewayDelivery', 4 => 'SmartHostConnectorDelivery', 5 => 'SmtpRelayToRemoteAdSite', 6 => 'SmtpRelayToTiRg', 7 => 'SmtpRelayWithinAdSite', 8 => 'SmtpRelayWithinAdSiteToEdge', 9 => 'Unreachable', 10 => 'ShadowRedundancy', 11 => 'Heartbeat', 12 => 'DeliveryAgent', 13 => 'SmtpDeliveryToMailbox', 14 => 'SmtpRelayToDag', 15 => 'SmtpRelayToMailboxDeliveryGroup', 16 => 'SmtpRelayToConnectorSourceServers', 17 => 'SmtpRelayToServers', 18 => 'SmtpRelayToRemoteForest', 19 => 'SmtpDeliveryToExo', 20 => 'HttpDeliveryToMailbox', 21 => 'HttpDeliveryToExo', 22 => 'Delay', 23 => 'SmtpSubmissionToEop', 24 => 'SmtpSubmissionToExo', 25 => 'HttpDeliveryToApp' }; $copystatus_contentindexstate = { 0 => 'Unknown', 1 => 'Healthy', 2 => 'Crawling', 3 => 'Failed', 4 => 'Seeding', 5 => 'FailedAndSuspended', 6 => 'Suspended', 7 => 'Disabled', 8 => 'AutoSuspended', 9 => 'HealthyAndUpgrading', 10 => 'DiskUnavailable' }; $mapi_result = { 0 => 'Undefined', 1 => 'Success', 2 => 'Failure', 3 => 'MdbMoved', 4 => 'StoreNotRunning' }; 1; centreon-plugins-20220113/apps/microsoft/exchange/local/mode/services.pm000066400000000000000000000126341417000230700261730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::exchange::local::mode::services; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::misc; use centreon::common::powershell::exchange::services; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'remote-host:s' => { name => 'remote_host' }, 'remote-user:s' => { name => 'remote_user' }, 'remote-password:s' => { name => 'remote_password' }, 'no-ps' => { name => 'no_ps' }, 'timeout:s' => { name => 'timeout', default => 50 }, 'command:s' => { name => 'command', default => 'powershell.exe' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '-InputFormat none -NoLogo -EncodedCommand' }, 'ps-exec-only' => { name => 'ps_exec_only' }, 'ps-display' => { name => 'ps_display' }, 'warning:s' => { name => 'warning' }, 'critical:s' => { name => 'critical', default => '%{requiredservicesrunning} =~ /True/i and %{servicesnotrunning} ne ""' } }); return $self; } sub change_macros { my ($self, %options) = @_; foreach (('warning', 'critical')) { if (defined($self->{option_results}->{$_})) { $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$values->{$1}/g; } } } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); $self->change_macros(); } sub run { my ($self, %options) = @_; if (!defined($self->{option_results}->{no_ps})) { my $ps = centreon::common::powershell::exchange::services::get_powershell( remote_host => $self->{option_results}->{remote_host}, remote_user => $self->{option_results}->{remote_user}, remote_password => $self->{option_results}->{remote_password} ); if (defined($self->{option_results}->{ps_display})) { $self->{output}->output_add( severity => 'OK', short_msg => $ps ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{option_results}->{command_options} .= " " . centreon::plugins::misc::powershell_encoded($ps); } my ($stdout) = centreon::plugins::misc::windows_execute( output => $self->{output}, timeout => $self->{option_results}->{timeout}, command => $self->{option_results}->{command}, command_path => $self->{option_results}->{command_path}, command_options => $self->{option_results}->{command_options} ); if (defined($self->{option_results}->{ps_exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } centreon::common::powershell::exchange::services::check($self, stdout => $stdout); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check exchange services. =over 8 =item B<--remote-host> Open a session to the remote-host (fully qualified host name). --remote-user and --remote-password are optional =item B<--remote-user> Open a session to the remote-host with authentication. This also needs --remote-host and --remote-password. =item B<--remote-password> Open a session to the remote-host with authentication. This also needs --remote-user and --remote-host. =item B<--timeout> Set timeout time for command execution (Default: 50 sec) =item B<--no-ps> Don't encode powershell. To be used with --command and 'type' command. =item B<--command> Command to get information (Default: 'powershell.exe'). Can be changed if you have output in a file. To be used with --no-ps option!!! =item B<--command-path> Command path (Default: none). =item B<--command-options> Command options (Default: '-InputFormat none -NoLogo -EncodedCommand'). =item B<--ps-display> Display powershell script. =item B<--ps-exec-only> Print powershell output. =item B<--warning> Set warning threshold. Can used special variables like: %{servicesrunning}, %{servicesnotrunning}, %{role}, %{requiredservicesrunning} =item B<--critical> Set critical threshold (Default: '%{requiredservicesrunning} =~ /True/i and %{servicesnotrunning} ne ""'). Can used special variables like: %{servicesrunning}, %{servicesnotrunning}, %{role}, %{requiredservicesrunning} =back =cut centreon-plugins-20220113/apps/microsoft/exchange/local/plugin.pm000066400000000000000000000042021417000230700247120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::exchange::local::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} = '0.1'; $self->{modes} = { 'activesync-mailbox' => 'apps::microsoft::exchange::local::mode::activesyncmailbox', 'databases' => 'apps::microsoft::exchange::local::mode::databases', 'list-databases' => 'apps::microsoft::exchange::local::mode::listdatabases', 'imap-mailbox' => 'apps::microsoft::exchange::local::mode::imapmailbox', 'mailboxes' => 'apps::microsoft::exchange::local::mode::mailboxes', 'mapi-mailbox' => 'apps::microsoft::exchange::local::mode::mapimailbox', 'outlook-webservices' => 'apps::microsoft::exchange::local::mode::outlookwebservices', 'owa-mailbox' => 'apps::microsoft::exchange::local::mode::owamailbox', 'queues' => 'apps::microsoft::exchange::local::mode::queues', 'replication-health' => 'apps::microsoft::exchange::local::mode::replicationhealth', 'services' => 'apps::microsoft::exchange::local::mode::services' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Windows Exchange 2010/2016 locally. =cut centreon-plugins-20220113/apps/microsoft/hyperv/000077500000000000000000000000001417000230700215215ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/hyperv/2012/000077500000000000000000000000001417000230700221055ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/hyperv/2012/local/000077500000000000000000000000001417000230700231775ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/hyperv/2012/local/mode/000077500000000000000000000000001417000230700241235ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/hyperv/2012/local/mode/listnodevms.pm000066400000000000000000000142541417000230700270360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::hyperv::2012::local::mode::listnodevms; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::misc; use centreon::common::powershell::hyperv::2012::listnodevms; use apps::microsoft::hyperv::2012::local::mode::resources::types qw($node_vm_state); use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'timeout:s' => { name => 'timeout', default => 50 }, 'command:s' => { name => 'command', default => 'powershell.exe' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '-InputFormat none -NoLogo -EncodedCommand' }, 'no-ps' => { name => 'no_ps' }, 'ps-exec-only' => { name => 'ps_exec_only' }, 'ps-display' => { name => 'ps_display' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; #[ # { "name": "XXXX1", "state": 2, "status": "Operating normally", "is_clustered": true, "note": null }, # { "name": "XXXX2", "state": 2, "status": "Operating normally", "is_clustered": false, "note": null }, # { "name": "XXXX3", "state": 2, "status": "Operating normally", "is_clustered": true, "note": null } #] my $decoded; eval { $decoded = JSON::XS->new->decode($options{stdout}); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } return $decoded; } sub run { my ($self, %options) = @_; if (!defined($self->{option_results}->{no_ps})) { my $ps = centreon::common::powershell::hyperv::2012::listnodevms::get_powershell(); if (defined($self->{option_results}->{ps_display})) { $self->{output}->output_add( severity => 'OK', short_msg => $ps ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{option_results}->{command_options} .= " " . centreon::plugins::misc::powershell_encoded($ps); } my ($stdout) = centreon::plugins::misc::execute( output => $self->{output}, options => $self->{option_results}, command => $self->{option_results}->{command}, command_path => $self->{option_results}->{command_path}, command_options => $self->{option_results}->{command_options} ); if (defined($self->{option_results}->{ps_exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); } else { $self->{output}->output_add( severity => 'OK', short_msg => 'List virtual machines:' ); my $decoded = $self->manage_selection(stdout => $stdout); foreach my $node (@$decoded) { $self->{output}->output_add( long_msg => sprintf( "'%s' [state = %s] [status = %s]", $node->{name}, $node_vm_state->{ $node->{state} }, $node->{status} ) ); } } $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', 'status', 'is_clustered', 'note']); } sub disco_show { my ($self, %options) = @_; if (!defined($self->{option_results}->{no_ps})) { my $ps = centreon::common::powershell::hyperv::2012::listnodevms::get_powershell(); $self->{option_results}->{command_options} .= " " . centreon::plugins::misc::powershell_encoded($ps); } my ($stdout) = centreon::plugins::misc::execute( output => $self->{output}, options => $self->{option_results}, command => $self->{option_results}->{command}, command_path => $self->{option_results}->{command_path}, command_options => $self->{option_results}->{command_options} ); my $decoded = $self->manage_selection(stdout => $stdout); foreach my $node (@$decoded) { $self->{output}->add_disco_entry( name => $node->{name}, state => $node_vm_state->{ $node->{state} }, status => $node->{status}, is_clustered => $node->{is_clustered} =~ /True|1/i ? 1 : 0, note => defined($node->{note}) ? $node->{note} : '' ); } } 1; __END__ =head1 MODE List virtual machines on hyper-v node. =over 8 =item B<--timeout> Set timeout time for command execution (Default: 50 sec) =item B<--no-ps> Don't encode powershell. To be used with --command and 'type' command. =item B<--command> Command to get information (Default: 'powershell.exe'). Can be changed if you have output in a file. To be used with --no-ps option!!! =item B<--command-path> Command path (Default: none). =item B<--command-options> Command options (Default: '-InputFormat none -NoLogo -EncodedCommand'). =item B<--ps-display> Display powershell script. =item B<--ps-exec-only> Print powershell output. =back =cut centreon-plugins-20220113/apps/microsoft/hyperv/2012/local/mode/nodeintegrationservice.pm000066400000000000000000000316471417000230700312460ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::hyperv::2012::local::mode::nodeintegrationservice; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::common::powershell::hyperv::2012::nodeintegrationservice; use apps::microsoft::hyperv::2012::local::mode::resources::types qw($node_vm_state $node_vm_integration_service_operational_status); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); use JSON::XS; sub custom_service_status_output { my ($self, %options) = @_; return 'status: ' . $self->{result_values}->{primary_status} . '/' . $self->{result_values}->{secondary_status}; } sub custom_global_status_output { my ($self, %options) = @_; return 'state/version: ' . $self->{result_values}->{integration_service_state} . '/' . $self->{result_values}->{integration_service_version}; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'vm', type => 2, cb_prefix_output => 'prefix_vm_output', cb_long_output => 'vm_long_output', message_multiple => 'All integration services are ok', group => [ { name => 'global', cb_prefix_output => 'prefix_global_output' }, { name => 'service', cb_prefix_output => 'prefix_service_output' } ] } ]; $self->{maps_counters}->{global} = [ { label => 'global-status', threshold => 0, set => { key_values => [ { name => 'integration_service_state' }, { name => 'integration_service_version' }, { name => 'state' }, { name => 'vm' } ], closure_custom_output => $self->can('custom_global_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } } ]; $self->{maps_counters}->{service} = [ { label => 'service-status', threshold => 0, set => { key_values => [ { name => 'primary_status' }, { name => 'secondary_status' }, { name => 'enabled' }, { name => 'vm' }, { name => 'service' } ], closure_custom_output => $self->can('custom_service_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } } ]; } sub vm_long_output { my ($self, %options) = @_; return "checking virtual machine '" . $options{instance_value}->{vm} . "'"; } sub prefix_vm_output { my ($self, %options) = @_; return "VM '" . $options{instance_value}->{vm} . "' "; } sub prefix_service_output { my ($self, %options) = @_; return "integration service '" . $options{instance_value}->{service} . "' "; } sub prefix_global_output { my ($self, %options) = @_; return "global virtual machine '" . $options{instance_value}->{vm} . "' integration service "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'timeout:s' => { name => 'timeout', default => 50 }, 'command:s' => { name => 'command', default => 'powershell.exe' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '-InputFormat none -NoLogo -EncodedCommand' }, 'no-ps' => { name => 'no_ps' }, 'ps-exec-only' => { name => 'ps_exec_only' }, 'ps-display' => { name => 'ps_display' }, '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 => '' }, 'warning-service-status:s' => { name => 'warning_service_status', default => '' }, 'critical-service-status:s' => { name => 'critical_service_status', default => '%{primary_status} !~ /Ok/i' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_service_status', 'critical_service_status', 'warning_global_status', 'critical_global_status']); } sub manage_selection { my ($self, %options) = @_; if (!defined($self->{option_results}->{no_ps})) { my $ps = centreon::common::powershell::hyperv::2012::nodeintegrationservice::get_powershell(); if (defined($self->{option_results}->{ps_display})) { $self->{output}->output_add( severity => 'OK', short_msg => $ps ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{option_results}->{command_options} .= " " . centreon::plugins::misc::powershell_encoded($ps); } my ($stdout) = centreon::plugins::misc::execute( output => $self->{output}, options => $self->{option_results}, command => $self->{option_results}->{command}, command_path => $self->{option_results}->{command_path}, command_options => $self->{option_results}->{command_options} ); if (defined($self->{option_results}->{ps_exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } my $decoded; eval { $decoded = JSON::XS->new->decode($stdout); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } #[ # { # "name": "test1", "state": 2, "integration_services_state": "Update required", "integration_services_version": "3.1", "note": null, # "services": [ # { "service": "Time Synchronization", "enabled": true, "primary_operational_status": 12, "secondary_operational_status": null }, # { "service": "Key-Value Pair Exchange", "enabled": true, "primary_operational_status": 12, "secondary_operational_status": null }, # { "service": "Shutdown", "enabled": true, "primary_operational_status": 12, "secondary_operational_status": null }, # { "service": "VSS", "enabled": true, "primary_operational_status": 12, "secondary_operational_status": null }, # { "service": "Guest Service Interface", "enabled": false, "primary_operational_status": 2, "secondary_operational_status": null } # ] # }, # { # "name": "test2", "state": 2, "integration_services_state": null, "integration_services_version": null, "note": null, # "services": [ # { "service": "Time Synchronization", "enabled": true, "primary_operational_status": 12, "secondary_operational_status": null }, # { "service": "Key-Value Pair Exchange", "enabled": true, "primary_operational_status": 12, "secondary_operational_status": null }, # { "service": "Shutdown", "enabled": true, "primary_operational_status": 12, "secondary_operational_status": null }, # { "service": "VSS", "enabled": true, "primary_operational_status": 12, "secondary_operational_status": null }, # { "service": "Guest Service Interface", "enabled": false, "primary_operational_status": 2, "secondary_operational_status": null } # ] # } #] $self->{vm} = {}; my $id = 1; foreach my $node (@$decoded) { if (defined($self->{option_results}->{filter_vm}) && $self->{option_results}->{filter_vm} ne '' && $node->{name} !~ /$self->{option_results}->{filter_vm}/i) { $self->{output}->output_add(long_msg => "skipping '" . $node->{name} . "': no matching filter.", debug => 1); next; } if (defined($self->{option_results}->{filter_status}) && $self->{option_results}->{filter_status} ne '' && $node_vm_state->{ $node->{state} } !~ /$self->{option_results}->{filter_status}/i) { $self->{output}->output_add(long_msg => "skipping '" . $node->{name} . "': no matching filter.", debug => 1); next; } if (defined($self->{option_results}->{filter_note}) && $self->{option_results}->{filter_note} ne '' && defined($node->{note}) && $node->{note} !~ /$self->{option_results}->{filter_note}/i) { $self->{output}->output_add(long_msg => "skipping '" . $node->{name} . "': no matching filter.", debug => 1); next; } $self->{vm}->{$id} = { vm => $node->{name}, service => {} }; $self->{vm}->{$id}->{global} = { $node->{name} => { vm => $node->{name}, integration_service_state => defined($node->{integration_services_state}) ? $node->{integration_services_state} : '-', integration_service_version => defined($node->{integration_services_version}) ? $node->{integration_services_version} : '-', state => $node_vm_state->{ $node->{state} } } }; my $id2 = 1; my $services = (ref($node->{services}) eq 'ARRAY') ? $node->{services} : [ $node->{services} ]; foreach my $service (@$services) { $self->{vm}->{$id}->{service}->{$id2} = { vm => $node->{name}, service => $service->{service}, enabled => $service->{enabled} =~ /True|1/i ? 1 : 0, primary_status => defined($service->{primary_operational_status}) && defined($node_vm_integration_service_operational_status->{ $service->{primary_operational_status} }) ? $node_vm_integration_service_operational_status->{ $service->{primary_operational_status} } : '-', secondary_status => defined($service->{secondary_operational_status}) && defined($node_vm_integration_service_operational_status->{ $service->{secondary_operational_status} }) ? $node_vm_integration_service_operational_status->{ $service->{secondary_operational_status} } : '-' }; $id2++; } $id++; } } 1; __END__ =head1 MODE Check virtual machine integration services on hyper-v node. =over 8 =item B<--timeout> Set timeout time for command execution (Default: 50 sec) =item B<--no-ps> Don't encode powershell. To be used with --command and 'type' command. =item B<--command> Command to get information (Default: 'powershell.exe'). Can be changed if you have output in a file. To be used with --no-ps option!!! =item B<--command-path> Command path (Default: none). =item B<--command-options> Command options (Default: '-InputFormat none -NoLogo -EncodedCommand'). =item B<--ps-display> Display powershell script. =item B<--ps-exec-only> Print powershell output. =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'). Can used special variables like: %{vm}, %{integration_service_state}, %{integration_service_version}, %{state} =item B<--critical-global-status> Set critical threshold for status (Default: ''). Can used special variables like: %{vm}, %{integration_service_state}, %{integration_service_version}, %{state} =item B<--warning-service-status> Set warning threshold for status (Default: ''). Can used special variables like: %{vm}, %{service}, %{primary_status}, %{secondary_status}, %{enabled} =item B<--critical-service-status> Set critical threshold for status (Default: '%{primary_status} !~ /Ok/i'). Can used special variables like: %{vm}, %{service}, %{primary_status}, %{secondary_status}, %{enabled} =back =cut centreon-plugins-20220113/apps/microsoft/hyperv/2012/local/mode/nodereplication.pm000066400000000000000000000150441417000230700276440ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::hyperv::2012::local::mode::nodereplication; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::common::powershell::hyperv::2012::nodereplication; use apps::microsoft::hyperv::2012::local::mode::resources::types qw($node_replication_state); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); use JSON::XS; sub custom_status_output { my ($self, %options) = @_; return 'replication health: ' . $self->{result_values}->{health}; } 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' } ]; $self->{maps_counters}->{vm} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'vm' }, { name => 'state' }, { name => 'health' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } } ]; } sub prefix_vm_output { my ($self, %options) = @_; return "VM '" . $options{instance_value}->{vm} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'timeout:s' => { name => 'timeout', default => 50 }, 'command:s' => { name => 'command', default => 'powershell.exe' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '-InputFormat none -NoLogo -EncodedCommand' }, 'no-ps' => { name => 'no_ps' }, 'ps-exec-only' => { name => 'ps_exec_only' }, 'ps-display' => { name => 'ps_display' }, 'filter-vm:s' => { name => 'filter_vm' }, 'warning-status:s' => { name => 'warning_status', default => '%{health} =~ /Warning/i' }, 'critical-status:s' => { name => 'critical_status', default => '%{health} =~ /Critical/i' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; if (!defined($self->{option_results}->{no_ps})) { my $ps = centreon::common::powershell::hyperv::2012::nodereplication::get_powershell(); if (defined($self->{option_results}->{ps_display})) { $self->{output}->output_add( severity => 'OK', short_msg => $ps ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{option_results}->{command_options} .= " " . centreon::plugins::misc::powershell_encoded($ps); } my ($stdout) = centreon::plugins::misc::execute( output => $self->{output}, options => $self->{option_results}, command => $self->{option_results}->{command}, command_path => $self->{option_results}->{command_path}, command_options => $self->{option_results}->{command_options} ); if (defined($self->{option_results}->{ps_exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } my $decoded; eval { $decoded = JSON::XS->new->decode($stdout); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } #[ # { "name": "XXXX1", "state": "Replicating", "health": "Critical" }, # { "name": "XXXX2", "state": "Replicating", "health": "Normal" }, # { "name": "XXXX3", "state": "Replicating", "health": "Warning" } #] $self->{vm} = {}; my $id = 1; foreach my $node (@$decoded) { if (defined($self->{option_results}->{filter_vm}) && $self->{option_results}->{filter_vm} ne '' && $node->{name} !~ /$self->{option_results}->{filter_vm}/i) { $self->{output}->output_add(long_msg => "skipping '" . $node->{name} . "': no matching filter.", debug => 1); next; } $self->{vm}->{$id} = { vm => $node->{name}, state => $node_replication_state->{ $node->{state} }, health => $node->{health} }; $id++; } } 1; __END__ =head1 MODE Check virtual machine replication on hyper-v node. =over 8 =item B<--timeout> Set timeout time for command execution (Default: 50 sec) =item B<--no-ps> Don't encode powershell. To be used with --command and 'type' command. =item B<--command> Command to get information (Default: 'powershell.exe'). Can be changed if you have output in a file. To be used with --no-ps option!!! =item B<--command-path> Command path (Default: none). =item B<--command-options> Command options (Default: '-InputFormat none -NoLogo -EncodedCommand'). =item B<--ps-display> Display powershell script. =item B<--ps-exec-only> Print powershell output. =item B<--filter-vm> Filter virtual machines (can be a regexp). =item B<--warning-status> Set warning threshold for status (Default: '%{health} =~ /Warning/i'). Can used special variables like: %{vm}, %{state}, %{health} =item B<--critical-status> Set critical threshold for status (Default: '%{health} =~ /Critical/i'). Can used special variables like: %{vm}, %{state}, %{health} =back =cut centreon-plugins-20220113/apps/microsoft/hyperv/2012/local/mode/nodesnapshot.pm000066400000000000000000000210401417000230700271630ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::hyperv::2012::local::mode::nodesnapshot; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::common::powershell::hyperv::2012::nodesnapshot; use apps::microsoft::hyperv::2012::local::mode::resources::types qw($node_vm_state); use JSON::XS; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'vm', type => 1, cb_prefix_output => 'prefix_vm_output', message_multiple => 'All VM snapshots are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{vm} = [ { label => 'snapshot', set => { key_values => [ { name => 'snapshot' }, { name => 'status' }, { name => 'display' } ], closure_custom_output => $self->can('custom_snapshot_output'), closure_custom_perfdata => sub { return 0; } } }, { label => 'backing', set => { key_values => [ { name => 'backing' }, { name => 'status' }, { name => 'display' } ], closure_custom_output => $self->can('custom_backing_output'), closure_custom_perfdata => sub { return 0; } } } ]; } sub custom_snapshot_output { my ($self, %options) = @_; return "checkpoint started " . centreon::plugins::misc::change_seconds(value => $self->{result_values}->{snapshot}) . " ago"; } sub custom_backing_output { my ($self, %options) = @_; return "backing started " . centreon::plugins::misc::change_seconds(value => $self->{result_values}->{backing}) . " ago"; } sub prefix_vm_output { my ($self, %options) = @_; return "VM '" . $options{instance_value}->{display} . "' [status = " . $options{instance_value}->{status} . '] '; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'timeout:s' => { name => 'timeout', default => 50 }, 'command:s' => { name => 'command', default => 'powershell.exe' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '-InputFormat none -NoLogo -EncodedCommand' }, 'no-ps' => { name => 'no_ps' }, 'ps-exec-only' => { name => 'ps_exec_only' }, 'ps-display' => { name => 'ps_display' }, 'filter-vm:s' => { name => 'filter_vm' }, 'filter-note:s' => { name => 'filter_note' }, 'filter-status:s' => { name => 'filter_status', default => 'running' } }); return $self; } sub manage_selection { my ($self, %options) = @_; if (!defined($self->{option_results}->{no_ps})) { my $ps = centreon::common::powershell::hyperv::2012::nodesnapshot::get_powershell(); if (defined($self->{option_results}->{ps_display})) { $self->{output}->output_add( severity => 'OK', short_msg => $ps ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{option_results}->{command_options} .= " " . centreon::plugins::misc::powershell_encoded($ps); } my ($stdout) = centreon::plugins::misc::execute( output => $self->{output}, options => $self->{option_results}, command => $self->{option_results}->{command}, command_path => $self->{option_results}->{command_path}, command_options => $self->{option_results}->{command_options} ); if (defined($self->{option_results}->{ps_exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } my $decoded; eval { $decoded = JSON::XS->new->decode($stdout); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } #[ # { # "name": "ISC1-SV04404", "state": 2, "note": null, # "checkpoints": [ # { "creation_time": 1475502921.28734, "type": "snapshot" }, # { "creation_time": 1475503073.81975, "type": "backing" } # ] # } #] $self->{vm} = {}; my ($id, $time) = (1, time()); foreach my $node (@$decoded) { my ($name, $status, $note, $content) = ($1, $2, $3, $4); my $checkpoint = { backing => -1, snapshot => -1 }; my $checkpoints = (ref($node->{checkpoints}) eq 'ARRAY') ? $node->{checkpoints} : [ $node->{checkpoints} ]; foreach my $chkpt (@$checkpoints) { next if (!defined($chkpt)); $chkpt->{creation_time} =~ s/,/\./g; $checkpoint->{ $chkpt->{type} } = $chkpt->{creation_time} if ($chkpt->{creation_time} > 0 && ($checkpoint->{ $chkpt->{type} } == -1 || $checkpoint->{ $chkpt->{type} } > $chkpt->{creation_time})); } next if ($checkpoint->{backing} == -1 && $checkpoint->{snapshot} == -1); if (defined($self->{option_results}->{filter_vm}) && $self->{option_results}->{filter_vm} ne '' && $node->{name} !~ /$self->{option_results}->{filter_vm}/i) { $self->{output}->output_add(long_msg => "skipping '" . $node->{name} . "': no matching filter.", debug => 1); next; } if (defined($self->{option_results}->{filter_note}) && $self->{option_results}->{filter_note} ne '' && defined($node->{note}) && $node->{note} !~ /$self->{option_results}->{filter_note}/i) { $self->{output}->output_add(long_msg => "skipping '" . $node->{name} . "': no matching filter.", debug => 1); next; } if (defined($self->{option_results}->{filter_status}) && $self->{option_results}->{filter_status} ne '' && $node_vm_state->{ $node->{state} } !~ /$self->{option_results}->{filter_status}/i) { $self->{output}->output_add(long_msg => "skipping '" . $node->{name} . "': no matching filter.", debug => 1); next; } $self->{vm}->{$id} = { display => $node->{name}, snapshot => $checkpoint->{snapshot} > 0 ? $time - $checkpoint->{snapshot} : undef, backing => $checkpoint->{backing} > 0 ? $time - $checkpoint->{backing} : undef, status => $node_vm_state->{ $node->{state} } }; $id++; } if (scalar(keys %{$self->{vm}}) <= 0) { $self->{output}->output_add( severity => 'OK', short_msg => 'no snapshot found' ); } } 1; __END__ =head1 MODE Check virtual machine snapshots on hyper-v node. =over 8 =item B<--timeout> Set timeout time for command execution (Default: 50 sec) =item B<--no-ps> Don't encode powershell. To be used with --command and 'type' command. =item B<--command> Command to get information (Default: 'powershell.exe'). Can be changed if you have output in a file. To be used with --no-ps option!!! =item B<--command-path> Command path (Default: none). =item B<--command-options> Command options (Default: '-InputFormat none -NoLogo -EncodedCommand'). =item B<--ps-display> Display powershell script. =item B<--ps-exec-only> 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<--warning-*> Threshold warning. Can be: 'snapshot' (in seconds), 'backing' (in seconds). =item B<--critical-*> Threshold critical. Can be: 'snapshot' (in seconds), 'backing' (in seconds). =back =cut centreon-plugins-20220113/apps/microsoft/hyperv/2012/local/mode/nodevmstatus.pm000066400000000000000000000170621417000230700272230ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::hyperv::2012::local::mode::nodevmstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::common::powershell::hyperv::2012::nodevmstatus; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); use apps::microsoft::hyperv::2012::local::mode::resources::types qw($node_vm_state); use JSON::XS; sub custom_status_output { my ($self, %options) = @_; return 'status: ' . $self->{result_values}->{status} . " (state: " . $self->{result_values}->{state} . ", is clustered: " . $self->{result_values}->{is_clustered} . ")"; } 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' }, ]; $self->{maps_counters}->{vm} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'vm' }, { name => 'state' }, { name => 'status' }, { name => 'is_clustered' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } } ]; } sub prefix_vm_output { my ($self, %options) = @_; return "VM '" . $options{instance_value}->{vm} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'timeout:s' => { name => 'timeout', default => 50 }, 'command:s' => { name => 'command', default => 'powershell.exe' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '-InputFormat none -NoLogo -EncodedCommand' }, 'no-ps' => { name => 'no_ps' }, 'ps-exec-only' => { name => 'ps_exec_only' }, 'ps-display' => { name => 'ps_display' }, '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' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; if (!defined($self->{option_results}->{no_ps})) { my $ps = centreon::common::powershell::hyperv::2012::nodevmstatus::get_powershell(); if (defined($self->{option_results}->{ps_display})) { $self->{output}->output_add( severity => 'OK', short_msg => $ps ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{option_results}->{command_options} .= " " . centreon::plugins::misc::powershell_encoded($ps); } my ($stdout) = centreon::plugins::misc::execute( output => $self->{output}, options => $self->{option_results}, command => $self->{option_results}->{command}, command_path => $self->{option_results}->{command_path}, command_options => $self->{option_results}->{command_options} ); if (defined($self->{option_results}->{ps_exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } my $decoded; eval { $decoded = JSON::XS->new->decode($stdout); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } #[ # { "name": "XXXX1", "state": 2, "status": "Operating normally", "is_clustered": true, "note": null }, # { "name": "XXXX2", "state": 2, "status": "Operating normally", "is_clustered": false, "note": null }, # { "name": "XXXX3", "state": 2, "status": "Operating normally", "is_clustered": true, "note": null } #] $self->{vm} = {}; my $id = 1; foreach my $node (@$decoded) { 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 '' && $node->{name} !~ /$self->{option_results}->{filter_vm}/i) { $self->{output}->output_add(long_msg => "skipping '" . $node->{name} . "': no matching filter.", debug => 1); next; } if (defined($self->{option_results}->{filter_note}) && $self->{option_results}->{filter_note} ne '' && defined($node->{note}) && $node->{note} !~ /$self->{option_results}->{filter_note}/i) { $self->{output}->output_add(long_msg => "skipping '" . $node->{name} . "': no matching filter.", debug => 1); next; } $self->{vm}->{$id} = { vm => $node->{name}, status => $node->{status}, state => $node_vm_state->{ $node->{state} }, is_clustered => $node->{is_clustered} =~ /True|1/i ? 1 : 0 }; $id++; } if (scalar(keys %{$self->{vm}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No virtual machine found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check virtual machine status on hyper-v node. =over 8 =item B<--timeout> Set timeout time for command execution (Default: 50 sec) =item B<--no-ps> Don't encode powershell. To be used with --command and 'type' command. =item B<--command> Command to get information (Default: 'powershell.exe'). Can be changed if you have output in a file. To be used with --no-ps option!!! =item B<--command-path> Command path (Default: none). =item B<--command-options> Command options (Default: '-InputFormat none -NoLogo -EncodedCommand'). =item B<--ps-display> Display powershell script. =item B<--ps-exec-only> Print powershell output. =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<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{vm}, %{state}, %{status}, %{is_clustered} =item B<--critical-status> Set critical threshold for status (Default: '%{status} !~ /Operating normally/i'). Can used special variables like: %{vm}, %{state}, %{status}, %{is_clustered} =back =cut centreon-plugins-20220113/apps/microsoft/hyperv/2012/local/mode/resources/000077500000000000000000000000001417000230700261355ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/hyperv/2012/local/mode/resources/types.pm000066400000000000000000000102271417000230700276410ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::hyperv::2012::local::mode::resources::types; use strict; use warnings; use Exporter; our $node_replication_state; our $node_vm_integration_service_operational_status; our $node_vm_state; our $scvmm_vm_status; our @ISA = qw(Exporter); our @EXPORT_OK = qw( $node_replication_state $node_vm_integration_service_operational_status $node_vm_state $scvmm_vm_status ); $node_vm_state = { 1 => 'Other', 2 => 'Running', 3 => 'Off', 4 => 'Stopping', 6 => 'Saved', 9 => 'Paused', 10 => 'Starting', 11 => 'Reset', 32773 => 'Saving', 32776 => 'Pausing', 32777 => 'Resuming', 32779 => 'FastSaved', 32780 => 'FastSaving', 32781 => 'ForceShutdown', 32782 => 'ForceReboot', 32783 => 'RunningCritical', 32784 => 'OffCritical', 32785 => 'StoppingCritical', 32786 => 'SavedCritical', 32787 => 'PausedCritical', 32788 => 'StartingCritical', 32789 => 'ResetCritical', 32790 => 'SavingCritical', 32791 => 'PausingCritical', 32792 => 'ResumingCritical', 32793 => 'FastSavedCritical', 32794 => 'FastSavingCritical' }; $node_replication_state = { 0 => 'Disabled', 1 => 'ReadyForInitialReplication', 2 => 'InitialReplicationInProgress', 3 => 'WaitingForInitialReplication', 4 => 'Replicating', 5 => 'PreparedForFailover', 6 => 'FailedOverWaitingCompletion', 7 => 'FailedOver', 8 => 'Suspended', 9 => 'Error', 10 => 'WaitingForStartResynchronize', 11 => 'Resynchronizing', 12 => 'ResynchronizeSuspended', 13 => 'RecoveryInProgress', 14 => 'FailbackInProgress', 15 => 'FailbackComplete', 16 => 'WaitingForUpdateCompletion', 17 => 'UpdateError', 18 => 'WaitingForRepurposeCompletion', 19 => 'PreparedForSyncReplication', 20 => 'PreparedForGroupReverseReplication', 21 => 'FiredrillInProgress' }; $node_vm_integration_service_operational_status = { 2 => 'Ok', 3 => 'Degraded', 6 => 'Error', 7 => 'NonRecoverableError', 12 => 'NoContact', 13 => 'LostCommunication', 32775 => 'ProtocolMismatch', 32782 => 'ApplicationCritical', 32783 => 'CommunicationTimedOut', 32784 => 'CommunicationFailed', 32896 => 'Disabled' }; $scvmm_vm_status = { 0 => 'Running', 1 => 'PowerOff', 2 => 'PoweringOff', 3 => 'Saved', 4 => 'Saving', 5 => 'Restoring', 6 => 'Paused', 10 => 'DiscardSavedState', 11 => 'Starting', 12 => 'MergingDrives', 13 => 'Deleting', 14 => 'Reset', 80 => 'DiscardingDrives', 81 => 'Pausing', 100 => 'UnderCreation', 101 => 'CreationFailed', 102 => 'Stored', 103 => 'UnderTemplateCreation', 104 => 'TemplateCreationFailed', 105 => 'CustomizationFailed', 106 => 'UnderUpdate', 107 => 'UpdateFailed', 108 => 'ReplacementFailed', 109 => 'UnderReplacement', 200 => 'UnderMigration', 201 => 'MigrationFailed', 210 => 'CreatingCheckpoint', 211 => 'DeletingCheckpoint', 212 => 'RecoveringCheckpoint', 213 => 'CheckpointFailed', 214 => 'InitializingCheckpointOperation', 215 => 'FinishingCheckpointOperation', 220 => 'Missing', 221 => 'HostNotResponding', 222 => 'Unsupported', 223 => 'IncompleteVMConfig', 224 => 'UnsupportedSharedFiles', 225 => 'UnsupportedCluster', 226 => 'UnderLiveCloning', 227 => 'DbOnly', 240 => 'P2VCreationFailed', 250 => 'V2VCreationFailed' }; 1; centreon-plugins-20220113/apps/microsoft/hyperv/2012/local/mode/scvmmdiscovery.pm000066400000000000000000000212411417000230700275360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::hyperv::2012::local::mode::scvmmdiscovery; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::misc; use centreon::common::powershell::hyperv::2012::scvmmdiscovery; use apps::microsoft::hyperv::2012::local::mode::resources::types qw($scvmm_vm_status); use JSON::XS; sub prefix_vm_output { my ($self, %options) = @_; return "VM '" . $options{instance_value}->{vm} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'prettify' => { name => 'prettify' }, 'resource-type:s' => { name => 'resource_type', type => 'vm' }, 'scvmm-hostname:s' => { name => 'scvmm_hostname' }, 'scvmm-username:s' => { name => 'scvmm_username' }, 'scvmm-password:s' => { name => 'scvmm_password' }, 'scvmm-port:s' => { name => 'scvmm_port', default => 8100 }, 'timeout:s' => { name => 'timeout', default => 90 }, 'command:s' => { name => 'command', default => 'powershell.exe' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '-InputFormat none -NoLogo -EncodedCommand' }, 'no-ps' => { name => 'no_ps' }, 'ps-exec-only' => { name => 'ps_exec_only' }, 'ps-display' => { name => 'ps_display' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{resource_type}) || $self->{option_results}->{resource_type} eq '') { $self->{option_results}->{resource_type} = 'vm'; } if ($self->{option_results}->{resource_type} !~ /^vm|host$/) { $self->{output}->add_option_msg(short_msg => 'unknown resource type'); $self->{output}->option_exit(); } foreach my $label (('scvmm_username', 'scvmm_password', 'scvmm_port')) { if (!defined($self->{option_results}->{$label}) || $self->{option_results}->{$label} eq '') { my ($label_opt) = $label; $label_opt =~ tr/_/-/; $self->{output}->add_option_msg(short_msg => "Need to specify --" . $label_opt . " option."); $self->{output}->option_exit(); } } } sub powershell_exec { my ($self, %options) = @_; if (!defined($self->{option_results}->{no_ps})) { my $ps = centreon::common::powershell::hyperv::2012::scvmmdiscovery::get_powershell( scvmm_hostname => $self->{option_results}->{scvmm_hostname}, scvmm_username => $self->{option_results}->{scvmm_username}, scvmm_password => $self->{option_results}->{scvmm_password}, scvmm_port => $self->{option_results}->{scvmm_port} ); if (defined($self->{option_results}->{ps_display})) { $self->{output}->output_add( severity => 'OK', short_msg => $ps ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{option_results}->{command_options} .= " " . centreon::plugins::misc::powershell_encoded($ps); } my ($stdout) = centreon::plugins::misc::execute( output => $self->{output}, options => $self->{option_results}, command => $self->{option_results}->{command}, command_path => $self->{option_results}->{command_path}, command_options => $self->{option_results}->{command_options} ); if (defined($self->{option_results}->{ps_exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } my $decoded; eval { $decoded = JSON::XS->new->decode($self->{output}->decode($stdout)); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } return $decoded; } sub run { my ($self, %options) = @_; my $decoded = $self->powershell_exec(); my $hosts = {}; foreach my $entry (@$decoded) { next if ($entry->{type} ne 'host'); $hosts->{ $entry->{id} } = { cluster_name => $entry->{clusterName}, name => $entry->{name} }; } my $disco_data; my $disco_stats; foreach my $entry (@$decoded) { my $item = {}; $item->{type} = $entry->{type}; if ($self->{option_results}->{resource_type} eq 'vm' && $entry->{type} eq 'vm') { $item->{id} = $entry->{vmId}; $item->{name} = $entry->{name}; $item->{description} = $entry->{description}; $item->{operating_system} = $entry->{operatingSystem}; $item->{status} = $scvmm_vm_status->{ $entry->{status} }; $item->{hostgroup_path} = $entry->{hostGroupPath}; $item->{enabled} = ($entry->{enabled} =~ /True|1/i) ? 'yes' : 'no'; $item->{computer_name} = $entry->{computerName}; $item->{tag} = $entry->{tag}; $entry->{ipv4Addresses} = [$entry->{ipv4Addresses}] if (ref($entry->{ipv4Addresses}) ne 'ARRAY'); $item->{ipv4_addresses} = $entry->{ipv4Addresses}; $item->{ipv4_address} = defined($entry->{ipv4Addresses}->[0]) ? $entry->{ipv4Addresses}->[0] : ''; $item->{vmhost_name} = $hosts->{ $entry->{vmHostId} }->{name}; $item->{cluster_name} = $hosts->{ $entry->{vmHostId} }->{cluster_name}; push @$disco_data, $item; } elsif ($self->{option_results}->{resource_type} eq 'host' && $entry->{type} eq 'host') { $item->{id} = $entry->{id}; $item->{name} = $entry->{name}; $item->{description} = $entry->{description}; $item->{fqdn} = $entry->{FQDN}; $item->{cluster_name} = $entry->{clusterName}; $item->{operating_system} = $entry->{operatingSystem}; push @$disco_data, $item; } } $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; $disco_stats->{discovered_items} = scalar(@$disco_data); $disco_stats->{results} = $disco_data; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE Resources discovery. =over 8 =item B<--prettify> Prettify JSON output. =item B<--resource-type> Choose the type of resources to discover (Can be: 'host', 'vm') (Mandatory). =item B<--scvmm-hostname> SCVMM hostname. =item B<--scvmm-username> SCVMM username (Required). =item B<--scvmm-password> SCVMM password (Required). =item B<--scvmm-port> SCVMM port (Default: 8100). =item B<--timeout> Set timeout time for command execution (Default: 90 sec) =item B<--no-ps> Don't encode powershell. To be used with --command and 'type' command. =item B<--command> Command to get information (Default: 'powershell.exe'). Can be changed if you have output in a file. To be used with --no-ps option!!! =item B<--command-path> Command path (Default: none). =item B<--command-options> Command options (Default: '-InputFormat none -NoLogo -EncodedCommand'). =item B<--ps-display> Display powershell script. =item B<--ps-exec-only> Print powershell output. =back =cut centreon-plugins-20220113/apps/microsoft/hyperv/2012/local/mode/scvmmintegrationservice.pm000066400000000000000000000364611417000230700314450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::hyperv::2012::local::mode::scvmmintegrationservice; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::common::powershell::hyperv::2012::scvmmintegrationservice; use apps::microsoft::hyperv::2012::local::mode::resources::types qw($scvmm_vm_status); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); use JSON::XS; sub custom_status_output { my ($self, %options) = @_; return 'VMAddition: ' . $self->{result_values}->{vmaddition}; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{vm} = $options{new_datas}->{$self->{instance} . '_vm'}; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; $self->{result_values}->{vmaddition} = $options{new_datas}->{$self->{instance} . '_vm_addition'}; $self->{result_values}->{operatingsystemshutdownenabled} = $options{new_datas}->{$self->{instance} . '_operating_system_shutdown_enabled'}; $self->{result_values}->{timesynchronizationenabled} = $options{new_datas}->{$self->{instance} . '_time_synchronization_enabled'}; $self->{result_values}->{dataexchangeenabled} = $options{new_datas}->{$self->{instance} . '_data_exchange_enabled'}; $self->{result_values}->{heartbeatenabled} = $options{new_datas}->{$self->{instance} . '_heartbeat_enabled'}; $self->{result_values}->{backupenabled} = $options{new_datas}->{$self->{instance} . '_backup_enabled'}; return 0; } sub custom_integrationservice_output { my ($self, %options) = @_; return $self->{result_values}->{output_label} . ': ' . $self->{result_values}->{service_status}; } sub custom_integrationservice_calc { my ($self, %options) = @_; $self->{result_values}->{output_label} = $options{extra_options}->{output_label}; $self->{result_values}->{service_status} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{name_status}}; $self->{result_values}->{vm} = $options{new_datas}->{$self->{instance} . '_vm'}; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'vm', type => 1, cb_prefix_output => 'prefix_vm_output', message_multiple => 'All integration services are ok' } ]; $self->{maps_counters}->{vm} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'vm' }, { name => 'status' }, { name => 'vm_addition' }, { name => 'operating_system_shutdown_enabled' }, { name => 'time_synchronization_enabled' }, { name => 'data_exchange_enabled' }, { name => 'heartbeat_enabled' }, { name => 'backup_enabled' } ], 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 => \&catalog_status_threshold } }, { label => 'osshutdown-status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'vm' }, { name => 'operating_system_shutdown_enabled' } ], closure_custom_calc => $self->can('custom_integrationservice_calc'), closure_custom_calc_extra_options => { output_label => 'operating system shutdown', name_status => 'operating_system_shutdown_enabled' }, closure_custom_output => $self->can('custom_integrationservice_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } }, { label => 'timesync-status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'vm' }, { name => 'time_synchronization_enabled' } ], closure_custom_calc => $self->can('custom_integrationservice_calc'), closure_custom_calc_extra_options => { output_label => 'time synchronization', name_status => 'time_synchronization_enabled' }, closure_custom_output => $self->can('custom_integrationservice_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } }, { label => 'dataexchange-status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'vm' }, { name => 'data_exchange_enabled' } ], closure_custom_calc => $self->can('custom_integrationservice_calc'), closure_custom_calc_extra_options => { output_label => 'data exchange', name_status => 'data_exchange_enabled' }, closure_custom_output => $self->can('custom_integrationservice_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } }, { label => 'heartbeat-status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'vm' }, { name => 'heartbeat_enabled' } ], closure_custom_calc => $self->can('custom_integrationservice_calc'), closure_custom_calc_extra_options => { output_label => 'heartbeat', name_status => 'heartbeat_enabled' }, closure_custom_output => $self->can('custom_integrationservice_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } }, { label => 'backup-status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'vm' }, { name => 'backup_enabled' } ], closure_custom_calc => $self->can('custom_integrationservice_calc'), closure_custom_calc_extra_options => { output_label => 'backup', name_status => 'backup_enabled' }, closure_custom_output => $self->can('custom_integrationservice_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } } ]; } sub prefix_vm_output { my ($self, %options) = @_; return "VM '" . $options{instance_value}->{vm} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'scvmm-hostname:s' => { name => 'scvmm_hostname' }, 'scvmm-username:s' => { name => 'scvmm_username' }, 'scvmm-password:s' => { name => 'scvmm_password' }, 'scvmm-port:s' => { name => 'scvmm_port', default => 8100 }, 'timeout:s' => { name => 'timeout', default => 50 }, 'command:s' => { name => 'command', default => 'powershell.exe' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '-InputFormat none -NoLogo -EncodedCommand' }, 'no-ps' => { name => 'no_ps' }, 'ps-exec-only' => { name => 'ps_exec_only' }, 'ps-display' => { name => 'ps_display' }, 'filter-vm:s' => { name => 'filter_vm' }, 'filter-description:s' => { name => 'filter_description' }, 'filter-hostgroup:s' => { name => 'filter_hostgroup' }, 'filter-status:s' => { name => 'filter_status' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{vmaddition} =~ /not detected/i' }, 'warning-osshutdown-status:s' => { name => 'warning_osshutdown_status', default => '' }, 'critical-osshutdown-status:s' => { name => 'critical_osshutdown_status', default => '' }, 'warning-timesync-status:s' => { name => 'warning_timesync_status', default => '' }, 'critical-timesync-status:s' => { name => 'critical_timesync_status', default => '' }, 'warning-dataexchange-status:s' => { name => 'warning_dataexchange_status', default => '' }, 'critical-dataexchange-status:s' => { name => 'critical_dataexchange_status', default => '' }, 'warning-heartbeat-status:s' => { name => 'warning_heartbeat_status', default => '' }, 'critical-heartbeat-status:s' => { name => 'critical_heartbeat_status', default => '' }, 'warning-backup-status:s' => { name => 'warning_backup_status', default => '' }, 'critical-backup-status:s' => { name => 'critical_backup_status', default => '' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); foreach my $label (('scvmm_username', 'scvmm_password', 'scvmm_port')) { if (!defined($self->{option_results}->{$label}) || $self->{option_results}->{$label} eq '') { my ($label_opt) = $label; $label_opt =~ tr/_/-/; $self->{output}->add_option_msg(short_msg => "Need to specify --" . $label_opt . " option."); $self->{output}->option_exit(); } } $self->change_macros(macros => [ 'warning_status', 'critical_status', 'warning_osshutdown_status', 'critical_osshutdown_status', 'warning_timesync_status', 'critical_timesync_status', 'warning_dataexchange_status', 'critical_dataexchange_status', 'warning_heartbeat_status', 'critical_heartbeat_status', 'warning_backup_status', 'critical_backup_status' ]); } sub manage_selection { my ($self, %options) = @_; if (!defined($self->{option_results}->{no_ps})) { my $ps = centreon::common::powershell::hyperv::2012::scvmmintegrationservice::get_powershell( scvmm_hostname => $self->{option_results}->{scvmm_hostname}, scvmm_username => $self->{option_results}->{scvmm_username}, scvmm_password => $self->{option_results}->{scvmm_password}, scvmm_port => $self->{option_results}->{scvmm_port} ); if (defined($self->{option_results}->{ps_display})) { $self->{output}->output_add( severity => 'OK', short_msg => $ps ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{option_results}->{command_options} .= " " . centreon::plugins::misc::powershell_encoded($ps); } my ($stdout) = centreon::plugins::misc::execute( output => $self->{output}, options => $self->{option_results}, command => $self->{option_results}->{command}, command_path => $self->{option_results}->{command_path}, command_options => $self->{option_results}->{command_options} ); if (defined($self->{option_results}->{ps_exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } my $decoded; eval { $decoded = JSON::XS->new->decode($stdout); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } #[ # { "name": "test1", "description": "Test Descr - - pp - - aa", "status": 0, "cloud": "", "host_group_path": "All Hosts\\\CORP\\\test1", "vm_addition": "6.3.9600.16384" }, # { # "name": "test2", "description": "", "status": 0, "cloud": "", "host_group_path": "All Hosts\\\CORP\\\test2", "vm_addition": "Not Detected", # "operating_system_shutdown_enabled": true, # "time_synchronization_enabled": false, # "data_exchange_enabled": true, # "heartbeat_enabled": false, # "backup_enabled": true # } #] $self->{vm} = {}; my $id = 1; foreach my $node (@$decoded) { $node->{hostgroup} = $node->{host_group_path}; $node->{vm} = $node->{name}; $node->{status} = $scvmm_vm_status->{ $node->{status} }; foreach (('operating_system_shutdown_enabled', 'time_synchronization_enabled', 'data_exchange_enabled', 'heartbeat_enabled', 'backup_enabled')) { $node->{$_} = ($node->{$_} =~ /True|1/i ? 1 : 0) if (defined($node->{$_})); } my $filtered = 0; foreach (('vm', 'description', 'status', 'hostgroup')) { if (defined($self->{option_results}->{'filter_' . $_}) && $self->{option_results}->{'filter_' . $_} ne '' && $node->{$_} !~ /$self->{option_results}->{'filter_' . $_}/i) { $self->{output}->output_add(long_msg => "skipping '" . $node->{name} . "': no matching filter.", debug => 1); $filtered = 1; last; } } next if ($filtered == 1); $self->{vm}->{$id} = { %$node }; $id++; } } 1; __END__ =head1 MODE Check virtual machine integration services on SCVMM. =over 8 =item B<--scvmm-hostname> SCVMM hostname. =item B<--scvmm-username> SCVMM username (Required). =item B<--scvmm-password> SCVMM password (Required). =item B<--scvmm-port> SCVMM port (Default: 8100). =item B<--timeout> Set timeout time for command execution (Default: 50 sec) =item B<--no-ps> Don't encode powershell. To be used with --command and 'type' command. =item B<--command> Command to get information (Default: 'powershell.exe'). Can be changed if you have output in a file. To be used with --no-ps option!!! =item B<--command-path> Command path (Default: none). =item B<--command-options> Command options (Default: '-InputFormat none -NoLogo -EncodedCommand'). =item B<--ps-display> Display powershell script. =item B<--ps-exec-only> Print powershell output. =item B<--filter-status> Filter virtual machine status (can be a regexp). =item B<--filter-description> Filter by description (can be a regexp). =item B<--filter-vm> Filter virtual machines (can be a regexp). =item B<--filter-hostgroup> Filter hostgroup (can be a regexp). =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{vm}, %{vmaddition}, %{status} =item B<--critical-status> Set critical threshold for status (Default: '%{vmaddition} =~ /not detected/i'). Can used special variables like: %{vm}, %{vmaddition}, %{status} =back =cut centreon-plugins-20220113/apps/microsoft/hyperv/2012/local/mode/scvmmsnapshot.pm000066400000000000000000000203341417000230700273700ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::hyperv::2012::local::mode::scvmmsnapshot; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::common::powershell::hyperv::2012::scvmmsnapshot; use apps::microsoft::hyperv::2012::local::mode::resources::types qw($scvmm_vm_status); use JSON::XS; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'vm', type => 1, cb_prefix_output => 'prefix_vm_output', message_multiple => 'All VM snapshots are ok' } ]; $self->{maps_counters}->{vm} = [ { label => 'snapshot', set => { key_values => [ { name => 'snapshot' }, { name => 'display' } ], closure_custom_output => $self->can('custom_vm_output'), closure_custom_perfdata => sub { return 0; } } } ]; } sub custom_vm_output { my ($self, %options) = @_; return 'checkpoint started since: ' . centreon::plugins::misc::change_seconds(value => $self->{result_values}->{snapshot}); } sub prefix_vm_output { my ($self, %options) = @_; return "VM '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'scvmm-hostname:s' => { name => 'scvmm_hostname' }, 'scvmm-username:s' => { name => 'scvmm_username' }, 'scvmm-password:s' => { name => 'scvmm_password' }, 'scvmm-port:s' => { name => 'scvmm_port', default => 8100 }, 'timeout:s' => { name => 'timeout', default => 50 }, 'command:s' => { name => 'command', default => 'powershell.exe' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '-InputFormat none -NoLogo -EncodedCommand' }, 'no-ps' => { name => 'no_ps' }, 'ps-exec-only' => { name => 'ps_exec_only' }, 'ps-display' => { name => 'ps_display' }, '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' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); foreach my $label (('scvmm_username', 'scvmm_password', 'scvmm_port')) { if (!defined($self->{option_results}->{$label}) || $self->{option_results}->{$label} eq '') { my ($label_opt) = $label; $label_opt =~ tr/_/-/; $self->{output}->add_option_msg(short_msg => "Need to specify --" . $label_opt . " option."); $self->{output}->option_exit(); } } } sub manage_selection { my ($self, %options) = @_; if (!defined($self->{option_results}->{no_ps})) { my $ps = centreon::common::powershell::hyperv::2012::scvmmsnapshot::get_powershell( scvmm_hostname => $self->{option_results}->{scvmm_hostname}, scvmm_username => $self->{option_results}->{scvmm_username}, scvmm_password => $self->{option_results}->{scvmm_password}, scvmm_port => $self->{option_results}->{scvmm_port}, ); if (defined($self->{option_results}->{ps_display})) { $self->{output}->output_add( severity => 'OK', short_msg => $ps ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{option_results}->{command_options} .= " " . centreon::plugins::misc::powershell_encoded($ps); } my ($stdout) = centreon::plugins::misc::execute( output => $self->{output}, options => $self->{option_results}, command => $self->{option_results}->{command}, command_path => $self->{option_results}->{command_path}, command_options => $self->{option_results}->{command_options} ); if (defined($self->{option_results}->{ps_exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } my $decoded; eval { $decoded = JSON::XS->new->decode($stdout); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } #[ # { # "name": "test-server", "description": "", "status": 0, "cloud": "", "host_group_path": "All Hosts\\\CORP\\\Test\\\test-server", # "checkpoints": [ # { "added_time": 1475502741.957 }, # { "added_time": 1475502963.21 } # ] # } #] $self->{vm} = {}; my $id = 1; foreach my $node (@$decoded) { $node->{hostgroup} = $node->{host_group_path}; $node->{vm} = $node->{name}; $node->{status} = $scvmm_vm_status->{ $node->{status} }; my $chkpt = -1; my $checkpoints = (ref($node->{checkpoints}) eq 'ARRAY') ? $node->{checkpoints} : [ $node->{checkpoints} ]; foreach (@$checkpoints) { $chkpt = $_->{added_time} if ($chkpt == -1 || $chkpt > $_->{added_time}); } next if ($chkpt == -1); my $filtered = 0; foreach (('vm', 'description', 'status', 'hostgroup')) { if (defined($self->{option_results}->{'filter_' . $_}) && $self->{option_results}->{'filter_' . $_} ne '' && $node->{$_} !~ /$self->{option_results}->{'filter_' . $_}/i) { $self->{output}->output_add(long_msg => "skipping '" . $node->{$_} . "': no matching filter.", debug => 1); $filtered = 1; last; } } next if ($filtered == 1); $self->{vm}->{$id} = { display => $node->{name}, snapshot => time() - $chkpt }; $id++; } } 1; __END__ =head1 MODE Check virtual machine snapshots on SCVMM. =over 8 =item B<--scvmm-hostname> SCVMM hostname. =item B<--scvmm-username> SCVMM username (Required). =item B<--scvmm-password> SCVMM password (Required). =item B<--scvmm-port> SCVMM port (Default: 8100). =item B<--timeout> Set timeout time for command execution (Default: 50 sec) =item B<--no-ps> Don't encode powershell. To be used with --command and 'type' command. =item B<--command> Command to get information (Default: 'powershell.exe'). Can be changed if you have output in a file. To be used with --no-ps option!!! =item B<--command-path> Command path (Default: none). =item B<--command-options> Command options (Default: '-InputFormat none -NoLogo -EncodedCommand'). =item B<--ps-display> Display powershell script. =item B<--ps-exec-only> 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-description> Filter by description (can be a regexp). =item B<--filter-hostgroup> Filter hostgroup (can be a regexp). =item B<--warning-*> Threshold warning. Can be: 'snapshot' (in seconds). =item B<--critical-*> Threshold critical. Can be: 'snapshot' (in seconds). =back =cut centreon-plugins-20220113/apps/microsoft/hyperv/2012/local/mode/scvmmvmstatus.pm000066400000000000000000000216131417000230700274200ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::hyperv::2012::local::mode::scvmmvmstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::common::powershell::hyperv::2012::scvmmvmstatus; use apps::microsoft::hyperv::2012::local::mode::resources::types qw($scvmm_vm_status); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); use JSON::XS; sub custom_status_output { my ($self, %options) = @_; return 'status: ' . $self->{result_values}->{status}; } 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' } ]; $self->{maps_counters}->{vm} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'vm' }, { name => 'hostgroup' }, { name => 'status' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } } ]; } sub prefix_vm_output { my ($self, %options) = @_; return "VM '" . $options{instance_value}->{vm} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'scvmm-hostname:s' => { name => 'scvmm_hostname' }, 'scvmm-username:s' => { name => 'scvmm_username' }, 'scvmm-password:s' => { name => 'scvmm_password' }, 'scvmm-port:s' => { name => 'scvmm_port', default => 8100 }, 'timeout:s' => { name => 'timeout', default => 50 }, 'command:s' => { name => 'command', default => 'powershell.exe' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '-InputFormat none -NoLogo -EncodedCommand' }, 'no-ps' => { name => 'no_ps' }, 'ps-exec-only' => { name => 'ps_exec_only' }, 'ps-display' => { name => 'ps_display' }, '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' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); foreach my $label (('scvmm_username', 'scvmm_password', 'scvmm_port')) { if (!defined($self->{option_results}->{$label}) || $self->{option_results}->{$label} eq '') { my ($label_opt) = $label; $label_opt =~ tr/_/-/; $self->{output}->add_option_msg(short_msg => "Need to specify --" . $label_opt . " option."); $self->{output}->option_exit(); } } $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; if (!defined($self->{option_results}->{no_ps})) { my $ps = centreon::common::powershell::hyperv::2012::scvmmvmstatus::get_powershell( scvmm_hostname => $self->{option_results}->{scvmm_hostname}, scvmm_username => $self->{option_results}->{scvmm_username}, scvmm_password => $self->{option_results}->{scvmm_password}, scvmm_port => $self->{option_results}->{scvmm_port} ); if (defined($self->{option_results}->{ps_display})) { $self->{output}->output_add( severity => 'OK', short_msg => $ps ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{option_results}->{command_options} .= " " . centreon::plugins::misc::powershell_encoded($ps); } my ($stdout) = centreon::plugins::misc::execute( output => $self->{output}, options => $self->{option_results}, command => $self->{option_results}->{command}, command_path => $self->{option_results}->{command_path}, command_options => $self->{option_results}->{command_options} ); if (defined($self->{option_results}->{ps_exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } my $decoded; eval { $decoded = JSON::XS->new->decode($stdout); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } #[ # { "name": "test-server", "description": "", "status": 0, "cloud": "", "host_group_path": "All Hosts\\\CORP\\\Test\\\test-server" }, # { "name": "test-server2", "description": "", "status": 0, "cloud": "", "host_group_path": "All Hosts\\\CORP\\\Test\\\test-server2" } #] $self->{vm} = {}; my $id = 1; foreach my $node (@$decoded) { if (defined($self->{option_results}->{filter_vm}) && $self->{option_results}->{filter_vm} ne '' && $node->{name} !~ /$self->{option_results}->{filter_vm}/i) { $self->{output}->output_add(long_msg => "skipping '" . $node->{name} . "': no matching filter.", debug => 1); next; } if (defined($self->{option_results}->{filter_description}) && $self->{option_results}->{filter_description} ne '' && $node->{description} !~ /$self->{option_results}->{filter_description}/i) { $self->{output}->output_add(long_msg => "skipping '" . $node->{node} . "': no matching filter.", debug => 1); next; } if (defined($self->{option_results}->{filter_hostgroup}) && $self->{option_results}->{filter_hostgroup} ne '' && $node->{host_group_path} !~ /$self->{option_results}->{filter_hostgroup}/i) { $self->{output}->output_add(long_msg => "skipping '" . $node->{node} . "': no matching filter.", debug => 1); next; } $self->{vm}->{$id} = { vm => $node->{name}, status => $scvmm_vm_status->{ $node->{status} }, hostgroup => $node->{host_group_path} }; $id++; } if (scalar(keys %{$self->{vm}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No virtual machine found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check virtual machine status on SCVMM. =over 8 =item B<--scvmm-hostname> SCVMM hostname. =item B<--scvmm-username> SCVMM username (Required). =item B<--scvmm-password> SCVMM password (Required). =item B<--scvmm-port> SCVMM port (Default: 8100). =item B<--timeout> Set timeout time for command execution (Default: 50 sec) =item B<--no-ps> Don't encode powershell. To be used with --command and 'type' command. =item B<--command> Command to get information (Default: 'powershell.exe'). Can be changed if you have output in a file. To be used with --no-ps option!!! =item B<--command-path> Command path (Default: none). =item B<--command-options> Command options (Default: '-InputFormat none -NoLogo -EncodedCommand'). =item B<--ps-display> Display powershell script. =item B<--ps-exec-only> Print powershell output. =item B<--filter-vm> Filter virtual machines (can be a regexp). =item B<--filter-hostgroup> 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: ''). Can used special variables like: %{vm}, %{status}, %{hostgroup} =item B<--critical-status> Set critical threshold for status (Default: '%{status} !~ /Running|Stopped/i'). Can used special variables like: %{vm}, %{status}, %{hostgroup} =back =cut centreon-plugins-20220113/apps/microsoft/hyperv/2012/local/plugin.pm000066400000000000000000000040661417000230700250410ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::hyperv::2012::local::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} = '0.1'; $self->{modes} = { 'list-node-vms' => 'apps::microsoft::hyperv::2012::local::mode::listnodevms', 'node-integration-service' => 'apps::microsoft::hyperv::2012::local::mode::nodeintegrationservice', 'node-replication' => 'apps::microsoft::hyperv::2012::local::mode::nodereplication', 'node-snapshot' => 'apps::microsoft::hyperv::2012::local::mode::nodesnapshot', 'node-vm-status' => 'apps::microsoft::hyperv::2012::local::mode::nodevmstatus', 'scvmm-discovery' => 'apps::microsoft::hyperv::2012::local::mode::scvmmdiscovery', 'scvmm-integration-service' => 'apps::microsoft::hyperv::2012::local::mode::scvmmintegrationservice', 'scvmm-snapshot' => 'apps::microsoft::hyperv::2012::local::mode::scvmmsnapshot', 'scvmm-vm-status' => 'apps::microsoft::hyperv::2012::local::mode::scvmmvmstatus' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Windows Hyper-V locally. =cut centreon-plugins-20220113/apps/microsoft/iis/000077500000000000000000000000001417000230700207705ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/iis/local/000077500000000000000000000000001417000230700220625ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/iis/local/mode/000077500000000000000000000000001417000230700230065ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/iis/local/mode/applicationpoolstate.pm000066400000000000000000000112361417000230700276050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::iis::local::mode::applicationpoolstate; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Win32::OLE; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; return sprintf( 'state: %s [auto: %s]', $self->{result_values}->{state}, $self->{result_values}->{auto_start} ); } sub prefix_pool_output { my ($self, %options) = @_; return "Application pool '" . $options{instance_value}->{name} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'pools', type => 1, cb_prefix_output => 'prefix_pool_output', message_multiple => 'All application pools are ok' } ]; $self->{maps_counters}->{pools} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'name' }, { name => 'auto_start' }, { name => 'state' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'unknown-status:s' => { name => 'unknown_status', default => '' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{auto_start} eq "on" and not %{state} =~ /started|starting/' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status', 'unknown_status']); } my $state_map = { 0 => 'starting', 1 => 'started', 2 => 'stopping', 3 => 'stopped', 4 => 'unknown' }; sub manage_selection { my ($self, %options) = @_; my $wmi = Win32::OLE->GetObject('winmgmts:root\WebAdministration'); if (!defined($wmi)) { $self->{output}->add_option_msg(short_msg => "Cant create server object:" . Win32::OLE->LastError()); $self->{output}->option_exit(); } my $query = "Select Name, AutoStart From ApplicationPool"; my $resultset = $wmi->ExecQuery($query); $self->{pools} = {}; foreach my $obj (in $resultset) { my $name = $obj->{Name}; my $state = $state_map->{ $obj->GetState() }; 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 pool '" . $name . "': no matching filter.", debug => 1); next; } $self->{pools}->{$name} = { name => $name, state => $state, auto_start => $obj->{AutoStart} == 0 ? 'off' : 'on' }; } if (scalar(keys %{$self->{pools}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No application pool found'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check IIS application pools. =over 8 =item B<--filter-name> Filter application pool name (can be a regexp). =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{name}, %{state}, %{auto_start}. =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{name}, %{state}, %{auto_start}. =item B<--critical-status> Set critical threshold for status (Default: '%{auto_start} eq "on" and not %{state} =~ /started|starting/'). Can used special variables like: %{name}, %{state}, %{auto_start}. =back =cut centreon-plugins-20220113/apps/microsoft/iis/local/mode/listapplicationpools.pm000066400000000000000000000110271417000230700276210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::iis::local::mode::listapplicationpools; use base qw(centreon::plugins::mode); use strict; use warnings; use Win32::OLE; my %state_map = ( 0 => 'starting', 1 => 'started', 2 => 'stopping', 3 => 'stopped', 4 => 'unknown', ); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'name:s' => { name => 'name' }, 'regexp' => { name => 'use_regexp' }, 'filter-state:s' => { name => 'filter_state' } }); $self->{result} = {}; return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; my $wmi = Win32::OLE->GetObject('winmgmts:root\WebAdministration'); if (!defined($wmi)) { $self->{output}->add_option_msg(short_msg => "Cant create server object:" . Win32::OLE->LastError()); $self->{output}->option_exit(); } my $query = 'SELECT Name, AutoStart FROM ApplicationPool'; my $resultset = $wmi->ExecQuery($query); # AutoStart -> 1/0 foreach my $obj (in $resultset) { my $name = $obj->{Name}; my $auto_start = $obj->{AutoStart}; my $state = $obj->GetState(); if (defined($self->{option_results}->{filter_state}) && $state_map{$state} !~ /$self->{option_results}->{filter_state}/) { $self->{output}->output_add(long_msg => "Skipping application pool '" . $name . "': no matching filter state"); next; } if (defined($self->{option_results}->{name}) && !defined($self->{option_results}->{use_regexp}) && $name ne $self->{option_results}->{name}) { $self->{output}->output_add(long_msg => "Skipping application pool '" . $name . "': no matching filter name"); next; } if (defined($self->{option_results}->{name}) && defined($self->{option_results}->{use_regexp}) && $name !~ /$self->{option_results}->{name}/) { $self->{output}->output_add(long_msg => "Skipping application pool '" . $name . "': no matching filter name (regexp)"); next; } $self->{result}->{$name} = {AutoStart => $auto_start, State => $state}; } } sub run { my ($self, %options) = @_; $self->manage_selection(); foreach my $name (sort(keys %{$self->{result}})) { $self->{output}->output_add(long_msg => "'" . $name . "' . '[AutoStart = " . $self->{result}->{$name}->{AutoStart} . ']' . '[State = ' . $state_map{$self->{result}->{$name}->{State}} . ']' ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List application 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', 'auto_start', 'state']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(); foreach my $name (sort(keys %{$self->{result}})) { $self->{output}->add_disco_entry( name => $name, auto_start => $self->{result}->{$name}->{AutoStart}, state => $state_map{$self->{result}->{$name}->{State}} ); } } 1; __END__ =head1 MODE List IIS Application Pools. =over 8 =item B<--name> Set the application pool name. =item B<--regexp> Allows to use regexp to filter application pool name (with option --name). =item B<--filter-state> Filter application pool state. Regexp can be used. Available states are: - 'started', - 'starting', - 'stopped', - 'stopping' - 'unknown' =back =cut centreon-plugins-20220113/apps/microsoft/iis/local/mode/listsites.pm000066400000000000000000000110671417000230700253740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::iis::local::mode::listsites; use base qw(centreon::plugins::mode); use strict; use warnings; use Win32::OLE; my %state_map = ( 0 => 'starting', 1 => 'started', 2 => 'stopping', 3 => 'stopped', 4 => 'unknown' ); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'name:s' => { name => 'name' }, 'regexp' => { name => 'use_regexp' }, 'filter-state:s' => { name => 'filter_state' } }); $self->{result} = {}; return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; my $wmi = Win32::OLE->GetObject('winmgmts:root\WebAdministration'); if (!defined($wmi)) { $self->{output}->add_option_msg(short_msg => "Cant create server object:" . Win32::OLE->LastError()); $self->{output}->option_exit(); } my $query = 'SELECT Name, ServerAutoStart FROM Site'; my $resultset = $wmi->ExecQuery($query); # ServerAutoStart -> 1/0 foreach my $obj (in $resultset) { my $name = $obj->{Name}; my $auto_start = $obj->{ServerAutoStart}; my $state = $obj->GetState(); if (defined($self->{option_results}->{filter_state}) && $state_map{$state} !~ /$self->{option_results}->{filter_state}/) { $self->{output}->output_add(long_msg => "Skipping site '" . $name . "': no matching filter state"); next; } if (defined($self->{option_results}->{name}) && !defined($self->{option_results}->{use_regexp}) && $name ne $self->{option_results}->{name}) { $self->{output}->output_add(long_msg => "Skipping site '" . $name . "': no matching filter name"); next; } if (defined($self->{option_results}->{name}) && defined($self->{option_results}->{use_regexp}) && $name !~ /$self->{option_results}->{name}/) { $self->{output}->output_add(long_msg => "Skipping site '" . $name . "': no matching filter name (regexp)"); next; } $self->{result}->{$name} = {AutoStart => $auto_start, State => $state}; } } sub run { my ($self, %options) = @_; $self->manage_selection(); foreach my $name (sort(keys %{$self->{result}})) { $self->{output}->output_add(long_msg => "'" . $name . "' [AutoStart = " . $self->{result}->{$name}->{AutoStart} . '] [' . 'State = ' . $state_map{$self->{result}->{$name}->{State}} . ']'); } $self->{output}->output_add(severity => 'OK', short_msg => 'List sites:'); $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', 'auto_start', 'state']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(); foreach my $name (sort(keys %{$self->{result}})) { $self->{output}->add_disco_entry(name => $name, auto_start => $self->{result}->{$name}->{AutoStart}, state => $state_map{$self->{result}->{$name}->{State}} ); } } 1; __END__ =head1 MODE List IIS Sites. =over 8 =item B<--name> Set the site name. =item B<--regexp> Allows to use regexp to filter site name (with option --name). =item B<--filter-state> Filter sites state. Regexp can be used. Available states are: 'started', 'starting', 'stopped', 'stopping', 'unknown' =back =cut centreon-plugins-20220113/apps/microsoft/iis/local/mode/webservicestatistics.pm000066400000000000000000000156701417000230700276260ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::iis::local::mode::webservicestatistics; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Win32::OLE; use Digest::MD5 qw(md5_hex); sub prefix_site_output { my ($self, %options) = @_; return "Site '" . $options{instance_value}->{name} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'sites', type => 1, cb_prefix_output => 'prefix_site_output', message_multiple => 'All sites are ok' } ]; $self->{maps_counters}->{sites} = [ { label => 'connections-attempt', nlabel => 'site.connections.attempt.persecond', set => { key_values => [ { name => 'connections_attempt', per_second => 1 } ], output_template => 'connections attempt: %.2f/s', perfdatas => [ { template => '%.2f', unit => '/s', min => 0, label_extra_instance => 1 } ] } }, { label => 'users-anonymous', nlabel => 'site.users.anonymous.persecond', display_ok => 0, set => { key_values => [ { name => 'anonymous_users', per_second => 1 } ], output_template => 'anonymous users: %.2f/s', perfdatas => [ { template => '%.2f', unit => '/s', min => 0, label_extra_instance => 1 } ] } }, { label => 'requests-post', nlabel => 'site.requests.post.persecond', set => { key_values => [ { name => 'requests_post', per_second => 1 } ], output_template => 'requests post: %.2f/s', perfdatas => [ { template => '%.2f', unit => '/s', min => 0, label_extra_instance => 1 } ] } }, { label => 'requests-get', nlabel => 'site.requests.get.persecond', set => { key_values => [ { name => 'requests_get', per_second => 1 } ], output_template => 'requests get: %.2f/s', perfdatas => [ { template => '%.2f', unit => '/s', min => 0, label_extra_instance => 1 } ] } }, { label => 'traffic-in', nlabel => 'site.traffic.in.bitspersecond', set => { key_values => [ { name => 'traffic_in', per_second => 1 } ], output_template => 'traffic in: %s %s/s', output_change_bytes => 2, perfdatas => [ { template => '%d', unit => 'b/s', min => 0, label_extra_instance => 1 } ] } }, { label => 'traffic-out', nlabel => 'site.traffic.out.bitspersecond', set => { key_values => [ { name => 'traffic_out', per_second => 1 } ], output_template => 'traffic out: %s %s/s', output_change_bytes => 2, perfdatas => [ { template => '%d', unit => 'b/s', min => 0, label_extra_instance => 1 } ] } }, { label => 'files-received', nlabel => 'site.files.received.count', display_ok => 0, set => { key_values => [ { name => 'files_received', diff => 1 } ], output_template => 'files received: %s', perfdatas => [ { template => '%d', min => 0, label_extra_instance => 1 } ] } }, { label => 'files-sent', nlabel => 'site.files.sent.count', display_ok => 0, set => { key_values => [ { name => 'files_sent', diff => 1 } ], output_template => 'files sent: %s', perfdatas => [ { template => '%d', min => 0, label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $wmi = Win32::OLE->GetObject('winmgmts:root\cimv2'); if (!defined($wmi)) { $self->{output}->add_option_msg(short_msg => "Cant create server object:" . Win32::OLE->LastError()); $self->{output}->option_exit(); } my $query = 'Select * From Win32_PerfRawData_W3SVC_WebService'; my $resultset = $wmi->ExecQuery($query); $self->{sites} = {}; foreach my $obj (in $resultset) { my $name = $obj->{Name}; 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 site '" . $name . "': no matching filter.", debug => 1); next; } $self->{sites}->{$name} = { name => $name, anonymous_users => $obj->{TotalAnonymousUsers}, connections_attempt => $obj->{TotalConnectionAttemptsAllInstances}, requests_get => $obj->{TotalGetRequests}, requests_post => $obj->{TotalPostRequests}, traffic_in => $obj->{TotalBytesReceived}, traffic_out => $obj->{TotalBytesSent}, files_received => $obj->{TotalFilesReceived}, files_sent => $obj->{TotalFilesSent} }; } if (scalar(keys %{$self->{sites}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No site found'); $self->{output}->option_exit(); } $self->{cache_name} = 'iis_' . $self->{mode} . '_' . (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 IIS site statistics. =over 8 =item B<--filter-name> Filter site name (can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'connections-attempt', 'users-anonymous', 'requests-post', 'requests-get', 'traffic-in', 'traffic-out'. 'files-received', 'files-sent'. =back =cut centreon-plugins-20220113/apps/microsoft/iis/local/plugin.pm000066400000000000000000000030001417000230700237070ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::iis::local::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} = '0.1'; $self->{modes} = { 'applicationpool-state' => 'apps::microsoft::iis::local::mode::applicationpoolstate', 'list-applicationpools' => 'apps::microsoft::iis::local::mode::listapplicationpools', 'list-sites' => 'apps::microsoft::iis::local::mode::listsites', 'webservice-statistics' => 'apps::microsoft::iis::local::mode::webservicestatistics' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Windows IIS locally. =cut centreon-plugins-20220113/apps/microsoft/iis/restapi/000077500000000000000000000000001417000230700224375ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/iis/restapi/custom/000077500000000000000000000000001417000230700237515ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/iis/restapi/custom/api.pm000066400000000000000000000210711417000230700250610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::iis::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use JSON::XS; 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 => { 'api-username:s' => { name => 'api_username' }, 'api-password:s' => { name => 'api_password' }, 'api-token:s' => { name => 'api_token' }, 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'timeout:s' => { name => 'timeout' }, 'unknown-http-status:s' => { name => 'unknown_http_status' }, 'warning-http-status:s' => { name => 'warning_http_status' }, 'critical-http-status:s' => { name => 'critical_http_status' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 55539; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : ''; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : ''; $self->{api_token} = (defined($self->{option_results}->{api_token})) ? $self->{option_results}->{api_token} : ''; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300'; $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } if ($self->{api_username} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-username option."); $self->{output}->option_exit(); } if ($self->{api_password} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-password option."); $self->{output}->option_exit(); } if ($self->{api_token} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-token option."); $self->{output}->option_exit(); } return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; } sub settings { my ($self, %options) = @_; return if (defined($self->{settings_done})); $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->add_header(key => 'Content-Type', value => 'application/json'); $self->{http}->add_header(key => 'Access-Token', value => 'Bearer ' . $self->{api_token}); $self->{http}->set_options(%{$self->{option_results}}); $self->{settings_done} = 1; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub request_api { my ($self, %options) = @_; $self->settings(); my $login = {}; if (!defined($self->{login_done})) { $login = { credentials => 1, ntlmv2 => 1, username => $self->{api_username}, password => $self->{api_password} }; $self->{login_done} = 1; } my $content = $self->{http}->request( url_path => $options{endpoint}, unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status}, %$login ); if (!defined($content) || $content eq '') { $self->{output}->add_option_msg(short_msg => "API returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } return $decoded; } sub get_application_pools { my ($self, %options) = @_; my $results = {}; my $pools = $self->request_api(endpoint => '/api/webserver/application-pools'); foreach (@{$pools->{app_pools}}) { if (defined($options{filter_name}) && $options{filter_name} ne '' && $_->{name} !~ /$options{filter_name}/) { $self->{output}->output_add(long_msg => "skipping pool '" . $_->{name} . "': no matching filter.", debug => 1); next; } $results->{ $_->{name} } = $_; my $detail = $self->request_api(endpoint => '/api/webserver/application-pools/' . $_->{id}); $results->{ $_->{name} }->{auto_start} = $detail->{auto_start}; next if (defined($options{no_monitoring})); my $monitor = $self->request_api(endpoint => '/api/webserver/application-pools/monitoring/' . $_->{id}); $results->{ $_->{name} }->{requests} = $monitor->{requests}; } return $results; } sub get_websites { my ($self, %options) = @_; my $results = {}; my $websites = $self->request_api(endpoint => '/api/webserver/websites'); foreach (@{$websites->{websites}}) { if (defined($options{filter_name}) && $options{filter_name} ne '' && $_->{name} !~ /$options{filter_name}/) { $self->{output}->output_add(long_msg => "skipping website '" . $_->{name} . "': no matching filter.", debug => 1); next; } $results->{ $_->{name} } = $_; next if (defined($options{no_monitoring})); my $monitor = $self->request_api(endpoint => '/api/webserver/websites/monitoring/' . $_->{id}); $results->{ $_->{name} }->{network} = $monitor->{network}; } return $results; } 1; __END__ =head1 NAME IIS Rest API =head1 REST API OPTIONS IIS Rest API =over 8 =item B<--hostname> IIS hostname. =item B<--port> Port used (Default: 55539) =item B<--proto> Specify https if needed (Default: 'https') =item B<--api-username> IIS API username. =item B<--api-password> IIS API password. =item B<--api-token> IIS API token. =item B<--timeout> Set timeout in seconds (Default: 10). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/microsoft/iis/restapi/mode/000077500000000000000000000000001417000230700233635ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/iis/restapi/mode/applicationpools.pm000066400000000000000000000115261417000230700273060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::iis::restapi::mode::applicationpools; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); use Digest::MD5 qw(md5_hex); sub custom_status_output { my ($self, %options) = @_; return sprintf( 'status: %s [auto start: %s]', $self->{result_values}->{status}, $self->{result_values}->{auto_start} ); } sub prefix_pool_output { my ($self, %options) = @_; return "Application pool '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'pools', type => 1, cb_prefix_output => 'prefix_pool_output', message_multiple => 'All application pools are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{pools} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'auto_start' }, { name => 'display' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } }, { label => 'requests', nlabel => 'applicationpool.requests.persecond', set => { key_values => [ { name => 'requests_total', per_second => 1 }, { name => 'display' } ], output_template => 'requests: %.2f/s', perfdatas => [ { template => '%.2f', min => 0, unit => '/s', label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'unknown-status:s' => { name => 'unknown_status', default => '' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{auto_start} eq "true" and %{status} !~ /starting|started/' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status', 'unknown_status']); } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->get_application_pools(filter_name => $self->{option_results}->{filter_name}); $self->{pools} = {}; foreach (values %$results) { $self->{pools}->{$_->{name}} = { display => $_->{name}, status => $_->{status}, auto_start => $_->{auto_start} ? 'true' : 'false', requests_total => $_->{requests}->{total} }; } $self->{cache_name} = 'iis_' . $self->{mode} . '_' . $options{custom}->get_hostname() . '_' . (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 application pools. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='status' =item B<--filter-name> Filter application pool name (can be a regexp). =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{status}, %{auto_start}, %{display} =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{status}, %{auto_start}, %{display} =item B<--critical-status> Set critical threshold for status (Default: '%{auto_start} eq "true" and %{status} !~ /starting|started/'). Can used special variables like: %{status}, %{auto_start}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'requests'. =back =cut centreon-plugins-20220113/apps/microsoft/iis/restapi/mode/listapplicationpools.pm000066400000000000000000000051151417000230700301770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::iis::restapi::mode::listapplicationpools; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; return $options{custom}->get_application_pools(no_monitoring => 1); } sub run { my ($self, %options) = @_; my $results = $self->manage_selection(custom => $options{custom}); foreach (sort(keys %$results)) { $self->{output}->output_add( long_msg => sprintf( '[name: %s] [status: %s] [auto_start: %s]', $results->{$_}->{name}, $results->{$_}->{status}, $results->{$_}->{auto_start} ? 'true' : 'false' ) ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List application 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', 'auto_start', 'status']); } sub disco_show { my ($self, %options) = @_; my $results = $self->manage_selection(custom => $options{custom}); foreach (sort(keys %$results)) { $self->{output}->add_disco_entry( name => $results->{$_}->{name}, status => $results->{$_}->{status}, auto_start => $results->{$_}->{auto_start} ? 'true' : 'false' ); } } 1; __END__ =head1 MODE List application pools. =over 8 =back =cut centreon-plugins-20220113/apps/microsoft/iis/restapi/mode/listwebsites.pm000066400000000000000000000045771417000230700264570ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::iis::restapi::mode::listwebsites; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; return $options{custom}->get_websites(no_monitoring => 1); } sub run { my ($self, %options) = @_; my $results = $self->manage_selection(custom => $options{custom}); foreach (sort(keys %$results)) { $self->{output}->output_add( long_msg => sprintf( '[name: %s] [status: %s]', $results->{$_}->{name}, $results->{$_}->{status} ) ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List websites:' ); $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', 'status']); } sub disco_show { my ($self, %options) = @_; my $results = $self->manage_selection(custom => $options{custom}); foreach (sort(keys %$results)) { $self->{output}->add_disco_entry( name => $results->{$_}->{name}, status => $results->{$_}->{status} ); } } 1; __END__ =head1 MODE List websites. =over 8 =back =cut centreon-plugins-20220113/apps/microsoft/iis/restapi/mode/websites.pm000066400000000000000000000151531417000230700255530ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::iis::restapi::mode::websites; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); use Digest::MD5 qw(md5_hex); sub custom_status_output { my ($self, %options) = @_; return sprintf( 'status: %s', $self->{result_values}->{status} ); } sub prefix_website_output { my ($self, %options) = @_; return "Website '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'websites', type => 1, cb_prefix_output => 'prefix_website_output', message_multiple => 'All websites are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{websites} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'display' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } }, { label => 'requests', nlabel => 'website.requests.persecond', set => { key_values => [ { name => 'requests_total', per_second => 1 }, { name => 'display' } ], output_template => 'requests: %.2f/s', perfdatas => [ { template => '%.2f', min => 0, unit => '/s', label_extra_instance => 1 } ] } }, { label => 'traffic-in', nlabel => 'website.traffic.in.bitspersecond', set => { key_values => [ { name => 'traffic_in', per_second => 1 }, { name => 'display' } ], output_template => 'traffic in: %s %s/s', output_change_bytes => 2, perfdatas => [ { template => '%s', min => 0, unit => 'b/s', label_extra_instance => 1 } ] } }, { label => 'traffic-out', nlabel => 'website.traffic.out.bitspersecond', set => { key_values => [ { name => 'traffic_out', per_second => 1 }, { name => 'display' } ], output_template => 'traffic out: %s %s/s', output_change_bytes => 2, perfdatas => [ { template => '%s', min => 0, unit => 'b/s', label_extra_instance => 1 } ] } }, { label => 'connections-current', nlabel => 'website.connections.current.count', set => { key_values => [ { name => 'current_connections' }, { name => 'display' } ], output_template => 'current connections: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } }, { label => 'connections-total', nlabel => 'website.connections.total.persecond', set => { key_values => [ { name => 'total_connections', per_second => 1 }, { name => 'display' } ], output_template => 'total connections: %.2f/s', perfdatas => [ { template => '%.2f', min => 0, unit => '/s', label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'unknown-status:s' => { name => 'unknown_status', default => '' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{status} !~ /starting|started/' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status', 'unknown_status']); } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->get_websites(filter_name => $self->{option_results}->{filter_name}); $self->{websites} = {}; foreach (values %$results) { $self->{websites}->{$_->{name}} = { display => $_->{name}, status => $_->{status}, requests_total => $_->{requests}->{total}, traffic_in => $_->{network}->{total_bytes_recv} * 8, traffic_out => $_->{network}->{total_bytes_sent} * 8, current_connections => $_->{network}->{current_connections}, total_connections => $_->{network}->{total_connection_attempts} }; } $self->{cache_name} = 'iis_' . $self->{mode} . '_' . $options{custom}->get_hostname() . '_' . (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 websites. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='status' =item B<--filter-name> Filter website name (can be a regexp). =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{status}, %{display} =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 (Default: '%{status} !~ /starting|started/'). Can used special variables like: %{status}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'requests', 'traffic-in', 'traffic-out', 'connections-current', 'connections-total'. =back =cut centreon-plugins-20220113/apps/microsoft/iis/restapi/plugin.pm000066400000000000000000000031301417000230700242700ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::iis::restapi::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} = { 'application-pools' => 'apps::microsoft::iis::restapi::mode::applicationpools', 'list-application-pools' => 'apps::microsoft::iis::restapi::mode::listapplicationpools', 'list-websites' => 'apps::microsoft::iis::restapi::mode::listwebsites', 'websites' => 'apps::microsoft::iis::restapi::mode::websites' }; $self->{custom_modes}->{api} = 'apps::microsoft::iis::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Windows IIS in Rest API. =cut centreon-plugins-20220113/apps/microsoft/iis/wsman/000077500000000000000000000000001417000230700221155ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/iis/wsman/mode/000077500000000000000000000000001417000230700230415ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/iis/wsman/mode/applicationpoolstate.pm000066400000000000000000000173761417000230700276530ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::iis::wsman::mode::applicationpoolstate; use base qw(centreon::plugins::mode); use strict; use warnings; my %state_map = ( 1 => 'started', 2 => 'starting', 3 => 'stopped', 4 => 'stopping' ); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning" => { name => 'warning' }, "critical" => { name => 'critical' }, "pools:s" => { name => 'pools' }, "auto" => { name => 'auto' }, "exclude:s" => { name => 'exclude' } }); $self->{pools_rules} = {}; $self->{wql_filter} = ''; $self->{threshold} = 'CRITICAL'; return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{pools}) && !defined($self->{option_results}->{auto})) { $self->{output}->add_option_msg(short_msg => "Need to specify at least '--pools' or '--auto' option."); $self->{output}->option_exit(); } if (defined($self->{option_results}->{pools})) { my $append = ''; foreach my $rule (split /,/, $self->{option_results}->{pools}) { if ($rule !~ /^([^\!=]*)(\!=|=){0,1}(.*){0,1}/) { $self->{output}->add_option_msg(short_msg => "Wrong rule in --pools option: " . $rule); $self->{output}->option_exit(); } if (!defined($1) || $1 eq '') { $self->{output}->add_option_msg(short_msg => "Need pool name for rule: " . $rule); $self->{output}->option_exit(); } my $poolname = $1; my $operator = defined($2) && $2 ne '' ? $2 : '!='; my $state = defined($3) && $3 ne '' ? lc($3) : 'starting'; if ($operator !~ /^(=|\!=)$/) { $self->{output}->add_option_msg(short_msg => "Wrong operator for rule: " . $rule . ". Should be '=' or '!='."); $self->{output}->option_exit(); } if ($state !~ /^(started|starting|stopped|stopping)$/i) { $self->{output}->add_option_msg(short_msg => "Wrong state for rule: " . $rule . ". See help for available state."); $self->{output}->option_exit(); } $self->{service_rules}->{$poolname} = {operator => $operator, state => $state}; $self->{wql_filter} .= $append . "Name = '" . $poolname . "'"; $append = ' Or '; } if ($self->{wql_filter} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify one rule for --pools option."); $self->{output}->option_exit(); } } $self->{threshold} = 'WARNING' if (defined($self->{option_results}->{warning})); $self->{threshold} = 'CRITICAL' if (defined($self->{option_results}->{critical})); } sub check_auto { my ($self, %options) = @_; $self->{result} = $self->{wsman}->request(uri => 'http://schemas.microsoft.com/wbem/wsman/1/wmi/root/MicrosoftIISv2/*', wql_filter => "Select AppPoolState, Name From IIsApplicationPoolSetting Where AppPoolAutoStart = 'true'", result_type => 'hash', hash_key => 'Name'); foreach my $name (sort(keys %{$self->{result}})) { if (defined($self->{option_results}->{exclude}) && $self->{option_results}->{exclude} ne '' && $self->{result}->{$name}->{Name} =~ /$self->{option_results}->{exclude}/) { $self->{output}->output_add(long_msg => "Skipping pool '" . $self->{result}->{$name}->{Name} . "'"); next; } $self->{output}->output_add(long_msg => "Pool '" . $self->{result}->{$name}->{Name} . "' state: " . $state_map{$self->{result}->{$name}->{AppPoolState}}); if ($state_map{$self->{result}->{$name}->{AppPoolState}} !~ /^starting$/i) { $self->{output}->output_add(severity => $self->{threshold}, short_msg => "Service '" . $self->{result}->{$name}->{Name} . "' is " . $state_map{$self->{result}->{$name}->{AppPoolState}}); } } } sub check { my ($self, %options) = @_; $self->{result} = $self->{wsman}->request(uri => 'http://schemas.microsoft.com/wbem/wsman/1/wmi/root/MicrosoftIISv2/*', wql_filter => 'Select AppPoolState, Name From IIsApplicationPoolSetting Where ' . $self->{wql_filter}, result_type => 'hash', hash_key => 'Name'); foreach my $name (sort(keys %{$self->{service_rules}})) { if (!defined($self->{result}->{$name})) { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => "Pool '" . $name . "' not found"); next; } $self->{output}->output_add(long_msg => "Pool '" . $name . "' state: " . $state_map{$self->{result}->{$name}->{AppPoolState}}); if ($self->{service_rules}->{$name}->{operator} eq '=' && $state_map{$self->{result}->{$name}->{AppPoolState}} eq $self->{service_rules}->{$name}->{state}) { $self->{output}->output_add(severity => $self->{threshold}, short_msg => "Pool '" . $self->{result}->{$name}->{Name} . "' is " . $state_map{$self->{result}->{$name}->{AppPoolState}}); } elsif ($self->{service_rules}->{$name}->{operator} eq '!=' && $state_map{$self->{result}->{$name}->{AppPoolState}} ne $self->{service_rules}->{$name}->{state}) { $self->{output}->output_add(severity => $self->{threshold}, short_msg => "Service '" . $self->{result}->{$name}->{Name} . "' is " . $state_map{$self->{result}->{$name}->{AppPoolState}}); } } } sub run { my ($self, %options) = @_; # $options{wsman} = wsman object $self->{wsman} = $options{wsman}; $self->{output}->output_add(severity => 'OK', short_msg => 'All application pools are ok'); if (defined($self->{option_results}->{auto})) { $self->check_auto(); } else { $self->check(); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check IIS Application Pools State. Need to install IIS WMI provider by installing the IIS Management Scripts and Tools component (compatibility IIS 6.0). =over 8 =item B<--warning> Return warning. =item B<--critical> Return critical. =item B<--pools> Application Pool to monitor. Syntax: [pool_name[[=|!=]state]],... Available states are: - 'started', - 'starting', - 'stopped', - 'stopping' =item B<--auto> Return threshold for auto start pools not starting. =item B<--exclude> Exclude some pool for --auto option (Can be a regexp). =back =cut centreon-plugins-20220113/apps/microsoft/iis/wsman/mode/listapplicationpools.pm000066400000000000000000000115031417000230700276530ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::iis::wsman::mode::listapplicationpools; use base qw(centreon::plugins::mode); use strict; use warnings; my %state_map = ( 1 => 'started', 2 => 'starting', 3 => 'stopped', 4 => 'stopping' ); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "name:s" => { name => 'name' }, "regexp" => { name => 'use_regexp' }, "filter-state:s" => { name => 'filter_state' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{result} = $self->{wsman}->request(uri => 'http://schemas.microsoft.com/wbem/wsman/1/wmi/root/MicrosoftIISv2/*', wql_filter => 'Select AppPoolState, AppPoolAutoStart, Name From IIsApplicationPoolSetting', result_type => 'hash', hash_key => 'Name'); # AppPoolAutoStart -> true/false # AppPoolState -> 1=started, 2=starting, 3 = stopped, 4=stopping foreach my $name (sort(keys %{$self->{result}})) { if (defined($self->{option_results}->{filter_state}) && $state_map{$self->{result}->{$name}->{AppPoolState}} !~ /$self->{option_results}->{filter_state}/) { $self->{output}->output_add(long_msg => "Skipping application pool '" . $name . "': no matching filter state"); delete $self->{result}->{$name}; next; } # Get all without a name next if (!defined($self->{option_results}->{name})); next if (!defined($self->{option_results}->{use_regexp}) && $name eq $self->{option_results}->{name}); next if (defined($self->{option_results}->{use_regexp}) && $name =~ /$self->{option_results}->{name}/); $self->{output}->output_add(long_msg => "Skipping application pool '" . $name . "': no matching filter name"); delete $self->{result}->{$name}; } } sub run { my ($self, %options) = @_; # $options{wsman} = wsman object $self->{wsman} = $options{wsman}; $self->manage_selection(); foreach my $name (sort(keys %{$self->{result}})) { $self->{output}->output_add(long_msg => "'" . $name . "' [AutoStart = " . $self->{result}->{$name}->{AppPoolAutoStart} . '] [' . 'State = ' . $state_map{$self->{result}->{$name}->{AppPoolState}} . ']'); } $self->{output}->output_add(severity => 'OK', short_msg => 'List application 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', 'auto_start', 'state']); } sub disco_show { my ($self, %options) = @_; # $options{wsman} = wsman object $self->{wsman} = $options{wsman}; $self->manage_selection(); foreach my $name (sort(keys %{$self->{result}})) { $self->{output}->add_disco_entry(name => $name, auto_start => $self->{result}->{$name}->{AppPoolAutoStart}, state => $state_map{$self->{result}->{$name}->{AppPoolState}} ); } } 1; __END__ =head1 MODE List IIS Application Pools. Need to install IIS WMI provider by installing the IIS Management Scripts and Tools component (compatibility IIS 6.0). =over 8 =item B<--name> Set the application pool name. =item B<--regexp> Allows to use regexp to filter application pool name (with option --name). =item B<--filter-state> Filter application pool state. Regexp can be used. =back =cut centreon-plugins-20220113/apps/microsoft/iis/wsman/plugin.pm000066400000000000000000000025571417000230700237620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::iis::wsman::plugin; use strict; use warnings; use base qw(centreon::plugins::script_wsman); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $self->{version} = '0.1'; $self->{modes} = { 'applicationpool-state' => 'apps::microsoft::iis::wsman::mode::applicationpoolstate', 'list-applicationpools' => 'apps::microsoft::iis::wsman::mode::listapplicationpools' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Windows IIS through "WinRM" (ws-management protocol). =cut centreon-plugins-20220113/apps/microsoft/mscs/000077500000000000000000000000001417000230700211515ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/mscs/local/000077500000000000000000000000001417000230700222435ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/mscs/local/mode/000077500000000000000000000000001417000230700231675ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/mscs/local/mode/listnodes.pm000066400000000000000000000065311417000230700255360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::mscs::local::mode::listnodes; use base qw(centreon::plugins::mode); use strict; use warnings; use Win32::OLE; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } my %map_state = ( -1 => 'unknown', 0 => 'up', 1 => 'down', 2 => 'paused', 3 => 'joining', ); sub manage_selection { my ($self, %options) = @_; # winmgmts:{impersonationLevel=impersonate,authenticationLevel=pktPrivacy}!\\.\root\mscluster my $wmi = Win32::OLE->GetObject('winmgmts:root\mscluster'); if (!defined($wmi)) { $self->{output}->add_option_msg(short_msg => "Cant create server object:" . Win32::OLE->LastError()); $self->{output}->option_exit(); } $self->{nodes} = {}; my $query = "Select * from MSCluster_Node"; my $resultset = $wmi->ExecQuery($query); foreach my $obj (in $resultset) { my $name = $obj->{Name}; my $state = $map_state{$obj->{State}}; 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->{nodes}->{$name} = { name => $name, state => $state }; } } sub run { my ($self, %options) = @_; $self->manage_selection(); foreach my $name (sort keys %{$self->{nodes}}) { $self->{output}->output_add(long_msg => "'" . $name . "' [state = " . $self->{nodes}->{$name}->{state} . "]"); } $self->{output}->output_add( severity => 'OK', short_msg => 'List nodes:' ); $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->manage_selection(disco => 1); foreach my $name (sort keys %{$self->{nodes}}) { $self->{output}->add_disco_entry(name => $name, state => $self->{nodes}->{$name}->{state}); } } 1; __END__ =head1 MODE List nodes. =over 8 =item B<--filter-name> Filter node name (can be a regexp). =back =cut centreon-plugins-20220113/apps/microsoft/mscs/local/mode/listresources.pm000066400000000000000000000105101417000230700264300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::mscs::local::mode::listresources; use base qw(centreon::plugins::mode); use strict; use warnings; use Win32::OLE; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } my %map_state = ( -1 => 'unknown', 0 => 'inherited', 1 => 'initializing', 2 => 'online', 3 => 'offline', 4 => 'failed', 128 => 'pending', 129 => 'online pending', 130 => 'offline pending', ); my %map_class = ( 0 => 'unknown', 1 => 'storage', 2 => 'network', 32768 => 'user', ); sub manage_selection { my ($self, %options) = @_; # winmgmts:{impersonationLevel=impersonate,authenticationLevel=pktPrivacy}!\\.\root\mscluster my $wmi = Win32::OLE->GetObject('winmgmts:root\mscluster'); if (!defined($wmi)) { $self->{output}->add_option_msg(short_msg => "Cant create server object:" . Win32::OLE->LastError()); $self->{output}->option_exit(); } $self->{resources} = {}; my $query = "Select * from MSCluster_Resource"; my $resultset = $wmi->ExecQuery($query); foreach my $obj (in $resultset) { my $name = $obj->{Name}; my $state = $map_state{$obj->{State}}; my $class = defined($obj->{ResourceClass}) ? $map_class{$obj->{ResourceClass}} : '-'; my $id = defined($obj->{Id}) ? $obj->{Id} : $name; my $owner_node = defined($obj->{OwnerNode}) ? $obj->{OwnerNode} : '-'; 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->{resources}->{$id} = { name => $name, state => $state, owner_node => $owner_node, class => $class }; } } sub run { my ($self, %options) = @_; $self->manage_selection(); foreach my $id (sort keys %{$self->{resources}}) { $self->{output}->output_add(long_msg => "'" . $self->{resources}->{$id}->{name} . "' [state = " . $self->{resources}->{$id}->{state} . "]" . "[owner node = " . $self->{resources}->{$id}->{owner_node} . "]" . "[class = " . $self->{resources}->{$id}->{class} . "]"); } $self->{output}->output_add(severity => 'OK', short_msg => 'List Resources:'); $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', 'id', 'owner_node', 'class']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(disco => 1); foreach my $id (sort keys %{$self->{resources}}) { $self->{output}->add_disco_entry( name => $self->{resources}->{$id}->{name}, state => $self->{resources}->{$id}->{state}, id => $id, owner_node => $self->{resources}->{$id}->{owner_node}, class => $self->{resources}->{$id}->{class} ); } } 1; __END__ =head1 MODE List resources. =over 8 =item B<--filter-name> Filter resource name (can be a regexp). =back =cut centreon-plugins-20220113/apps/microsoft/mscs/local/mode/networkstatus.pm000066400000000000000000000101601417000230700264600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::mscs::local::mode::networkstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Win32::OLE; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'network', type => 1, cb_prefix_output => 'prefix_network_output', message_multiple => 'All networks are ok' } ]; $self->{maps_counters}->{network} = [ { label => 'status', type => 2, unknown_default => '%{state} =~ /unknown/', critical_default => '%{state} =~ /down|partitioned|unavailable/', set => { key_values => [ { name => 'state' }, { name => 'display' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub custom_status_output { my ($self, %options) = @_; my $msg = 'state : ' . $self->{result_values}->{state}; return $msg; } sub prefix_network_output { my ($self, %options) = @_; return "Network '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } my %map_state = ( -1 => 'unknown', 0 => 'unavailable', 1 => 'down', 2 => 'partitioned', 3 => 'up', ); sub manage_selection { my ($self, %options) = @_; # winmgmts:{impersonationLevel=impersonate,authenticationLevel=pktPrivacy}!\\.\root\mscluster my $wmi = Win32::OLE->GetObject('winmgmts:root\mscluster'); if (!defined($wmi)) { $self->{output}->add_option_msg(short_msg => "Cant create server object:" . Win32::OLE->LastError()); $self->{output}->option_exit(); } $self->{network} = {}; my $query = "Select * from MSCluster_Network"; my $resultset = $wmi->ExecQuery($query); foreach my $obj (in $resultset) { my $name = $obj->{Name}; my $state = $map_state{$obj->{State}}; my $id = defined($obj->{ID}) ? $obj->{ID} : $name; 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->{network}->{$id} = { display => $name, state => $state }; } } 1; __END__ =head1 MODE Check network status. =over 8 =item B<--filter-name> Filter interface name (can be a regexp). =item B<--unknown-status> Set warning threshold for status (Default: '%{state} =~ /unknown/'). Can used special variables like: %{state}, %{display} =item B<--warning-status> Set warning threshold for status (Default: none). Can used special variables like: %{state}, %{display} =item B<--critical-status> Set critical threshold for status (Default: '%{state} =~ /down|partitioned|unavailable/'). Can used special variables like: %{state}, %{display} =back =cut centreon-plugins-20220113/apps/microsoft/mscs/local/mode/nodestatus.pm000066400000000000000000000100331417000230700257130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::mscs::local::mode::nodestatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Win32::OLE; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'node', type => 1, cb_prefix_output => 'prefix_node_output', message_multiple => 'All nodes are ok' } ]; $self->{maps_counters}->{node} = [ { label => 'status', type => 2, unknown_default => '%{state} =~ /unknown/', warning_default => '%{state} =~ /pause|joining/', critical_default => '%{state} =~ /down/', set => { key_values => [ { name => 'state' }, { name => 'display' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub custom_status_output { my ($self, %options) = @_; return 'state : ' . $self->{result_values}->{state}; } sub prefix_node_output { my ($self, %options) = @_; return "Node '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } my %map_state = ( -1 => 'unknown', 0 => 'up', 1 => 'down', 2 => 'paused', 3 => 'joining', ); sub manage_selection { my ($self, %options) = @_; # winmgmts:{impersonationLevel=impersonate,authenticationLevel=pktPrivacy}!\\.\root\mscluster my $wmi = Win32::OLE->GetObject('winmgmts:root\mscluster'); if (!defined($wmi)) { $self->{output}->add_option_msg(short_msg => "Cant create server object:" . Win32::OLE->LastError()); $self->{output}->option_exit(); } $self->{node} = {}; my $query = "Select * from MSCluster_Node"; my $resultset = $wmi->ExecQuery($query); foreach my $obj (in $resultset) { my $name = $obj->{Name}; my $state = $map_state{$obj->{State}}; 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->{node}->{$name} = { display => $name, state => $state }; } } 1; __END__ =head1 MODE Check node status. =over 8 =item B<--filter-name> Filter node name (can be a regexp). =item B<--unknown-status> Set warning threshold for status (Default: '%{state} =~ /unknown/'). Can used special variables like: %{state}, %{display} =item B<--warning-status> Set warning threshold for status (Default: '%{state} =~ /pause|joining/'). Can used special variables like: %{state}, %{display} =item B<--critical-status> Set critical threshold for status (Default: '%{state} =~ /down/'). Can used special variables like: %{state}, %{display} =back =cut centreon-plugins-20220113/apps/microsoft/mscs/local/mode/resourcegroupstatus.pm000066400000000000000000000155311417000230700277020ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::mscs::local::mode::resourcegroupstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Win32::OLE; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub is_preferred_node { my (%options) = @_; if (!defined($options{preferred_owners}) || scalar(@{$options{preferred_owners}}) == 0) { return 1; } foreach my $pref_node (@{$options{preferred_owners}}) { if ($pref_node eq $options{owner_node}) { return 1; } } return 0; } sub custom_status_output { my ($self, %options) = @_; my $pref_nodes = 'any'; if (defined($self->{result_values}->{preferred_owners}) && scalar(@{$self->{result_values}->{preferred_owners}}) > 0) { $pref_nodes = join(', ', @{$self->{result_values}->{preferred_owners}}); } return 'state: ' . $self->{result_values}->{state} . ' [node: ' . $self->{result_values}->{owner_node} . '] [preferred nodes: ' . $pref_nodes . ']'; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{state} = $options{new_datas}->{$self->{instance} . '_state'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{owner_node} = $options{new_datas}->{$self->{instance} . '_owner_node'}; $self->{result_values}->{preferred_owners} = $options{new_datas}->{$self->{instance} . '_preferred_owners'}; $self->{result_values}->{is_preferred_node} = is_preferred_node( preferred_owners => $self->{result_values}->{preferred_owners}, owner_node => $self->{result_values}->{owner_node} ); return 0; } sub prefix_rg_output { my ($self, %options) = @_; return "Resource group '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'rg', type => 1, cb_prefix_output => 'prefix_rg_output', message_multiple => 'All resource groups are ok' } ]; $self->{maps_counters}->{rg} = [ { label => 'status', type => 2, unknown_default => '%{state} =~ /unknown/', warning_default => '%{is_preferred_node} == 0', critical_default => '%{state} =~ /failed|offline/', set => { key_values => [ { name => 'state' }, { name => 'display' }, { name => 'owner_node' }, { name => 'preferred_owners' } ], 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 => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); # compatibility foreach (('unknown_status', 'warning_status', 'critical_status')) { if (defined($self->{option_results}->{$_}) && $self->{option_results}->{$_} ne '') { $self->{option_results}->{$_} =~ s/is_preferred_node\(\)/\$values->{is_preferred_node}/g; } } } my %map_state = ( -1 => 'unknown', 0 => 'online', 1 => 'offline', 2 => 'failed', 3 => 'partial online', 4 => 'pending' ); sub manage_selection { my ($self, %options) = @_; # winmgmts:{impersonationLevel=impersonate,authenticationLevel=pktPrivacy}!\\.\root\mscluster my $wmi = Win32::OLE->GetObject('winmgmts:root\mscluster'); if (!defined($wmi)) { $self->{output}->add_option_msg(short_msg => "Cant create server object:" . Win32::OLE->LastError()); $self->{output}->option_exit(); } my $query = 'Select * from MSCluster_ResourceGroupToPreferredNode'; my $resultset = $wmi->ExecQuery($query); my $preferred_nodes = {}; foreach my $obj (in $resultset) { # MSCluster_ResourceGroup.Name="xxx" if ($obj->GroupComponent =~ /MSCluster_ResourceGroup.Name="(.*?)"/i) { my $rg = $1; next if ($obj->PartComponent !~ /MSCluster_Node.Name="(.*?)"/i); my $node = $1; $preferred_nodes->{$rg} = [] if (!defined($preferred_nodes->{$rg})); push @{$preferred_nodes->{$rg}}, $node; } } $self->{rg} = {}; $query = 'Select * from MSCluster_ResourceGroup'; $resultset = $wmi->ExecQuery($query); foreach my $obj (in $resultset) { my $name = $obj->{Name}; my $state = $map_state{$obj->{State}}; my $id = defined($obj->{Id}) ? $obj->{Id} : $name; my $owner_node = defined($obj->{OwnerNode}) ? $obj->{OwnerNode} : '-'; 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->{rg}->{$id} = { display => $name, state => $state, owner_node => $owner_node, preferred_owners => defined($preferred_nodes->{$name}) ? $preferred_nodes->{$name} : [] }; } } 1; __END__ =head1 MODE Check resource group status. =over 8 =item B<--filter-name> Filter resource group name (can be a regexp). =item B<--unknown-status> Set warning threshold for status (Default: '%{state} =~ /unknown/'). Can used special variables like: %{state}, %{display}, %{owner_node} =item B<--warning-status> Set warning threshold for status (Default: '%{is_preferred_node} == 0'). Can used special variables like: %{state}, %{display}, %{owner_node} =item B<--critical-status> Set critical threshold for status (Default: '%{state} =~ /failed|offline/'). Can used special variables like: %{state}, %{display}, %{owner_node} =back =cut centreon-plugins-20220113/apps/microsoft/mscs/local/mode/resourcestatus.pm000066400000000000000000000106211417000230700266200ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::mscs::local::mode::resourcestatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Win32::OLE; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'resource', type => 1, cb_prefix_output => 'prefix_resource_output', message_multiple => 'All resources are ok' } ]; $self->{maps_counters}->{resource} = [ { label => 'status', type => 2, unknown_default => '%{state} =~ /unknown/', critical_default => '%{state} =~ /failed|offline/', set => { key_values => [ { name => 'state' }, { name => 'display' }, { name => 'owner_node' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub custom_status_output { my ($self, %options) = @_; return 'state : ' . $self->{result_values}->{state} . ' [node: ' . $self->{result_values}->{owner_node} . ']'; } sub prefix_resource_output { my ($self, %options) = @_; return "Resource '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } my %map_state = ( -1 => 'unknown', 0 => 'inherited', 1 => 'initializing', 2 => 'online', 3 => 'offline', 4 => 'failed', 128 => 'pending', 129 => 'online pending', 130 => 'offline pending', ); sub manage_selection { my ($self, %options) = @_; # winmgmts:{impersonationLevel=impersonate,authenticationLevel=pktPrivacy}!\\.\root\mscluster my $wmi = Win32::OLE->GetObject('winmgmts:root\mscluster'); if (!defined($wmi)) { $self->{output}->add_option_msg(short_msg => "Cant create server object:" . Win32::OLE->LastError()); $self->{output}->option_exit(); } $self->{resource} = {}; my $query = "Select * from MSCluster_Resource"; my $resultset = $wmi->ExecQuery($query); foreach my $obj (in $resultset) { my $name = $obj->{Name}; my $state = $map_state{$obj->{State}}; my $id = defined($obj->{Id}) ? $obj->{Id} : $name; my $owner_node = defined($obj->{OwnerNode}) ? $obj->{OwnerNode} : '-'; 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->{resource}->{$id} = { display => $name, state => $state, owner_node => $owner_node }; } } 1; __END__ =head1 MODE Check resource status. =over 8 =item B<--filter-name> Filter resource name (can be a regexp). =item B<--unknown-status> Set warning threshold for status (Default: '%{state} =~ /unknown/'). Can used special variables like: %{state}, %{display} =item B<--warning-status> Set warning threshold for status (Default: none). Can used special variables like: %{state}, %{display}, %{owner_node} =item B<--critical-status> Set critical threshold for status (Default: '%{state} =~ /failed|offline/'). Can used special variables like: %{state}, %{display}, %{owner_node} =back =cut centreon-plugins-20220113/apps/microsoft/mscs/local/plugin.pm000066400000000000000000000032441417000230700241020ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::mscs::local::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} = '0.1'; $self->{modes} = { 'list-nodes' => 'apps::microsoft::mscs::local::mode::listnodes', 'list-resources' => 'apps::microsoft::mscs::local::mode::listresources', 'network-status' => 'apps::microsoft::mscs::local::mode::networkstatus', 'node-status' => 'apps::microsoft::mscs::local::mode::nodestatus', 'resource-status' => 'apps::microsoft::mscs::local::mode::resourcestatus', 'resourcegroup-status' => 'apps::microsoft::mscs::local::mode::resourcegroupstatus' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Cluster Service. =cut centreon-plugins-20220113/apps/microsoft/sccm/000077500000000000000000000000001417000230700211315ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/sccm/local/000077500000000000000000000000001417000230700222235ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/sccm/local/mode/000077500000000000000000000000001417000230700231475ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/sccm/local/mode/databasereplicationstatus.pm000066400000000000000000000230311417000230700307460ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::sccm::local::mode::databasereplicationstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use JSON::XS; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use centreon::common::powershell::sccm::databasereplicationstatus; use centreon::plugins::misc; use DateTime; my %map_link_status = ( 1 => 'Degraded', 2 => 'Active', 3 => 'Failed' ); my %map_status = ( 100 => 'SITE_INSTALLING', 105 => 'SITE_INSTALL_COMPLETE', 110 => 'INACTIVE', 115 => 'INITIALIZING', 120 => 'MAINTENANCE_MODE', 125 => 'ACTIVE', 130 => 'DETACHING', 135 => 'READY_TO_DETACH', 199 => 'STATUS_UNKNOWN', 200 => 'SITE_RECOVERED', 205 => 'SITE_PREPARE_FOR_RECOVERY', 210 => 'SITE_PREPARED_FOR_RECOVERY', 215 => 'REPLCONFIG_REINITIALIZING', 220 => 'REPLCONFIG_REINITIALIZED', 225 => 'RECOVERY_IN_PROGRESS', 230 => 'RECOVERING_DELTAS', 250 => 'RECOVERY_RETRY', 255 => 'RECOVERY_FAILED' ); my %map_type = ( 0 => 'Unknown', 1 => 'SECONDARY', 2 => 'PRIMARY', 4 => 'CAS' ); sub custom_status_output { my ($self, %options) = @_; return sprintf("Overall Link status is '%s'", $self->{result_values}->{status}); } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_LinkStatus'}; return 0; } sub custom_site_status_output { my ($self, %options) = @_; return sprintf("status is '%s', Site-to-Site state is '%s' [Type: %s] [Last sync: %s]", $self->{result_values}->{status}, $self->{result_values}->{site_to_site_state}, $self->{result_values}->{type}, centreon::plugins::misc::change_seconds(value => $self->{result_values}->{last_sync_time}) ); } sub custom_site_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_SiteStatus'}; $self->{result_values}->{type} = $options{new_datas}->{$self->{instance} . '_SiteType'}; $self->{result_values}->{site_to_site_state} = $options{new_datas}->{$self->{instance} . '_SiteToSiteGlobalState'}; $self->{result_values}->{sync_time} = $options{new_datas}->{$self->{instance} . '_SiteToSiteGlobalSyncTime'}; my $tz = centreon::plugins::misc::set_timezone(name => $self->{option_results}->{timezone}); $self->{result_values}->{sync_time} =~ /^(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)$/; my $sync_time = DateTime->new(year => $1, month => $2, day => $3, hour => $4, minute => $5, second => $6, %$tz); $self->{result_values}->{last_sync_time} = time() - $sync_time->epoch; return 0; } sub prefix_output_site { my ($self, %options) = @_; return "Site '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'sites', type => 1, cb_prefix_output => 'prefix_output_site', message_multiple => 'All sites status are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'link-status', threshold => 0, set => { key_values => [ { name => 'LinkStatus' } ], 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 => \&catalog_status_threshold_ng } }, ]; $self->{maps_counters}->{sites} = [ { label => 'site-status', threshold => 0, set => { key_values => [ { name => 'SiteType' }, { name => 'SiteStatus' }, { name => 'SiteToSiteGlobalState' }, { name => 'SiteToSiteGlobalSyncTime' } ], closure_custom_calc => $self->can('custom_site_status_calc'), closure_custom_output => $self->can('custom_site_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'timeout:s' => { name => 'timeout', default => 30 }, 'command:s' => { name => 'command', default => 'powershell.exe' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '-InputFormat none -NoLogo -EncodedCommand' }, 'no-ps' => { name => 'no_ps' }, 'ps-exec-only' => { name => 'ps_exec_only' }, 'ps-display' => { name => 'ps_display' }, 'timezone:s' => { name => 'timezone', default => 'UTC' } }); return $self; } sub manage_selection { my ($self, %options) = @_; if (!defined($self->{option_results}->{no_ps})) { my $ps = centreon::common::powershell::sccm::databasereplicationstatus::get_powershell(); if (defined($self->{option_results}->{ps_display})) { $self->{output}->output_add( severity => 'OK', short_msg => $ps ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{option_results}->{command_options} .= " " . centreon::plugins::misc::powershell_encoded($ps); } my ($stdout) = centreon::plugins::misc::execute( output => $self->{output}, options => $self->{option_results}, command => $self->{option_results}->{command}, command_path => $self->{option_results}->{command_path}, command_options => $self->{option_results}->{command_options} ); if (defined($self->{option_results}->{ps_exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } my $decoded; eval { $decoded = JSON::XS->new->decode($self->{output}->decode($stdout)); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } $self->{sites} = {}; foreach (@$decoded) { $self->{sites}->{ $_->{Site1} } = { display => $_->{Site1}, SiteType => $map_type{$_->{SiteType1}}, SiteStatus => $map_status{$_->{Site1Status}}, SiteToSiteGlobalState => $_->{Site1ToSite2GlobalState}, SiteToSiteGlobalSyncTime => $_->{Site1ToSite2GlobalSyncTime} }; $self->{sites}->{ $_->{Site2} } = { display => $_->{Site2}, SiteType => $map_type{$_->{SiteType2}}, SiteStatus => $map_status{$_->{Site2Status}}, SiteToSiteGlobalState => $_->{Site2ToSite1GlobalState}, SiteToSiteGlobalSyncTime => $_->{Site2ToSite1GlobalSyncTime} }; } if (scalar(keys %{$self->{sites}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No database replication'); $self->{output}->option_exit(); } $self->{global} = { LinkStatus => $map_link_status{ $decoded->[0]->{LinkStatus} } }; } 1; __END__ =head1 MODE Check database replication status. =over 8 =item B<--timeout> Set timeout time for command execution (Default: 30 sec) =item B<--no-ps> Don't encode powershell. To be used with --command and 'type' command. =item B<--command> Command to get information (Default: 'powershell.exe'). Can be changed if you have output in a file. To be used with --no-ps option. =item B<--command-path> Command path (Default: none). =item B<--command-options> Command options (Default: '-InputFormat none -NoLogo -EncodedCommand'). =item B<--ps-display> Display powershell script. =item B<--ps-exec-only> Print powershell output. =item B<--warning-link-status> Set warning threshold for current synchronisation status (Default: '') Can used special variables like: %{status}. =item B<--critical-link-status> Set critical threshold for current synchronisation status (Default: ''). Can used special variables like: %{status}. =item B<--warning-site-status> Set warning threshold for current synchronisation status (Default: '') Can used special variables like: %{status}, %{type}, %{site_to_site_state}, %{last_sync_time}. =item B<--critical-site-status> Set critical threshold for current synchronisation status (Default: ''). Can used special variables like: %{status}, %{type}, %{site_to_site_state}, %{last_sync_time}. =back =cut centreon-plugins-20220113/apps/microsoft/sccm/local/mode/sitestatus.pm000066400000000000000000000167151417000230700257270ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::sccm::local::mode::sitestatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use JSON::XS; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use centreon::plugins::misc; use centreon::common::powershell::sccm::sitestatus; my %map_mode = ( 0 => '-', 1 => 'Replication maintenance', 2 => 'Recovery in progress', 3 => 'Upgrade in progress', 4 => 'Evaluation has expired', 5 => 'Site expansion in progress', 6 => 'Interop mode where there are primary sites, having the same version as the CAS, were not upgraded', 7 => 'Interop mode where there are secondary sites, having the same version as the top-level site server, were not upgraded' ); my %map_status = ( 0 => 'Unknown', 1 => 'ACTIVE', 2 => 'PENDING', 3 => 'FAILED', 4 => 'DELETED', 5 => 'UPGRADE', 6 => 'Failed to delete or deinstall the secondary site', 7 => 'Failed to upgrade the secondary site', 8 => 'Secondary site recovery is in progress', 9 => 'Failed to recover secondary site' ); my %map_type = ( 0 => 'Unknown', 1 => 'SECONDARY', 2 => 'PRIMARY', 4 => 'CAS' ); sub custom_status_output { my ($self, %options) = @_; return sprintf("status is '%s' [type: %s] [mode: '%s']", $self->{result_values}->{status}, $self->{result_values}->{type}, $self->{result_values}->{mode} ); } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_SiteName'}; $self->{result_values}->{type} = $options{new_datas}->{$self->{instance} . '_Type'}; $self->{result_values}->{mode} = $options{new_datas}->{$self->{instance} . '_Mode'}; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_Status'}; $self->{result_values}->{secondary_site_status} = $options{new_datas}->{$self->{instance} . '_SecondarySiteCMUpdateStatus'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'sites', type => 1, cb_prefix_output => 'prefix_output_site', message_multiple => 'All sites status are ok' }, ]; $self->{maps_counters}->{sites} = [ { label => 'status', type => 2, set => { key_values => [ { name => 'display' }, { name => 'SiteName' }, { name => 'Type' }, { name => 'Mode' }, { name => 'Status' }, { name => 'SecondarySiteCMUpdateStatus' } ], 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 => \&catalog_status_threshold_ng } } ]; } sub prefix_output_site { my ($self, %options) = @_; return "Site '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'timeout:s' => { name => 'timeout', default => 30 }, 'command:s' => { name => 'command', default => 'powershell.exe' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '-InputFormat none -NoLogo -EncodedCommand' }, 'no-ps' => { name => 'no_ps' }, 'ps-exec-only' => { name => 'ps_exec_only' }, 'ps-display' => { name => 'ps_display' } }); return $self; } sub manage_selection { my ($self, %options) = @_; if (!defined($self->{option_results}->{no_ps})) { my $ps = centreon::common::powershell::sccm::sitestatus::get_powershell(); if (defined($self->{option_results}->{ps_display})) { $self->{output}->output_add( severity => 'OK', short_msg => $ps ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{option_results}->{command_options} .= " " . centreon::plugins::misc::powershell_encoded($ps); } my ($stdout) = centreon::plugins::misc::execute( output => $self->{output}, options => $self->{option_results}, command => $self->{option_results}->{command}, command_path => $self->{option_results}->{command_path}, command_options => $self->{option_results}->{command_options} ); if (defined($self->{option_results}->{ps_exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } my $decoded; eval { $decoded = JSON::XS->new->decode($self->{output}->decode($stdout)); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } foreach my $site (@{$decoded}) { $self->{sites}->{$site->{SiteCode}} = { display => $site->{SiteCode}, SiteName => $site->{SiteName}, Type => $map_type{$site->{Type}}, Mode => $map_mode{$site->{Mode}}, Status => $map_status{$site->{Status}}, SecondarySiteCMUpdateStatus => $site->{SecondarySiteCMUpdateStatus} }; } if (scalar(keys %{$self->{sites}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No sites found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check sites status. =over 8 =item B<--timeout> Set timeout time for command execution (Default: 30 sec) =item B<--no-ps> Don't encode powershell. To be used with --command and 'type' command. =item B<--command> Command to get information (Default: 'powershell.exe'). Can be changed if you have output in a file. To be used with --no-ps option. =item B<--command-path> Command path (Default: none). =item B<--command-options> Command options (Default: '-InputFormat none -NoLogo -EncodedCommand'). =item B<--ps-display> Display powershell script. =item B<--ps-exec-only> Print powershell output. =item B<--warning-status> Set warning threshold for current synchronisation status (Default: ''). Can used special variables like: %{status}, %{mode}, %{type}, %{name}. =item B<--critical-status> Set critical threshold for current synchronisation status (Default: ''). Can used special variables like: %{status}, %{mode}, %{type}, %{name}. =back =cut centreon-plugins-20220113/apps/microsoft/sccm/local/plugin.pm000066400000000000000000000025351417000230700240640ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::sccm::local::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} = '0.1'; $self->{modes} = { 'database-replication-status' => 'apps::microsoft::sccm::local::mode::databasereplicationstatus', 'site-status' => 'apps::microsoft::sccm::local::mode::sitestatus' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check SCCM through powershell. =cut centreon-plugins-20220113/apps/microsoft/wsus/000077500000000000000000000000001417000230700212055ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/wsus/local/000077500000000000000000000000001417000230700222775ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/wsus/local/mode/000077500000000000000000000000001417000230700232235ustar00rootroot00000000000000centreon-plugins-20220113/apps/microsoft/wsus/local/mode/computersstatus.pm000066400000000000000000000160641417000230700270550ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::wsus::local::mode::computersstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use JSON::XS; use centreon::plugins::misc; use centreon::common::powershell::wsus::computersstatus; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_output' }, ]; $self->{maps_counters}->{global} = [ { label => 'up-to-date', set => { key_values => [ { name => 'ComputersUpToDateCount' } ], output_template => 'Up-to-date: %d', perfdatas => [ { label => 'computers_up_to_date', template => '%d', min => 0 } ] } }, { label => 'needing-updates', set => { key_values => [ { name => 'ComputerTargetsNeedingUpdatesCount' } ], output_template => 'Needing Updates: %d', perfdatas => [ { label => 'computers_needing_updates', template => '%d', min => 0 } ] } }, { label => 'with-update-errors', set => { key_values => [ { name => 'ComputerTargetsWithUpdateErrorsCount' } ], output_template => 'With Update Errors: %d', perfdatas => [ { label => 'computers_with_update_errors', template => '%d', min => 0 } ] } }, { label => 'not-contacted', set => { key_values => [ { name => 'ComputersNotContactedSinceCount' } ], output_template => 'Not Contacted: %d', perfdatas => [ { label => 'computers_not_contacted', template => '%d', min => 0 } ] } }, { label => 'unassigned', set => { key_values => [ { name => 'UnassignedComputersCount' } ], output_template => 'Unassigned: %s', perfdatas => [ { label => 'computers_unassigned', template => '%d', min => 0 } ] } } ]; } sub prefix_output { my ($self, %options) = @_; return "Computers "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'timeout:s' => { name => 'timeout', default => 30 }, 'command:s' => { name => 'command', default => 'powershell.exe' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '-InputFormat none -NoLogo -EncodedCommand' }, 'no-ps' => { name => 'no_ps' }, 'ps-exec-only' => { name => 'ps_exec_only' }, 'ps-display' => { name => 'ps_display' }, 'wsus-server:s' => { name => 'wsus_server', default => 'localhost' }, 'wsus-port:s' => { name => 'wsus_port', default => 8530 }, 'not-updated-since:s' => { name => 'not_updated_since', default => 10 }, 'use-ssl' => { name => 'use_ssl' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $use_ssl = "\$false"; $use_ssl = "\$true" if (defined($self->{option_results}->{use_ssl})); if (!defined($self->{option_results}->{no_ps})) { my $ps = centreon::common::powershell::wsus::computersstatus::get_powershell( wsus_server => $self->{option_results}->{wsus_server}, wsus_port => $self->{option_results}->{wsus_port}, not_updated_since => $self->{option_results}->{not_updated_since}, use_ssl => $use_ssl ); if (defined($self->{option_results}->{ps_display})) { $self->{output}->output_add( severity => 'OK', short_msg => $ps ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{option_results}->{command_options} .= " " . centreon::plugins::misc::powershell_encoded($ps); } my ($stdout) = centreon::plugins::misc::execute( output => $self->{output}, options => $self->{option_results}, command => $self->{option_results}->{command}, command_path => $self->{option_results}->{command_path}, command_options => $self->{option_results}->{command_options} ); if (defined($self->{option_results}->{ps_exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($stdout); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } $self->{global} = { %$decoded }; } 1; __END__ =head1 MODE Check computers status. =over 8 =item B<--timeout> Set timeout time for command execution (Default: 30 sec) =item B<--no-ps> Don't encode powershell. To be used with --command and 'type' command. =item B<--command> Command to get information (Default: 'powershell.exe'). Can be changed if you have output in a file. To be used with --no-ps option. =item B<--command-path> Command path (Default: none). =item B<--command-options> Command options (Default: '-InputFormat none -NoLogo -EncodedCommand'). =item B<--ps-display> Display powershell script. =item B<--ps-exec-only> Print powershell output. =item B<--wsus-server> Set WSUS hostname/IP. =item B<--wsus-port> Set WSUS port. =item B<--not-updated-since> Time in minutes to count computers not updated since. =item B<--use-ssl> Set if WSUS use ssl. =item B<--warning-*> Warning thresholds. Can be: 'needing-updates', 'with-update-errors', 'up-to-date', 'not-contacted', 'unassigned' =item B<--critical-*> Critical thresholds. Can be: 'needing-updates', 'with-update-errors', 'up-to-date', 'not-contacted', 'unassigned' =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='errors' =back =cut centreon-plugins-20220113/apps/microsoft/wsus/local/mode/serverstatistics.pm000066400000000000000000000173321417000230700272100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::wsus::local::mode::serverstatistics; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use JSON::XS; use centreon::plugins::misc; use centreon::common::powershell::wsus::serverstatistics; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, ]; $self->{maps_counters}->{global} = [ { label => 'computers', set => { key_values => [ { name => 'ComputerTargetCount' } ], output_template => 'Computers: %d', perfdatas => [ { label => 'computers', template => '%d', min => 0 } ] } }, { label => 'computer-groups', set => { key_values => [ { name => 'CustomComputerTargetGroupCount' } ], output_template => 'Computer Groups: %d', perfdatas => [ { label => 'computer_groups', template => '%d', min => 0 } ] } }, { label => 'updates', set => { key_values => [ { name => 'UpdateCount' } ], output_template => 'Updates: %d', perfdatas => [ { label => 'updates', template => '%d', min => 0 } ] } }, { label => 'approved-updates', set => { key_values => [ { name => 'ApprovedUpdateCount' } ], output_template => 'Approved Updates: %d', perfdatas => [ { label => 'approved_updates', template => '%d', min => 0 } ] } }, { label => 'declined-updates', set => { key_values => [ { name => 'DeclinedUpdateCount' } ], output_template => 'Declined Updates: %d', perfdatas => [ { label => 'declined_updates', template => '%d', min => 0 } ] } }, { label => 'not-approved-updates', set => { key_values => [ { name => 'NotApprovedUpdateCount' } ], output_template => 'Not Approved Updates: %d', perfdatas => [ { label => 'not_approved_updates', template => '%d', min => 0 } ] } }, { label => 'stale-updates', set => { key_values => [ { name => 'UpdatesWithStaleUpdateApprovalsCount' } ], output_template => 'Stale Updates: %d', perfdatas => [ { label => 'stale_updates', template => '%d', min => 0 } ] } }, { label => 'expired-updates', set => { key_values => [ { name => 'ExpiredUpdateCount' } ], output_template => 'Expired Updates: %d', perfdatas => [ { label => 'expired_updates', template => '%d', min => 0 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'timeout:s' => { name => 'timeout', default => 30 }, 'command:s' => { name => 'command', default => 'powershell.exe' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '-InputFormat none -NoLogo -EncodedCommand' }, 'no-ps' => { name => 'no_ps' }, 'ps-exec-only' => { name => 'ps_exec_only' }, 'ps-display' => { name => 'ps_display' }, 'wsus-server:s' => { name => 'wsus_server', default => 'localhost' }, 'wsus-port:s' => { name => 'wsus_port', default => 8530 }, 'use-ssl' => { name => 'use_ssl' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $use_ssl = "\$false"; $use_ssl = "\$true" if (defined($self->{option_results}->{use_ssl})); if (!defined($self->{option_results}->{no_ps})) { my $ps = centreon::common::powershell::wsus::serverstatistics::get_powershell( wsus_server => $self->{option_results}->{wsus_server}, wsus_port => $self->{option_results}->{wsus_port}, use_ssl => $use_ssl ); if (defined($self->{option_results}->{ps_display})) { $self->{output}->output_add( severity => 'OK', short_msg => $ps ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{option_results}->{command_options} .= " " . centreon::plugins::misc::powershell_encoded($ps); } my ($stdout) = centreon::plugins::misc::execute( output => $self->{output}, options => $self->{option_results}, command => $self->{option_results}->{command}, command_path => $self->{option_results}->{command_path}, command_options => $self->{option_results}->{command_options} ); if (defined($self->{option_results}->{ps_exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($stdout); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } $self->{global} = { %$decoded }; } 1; __END__ =head1 MODE Check server statistics. =over 8 =item B<--timeout> Set timeout time for command execution (Default: 30 sec) =item B<--no-ps> Don't encode powershell. To be used with --command and 'type' command. =item B<--command> Command to get information (Default: 'powershell.exe'). Can be changed if you have output in a file. To be used with --no-ps option. =item B<--command-path> Command path (Default: none). =item B<--command-options> Command options (Default: '-InputFormat none -NoLogo -EncodedCommand'). =item B<--ps-display> Display powershell script. =item B<--ps-exec-only> Print powershell output. =item B<--wsus-server> Set WSUS hostname/IP (Dafault: localhost). =item B<--wsus-port> Set WSUS port (Default: 8530). =item B<--use-ssl> Set if WSUS use ssl. =item B<--warning-*> Warning thresholds. Can be: 'computers', 'computer-groups', 'updates', 'approved-updates', 'declined-updates', 'not-approved-updates', 'stale-updates', 'expired-updates' =item B<--critical-*> Critical thresholds. Can be: 'computers', 'computer-groups', 'updates', 'approved-updates', 'declined-updates', 'not-approved-updates', 'stale-updates', 'expired-updates' =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='not' =back =cut centreon-plugins-20220113/apps/microsoft/wsus/local/mode/synchronisationstatus.pm000066400000000000000000000326231417000230700302650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::wsus::local::mode::synchronisationstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use JSON::XS; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); use centreon::plugins::misc; use centreon::common::powershell::wsus::synchronisationstatus; use DateTime; sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("status is '%s'", $self->{result_values}->{status}); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_SynchronizationStatus'}; return 0; } sub custom_last_status_output { my ($self, %options) = @_; my $msg = sprintf("status is '%s'", $self->{result_values}->{status}); return $msg; } sub custom_last_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_LastSynchronizationResult'}; return 0; } sub custom_progress_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => 'synchronisation_progress', value => $self->{result_values}->{progress}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}), min => 0, max => 100 ); } sub custom_progress_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check(value => $self->{result_values}->{progress}, threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{label}, exit_litteral => 'warning' } ]); return $exit; } sub custom_progress_output { my ($self, %options) = @_; return sprintf("Progress: %.2f%% (%d/%d items)", $self->{result_values}->{progress}, $self->{result_values}->{processed}, $self->{result_values}->{total} ); } sub custom_progress_calc { my ($self, %options) = @_; $self->{result_values}->{processed} = $options{new_datas}->{$self->{instance} . '_ProcessedItems'}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_TotalItems'}; $self->{result_values}->{progress} = 0; return 0 if ($self->{result_values}->{total} == 0); $self->{result_values}->{progress} = $self->{result_values}->{processed} * 100 / $self->{result_values}->{total}; return 0; } sub custom_duration_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => 'last_synchronisation_duration', value => $self->{result_values}->{duration}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}), min => 0, unit => 's' ); } sub custom_duration_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check(value => $self->{result_values}->{duration}, threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{label}, exit_litteral => 'warning' } ]); return $exit; } sub custom_duration_output { my ($self, %options) = @_; return sprintf('Duration: %s', centreon::plugins::misc::change_seconds(value => $self->{result_values}->{duration})); } sub custom_duration_calc { my ($self, %options) = @_; my $start_time = $options{new_datas}->{$self->{instance} . '_LastSynchronizationStartTime'}; my $end_time = $options{new_datas}->{$self->{instance} . '_LastSynchronizationEndTime'}; # 2019-03-21T13:00:13 my $tz = centreon::plugins::misc::set_timezone(name => $self->{option_results}->{timezone}); $start_time =~ /^(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)$/; my $start_time_dt = DateTime->new(year => $1, month => $2, day => $3, hour => $4, minute => $5, second => $6, %$tz); $end_time =~ /^(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)$/; my $end_time_dt = DateTime->new(year => $1, month => $2, day => $3, hour => $4, minute => $5, second => $6, %$tz); $self->{result_values}->{duration} = $end_time_dt->epoch - $start_time_dt->epoch; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'current', type => 0, cb_prefix_output => 'prefix_output_current' }, { name => 'last', type => 0, cb_prefix_output => 'prefix_output_last' }, ]; $self->{maps_counters}->{current} = [ { label => 'synchronisation-status', threshold => 0, set => { key_values => [ { name => 'SynchronizationStatus' } ], 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 => \&catalog_status_threshold, } }, { label => 'synchronisation-progress', set => { key_values => [ { name => 'TotalItems' }, { name => 'ProcessedItems' } ], closure_custom_calc => $self->can('custom_progress_calc'), closure_custom_output => $self->can('custom_progress_output'), closure_custom_perfdata => $self->can('custom_progress_perfdata'), closure_custom_threshold_check => $self->can('custom_progress_threshold'), } }, ]; $self->{maps_counters}->{last} = [ { label => 'last-synchronisation-status', threshold => 0, set => { key_values => [ { name => 'LastSynchronizationResult' } ], closure_custom_calc => $self->can('custom_last_status_calc'), closure_custom_output => $self->can('custom_last_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold, } }, { label => 'last-synchronisation-duration', set => { key_values => [ { name => 'LastSynchronizationStartTime' }, { name => 'LastSynchronizationEndTime' } ], closure_custom_calc => $self->can('custom_duration_calc'), closure_custom_output => $self->can('custom_duration_output'), closure_custom_perfdata => $self->can('custom_duration_perfdata'), closure_custom_threshold_check => $self->can('custom_duration_threshold'), } }, ]; } sub prefix_output_current { my ($self, %options) = @_; return "Current Synchronisation "; } sub prefix_output_last { my ($self, %options) = @_; return "Last Synchronisation "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'timeout:s' => { name => 'timeout', default => 30 }, 'command:s' => { name => 'command', default => 'powershell.exe' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '-InputFormat none -NoLogo -EncodedCommand' }, 'no-ps' => { name => 'no_ps' }, 'ps-exec-only' => { name => 'ps_exec_only' }, 'ps-display' => { name => 'ps_display' }, 'wsus-server:s' => { name => 'wsus_server', default => 'localhost' }, 'wsus-port:s' => { name => 'wsus_port', default => 8530 }, 'use-ssl' => { name => 'use_ssl' }, 'timezone:s' => { name => 'timezone', default => 'UTC' }, 'warning-synchronisation-status:s' => { name => 'warning_synchronisation_status', default => '' }, 'critical-synchronisation-status:s' => { name => 'critical_synchronisation_status', default => '' }, 'warning-last-synchronisation-status:s' => { name => 'warning_last_synchronisation_status', default => '' }, 'critical-last-synchronisation-status:s' => { name => 'critical_last_synchronisation_status', default => '%{status} !~ /Succeeded/' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => [ 'warning_synchronisation_status', 'critical_synchronisation_status', 'warning_last_synchronisation_status', 'critical_last_synchronisation_status'] ); } sub manage_selection { my ($self, %options) = @_; my $use_ssl = "\$false"; $use_ssl = "\$true" if (defined($self->{option_results}->{use_ssl})); if (!defined($self->{option_results}->{no_ps})) { my $ps = centreon::common::powershell::wsus::synchronisationstatus::get_powershell( wsus_server => $self->{option_results}->{wsus_server}, wsus_port => $self->{option_results}->{wsus_port}, use_ssl => $use_ssl ); if (defined($self->{option_results}->{ps_display})) { $self->{output}->output_add( severity => 'OK', short_msg => $ps ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{option_results}->{command_options} .= " " . centreon::plugins::misc::powershell_encoded($ps); } my ($stdout) = centreon::plugins::misc::execute( output => $self->{output}, options => $self->{option_results}, command => $self->{option_results}->{command}, command_path => $self->{option_results}->{command_path}, command_options => $self->{option_results}->{command_options} ); if (defined($self->{option_results}->{ps_exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($stdout); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } $self->{current} = { SynchronizationStatus => $decoded->{SynchronizationStatus}, TotalItems => $decoded->{TotalItems}, ProcessedItems => $decoded->{ProcessedItems}, }; $self->{last} = { LastSynchronizationResult => $decoded->{LastSynchronizationResult}, LastSynchronizationStartTime => $decoded->{LastSynchronizationStartTime}, LastSynchronizationEndTime => $decoded->{LastSynchronizationEndTime}, }; } 1; __END__ =head1 MODE Check synchronisation status. =over 8 =item B<--timeout> Set timeout time for command execution (Default: 30 sec) =item B<--no-ps> Don't encode powershell. To be used with --command and 'type' command. =item B<--command> Command to get information (Default: 'powershell.exe'). Can be changed if you have output in a file. To be used with --no-ps option. =item B<--command-path> Command path (Default: none). =item B<--command-options> Command options (Default: '-InputFormat none -NoLogo -EncodedCommand'). =item B<--ps-display> Display powershell script. =item B<--ps-exec-only> Print powershell output. =item B<--wsus-server> Set WSUS hostname/IP (Dafault: localhost). =item B<--wsus-port> Set WSUS port (Default: 8530). =item B<--use-ssl> Set if WSUS use ssl. =item B<--warning-synchronisation-status> Set warning threshold for current synchronisation status (Default: '') Can used special variables like: %{status}. =item B<--critical-synchronisation-status> Set critical threshold for current synchronisation status (Default: ''). Can used special variables like: %{status}. =item B<--warning-last-synchronisation-status> Set warning threshold for current synchronisation status (Default: '') Can used special variables like: %{status}. =item B<--critical-last-synchronisation-status> Set critical threshold for current synchronisation status (Default: '%{status} !~ /Succeeded/'). Can used special variables like: %{status}. =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'last-synchronisation-duration' (s), 'synchronisation-progress' (%). =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='status' =back =cut centreon-plugins-20220113/apps/microsoft/wsus/local/mode/updatesstatus.pm000066400000000000000000000155601417000230700265010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::wsus::local::mode::updatesstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use JSON::XS; use centreon::plugins::misc; use centreon::common::powershell::wsus::updatesstatus; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_output' } ]; $self->{maps_counters}->{global} = [ { label => 'with-client-errors', set => { key_values => [ { name => 'UpdatesWithClientErrorsCount' } ], output_template => 'With Client Errors: %d', perfdatas => [ { label => 'updates_with_client_errors', template => '%d', min => 0 } ] } }, { label => 'with-server-errors', set => { key_values => [ { name => 'UpdatesWithServerErrorsCount' } ], output_template => 'With Server Errors: %d', perfdatas => [ { label => 'updates_with_server_errors', template => '%d', min => 0 } ] } }, { label => 'needing-files', set => { key_values => [ { name => 'UpdatesNeedingFilesCount' } ], output_template => 'Needing Files: %d', perfdatas => [ { label => 'updates_needing_files_count', template => '%d', min => 0 } ] } }, { label => 'needed-by-computers', set => { key_values => [ { name => 'UpdatesNeededByComputersCount' } ], output_template => 'Needed By Computers: %d', perfdatas => [ { label => 'updates_needed_by_computers', template => '%d', min => 0 } ] } }, { label => 'up-to-date', set => { key_values => [ { name => 'UpdatesUpToDateCount' } ], output_template => 'Up-to-date: %s', perfdatas => [ { label => 'updates_up_to_date', template => '%d', min => 0 } ] } } ]; } sub prefix_output { my ($self, %options) = @_; return "Updates "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'timeout:s' => { name => 'timeout', default => 30 }, 'command:s' => { name => 'command', default => 'powershell.exe' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '-InputFormat none -NoLogo -EncodedCommand' }, 'no-ps' => { name => 'no_ps' }, 'ps-exec-only' => { name => 'ps_exec_only' }, 'ps-display' => { name => 'ps_display' }, 'wsus-server:s' => { name => 'wsus_server', default => 'localhost' }, 'wsus-port:s' => { name => 'wsus_port', default => 8530 }, 'use-ssl' => { name => 'use_ssl' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $use_ssl = "\$false"; $use_ssl = "\$true" if (defined($self->{option_results}->{use_ssl})); if (!defined($self->{option_results}->{no_ps})) { my $ps = centreon::common::powershell::wsus::updatesstatus::get_powershell( wsus_server => $self->{option_results}->{wsus_server}, wsus_port => $self->{option_results}->{wsus_port}, use_ssl => $use_ssl ); if (defined($self->{option_results}->{ps_display})) { $self->{output}->output_add( severity => 'OK', short_msg => $ps ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } $self->{option_results}->{command_options} .= " " . centreon::plugins::misc::powershell_encoded($ps); } my ($stdout) = centreon::plugins::misc::execute( output => $self->{output}, options => $self->{option_results}, command => $self->{option_results}->{command}, command_path => $self->{option_results}->{command_path}, command_options => $self->{option_results}->{command_options} ); if (defined($self->{option_results}->{ps_exec_only})) { $self->{output}->output_add( severity => 'OK', short_msg => $stdout ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($stdout); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } $self->{global} = { %$decoded }; } 1; __END__ =head1 MODE Check updates status. =over 8 =item B<--timeout> Set timeout time for command execution (Default: 30 sec) =item B<--no-ps> Don't encode powershell. To be used with --command and 'type' command. =item B<--command> Command to get information (Default: 'powershell.exe'). Can be changed if you have output in a file. To be used with --no-ps option. =item B<--command-path> Command path (Default: none). =item B<--command-options> Command options (Default: '-InputFormat none -NoLogo -EncodedCommand'). =item B<--ps-display> Display powershell script. =item B<--ps-exec-only> Print powershell output. =item B<--wsus-server> Set WSUS hostname/IP (Dafault: localhost). =item B<--wsus-port> Set WSUS port (Default: 8530). =item B<--use-ssl> Set if WSUS use ssl. =item B<--warning-*> Warning thresholds. Can be: 'with-client-errors', 'with-server-errors', 'needing-files', 'needed-by-computers', 'up-to-date'. =item B<--critical-*> Critical thresholds. Can be: 'with-client-errors', 'with-server-errors', 'needing-files', 'needed-by-computers', 'up-to-date'. =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='errors' =back =cut centreon-plugins-20220113/apps/microsoft/wsus/local/plugin.pm000066400000000000000000000030111417000230700241260ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::microsoft::wsus::local::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} = '0.1'; $self->{modes} = { 'computers-status' => 'apps::microsoft::wsus::local::mode::computersstatus', 'server-statistics' => 'apps::microsoft::wsus::local::mode::serverstatistics', 'synchronisation-status' => 'apps::microsoft::wsus::local::mode::synchronisationstatus', 'updates-status' => 'apps::microsoft::wsus::local::mode::updatesstatus' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check WSUS through powershell. =cut centreon-plugins-20220113/apps/monitoring/000077500000000000000000000000001417000230700203645ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/alyvix/000077500000000000000000000000001417000230700217005ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/alyvix/restapi/000077500000000000000000000000001417000230700233475ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/alyvix/restapi/custom/000077500000000000000000000000001417000230700246615ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/alyvix/restapi/custom/api.pm000066400000000000000000000141551417000230700257760ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::alyvix::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use JSON::XS; 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 => { 'hostname:s' => { name => 'hostname' }, 'url-path:s' => { name => 'url_path' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'api-username:s' => { name => 'api_username' }, 'api-password:s' => { name => 'api_password' }, 'timeout:s' => { name => 'timeout' }, 'unknown-http-status:s' => { name => 'unknown_http_status' }, 'warning-http-status:s' => { name => 'warning_http_status' }, 'critical-http-status:s' => { name => 'critical_http_status' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 80; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'http'; $self->{url_path} = (defined($self->{option_results}->{url_path})) ? $self->{option_results}->{url_path} : '/v0/'; $self->{timeout} = (defined($self->{option_results}->{timeout}) && $self->{option_results}->{timeout} =~ /^(\d+)$/) ? $1 : 30; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : undef; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : undef; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_status} : '%{http_code} < 200 or %{http_code} >= 300'; $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_status} : ''; $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_status} : ''; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify hostname option.'); $self->{output}->option_exit(); } return 0; } sub settings { my ($self, %options) = @_; $self->{http}->add_header(key => 'Content-Type', value => 'application/json'); $self->{http}->set_options(%{$self->{option_results}}); } sub get_connection_info { my ($self, %options) = @_; return $self->{hostname} . ":" . $self->{port}; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub get_port { my ($self, %options) = @_; return $self->{port}; } sub json_decode { my ($self, %options) = @_; my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($options{content}); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } return $decoded; } sub request_api { my ($self, %options) = @_; $self->settings(); my ($content) = $self->{http}->request( url_path => $self->{url_path} . $options{endpoint}, unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status} ); my $decoded = $self->json_decode(content => $content); return $decoded; } 1; __END__ =head1 NAME Alyvix Server Rest API. =head1 SYNOPSIS Alyvix Rest API custom mode. =head1 REST API OPTIONS Alyvix Server Rest API. =over 8 =item B<--hostname> Alyvix Server hostname. =item B<--url-path> API url path (Default: '/v0/') =item B<--port> API port (Default: 80) =item B<--proto> Specify https if needed (Default: 'http') =item B<--credentials> Specify this option if you access the API with authentication =item B<--username> Specify username for authentication (Mandatory if --credentials is specified) =item B<--password> Specify password for authentication (Mandatory if --credentials is specified) =item B<--basic> Specify this option if you access the API over basic authentication and don't want a '401 UNAUTHORIZED' error to be logged on your webserver. Specify this option if you access the API over hidden basic authentication or you'll get a '404 NOT FOUND' error. (Use with --credentials) =item B<--timeout> Set HTTP timeout =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/monitoring/alyvix/restapi/mode/000077500000000000000000000000001417000230700242735ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/alyvix/restapi/mode/listtestcases.pm000066400000000000000000000055551417000230700275350ustar00rootroot00000000000000# ## Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::alyvix::restapi::mode::listtestcases; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-testcase:s' => { name => 'filter_testcase' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->request_api(endpoint => 'testcases'); return $result->{testcases}; } sub run { my ($self, %options) = @_; my $testcases = $self->manage_selection(%options); foreach my $testcase (@$testcases) { next if (defined($self->{option_results}->{filter_testcase}) && $self->{option_results}->{filter_testcase} ne '' && $testcase->{testcase_alias} !~ /$self->{option_results}->{filter_testcase}/); $self->{output}->output_add(long_msg => sprintf( '[name = %s]', $testcase->{testcase_alias} ) ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List test cases:' ); $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) = @_; my $testcases = $self->manage_selection(%options); foreach my $testcase (@$testcases) { next if (defined($self->{option_results}->{filter_testcase}) && $self->{option_results}->{filter_testcase} ne '' && $testcase->{testcase_alias} !~ /$self->{option_results}->{filter_testcase}/ ); $self->{output}->add_disco_entry(name => $testcase->{testcase_alias}); } } 1; __END__ =head1 MODE List Alyvix Server test cases. =over 8 =item B<--filter-testcase> Filter on specific test case. =back =cut centreon-plugins-20220113/apps/monitoring/alyvix/restapi/mode/testcases.pm000066400000000000000000000165651417000230700266440ustar00rootroot00000000000000# ## Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::alyvix::restapi::mode::testcases; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use POSIX qw(strftime); sub custom_status_output { my ($self, %options) = @_; return sprintf( 'state: %s', $self->{result_values}->{state} ); } sub custom_date_output { my ($self, %options) = @_; return sprintf( 'last execution: %s (%s ago)', $self->{result_values}->{lastexec}, centreon::plugins::misc::change_seconds(value => $self->{result_values}->{freshness}) ); } sub testcase_long_output { my ($self, %options) = @_; return "checking test case '" . $options{instance_value}->{display} . "'"; } sub prefix_testcases_output { my ($self, %options) = @_; return "test case '" . $options{instance_value}->{display} . "' "; } sub prefix_testcase_output { my ($self, %options) = @_; return "transaction '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'cases', type => 3, cb_prefix_output => 'prefix_testcases_output', cb_long_output => 'testcase_long_output', indent_long_output => ' ', message_multiple => 'All test cases are ok', group => [ { name => 'global', type => 0 }, { name => 'testcases', display_long => 1, cb_prefix_output => 'prefix_testcase_output', message_multiple => 'test cases are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'testcase-duration', nlabel => 'testcase.duration.milliseconds', set => { key_values => [ { name => 'duration' } ], output_template => 'duration: %s ms', perfdatas => [ { template => '%d', unit => 'ms', min => 0, label_extra_instance => 1 }, ], } }, { label => 'testcase-state', type => 2, critical_default => '%{state} eq "FAILED"', set => { key_values => [ { name => 'state' }], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'testcase-freshness', nlabel => 'testcase.freshness.seconds', set => { key_values => [ { name => 'freshness' }, { name => 'lastexec' } ], closure_custom_output => $self->can('custom_date_output'), perfdatas => [ { template => '%.3f', unit => 's', min => 0, label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{testcases} = [ { label => 'transaction-state', type => 2, critical_default => '%{state} eq "FAILED"', set => { key_values => [ { name => 'state' }, { name => 'display' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'transaction-duration', nlabel => 'transaction.duration.milliseconds', set => { key_values => [ { name => 'duration' } ], output_template => 'duration: %s ms', perfdatas => [ { template => '%s', unit => 'ms', min => 0, label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-testcase:s' => { name => 'filter_testcase' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $status = { 0 => 'OK', 2 => 'FAILED' }; my $results = $options{custom}->request_api(endpoint => '/testcases/'); foreach (@{$results->{testcases}}) { next if ( defined($self->{option_results}->{filter_testcase}) && $self->{option_results}->{filter_testcase} ne '' && $_->{testcase_alias} !~ /$self->{option_results}->{filter_testcase}/ ); my $measures = $options{custom}->request_api(endpoint => '/testcases/' . $_->{testcase_alias} . '/'); my $lastexec = $measures->{measures}->[0]->{timestamp_epoch} / 1000000000; $self->{cases}->{ $_->{testcase_alias} } = { display => $_->{testcase_alias}, global => { display => $_->{testcase_alias}, duration => $measures->{measures}->[0]->{test_case_duration_ms}, state => $status->{ $measures->{measures}->[0]->{test_case_state} }, lastexec => strftime('%Y-%m-%dT%H:%M:%S', localtime($lastexec)), freshness => (time() - $lastexec) }, testcases => {} }; my $i = 1; foreach my $transaction (@{$measures->{measures}}) { my $instance = $i . '_' . $transaction->{transaction_alias}; $instance =~ s/ /_/g; $self->{cases}->{ $_->{testcase_alias} }->{testcases}->{$instance} = { display => $instance, state => $status->{ $transaction->{transaction_state} }, duration => $transaction->{transaction_performance_ms} }; $i++; } } if (scalar(keys %{$self->{cases}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No test case found'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check Alyvix Server test cases using Alyvix Rest API Example: perl centreon_plugins.pl --plugin=apps::monitoring::alyvix::restapi::plugin --mode=testcases --hostname='10.0.0.1' =over 8 =item B<--filter-testcase> Filter on specific test case. =item B<--warning-*-state> Set warning status (Default: '') where '*' can be 'testcase' or 'transaction'. =item B<--critical-*-state> Set critical status (Default: '%{state} eq "FAILED"') where '*' can be 'testcase' or 'transaction'. =item B<--warning-*-duration> Set warning threshold for test cases or transactions duration (Default: '') where '*' can be 'testcase' or 'transaction'. =item B<--critical-*-duration> Set critical threshold for test cases or transactions duration (Default: '') where '*' can be 'testcase' or 'transaction'. =back =cut centreon-plugins-20220113/apps/monitoring/alyvix/restapi/plugin.pm000066400000000000000000000026401417000230700252050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::alyvix::restapi::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} = { 'list-testcases' => 'apps::monitoring::alyvix::restapi::mode::listtestcases', 'testcases' => 'apps::monitoring::alyvix::restapi::mode::testcases' }; $self->{custom_modes}->{api} = 'apps::monitoring::alyvix::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Alyvix Server using REST API. =cut centreon-plugins-20220113/apps/monitoring/dynatrace/000077500000000000000000000000001417000230700223365ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/dynatrace/restapi/000077500000000000000000000000001417000230700240055ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/dynatrace/restapi/custom/000077500000000000000000000000001417000230700253175ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/dynatrace/restapi/custom/api.pm000066400000000000000000000147001417000230700264300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::dynatrace::restapi::custom::api; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::http; use JSON::XS; use Digest::MD5 qw(md5_hex); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); 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 => { 'hostname:s' => { name => 'hostname' }, 'environment-id:s' => { name => 'environment_id' }, 'port:s' => { name => 'port'}, 'proto:s' => { name => 'proto' }, 'api-password:s' => { name => 'api_password' }, 'timeout:s' => { name => 'timeout', default => 30 } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : 'live.dynatrace.com'; $self->{environment_id} = (defined($self->{option_results}->{environment_id})) ? $self->{option_results}->{environment_id} : undef; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 30; $self->{ssl_opt} = (defined($self->{option_results}->{ssl_opt})) ? $self->{option_results}->{ssl_opt} : undef; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : undef; if (!defined($self->{hostname}) || $self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } if (!defined($self->{environment_id}) || $self->{environment_id} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --environment-id option."); $self->{output}->option_exit(); } if (!defined($self->{api_password}) || $self->{api_password} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-password option."); $self->{output}->option_exit(); } return 0; } sub build_options_for_httplib { my ($self, %options) = @_; if ($self->{hostname} eq 'live.dynatrace.com') { $self->{option_results}->{hostname} = $self->{environment_id} . '.' . $self->{hostname}; } else { $self->{option_results}->{hostname} = $self->{hostname}; } $self->{option_results}->{environment_id} = $self->{environment_id}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{ssl_opt} = $self->{ssl_opt}; $self->{option_results}->{timeout} = $self->{timeout}; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Content-Type', value => 'application/json;charset=UTF-8'); $self->{http}->add_header(key => 'Authorization', value => 'Api-Token ' . $self->{option_results}->{api_password}); $self->{http}->set_options(%{$self->{option_results}}); } sub request_api { my ($self, %options) = @_; $self->settings(); my $content = $self->{http}->request(%options, warning_status => '', unknown_status => '%{http_code} < 200 or %{http_code} >= 300', critical_status => '' ); my $decoded; eval { $decoded = JSON::XS->new->decode($content); }; if ($@) { $self->{output}->output_add(long_msg => $content, debug => 1); $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } if (!defined($decoded)) { $self->{output}->output_add(long_msg => $decoded, debug => 1); $self->{output}->add_option_msg(short_msg => "Error while retrieving data (add --debug option for detailed message)"); $self->{output}->option_exit(); } return $decoded; } sub internal_problem { my ($self, %options) = @_; my $status = $self->request_api( method => 'GET', url_path => (($self->{hostname} eq 'live.dynatrace.com') ? '' : '/e/' . $self->{option_results}->{environment_id}) . '/api/v1/problem/feed?relativeTime=' . $self->{option_results}->{relative_time} ); return $status; } sub api_problem { my ($self, %options) = @_; my $status = $self->internal_problem(); return $status->{result}->{problems}; } 1; __END__ =head1 NAME Dynatrace Rest API =head1 REST API OPTIONS =over 8 =item B<--hostname> Set hostname or IP of Dynatrace server (Default: live.dynatrace.com). =item B<--environment-id> Set Dynatrace environment ID. =item B<--port> Set Dynatrace Port (Default: '443'). =item B<--proto> Specify http if needed (Default: 'https'). =item B<--api-password> Set Dynatrace API token. =item B<--timeout> Threshold for HTTP timeout (Default: '30'). =back =cut centreon-plugins-20220113/apps/monitoring/dynatrace/restapi/mode/000077500000000000000000000000001417000230700247315ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/dynatrace/restapi/mode/problems.pm000066400000000000000000000132161417000230700271150ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::dynatrace::restapi::mode::problems; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf( "problem '%s' [type: %s] [severity: %s] [impact: %s] [entity: %s]", $self->{result_values}->{displayName}, $self->{result_values}->{eventType}, $self->{result_values}->{severityLevel}, $self->{result_values}->{impactLevel}, $self->{result_values}->{entityName} ); } sub prefix_service_output { my ($self, %options) = @_; return "Problem '" . $options{instance_value}->{displayName} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'problems', type => 2, message_multiple => '0 problems detected', display_counter_problem => { label => 'problems', min => 0 }, group => [ { name => 'problem' } ] } ]; $self->{maps_counters}->{global} = [ { label => 'problems-open', nlabel => 'problems.open.count', display_ok => 0, set => { key_values => [ { name => 'problems_open' } ], output_template => 'number of open problems : %s', perfdatas => [ { template => '%s', value => 'problems_open', min => 0 } ] } } ]; $self->{maps_counters}->{problem} = [ { label => 'status', type => 2, critical_default => '%{status} eq "OPEN"', set => { key_values => [ { name => 'status' }, { name => 'impactLevel' }, { name => 'severityLevel' }, { name => 'entityName' }, { name => 'eventType' }, { name => 'entityId' }, { name => 'displayName' }, { name => 'startTime' }, { name => 'endTime' }, { name => 'commentCount' }, { name => 'time' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $self->{version} = '1.0'; $options{options}->add_options(arguments => { 'relative-time:s' => { name => 'relative_time', default => 'min' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $problem = $options{custom}->api_problem(relative_time => $options{options}->{relative_time}); $self->{global} = { problems_open => 0 }; $self->{problem} = {}; $self->{problems}->{global} = { problem => {} }; my ($i, $time) = (1, time()); foreach my $item (@{$problem}) { $self->{problems}->{global}->{problem}->{$i} = { displayName => $item->{displayName}, status => $item->{status}, impactLevel => $item->{impactLevel}, severityLevel => $item->{severityLevel}, entityName => join(",", centreon::plugins::misc::uniq(map { "$_->{entityName}" } @{$item->{rankedImpacts}})), eventType => join(",", centreon::plugins::misc::uniq(map { "$_->{eventType}" } @{$item->{rankedImpacts}})), entityId => join(",", centreon::plugins::misc::uniq(map { "$_->{entityId}" } @{$item->{rankedImpacts}})), startTime => $item->{startTime} / 1000, endTime => $item->{endTime} > -1 ? $item->{endTime} / 1000 : -1, commentCount => $item->{commentCount}, time => $time }; if ($item->{status} eq 'OPEN') { $self->{global}->{problems_open}++; } $i++; } } 1; __END__ =head1 MODE Check problems. =over 8 =item B<--relative-time> Set request relative time (Default: 'min'). Can use: min, 5mins, 10mins, 15mins, 30mins, hour, 2hours, 6hours, day, 3days, week, month. =item B<--unknown-status> Set unknown threshold for status. Can use special variables like: %{status}, %{impactLevel}, %{severityLevel}, %{entityName}, %{eventType}, %{entityId}, %{startTime}, %{endTime}, %{commentCount}, %{time} =item B<--warning-status> Set warning threshold for status. Can use special variables like: %{status}, %{impactLevel}, %{severityLevel}, %{entityName}, %{eventType}, %{entityId}, %{startTime}, %{endTime}, %{commentCount}, %{time} =item B<--critical-status> Set critical threshold for status (Default: '%{status} eq "OPEN"'). Can use special variables like: %{status}, %{impactLevel}, %{severityLevel}, %{entityName}, %{eventType}, %{entityId}, %{startTime}, %{endTime}, %{commentCount}, %{time} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'problems-open'. =back =cut centreon-plugins-20220113/apps/monitoring/dynatrace/restapi/plugin.pm000066400000000000000000000025471417000230700256510ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::dynatrace::restapi::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} = '1.0'; %{$self->{modes}} = ( 'problems' => 'apps::monitoring::dynatrace::restapi::mode::problems', ); $self->{custom_modes}{api} = 'apps::monitoring::dynatrace::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Dynatrace through its HTTPS remote API. =over 8 =back =cut centreon-plugins-20220113/apps/monitoring/iplabel/000077500000000000000000000000001417000230700217745ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/iplabel/datametrie/000077500000000000000000000000001417000230700241135ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/iplabel/datametrie/restapi/000077500000000000000000000000001417000230700255625ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/iplabel/datametrie/restapi/custom/000077500000000000000000000000001417000230700270745ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/iplabel/datametrie/restapi/custom/api.pm000066400000000000000000000237621417000230700302150ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::iplabel::datametrie::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use centreon::plugins::statefile; use JSON::XS; use Digest::MD5 qw(md5_hex); 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 => { 'api-username:s' => { name => 'api_username' }, 'api-password:s' => { name => 'api_password' }, 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'timeout:s' => { name => 'timeout' }, 'unknown-http-status:s' => { name => 'unknown_http_status' }, 'warning-http-status:s' => { name => 'warning_http_status' }, 'critical-http-status:s' => { name => 'critical_http_status' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); $self->{cache} = centreon::plugins::statefile->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : 'api.ip-label.net'; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300'; $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : undef; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : undef; if (!defined($self->{hostname}) || $self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } if (!defined($self->{api_username}) || $self->{api_username} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-username option."); $self->{output}->option_exit(); } if (!defined($self->{api_password}) || $self->{api_password} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-password option."); $self->{output}->option_exit(); } $self->{cache}->check_options(option_results => $self->{option_results}); return 0; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub get_port { my ($self, %options) = @_; return $self->{port}; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Content-Type', value => 'application/json;charset=UTF-8'); $self->{http}->add_header(key => 'Accept', value => 'application/json;charset=UTF-8'); $self->{http}->set_options(%{$self->{option_results}}); } sub json_decode { my ($self, %options) = @_; my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($options{content}); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } return $decoded; } sub clean_session_token { my ($self, %options) = @_; my $datas = { last_timestamp => time() }; $options{statefile}->write(data => $datas); $self->{session_token} = undef; $self->{http}->add_header(key => 'Ipln-Auth', value => undef); } sub authenticate { my ($self, %options) = @_; my $has_cache_file = $options{statefile}->read(statefile => 'iplabel_datametrie_api_' . md5_hex($self->{option_results}->{hostname}) . '_' . md5_hex($self->{option_results}->{api_username})); my $session_token = $options{statefile}->get(name => 'session_token'); if ($has_cache_file == 0 || !defined($session_token)) { my $content = $self->{http}->request( url_path => '/REST/Get_Token/', credentials => 1, basic => 1, username => $self->{api_username}, password => $self->{api_password}, warning_status => '', unknown_status => '', critical_status => '' ); if ($self->{http}->get_code() != 200) { $self->{output}->add_option_msg(short_msg => "login error [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded = $self->json_decode(content => $content); if (!defined($decoded) || !defined($decoded->{Ipln_WS_REST_datametrie}->{Get_Token}->{status}) || $decoded->{Ipln_WS_REST_datametrie}->{Get_Token}->{status} ne 'success') { $self->{output}->add_option_msg(short_msg => 'error retrieving session_token'); $self->{output}->option_exit(); } $session_token = $decoded->{Ipln_WS_REST_datametrie}->{Get_Token}->{response}->{TOKEN}; my $datas = { last_timestamp => time(), session_token => $session_token }; $options{statefile}->write(data => $datas); } $self->{session_token} = $session_token; $self->{http}->add_header(key => 'Ipln-Auth', value => $self->{session_token}); } sub request_api { my ($self, %options) = @_; $self->settings(); if (!defined($self->{session_token})) { $self->authenticate(statefile => $self->{cache}); } my $content = $self->{http}->request( url_path => '/REST' . $options{endpoint}, get_param => $options{get_param}, unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status} ); # wrong token is 200 my $decoded = $self->json_decode(content => $content); if (!defined($decoded) || !defined($decoded->{Ipln_WS_REST_datametrie}->{ $options{label} }->{status})) { $self->{output}->add_option_msg(short_msg => 'error while retrieving data (add --debug option for detailed message)'); $self->{output}->option_exit(); } if ($decoded->{Ipln_WS_REST_datametrie}->{ $options{label} }->{status} ne 'success') { $self->clean_session_token(statefile => $self->{cache}); $self->authenticate(statefile => $self->{cache}); $content = $self->{http}->request( url_path => '/REST' . $options{endpoint}, get_param => $options{get_param}, unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status} ); $decoded = $self->json_decode(content => $content); if (!defined($decoded) || !defined($decoded->{Ipln_WS_REST_datametrie}->{ $options{label} }->{status})) { $self->{output}->add_option_msg(short_msg => 'error while retrieving data (add --debug option for detailed message)'); $self->{output}->option_exit(); } } if ($decoded->{Ipln_WS_REST_datametrie}->{ $options{label} }->{status} ne 'success') { $self->{output}->add_option_msg(short_msg => 'method failed'); $self->{output}->option_exit(); } return $decoded->{Ipln_WS_REST_datametrie}->{ $options{label} }->{response}; } 1; __END__ =head1 NAME Ip-Label Datametrie Rest API =head1 REST API OPTIONS Ip-Label Datametrie Rest API =over 8 =item B<--hostname> Set hostname (Default: 'api.ip-label.net'). =item B<--port> Port used (Default: 443) =item B<--proto> Specify https if needed (Default: 'https') =item B<--api-username> Set username. =item B<--api-password> Set password. =item B<--timeout> Set timeout in seconds (Default: 10). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/monitoring/iplabel/datametrie/restapi/mode/000077500000000000000000000000001417000230700265065ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/iplabel/datametrie/restapi/mode/alarms.pm000066400000000000000000000064121417000230700303260ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::iplabel::datametrie::restapi::mode::alarms; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_alarm_output { my ($self, %options) = @_; return 'current alarms '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_alarm_output', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'black', nlabel => 'alarms.black.count', set => { key_values => [ { name => 'black' } ], output_template => 'black: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'red', nlabel => 'alarms.red.count', set => { key_values => [ { name => 'red' } ], output_template => 'red: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'orange', nlabel => 'alarms.orange.count', set => { key_values => [ { name => 'orange' } ], output_template => 'orange: %s', perfdatas => [ { template => '%s', min => 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 => { }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['unknown_status', 'warning_status', 'critical_status', ]); } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->request_api( endpoint => '/Get_Current_Alarms_All_Monitors/', label => 'Get_Current_Alarms_All_Monitors' ); $self->{global} = { orange => 0, red => 0, black => 0 }; return if (ref($results) ne 'ARRAY'); foreach (@$results) { $self->{global}->{ lc($_->{ALARM_TYPE}) }++ if (defined($self->{global}->{ lc($_->{ALARM_TYPE}) })); } } 1; __END__ =head1 MODE Check current alarms. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='black' =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'black', 'red', 'orange'. =back =cut centreon-plugins-20220113/apps/monitoring/iplabel/datametrie/restapi/mode/kpi.pm000066400000000000000000000150721417000230700276340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::iplabel::datametrie::restapi::mode::kpi; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use POSIX; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; return sprintf('status: %s', $self->{result_values}->{status}); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'kpi', type => 1, cb_prefix_output => 'prefix_kpi_output', message_multiple => 'All KPI are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{kpi} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'display' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } }, { label => 'success-rate', nlabel => 'kpi.success.rate.percentage', set => { key_values => [ { name => 'success_rate', no_value => -1 }, { name => 'display' } ], output_template => 'success rate: %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 } ] } }, { label => 'sla-availability', nlabel => 'kpi.sla.availability.percentage', set => { key_values => [ { name => 'sla_availability', no_value => -1 }, { name => 'display' } ], output_template => 'sla availability: %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 } ] } }, { label => 'performance', nlabel => 'kpi.performance.milliseconds', set => { key_values => [ { name => 'performance', no_value => -1 }, { name => 'display' } ], output_template => 'performance: %s ms', perfdatas => [ { template => '%s', min => 0, unit => 'ms', label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-id:s' => { name => 'filter_id' }, 'filter-name:s' => { name => 'filter_name' }, 'unknown-status:s' => { name => 'unknown_status', default => '' }, '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); $self->change_macros(macros => ['unknown_status', 'warning_status', 'critical_status', ]); } sub prefix_kpi_output { my ($self, %options) = @_; return "KPI '" . $options{instance_value}->{display} . "' "; } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->request_api( endpoint => '/Get_Monitors/', label => 'Get_Monitors' ); $self->{kpi} = {}; my $time = time(); my $end_date = POSIX::strftime('%d/%m/%Y %H:%M:%S', gmtime()); foreach (@$results) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $_->{MONITOR_NAME} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping monitor '" . $_->{MONITOR_NAME} . "': no matching filter.", debug => 1); next; } if (defined($self->{option_results}->{filter_id}) && $self->{option_results}->{filter_id} ne '' && $_->{MONITOR_ID} !~ /$self->{option_results}->{filter_id}/) { $self->{output}->output_add(long_msg => "skipping monitor '" . $_->{MONITOR_NAME} . "': no matching filter.", debug => 1); next; } my $start_date = POSIX::strftime('%d/%m/%Y %H:%M:%S', gmtime($time - ($_->{PERIODICITY} * 60 * 2))); my $kpi_detail = $options{custom}->request_api( endpoint => '/GMT/Get_KPI/', label => 'Get_KPI', get_param => [ 'monitor_id=' . $_->{MONITOR_ID}, 'date_value1=' . $start_date, 'date_value2=' . $end_date ] ); $self->{kpi}->{ $_->{MONITOR_NAME} } = { display => $_->{MONITOR_NAME}, status => $_->{MONITOR_STATUS}, success_rate => $kpi_detail->{SUCCESS_RATE}, performance => $kpi_detail->{PERFORMANCE}, sla_availability => $kpi_detail->{SLA_AVAILABILITY}, }; } if (scalar(keys %{$self->{kpi}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No monitor found"); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check KPI. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='status' =item B<--filter-id> Filter by monitor id (can be a regexp). =item B<--filter-name> Filter by monitor name (can be a regexp). =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{status}, %{display} =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-*> B<--critical-*> Thresholds. Can be: 'success-rate' (%) 'sla-availability' (%), 'performance' (ms). =back =cut centreon-plugins-20220113/apps/monitoring/iplabel/datametrie/restapi/mode/listkpi.pm000066400000000000000000000053611417000230700305300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::iplabel::datametrie::restapi::mode::listkpi; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; my $api_results = $options{custom}->request_api( endpoint => '/Get_Monitors/', label => 'Get_Monitors' ); my $results = {}; foreach (@$api_results) { $results->{$_->{MONITOR_ID}} = { id => $_->{MONITOR_ID}, name => $_->{MONITOR_NAME}, client_id => $_->{CLIENT_ID}, status => $_->{MONITOR_STATUS} }; } return $results; } sub run { my ($self, %options) = @_; my $results = $self->manage_selection(%options); foreach (sort {lc $a->{name} cmp lc $b->{name}} values %$results) { $self->{output}->output_add( long_msg => sprintf( '[name = %s][id = %s][client id = %s][status = %s]', $_->{name}, $_->{id}, $_->{client_id}, $_->{status} ) ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List kpi:' ); $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 => ['id', 'name', 'client_id', 'status']); } sub disco_show { my ($self, %options) = @_; my $scenarios = $self->manage_selection(%options); foreach (sort {lc $a->{name} cmp lc $b->{name}} values %$scenarios) { $self->{output}->add_disco_entry(%$_); } } 1; __END__ =head1 MODE List KPI. =over 8 =back =cut centreon-plugins-20220113/apps/monitoring/iplabel/datametrie/restapi/plugin.pm000066400000000000000000000030271417000230700274200ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::iplabel::datametrie::restapi::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} = { 'alarms' => 'apps::monitoring::iplabel::datametrie::restapi::mode::alarms', 'list-kpi' => 'apps::monitoring::iplabel::datametrie::restapi::mode::listkpi', 'kpi' => 'apps::monitoring::iplabel::datametrie::restapi::mode::kpi' }; $self->{custom_modes}{api} = 'apps::monitoring::iplabel::datametrie::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check IP-Label Datametrie using Rest API. =cut centreon-plugins-20220113/apps/monitoring/iplabel/newtest/000077500000000000000000000000001417000230700234655ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/iplabel/newtest/restapi/000077500000000000000000000000001417000230700251345ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/iplabel/newtest/restapi/custom/000077500000000000000000000000001417000230700264465ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/iplabel/newtest/restapi/custom/api.pm000066400000000000000000000151441417000230700275620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::iplabel::newtest::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use JSON::XS; 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 => { 'api-username:s' => { name => 'api_username' }, 'api-password:s' => { name => 'api_password' }, 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'timeout:s' => { name => 'timeout' }, 'url-path:s' => { name => 'url_path' }, 'unknown-http-status:s' => { name => 'unknown_http_status' }, 'warning-http-status:s' => { name => 'warning_http_status' }, 'critical-http-status:s' => { name => 'critical_http_status' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{url_path} = (defined($self->{option_results}->{url_path})) ? $self->{option_results}->{url_path} : '/rest'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : ''; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : ''; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300'; $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } if ($self->{api_username} ne '' && $self->{api_password} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-password option."); $self->{output}->option_exit(); } return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; if ($self->{api_username} ne '') { $self->{option_results}->{credentials} = 1; $self->{option_results}->{basic} = 1; $self->{option_results}->{username} = $self->{api_username}; $self->{option_results}->{password} = $self->{api_password}; } } sub settings { my ($self, %options) = @_; return if (defined($self->{settings_done})); $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->add_header(key => 'Content-Type', value => 'application/json'); $self->{http}->set_options(%{$self->{option_results}}); $self->{settings_done} = 1; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub request_api { my ($self, %options) = @_; $self->settings(); my $content = $self->{http}->request( url_path => $self->{url_path} . $options{endpoint}, unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status} ); if (!defined($content) || $content eq '') { $self->{output}->add_option_msg(short_msg => "API returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } return $decoded; } 1; __END__ =head1 NAME IP-Label newtest Rest API =head1 REST API OPTIONS IP-Label newtest Rest API =over 8 =item B<--hostname> Newtest hostname. =item B<--port> Port used (Default: 8085) =item B<--proto> Specify https if needed (Default: 'http') =item B<--url-path> API url path (Default: '/rest') =item B<--api-username> API username. =item B<--api-password> API password. =item B<--timeout> Set timeout in seconds (Default: 10). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/monitoring/iplabel/newtest/restapi/mode/000077500000000000000000000000001417000230700260605ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/iplabel/newtest/restapi/mode/discovery.pm000066400000000000000000000114601417000230700304270ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::iplabel::newtest::restapi::mode::discovery; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'resource-type:s' => { name => 'resource_type' }, 'prettify' => { name => 'prettify' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{resource_type}) || $self->{option_results}->{resource_type} eq '') { $self->{option_results}->{resource_type} = 'robot'; } if ($self->{option_results}->{resource_type} !~ /^robot|scenario$/) { $self->{output}->add_option_msg(short_msg => 'unknown resource type'); $self->{output}->option_exit(); } } sub discovery_robots { my ($self, %options) = @_; my $robots = $options{custom}->request_api(endpoint => '/api/robots'); my $nodes = {}; foreach my $robot (@$robots) { $nodes->{ $robot->{Id} } = { id => $robot->{Id}, name => $robot->{Name}, description => $robot->{Description}, comment => $robot->{Comment}, status => $robot->{CurrentStatus}->{Value}, company => $robot->{Company}->{Name}, location => $robot->{Location}->{Name}, version => $robot->{Version}, ip => $robot->{IPAddress}, scenarios => [] }; foreach (@{$options{instances}}) { next if ($_->{Robot}->{Id} ne $robot->{Id}); push @{$nodes->{ $robot->{Id} }->{scenarios}}, $_->{Scenario}->{Name}; } } return [values %$nodes]; } sub discovery_scenarios { my ($self, %options) = @_; my $scenarios = $options{custom}->request_api(endpoint => '/api/measures'); my $nodes = {}; foreach my $scenario (@$scenarios) { $nodes->{ $scenario->{Id} } = { id => $scenario->{Id}, name => $scenario->{Name}, description => $scenario->{Description}, robots => [] }; foreach (keys %{$scenario->{Properties}}) { $nodes->{ $scenario->{Id} }->{lc($_)} = $scenario->{Properties}->{$_}; } foreach (@{$options{instances}}) { next if ($_->{Scenario}->{Id} ne $scenario->{Id}); push @{$nodes->{ $scenario->{Id} }->{robots}}, $_->{Robot}->{Name}; } } return [values %$nodes]; } sub run { my ($self, %options) = @_; my $disco_stats; $disco_stats->{start_time} = time(); my $instances = $options{custom}->request_api(endpoint => '/api/instances'); my $results = []; if ($self->{option_results}->{resource_type} eq 'robot') { $results = $self->discovery_robots( custom => $options{custom}, instances => $instances ); } else { $results = $self->discovery_scenarios( custom => $options{custom}, instances => $instances ); } $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; $disco_stats->{discovered_items} = scalar(@$results); $disco_stats->{results} = $results; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE Resources discovery. =over 8 =item B<--resource-type> Choose the type of resources to discover (Can be: 'robot', 'scenario'). =back =cut centreon-plugins-20220113/apps/monitoring/iplabel/newtest/restapi/mode/listinstances.pm000066400000000000000000000052721417000230700313070ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::iplabel::newtest::restapi::mode::listinstances; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; return $options{custom}->request_api(endpoint => '/api/instances'); } sub run { my ($self, %options) = @_; my $instances = $self->manage_selection(%options); foreach (@$instances) { $self->{output}->output_add(long_msg => sprintf( '[robot_id = %s][robot_name = %s][scenario_id = %s][scenario_name = %s][status = %s]', $_->{Robot}->{Id}, $_->{Robot}->{Name}, $_->{Scenario}->{Id}, $_->{Scenario}->{Name}, $_->{CurrentStatus}->{Value} )); } $self->{output}->output_add( severity => 'OK', short_msg => 'List instances:' ); $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 => [ 'scenario_id', 'scenario_name', 'robot_name', 'robot_id', 'status' ]); } sub disco_show { my ($self, %options) = @_; my $instances = $self->manage_selection(%options); foreach (@$instances) { $self->{output}->add_disco_entry( robot_id => $_->{Robot}->{Id}, robot_name => $_->{Robot}->{Name}, scenario_id => $_->{Scenario}->{Id}, scenario_name => $_->{Scenario}->{Name}, status => $_->{CurrentStatus}->{Value} ); } } 1; __END__ =head1 MODE List instances. =over 8 =back =cut centreon-plugins-20220113/apps/monitoring/iplabel/newtest/restapi/mode/scenarios.pm000066400000000000000000000330061417000230700304060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::iplabel::newtest::restapi::mode::scenarios; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use POSIX; use DateTime; sub robot_long_output { my ($self, %options) = @_; return "checking robot '" . $options{instance_value}->{display} . "'"; } sub prefix_robot_output { my ($self, %options) = @_; return "Robot '" . $options{instance_value}->{display} . "' "; } sub prefix_scenario_output { my ($self, %options) = @_; return "scenario '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'robots', type => 3, cb_prefix_output => 'prefix_robot_output', cb_long_output => 'robot_long_output', indent_long_output => ' ', message_multiple => 'All robots are ok', group => [ { name => 'scenarios', display_long => 1, cb_prefix_output => 'prefix_scenario_output', message_multiple => 'all scenarios are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{scenarios} = [ { label => 'dummy', threshold => 0, display_ok => 0, set => { key_values => [ { name => 'last_exec' } ], output_template => 'none', perfdatas => [] } }, { label => 'status-green', nlabel => 'scenario.status.green.percentage', set => { key_values => [ { name => 'green_prct' }, { name => 'display' } ], output_template => 'green status: %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 } ] } }, { label => 'status-red', nlabel => 'scenario.status.red.percentage', set => { key_values => [ { name => 'red_prct' }, { name => 'display' } ], output_template => 'red status: %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 } ] } }, { label => 'status-orange', nlabel => 'scenario.status.orange.percentage', set => { key_values => [ { name => 'orange_prct' }, { name => 'display' } ], output_template => 'orange status: %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 } ] } }, { label => 'status-grey', nlabel => 'scenario.status.grey.percentage', set => { key_values => [ { name => 'grey_prct' }, { name => 'display' } ], output_template => 'grey status: %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 } ] } }, { label => 'execution-time', nlabel => 'scenario.execution.time.milliseconds', set => { key_values => [ { name => 'execution_time' }, { name => 'display' } ], output_template => 'execution time: %s ms', perfdatas => [ { template => '%s', min => 0, unit => 'ms', label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-robot-name:s' => { name => 'filter_robot_name' }, 'filter-scenario-name:s' => { name => 'filter_scenario_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = 'iplabel_newtest_' . $self->{mode} . '_' . $options{custom}->get_hostname() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_robot_name}) ? md5_hex($self->{option_results}->{filter_robot_name}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_scenario_name}) ? md5_hex($self->{option_results}->{filter_scenario_name}) : md5_hex('all')); my $last_timestamp = $self->read_statefile_key(key => 'last_timestamp'); my $timespan = 5; if (defined($last_timestamp)) { $timespan = POSIX::ceil((time() - $last_timestamp) / 60); } else { $last_timestamp = time() - (60 * 5); } my $instances = $options{custom}->request_api(endpoint => '/api/instances'); $self->{robots} = {}; my $scenarios_last_exec = {}; my $query_filter = []; foreach (@$instances) { if (defined($self->{option_results}->{filter_robot_name}) && $self->{option_results}->{filter_robot_name} ne '' && $_->{Robot}->{Name} !~ /$self->{option_results}->{filter_robot_name}/i) { $self->{output}->output_add(long_msg => "skipping scenario '" . $_->{Scenario}->{Name} . "': no matching filter.", debug => 1); next; } if (defined($self->{option_results}->{filter_scenario_name}) && $self->{option_results}->{filter_scenario_name} ne '' && $_->{Scenario}->{Name} !~ /$self->{option_results}->{filter_scenario_name}/i) { $self->{output}->output_add(long_msg => "skipping scenario '" . $_->{Scenario}->{Name} . "': no matching filter.", debug => 1); next; } if (!defined($self->{robots}->{ $_->{Robot}->{Name} })) { push @$query_filter, 'robot=' . $_->{Robot}->{Id}; $self->{robots}->{ $_->{Robot}->{Name} } = { display => $_->{Robot}->{Name}, scenarios => {} }; } if (!defined($self->{robots}->{ $_->{Robot}->{Name} }->{scenarios}->{ $_->{Scenario}->{Name} })) { push @$query_filter, 'scenario=' . $_->{Scenario}->{Id}; $self->{robots}->{ $_->{Robot}->{Name}}->{scenarios}->{ $_->{Scenario}->{Name} } = { display => $_->{Scenario}->{Name}, red_seconds => 0, orange_seconds => 0, grey_seconds => 0, green_seconds => 0, execution_time_total => 0, execution_count => 0 }; } my $uuid = $_->{Robot}->{Name} . '~' . $_->{Scenario}->{Name}; if (!defined($scenarios_last_exec->{$uuid})) { $scenarios_last_exec->{$uuid} = $self->read_statefile_key(key => $uuid . '_last_exec'); } } my $query_filter_string = ''; my $query_filter_num = scalar(@$query_filter); # if it's too big, we request everything if ($query_filter_num > 0 && $query_filter_num < 50) { $query_filter_string = '&' . join('&', @$query_filter); } my $results = []; if ($query_filter_num > 0) { $results = $options{custom}->request_api(endpoint => '/api/results?range=' . $timespan . $query_filter_string); } my $mapping_status = { completed => 'green', failed => 'red', warning => 'orange', available => 'green', suspended => 'grey', outofrange => 'grey', canceled => 'grey', notrunning => 'grey', unknown => 'grey' }; # { # "Id": 54411512, # "ExecutionDate": "2020-06-24T15:01:39", # "ExecutionDateUtc": "2020-06-24T13:01:39", # "Status": "Warning", # "Value": 45000, # "ExclusionState": "None", # "Measure": { # "Id": 9, # "Name": "Sugar" # }, # "Robot": { # "Id": 12, # "Name": "STOCKHOLM" # }, # "ErrorMessage": "" #} my $i = scalar(@$results) - 1; for (; $i >= 0; $i--) { next if (!defined($self->{robots}->{ $results->[$i]->{Robot}->{Name} }) || !defined($self->{robots}->{ $results->[$i]->{Robot}->{Name} }->{scenarios}->{ $results->[$i]->{Measure}->{Name} })); next if ($results->[$i]->{ExecutionDateUtc} !~ /^(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)$/); my $exec_time = DateTime->new(year => $1, month => $2, day => $3, hour => $4, minute => $5, second => $6, time_zone => 'UTC'); my $exec_epoch = $exec_time->epoch(); my $uuid = $results->[$i]->{Robot}->{Name} . '~' . $results->[$i]->{Measure}->{Name}; if (!defined($scenarios_last_exec->{$uuid})) { $scenarios_last_exec->{$uuid} = { time => $last_timestamp, status => lc($results->[$i]->{Status}) }; $self->{robots}->{ $results->[$i]->{Robot}->{Name} }->{scenarios}->{ $results->[$i]->{Measure}->{Name} }->{execution_time_total} += $results->[$i]->{Value}; $self->{robots}->{ $results->[$i]->{Robot}->{Name} }->{scenarios}->{ $results->[$i]->{Measure}->{Name} }->{execution_count}++; next; } next if ($exec_epoch < $last_timestamp); $self->{robots}->{ $results->[$i]->{Robot}->{Name} }->{scenarios}->{ $results->[$i]->{Measure}->{Name} }->{ $mapping_status->{ $scenarios_last_exec->{$uuid}->{status} } . '_seconds' } += $exec_epoch - $scenarios_last_exec->{$uuid}->{time}; $self->{robots}->{ $results->[$i]->{Robot}->{Name} }->{scenarios}->{ $results->[$i]->{Measure}->{Name} }->{execution_time_total} += $results->[$i]->{Value}; $self->{robots}->{ $results->[$i]->{Robot}->{Name} }->{scenarios}->{ $results->[$i]->{Measure}->{Name} }->{execution_count}++; $scenarios_last_exec->{$uuid}->{time} = $exec_epoch; $scenarios_last_exec->{$uuid}->{status} = lc($results->[$i]->{Status}); } my $current_timestamp = time(); # we add current timestamp gap foreach my $robot_name (keys %{$self->{robots}}) { foreach my $scenario_name (keys %{$self->{robots}->{$robot_name}->{scenarios}}) { my $uuid = $robot_name . '~' . $scenario_name; next if (!defined($scenarios_last_exec->{$uuid}->{time})); $self->{robots}->{ $robot_name }->{scenarios}->{ $scenario_name }->{ $mapping_status->{ $scenarios_last_exec->{$uuid}->{status} } . '_seconds' } += $current_timestamp - $scenarios_last_exec->{$uuid}->{time}; $self->{robots}->{ $robot_name }->{scenarios}->{ $scenario_name }->{last_exec} = $scenarios_last_exec->{$uuid}; if ($self->{robots}->{ $robot_name }->{scenarios}->{ $scenario_name }->{execution_count} > 0) { $self->{robots}->{ $robot_name }->{scenarios}->{ $scenario_name }->{execution_time} = int($self->{robots}->{ $robot_name }->{scenarios}->{ $scenario_name }->{execution_time_total} / $self->{robots}->{ $robot_name }->{scenarios}->{ $scenario_name }->{execution_count}); $self->{robots}->{ $robot_name }->{scenarios}->{ $scenario_name }->{last_exec}->{execution_time} = $self->{robots}->{ $robot_name }->{scenarios}->{ $scenario_name }->{execution_time}; } elsif (defined($scenarios_last_exec->{$uuid}->{execution_time})) { $self->{robots}->{ $robot_name }->{scenarios}->{ $scenario_name }->{execution_time} = $scenarios_last_exec->{$uuid}->{execution_time}; $self->{robots}->{ $robot_name }->{scenarios}->{ $scenario_name }->{last_exec}->{execution_time} = $scenarios_last_exec->{$uuid}->{execution_time}; } my $total_time = $self->{robots}->{ $robot_name }->{scenarios}->{ $scenario_name }->{green_seconds} + $self->{robots}->{ $robot_name }->{scenarios}->{ $scenario_name }->{red_seconds} + $self->{robots}->{ $robot_name }->{scenarios}->{ $scenario_name }->{orange_seconds} + $self->{robots}->{ $robot_name }->{scenarios}->{ $scenario_name }->{grey_seconds}; $self->{robots}->{ $robot_name }->{scenarios}->{ $scenario_name }->{green_prct} = $self->{robots}->{ $robot_name }->{scenarios}->{ $scenario_name }->{green_seconds} * 100 / $total_time; $self->{robots}->{ $robot_name }->{scenarios}->{ $scenario_name }->{red_prct} = $self->{robots}->{ $robot_name }->{scenarios}->{ $scenario_name }->{red_seconds} * 100 / $total_time; $self->{robots}->{ $robot_name }->{scenarios}->{ $scenario_name }->{orange_prct} = $self->{robots}->{ $robot_name }->{scenarios}->{ $scenario_name }->{orange_seconds} * 100 / $total_time; $self->{robots}->{ $robot_name }->{scenarios}->{ $scenario_name }->{grey_prct} = $self->{robots}->{ $robot_name }->{scenarios}->{ $scenario_name }->{grey_seconds} * 100 / $total_time; } } } 1; __END__ =head1 MODE Check scenarios. =over 8 =item B<--filter-node-id> Filter nodes (can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'ping-received-lasttime' (s). =back =cut centreon-plugins-20220113/apps/monitoring/iplabel/newtest/restapi/plugin.pm000066400000000000000000000030461417000230700267730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::iplabel::newtest::restapi::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} = { 'discovery' => 'apps::monitoring::iplabel::newtest::restapi::mode::discovery', 'list-instances' => 'apps::monitoring::iplabel::newtest::restapi::mode::listinstances', 'scenarios' => 'apps::monitoring::iplabel::newtest::restapi::mode::scenarios' }; $self->{custom_modes}{api} = 'apps::monitoring::iplabel::newtest::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check IP-Label newtest using Rest API. =cut centreon-plugins-20220113/apps/monitoring/loggly/000077500000000000000000000000001417000230700216615ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/loggly/restapi/000077500000000000000000000000001417000230700233305ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/loggly/restapi/custom/000077500000000000000000000000001417000230700246425ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/loggly/restapi/custom/api.pm000066400000000000000000000204561417000230700257600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::loggly::restapi::custom::api; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::http; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port'}, 'proto:s' => { name => 'proto' }, 'api-password:s' => { name => 'api_password' }, 'timeout:s' => { name => 'timeout', default => 30 }, 'unknown-http-status:s' => { name => 'unknown_http_status' }, 'warning-http-status:s' => { name => 'warning_http_status' }, 'critical-http-status:s' => { name => 'critical_http_status' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 30; $self->{ssl_opt} = (defined($self->{option_results}->{ssl_opt})) ? $self->{option_results}->{ssl_opt} : undef; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : ''; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300'; $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --hostname option.'); $self->{output}->option_exit(); } if ($self->{api_password} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --api-password option.'); $self->{output}->option_exit(); } return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{ssl_opt} = $self->{ssl_opt}; $self->{option_results}->{timeout} = $self->{timeout}; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Content-Type', value => 'application/json;charset=UTF-8'); $self->{http}->add_header(key => 'Authorization', value => 'bearer ' . $self->{option_results}->{api_password}); $self->{http}->set_options(%{$self->{option_results}}); } sub request_api { my ($self, %options) = @_; $self->settings(); my $content = $self->{http}->request( %options, unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status} ); my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } if (!defined($decoded)) { $self->{output}->add_option_msg(short_msg => "Error while retrieving data (add --debug option for detailed message)"); $self->{output}->option_exit(); } return $decoded; } sub internal_search { my ($self, %options) = @_; my $status = $self->request_api( method => 'GET', url_path => '/apiv2/search', get_param => [ 'size=1', 'from=-' . $options{time_period} . 'm', 'q=' . $options{query} ] ); return $status->{rsid}->{id}; } sub internal_events { my ($self, %options) = @_; my $status = $self->request_api( method => 'GET', url_path => '/apiv2/events', get_param => ['rsid=' . $options{id}] ); return $status; } sub api_events { my ($self, %options) = @_; my $id = $self->internal_search( time_period => $options{time_period}, query => $options{query} ); my $status = $self->internal_events(id => $id); # Get a proper output message my $message = ''; if (length($options{output_field}) && scalar($status->{events}) && defined($status->{events}->[0]->{event})) { $message = $status->{events}->[0]->{event}; for (split /\./, $options{output_field}) { if (defined($message->{$_})) { $message = $message->{$_}; } else { $message = ''; last; } } } # Message may be messed-up with wrongly encoded characters, let's force some cleanup $message =~ s/[\r\n]//g; $message =~ s/^\s+|\s+$//g; # Clean returned hash $status->{message} = $message; delete $status->{events}; delete $status->{page}; return $status; } sub internal_fields { my ($self, %options) = @_; # 300 limitation comes from the API : https://documentation.solarwinds.com/en/Success_Center/loggly/Content/admin/api-retrieving-data.htm my $status = $self->request_api( method => 'GET', url_path => '/apiv2/fields/' . $options{field} . '/', get_param => [ 'facet_size=300', 'from=-' . $options{time_period} . 'm', 'q=' . $options{query} ] ); return $status; } sub api_fields { my ($self, %options) = @_; my $status = $self->internal_fields( time_period => $options{time_period}, field => $options{field}, query => $options{query} ); # Fields may be messed-up with wrongly encoded characters, let's force some cleanup for (my $i = 0; $i < scalar(@{$status->{ $options{field} }}); $i++) { $status->{ $options{field} }->[$i]->{term} =~ s/[\r\n]//g; $status->{ $options{field} }->[$i]->{term} =~ s/^\s+|\s+$//g; } return $status; } 1; __END__ =head1 NAME Loggly Rest API =head1 REST API OPTIONS =over 8 =item B<--hostname> Set hostname of the Loggly server (.loggly.com). =item B<--port> Set Loggly Port (Default: '443'). =item B<--proto> Specify http if needed (Default: 'https'). =item B<--api-password> Set Loggly API token. =item B<--timeout> Threshold for HTTP timeout (Default: '30'). =back =cut centreon-plugins-20220113/apps/monitoring/loggly/restapi/mode/000077500000000000000000000000001417000230700242545ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/loggly/restapi/mode/events.pm000066400000000000000000000063311417000230700261210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::loggly::restapi::mode::events; 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 } ]; $self->{maps_counters}->{global} = [ { label => 'events', nlabel => 'events.count', set => { key_values => [ { name => 'events' } ], output_template => 'Matching events: %s', perfdatas => [ { template => '%s', value => 'events', min => 0 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $self->{version} = '1.0'; $options{options}->add_options(arguments => { 'time-period:s' => { name => 'time_period' }, 'query:s' => { name => 'query' }, 'output-field:s' => { name => 'output_field' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{time_period}) || $self->{option_results}->{time_period} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --time-period option."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{query}) || $self->{option_results}->{query} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --query option."); $self->{output}->option_exit(); } } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->api_events( time_period => $self->{option_results}->{time_period}, query => $self->{option_results}->{query}, output_field => $self->{option_results}->{output_field} ); $self->{global} = { events => $results->{total_events} }; if (length($results->{message})) { $self->{output}->output_add(long_msg => 'Last ' . $self->{option_results}->{output_field} . ': ' . $results->{message}); } } 1; __END__ =head1 MODE Count events matching the query. =over 8 =item B<--time-period> Set request period, in minutes. =item B<--query> Set the query. =item B<--output-field> Set the field to verbose-output from the last matching event (ex: json.message). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'events'. =back =cut centreon-plugins-20220113/apps/monitoring/loggly/restapi/mode/fields.pm000066400000000000000000000127351417000230700260700ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::loggly::restapi::mode::fields; 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 }, { name => 'field', type => 1, cb_prefix_output => 'prefix_field_output' } ]; $self->{maps_counters}->{global} = [ { label => 'events', nlabel => 'events.count', display_ok => 1, set => { key_values => [ { name => 'events' } ], output_template => 'Matching events: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'fields', nlabel => 'fields.count', display_ok => 1, set => { key_values => [ { name => 'fields' } ], output_template => 'Matching fields: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, ]; $self->{maps_counters}->{field} = [ { label => 'field-events', nlabel => 'field.events.count', set => { key_values => [ { name => 'count' }, { name => 'display' } ], output_template => 'matching events: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub prefix_field_output { my ($self, %options) = @_; return "Field '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $self->{version} = '1.0'; $options{options}->add_options(arguments => { 'time-period:s' => { name => 'time_period' }, 'query:s' => { name => 'query' }, 'field:s' => { name => 'field' }, 'filter-field:s' => { name => 'filter_field' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{time_period}) || $self->{option_results}->{time_period} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --time-period option."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{query}) || $self->{option_results}->{query} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --query option."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{field}) || $self->{option_results}->{field} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --field option."); $self->{output}->option_exit(); } # 300 limitation comes from the API : https://documentation.solarwinds.com/en/Success_Center/loggly/Content/admin/api-retrieving-data.htm if (defined($self->{option_results}->{'warning-fields-count'}) && $self->{option_results}->{'warning-fields-count'} >= 300) { $self->{output}->add_option_msg(short_msg => "Threshold --warning-fields must be lower than 300."); $self->{output}->option_exit(); } if (defined($self->{option_results}->{'critical-fields-count'}) && $self->{option_results}->{'critical-fields-count'} >= 300) { $self->{output}->add_option_msg(short_msg => "Threshold --critical-fields must be lower than 300."); $self->{output}->option_exit(); } } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->api_fields( time_period => $self->{option_results}->{time_period}, query => $self->{option_results}->{query}, field => $self->{option_results}->{field} ); my ($events, $fields) = (0, 0); $self->{field} = {}; foreach (@{$results->{$self->{option_results}->{field}}}) { if (!defined($self->{option_results}->{filter_field}) || ($_->{term} =~ /$self->{option_results}->{filter_field}/i)) { $fields++; $events += $_->{count}; $self->{field}->{$fields} = { display => $_->{term}, count => $_->{count} }; } } $self->{global} = { events => $events, fields => $fields }; } 1; __END__ =head1 MODE Count unique field-values from events matching the query. =over 8 =item B<--time-period> Set request period, in minutes. =item B<--query> Set the query. =item B<--field> Set the field to count unique values for (ex: json.host). =item B<--filter-field> Set the a field filter. =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'events', 'fields', field-events'. =back =cut centreon-plugins-20220113/apps/monitoring/loggly/restapi/plugin.pm000066400000000000000000000026341417000230700251710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::loggly::restapi::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} = '1.0'; $self->{modes} = { 'events' => 'apps::monitoring::loggly::restapi::mode::events', 'fields' => 'apps::monitoring::loggly::restapi::mode::fields' }; $self->{custom_modes}->{api} = 'apps::monitoring::loggly::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Loggly through its HTTPS remote API. =over 8 =back =cut centreon-plugins-20220113/apps/monitoring/mip/000077500000000000000000000000001417000230700211515ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/mip/restapi/000077500000000000000000000000001417000230700226205ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/mip/restapi/custom/000077500000000000000000000000001417000230700241325ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/mip/restapi/custom/api.pm000066400000000000000000000141551417000230700252470ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::mip::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use JSON::XS; 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 => { 'api-key:s' => { name => 'api_key' }, 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'timeout:s' => { name => 'timeout' }, 'unknown-http-status:s' => { name => 'unknown_http_status' }, 'warning-http-status:s' => { name => 'warning_http_status' }, 'critical-http-status:s' => { name => 'critical_http_status' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{api_key} = (defined($self->{option_results}->{api_key})) ? $self->{option_results}->{api_key} : undef; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300'; $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; if (!defined($self->{hostname}) || $self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } if (!defined($self->{api_key}) || $self->{api_key} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-key option."); $self->{output}->option_exit(); } return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; } sub settings { my ($self, %options) = @_; return if (defined($self->{settings_done})); $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->add_header(key => 'Content-Type', value => 'application/json'); $self->{http}->set_options(%{$self->{option_results}}); $self->{settings_done} = 1; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub get_port { my ($self, %options) = @_; return $self->{port}; } sub request_api { my ($self, %options) = @_; $self->settings(); my $content = $self->{http}->request( method => defined($options{method}) ? $options{method} : 'GET', url_path => $options{url_path}, unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status}, curl_backend_options => { header => ['MIP_API_KEY: ' . $self->{api_key}] }, lwp_backend_options => { header => [':MIP_API_KEY: ' . $self->{api_key}] }, ); if (!defined($content) || $content eq '') { $self->{output}->add_option_msg(short_msg => "API returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } return $decoded; } 1; __END__ =head1 NAME MIP Rest API =head1 REST API OPTIONS Maltem Insight Performance Rest API =over 8 =item B<--hostname> Set hostname. =item B<--port> Port used (Default: 443) =item B<--proto> Specify https if needed (Default: 'https') =item B<--api-key> MIP API Token. =item B<--timeout> Set timeout in seconds (Default: 10). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/monitoring/mip/restapi/mode/000077500000000000000000000000001417000230700235445ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/mip/restapi/mode/listscenarios.pm000066400000000000000000000060011417000230700267610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::mip::restapi::mode::listscenarios; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; my $api_results = $options{custom}->request_api( url_path => '/api/measures/?type=ASA_DESKTOP&engineActivated=true&fields=name,alias,displayName,frequency,scenario.name,scenario.application.name,timeout,agent.id,agent.name,activated,engineActivated&limit=-1' ); my $results = {}; foreach (@{$api_results->{results}}) { $results->{$_->{id}} = { id => $_->{id}, name => $_->{name}, alias => $_->{alias}, display_name => $_->{displayName}, app_name => defined($_->{scenario}->{application}->{name}) ? $_->{scenario}->{application}->{name} : '-', }; } return $results; } sub run { my ($self, %options) = @_; my $scenarios = $self->manage_selection(%options); foreach (sort {lc $a->{name} cmp lc $b->{name}} values %$scenarios) { $self->{output}->output_add(long_msg => sprintf( '[name = %s][id = %s][alias = %s][display_name = %s][app_name = %s]', $_->{name}, $_->{id}, $_->{alias}, $_->{display_name}, $_->{app_name} )); } $self->{output}->output_add( severity => 'OK', short_msg => 'List scenarios:' ); $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 => ['id', 'name', 'alias', 'display_name', 'app_name']); } sub disco_show { my ($self, %options) = @_; my $scenarios = $self->manage_selection(%options); foreach (sort {lc $a->{name} cmp lc $b->{name}} values %$scenarios) { $self->{output}->add_disco_entry(%$_); } } 1; __END__ =head1 MODE List scenarios. =over 8 =back =cut centreon-plugins-20220113/apps/monitoring/mip/restapi/mode/scenarios.pm000066400000000000000000000303271417000230700260750ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::mip::restapi::mode::scenarios; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use centreon::plugins::statefile; use Digest::MD5 qw(md5_hex); my $mapping_units = { requests => { label => 'requests' }, bytes => { label => 'bytes', scale => 1, extra_unit => '' }, ms => { label => 'milliseconds' }, bps => { label => 'bitspersecond', scale => 1, extra_unit => '/s', network => 1 }, status => { label => 'count' } }; sub custom_status_output { my ($self, %options) = @_; return 'status: ' . $self->{result_values}->{status}; } sub custom_metric_output { my ($self, %options) = @_; my $msg; if (defined($mapping_units->{ $self->{result_values}->{unit} }->{scale})) { $msg = sprintf( 'value: %s %s%s', $self->{perfdata}->change_bytes( value => $self->{result_values}->{value}, network => $mapping_units->{ $self->{result_values}->{unit} }->{network} ), $mapping_units->{ $self->{result_values}->{unit} }->{extra_unit} ); } else { $msg = sprintf( 'value: %s %s', $self->{result_values}->{value}, $self->{result_values}->{unit} ); } return $msg; } sub custom_formatted_metric_output { my ($self, %options) = @_; return sprintf( 'value: %s', $self->{result_values}->{value} ); } sub custom_metric_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( unit => $self->{result_values}->{unit}, nlabel => 'scenario.metric.usage.' . $mapping_units->{ $self->{result_values}->{unit} }->{label}, instances => $self->{instance}, value => $self->{result_values}->{value} ); } sub custom_formatted_metric_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => 'scenario.formatted_metric.usage.count', instances => $self->{instance}, value => $self->{result_values}->{value} ); } sub scenario_long_output { my ($self, %options) = @_; return "checking scenario '" . $options{instance_value}->{display} . "'"; } sub prefix_scenario_output { my ($self, %options) = @_; return "Scenario '" . $options{instance_value}->{display} . "' "; } sub prefix_metric_output { my ($self, %options) = @_; return "metric '" . $options{instance_value}->{display} . "' "; } sub prefix_formatted_metric_output { my ($self, %options) = @_; return "formatted metric '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'scenario', type => 3, cb_prefix_output => 'prefix_scenario_output', cb_long_output => 'scenario_long_output', indent_long_output => ' ', message_multiple => 'All scenarios are ok', group => [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'metric', display_long => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => 'All metrics are ok', type => 1, skipped_code => { -10 => 1 } }, { name => 'formatted_metrics', display_long => 1, display_short => 0, cb_prefix_output => 'prefix_formatted_metric_output', message_multiple => 'All formatted metrics are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'status', type => 2, unknown_default => '%{status} =~ /unknown/i', warning_default => '%{status} =~ /warning/i', critical_default => '%{status} =~ /critical/i', set => { key_values => [ { name => 'status' }, { name => 'display' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{metric} = [ { label => 'metric', set => { key_values => [ { name => 'value' }, { name => 'unit' }, { name => 'display' }, ], closure_custom_output => $self->can('custom_metric_output'), closure_custom_perfdata => $self->can('custom_metric_perfdata'), closure_custom_threshold_check => sub { return 'ok'; } } } ]; $self->{maps_counters}->{formatted_metrics} = [ { label => 'formatted-metric', set => { key_values => [ { name => 'value' }, { name => 'display' }, ], closure_custom_output => $self->can('custom_formatted_metric_output'), closure_custom_perfdata => $self->can('custom_formatted_metric_perfdata'), closure_custom_threshold_check => sub { return 'ok'; } } } ]; } 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-id:s' => { name => 'filter_id' }, 'filter-display-name:s' => { name => 'filter_display_name' }, 'filter-name:s' => { name => 'filter_name' }, 'filter-app-name:s' => { name => 'filter_app_name' }, 'memory' => { name => 'memory' }, 'display-instance:s' => { name => 'display_instance', default => '%{name}' } }); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{option_results}->{display_instance} = '%{name}' if (!defined($self->{option_results}->{display_instance}) || $self->{option_results}->{display_instance} eq ''); if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->check_options(%options); } } sub manage_selection { my ($self, %options) = @_; # default time: &from=now-1h&to=now my $results = $options{custom}->request_api( url_path => '/api/measures/details?fields=displayName,frequency,timeout,scenario.name,scenario.application.name&scenario.name__neq=null&limit=-1' ); if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->read( statefile => 'mip_' . $self->{mode} . '_' . $options{custom}->get_hostname() . '_' . $options{custom}->get_port() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_id}) ? md5_hex($self->{option_results}->{filter_id}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_display_name}) ? md5_hex($self->{option_results}->{filter_display_name}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_app_name}) ? md5_hex($self->{option_results}->{filter_app_name}) : md5_hex('all')) ); } my $save_scenario_times = {}; $self->{scenario} = {}; foreach my $entry (@{$results->{results}}) { my $mapping = { id => $entry->{measure}->{id}, name => $entry->{measure}->{name}, display_name => $entry->{measure}->{displayName}, app_name => defined($entry->{measure}->{scenario}->{application}->{name}) ? $entry->{measure}->{scenario}->{application}->{name} : '-', }; my $filter = 0; foreach (keys %$mapping) { if (defined($self->{option_results}->{'filter_' . $_}) && $self->{option_results}->{'filter_' . $_} ne '' && $mapping->{$_} !~ /$self->{option_results}->{'filter_' . $_}/) { $filter = 1; $self->{output}->output_add(long_msg => "skipping scenario id '" . $mapping->{id} . "': no matching filter '$_'.", debug => 1); last; } } next if ($filter == 1); my $scenario_name = $self->{option_results}->{display_instance}; $scenario_name =~ s/%\{(.*?)\}/$mapping->{$1}/g; $self->{scenario}->{$scenario_name} = { display => $scenario_name, global => { display => $scenario_name, }, metric => {}, formatted_metrics => {} }; my @sorted = sort(keys %{$entry->{results}}); my $last_time = pop(@sorted); if (defined($self->{option_results}->{memory})) { my $save_time = $self->{statefile_cache}->get(name => $mapping->{id}); $save_scenario_times->{$mapping->{id}} = $last_time; if (defined($save_time) && $save_time eq $last_time) { $self->{scenario}->{$scenario_name}->{global}->{status} = 'noNewValue'; next; } } $self->{scenario}->{$scenario_name}->{global}->{status} = $entry->{results}->{$last_time}->{state}->{type}; foreach (keys %{$entry->{metricInfo}}) { $self->{scenario}->{$scenario_name}->{metric}->{ $entry->{metricInfo}->{$_}->{alias} } = { display => $entry->{metricInfo}->{$_}->{alias}, unit => $entry->{metricInfo}->{$_}->{unit}, value => $entry->{results}->{$last_time}->{metrics}->{$_} }; } foreach my $fmetric_label (keys %{$entry->{results}->{$last_time}->{formatedMetrics}}) { next if ($fmetric_label =~ /^(?:API_VERSION|SCRIPT_VERSION)$/); $self->{scenario}->{$scenario_name}->{formatted_metrics}->{ $fmetric_label } = { display => $fmetric_label, value => $entry->{results}->{$last_time}->{formatedMetrics}->{$fmetric_label} }; } } if (scalar(keys %{$self->{scenario}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No scenario found"); $self->{output}->option_exit(); } if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->write(data => $save_scenario_times); } } 1; __END__ =head1 MODE Check scenarios. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^status$' =item B<--filter-id> Filter scenarios by id (can be a regexp). =item B<--filter-display-name> Filter scenarios by display name (can be a regexp). =item B<--filter-name> Filter scenarios by name (can be a regexp). =item B<--filter-app-name> Filter scenarios by applicationn name (can be a regexp). =item B<--display-instance> Set the scenario display value (Default: '%{name}'). Can used special variables like: %{name}, %{app_name}, %{display_name}, %{id} =item B<--memory> Only check new result entries for scenarios. =item B<--unknown-status> Set warning threshold for status (Default: '%{status} =~ /unknown/i'). Can used special variables like: %{status}, %{display} =item B<--warning-status> Set warning threshold for status (Default: '%{status} =~ /warning/i'). Can used special variables like: %{status}, %{display} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /critical/i'). Can used special variables like: %{status}, %{display} =back =cut centreon-plugins-20220113/apps/monitoring/mip/restapi/plugin.pm000066400000000000000000000026501417000230700244570ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::mip::restapi::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} } = ( 'list-scenarios' => 'apps::monitoring::mip::restapi::mode::listscenarios', 'scenarios' => 'apps::monitoring::mip::restapi::mode::scenarios', ); $self->{custom_modes}{api} = 'apps::monitoring::mip::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Maltem Insight Performance using Rest API. =cut centreon-plugins-20220113/apps/monitoring/netdata/000077500000000000000000000000001417000230700220045ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/netdata/restapi/000077500000000000000000000000001417000230700234535ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/netdata/restapi/custom/000077500000000000000000000000001417000230700247655ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/netdata/restapi/custom/api.pm000066400000000000000000000154621417000230700261040ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::netdata::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use JSON::XS; 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'timeout:s' => { name => 'timeout' }, 'endpoint:s' => { name => 'endpoint'} }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 19999; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'http'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{endpoint} = (defined($self->{option_results}->{endpoint})) ? $self->{option_results}->{endpoint} : '/api/v1'; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{warning_status} = ''; $self->{option_results}->{critical_status} = ''; $self->{option_results}->{unknown_status} = '%{http_code} < 200 or %{http_code} >= 400'; } sub settings { my ($self, %options) = @_; return if (defined($self->{settings_done})); $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->set_options(%{$self->{option_results}}); $self->{settings_done} = 1; } sub request_api { my ($self, %options) = @_; $self->settings(); my $content = $self->{http}->request(%options); if (!defined($content) || $content eq '') { $self->{output}->add_option_msg(short_msg => "API returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } if (defined($decoded->{error_code})) { $self->{output}->output_add(long_msg => "Error message : " . $decoded->{error}, debug => 1); $self->{output}->add_option_msg(short_msg => "API returns error code '" . $decoded->{error_code} . "' (add --debug option for detailed message)"); $self->{output}->option_exit(); } return $decoded; } sub get_alarms { my ($self, %options) = @_; my $url_path = $self->{endpoint} . '/alarms'; my $response = $self->request_api(method => 'GET', url_path => $url_path); return $response; } sub list_charts { my ($self, %options) = @_; my $url_path = $self->{endpoint} . '/charts'; my $response = $self->request_api( method => 'GET', url_path => $url_path ); return $response; } sub get_chart_properties { my ($self, %options) = @_; my $url_path = $self->{endpoint} . '/chart'; my $response = $self->request_api( method => 'GET', url_path => $url_path, get_param => ['chart=' . $options{chart}] ); my $filter_info = defined ($options{filter_info}) ? $options{filter_info} : ''; return defined ($filter_info) ? $response->{$filter_info} : $response; } sub get_data { my ($self, %options) = @_; my $url_path = $self->{endpoint} . '/data'; my $get_param = [ 'chart=' . $options{chart}, 'options=null2zero', 'after=-' . $options{after_period}, 'group=' . $options{group}, defined($options{points}) ? 'points=' . $options{points} : 'points=1' ]; push @$get_param, 'options=abs' if (defined($options{absolute})); push @$get_param, 'dimensions=' . $options{dimensions} if (defined($options{dimensions})); my $response = $self->request_api( method => 'GET', url_path => $url_path, get_param => $get_param ); return $response; } sub get_info { my ($self, %options) = @_; my $url_path = $self->{endpoint} . '/info'; my $response = $self->request_api(method => 'GET', url_path => $url_path); my $filter_info = defined ($options{filter_info}) ? $options{filter_info} : ''; return defined ($filter_info) ? $response->{$filter_info} : $response; } 1; __END__ =head1 NAME Netdata Rest API =head1 REST API OPTIONS Netdata Rest API =over 8 =item B<--hostname> Netdata API hostname (server address) =item B<--port> Port used (Default: 19999) =item B<--proto> Specify https if needed (Default: 'http') =item B<--timeout> Set timeout in seconds (Default: 10). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/monitoring/netdata/restapi/mode/000077500000000000000000000000001417000230700243775ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/netdata/restapi/mode/alarms.pm000066400000000000000000000117701417000230700262220ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and alarm 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::monitoring::netdata::restapi::mode::alarms; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; return sprintf('status: %s, current state: %s', $self->{result_values}->{status}, $self->{result_values}->{value_string}); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }, { name => 'alarms', type => 1, cb_prefix_output => 'prefix_alarm_output', message_multiple => 'No current alarms' } ]; $self->{maps_counters}->{global} = [ { label => 'alarms-total', nlabel => 'netdata.alarms.current.total.count', set => { key_values => [ { name => 'total' } ], output_template => 'total: %s', perfdatas => [ { template => '%d', min => 0 } ] } }, { label => 'alarms-warning', nlabel => 'netdata.alarms.current.warning.count', set => { key_values => [ { name => 'warning' } ], output_template => 'warning: %s', perfdatas => [ { template => '%d', min => 0 } ] } }, { label => 'alarms-critical', nlabel => 'netdata.alarms.current.critical.count', set => { key_values => [ { name => 'critical' } ], output_template => 'critical: %s', perfdatas => [ { template => '%d', min => 0 } ] } } ]; $self->{maps_counters}->{alarms} = [ { label => 'alarm', threshold => 0, set => { key_values => [ { name => 'display' }, { name => 'name' }, { name => 'status' }, { name => 'value_string'} ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_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 => { 'filter-status:s' => { name => 'filter_status' } }); return $self; } sub prefix_global_output { my ($self, %options) = @_; return 'Alarms '; } sub prefix_alarm_output { my ($self, %options) = @_; return "Alarm on '" . $options{instance_value}->{name} . "' "; } sub manage_selection { my ($self, %options) = @_; $self->{global} = { warning => 0, critical => 0 }; $self->{alarms} = {}; my $result = $options{custom}->get_alarms(); foreach my $alarm (values %{$result->{alarms}}) { next if ( defined($self->{option_results}->{filter_status}) && $self->{option_results}->{filter_status} ne '' && $alarm->{status} !~ /$self->{option_results}->{filter_status}/ ); $self->{alarms}->{$alarm} = { display => $alarm, id => $alarm->{id}, name => $alarm->{name}, chart => $alarm->{chart}, status => $alarm->{status}, value_string => $alarm->{value_string} }; $self->{global}->{warning}++ if ($alarm->{status} =~ m/WARNING/); $self->{global}->{critical}++ if ($alarm->{status} =~ m/CRITICAL/); } $self->{global}->{total} = scalar(keys %{$self->{alarms}}); } 1; __END__ =head1 MODE Check Netdata agent current active alarms. Example: perl centreon_plugins.pl --plugin=apps::monitoring::netdata::restapi::plugin --mode=alarms --hostname=10.0.0.1 --warning-alarms-warning=0 --critical-alarms-critical=0--verbose More information on 'https://learn.netdata.cloud/docs/agent/web/api''. =over 8 =item B<--filter-status> Filter on specific alarm status. Can be 'WARNING' or 'CRITICAL' (Default: both status shown) =item B<--warning-alarms-*> Set Warning threshold for alarms count (Default: '') where '*' can be warning or 'critical' =item B<--critical-alarms-*> Set Critical threshold for alarms count (Default: '') where '*' can be 'warning' or 'critical' =back =cut centreon-plugins-20220113/apps/monitoring/netdata/restapi/mode/cpu.pm000066400000000000000000000111421417000230700255230ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and alarm 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::monitoring::netdata::restapi::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_avg', type => 0, cb_prefix_output => 'prefix_cpu_avg_output' }, { name => 'cpu_results', type => 1, cb_prefix_output => 'prefix_cpu_core_output' } ]; $self->{maps_counters}->{cpu_avg} = [ { label => 'average', nlabel => 'cpu.utilization.percentage', set => { key_values => [ { name => 'average' }, { name => 'count' } ], output_template => '%.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%' } ] } } ]; $self->{maps_counters}->{cpu_results} = [ { label => 'core', nlabel => 'core.cpu.utilization.percentage', set => { key_values => [ { name => 'usage' }, { name => 'display' } ], output_template => 'usage: %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 } ] } } ]; } sub prefix_cpu_avg_output { my ($self, %options) = @_; return $self->{cpu_avg}->{count} . " CPU(s) average usage is "; } sub prefix_cpu_core_output { my ($self, %options) = @_; return "CPU '" . $options{instance_value}->{display} . "' "; } 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 => { 'chart-period:s' => { name => 'chart_period', default => '300' }, 'chart-statistics:s' => { name => 'chart_statistics', default => 'average' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $cpu_total_usage; my $cpu_number = $options{custom}->get_info(filter_info => 'cores_total'); foreach (my $i = 0; $i < $cpu_number; $i++) { my $cpu_core = 'cpu.cpu' . $i; my $result = $options{custom}->get_data( chart => $cpu_core, after_period => $self->{option_results}->{chart_period}, group => $self->{option_results}->{chart_statistics} ); my ($usage, $count) = (0, 0); foreach my $data (@{$result->{data}}) { while (my ($index, $label) = each(@{$result->{labels}})) { next if ($label eq 'time'); $usage += $data->[$index]; } $count++; } if ($count > 0) { $self->{cpu_results}->{$i} = { display => $i, usage => $usage / $count }; $cpu_total_usage += ($usage / $count); } } my $avg_cpu = $cpu_total_usage / $cpu_number; $self->{cpu_avg} = { average => $avg_cpu, count => $cpu_number }; }; 1; __END__ =head1 MODE Check *nix based servers CPU using the Netdata agent RestAPI. Example: perl centreon_plugins.pl --plugin=apps::monitoring::netdata::restapi::plugin --mode=cpu --hostname=10.0.0.1 --chart-period=300 --warning-average=70 --critical-average=80 --verbose More information on 'https://learn.netdata.cloud/docs/agent/web/api'. =over 8 =item B<--chart-period> The period in seconds on which the values are calculated Default: 300 =item B<--chart-statistic> The statistic calculation method used to parse the collected data. Can be : average, sum, min, max Default: average =item B<--warning-average> Warning threshold on average CPU utilization. =item B<--critical-average> Critical threshold on average CPU utilization. =item B<--warning-core> Warning threshold for each CPU core =item B<--critical-core> Critical threshold for each CPU core =back =cut centreon-plugins-20220113/apps/monitoring/netdata/restapi/mode/disks.pm000066400000000000000000000173131417000230700260570ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::netdata::restapi::mode::disks; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_usage_output { my ($self, %options) = @_; my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); return sprintf( 'total: %s used: %s (%.2f%%) free: %s (%.2f%%)', $total_size_value . " " . $total_size_unit, $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}, $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free} ); } sub prefix_diskpath_output { my ($self, %options) = @_; return "Partition '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'diskpath', type => 1, cb_prefix_output => 'prefix_diskpath_output', message_multiple => 'All partitions are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'count', nlabel => 'storage.partitions.count', display_ok => 0, set => { key_values => [ { name => 'count' } ], output_template => 'Partitions count : %d', perfdatas => [ { label => 'count', value => 'count', template => '%d', min => 0 } ] } } ]; $self->{maps_counters}->{diskpath} = [ { label => 'usage', nlabel => 'storage.space.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' }, { name => 'display' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'free', display_ok => 0, nlabel => 'storage.space.free.bytes', set => { key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' }, { name => 'display' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'usage-prct', display_ok => 0, nlabel => 'storage.space.usage.percentage', set => { key_values => [ { name => 'prct_used' }, { name => 'display' } ], output_template => 'used: %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' } ] } } ]; } 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 => { 'chart-period:s' => { name => 'chart_period', default => '300' }, 'chart-statistics:s' => { name => 'chart_statistics', default => 'average' }, 'fs-name:s' => { name => 'fs_name' }, 'space-reservation' => { name => 'space_reservation'} }); return $self; } sub manage_selection { my ($self, %options) = @_; my $full_list = $options{custom}->list_charts(); foreach my $chart (values %{$full_list->{charts}}) { next if ($chart->{name} !~ 'disk_space._'); push @{$self->{fs_list}}, $chart->{name}; } foreach my $fs (@{$self->{fs_list}}) { my $result = $options{custom}->get_data( chart => $fs, dimensions => 'used,avail,reserved_for_root', after_period => $self->{option_results}->{chart_period}, group => $self->{option_results}->{chart_statistics} ); $fs =~ s/disk_space.//; $fs =~ s/_/\//g; next if (defined($self->{option_results}->{fs_name}) && $self->{option_results}->{fs_name} ne '' && $fs !~ /$self->{option_results}->{fs_name}/ ); foreach my $fs_value (@{$result->{data}}) { foreach my $fs_label (@{$result->{labels}}) { $self->{fs}->{$fs}->{$fs_label} = shift @{$fs_value}; } } my $reserved_space = defined($self->{option_results}->{space_reservation}) ? $self->{fs}->{$fs}->{'reserved for root'} * (1024 ** 3) : '0'; my $used = $self->{fs}->{$fs}->{used} * (1024 ** 3); my $free = $self->{fs}->{$fs}->{avail} * (1024 ** 3); my $total = $used + $free + $reserved_space; my $prct_used = $used * 100 / $total; my $prct_free = 100 - $prct_used; if ($prct_used > 100) { $free = 0; $prct_used = 100; $prct_free = 0; } $self->{diskpath}->{$fs} = { display => $fs, used => $used, total => $total, free => $free, prct_used => $prct_used, prct_free => $prct_free }; $self->{global}->{count}++; } }; 1; __END__ =head1 MODE Check disks FS usage of *nix based servers using the Netdata agent RestAPI. Example: perl centreon_plugins.pl --plugin=apps::monitoring::netdata::restapi::plugin --mode=disks --hostname=10.0.0.1 --chart-period=300 --chart-statistics=average --warning-usage-prct=80 --critical-usage-prct=90 --verbose More information on'https://learn.netdata.cloud/docs/agent/web/api'. =over 8 =item B<--chart-period> The period in seconds on which the values are calculated Default: 300 =item B<--chart-statistic> The statistic calculation method used to parse the collected data. Can be : average, sum, min, max Default: average =item B<--fs-name> Filter on one or more specific FS. Regexp can be used Example: --fs-name='(^/$|^/boot$)' =item B<--warning-usage> Warning threshold on FS space usage (in B). =item B<--critical-usage> Critical threshold on FS space usage (in B). =item B<--warning-usage-prct> Warning threshold on FS percentage space usage (in %). =item B<--critical-usage-prct> Critical threshold on FS percentage space usage (in %). =item B<--warning-free> Warning threshold on FS free space. =item B<--critical-free> Critical threshold on FS free space. =item B<--space-reservation> On specific systems, partitions can have reserved space (like ext4 for root). This option will consider this space in the calculation (like for the 'df' command). =back =cut centreon-plugins-20220113/apps/monitoring/netdata/restapi/mode/getchart.pm000066400000000000000000000136031417000230700265410ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and alarm 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::monitoring::netdata::restapi::mode::getchart; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_metric_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => $self->{result_values}->{perf_label}, value => $self->{result_values}->{value}, unit => $self->{result_values}->{unit}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-metric'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-metric') ); } sub custom_metric_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check( value => $self->{result_values}->{value}, threshold => [ { label => 'critical-metric', exit_litteral => 'critical' }, { label => 'warning-metric', exit_litteral => 'warning' } ] ); return $exit; } sub custom_metric_output { my ($self, %options) = @_; return sprintf( "Metric '%s' value is %.2f %s", $self->{result_values}->{display}, $self->{result_values}->{value}, $self->{result_values}->{unit} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, message_multiple => 'All metrics are ok' } ]; $self->{maps_counters}->{metric} = [ { label => 'metric', set => { key_values => [ { name => 'value' }, { name => 'perf_label' }, { name => 'display' }, { name => 'unit' } ], 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, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'chart-name:s' => { name => 'chart_name' }, 'chart-period:s' => { name => 'chart_period', default => '300' }, 'chart-statistics:s' => { name => 'chart_statistics', default => 'average' }, 'filter-metric:s' => { name => 'filter_metric' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{chart_name}) || $self->{option_results}->{chart_name} eq '') { $self->{output}->add_option_msg(short_msg => "Missing --chart-name option or value."); $self->{output}->option_exit(); } } sub manage_selection { my ($self, %options) = @_; my $dimensions = ''; if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '') { $dimensions = $self->{option_results}->{filter_metric} }; my $unit = $options{custom}->get_chart_properties(chart => $self->{option_results}->{chart_name}, filter_info => 'units'); my $result = $options{custom}->get_data( chart => $self->{option_results}->{chart_name}, points => $self->{option_results}->{chart_point}, after_period => $self->{option_results}->{chart_period}, group => $self->{option_results}->{chart_statistics}, dimensions => $dimensions ); my $chart_name = $self->{option_results}->{chart_name}; my $stat = $self->{option_results}->{chart_statistics}; $self->{metrics}->{$chart_name} = {}; # we remove the first time value shift @{$result->{labels}}; foreach my $chart_value (@{$result->{data}}) { shift(@$chart_value); foreach my $chart_label (@{$result->{labels}}) { $self->{metrics}->{$chart_name}->{$chart_label} = shift(@$chart_value); } } foreach my $metric (keys %{$self->{metrics}->{$chart_name}}) { $self->{metric}->{$metric . '_' . $stat} = { display => $metric . '_' . $stat, value => $self->{metrics}->{$chart_name}->{$metric}, unit => $unit, perf_label => $metric . '_' . $stat }; } }; 1; __END__ =head1 MODE Get data for charts available on the Netdata RestAPI. Example: perl centreon_plugins.pl --plugin=apps::monitoring::netdata::restapi::plugin --mode=get-chart --hostname=10.0.0.1 --chart-name='system.cpu' --filter-metric=iowait More information on'https://learn.netdata.cloud/docs/agent/web/api'. =over 8 =item B<--chart-name> The Netdata chart name to query This option is mandatory =item B<--chart-period> The period in seconds on which the values are calculated Default: 300 =item B<--chart-statistic> The statistic calculation method used to parse the collected data. Can be : average, sum, min, max Default: average =item B<--filter-metric> Filter on specific chart metric. By default, all the metrics will be displayed =item B<--warning-metric> Warning threshold (global to all the collected metrics) =item B<--critical-metric> Critical threshold (global to all the collected metrics) =back =cut centreon-plugins-20220113/apps/monitoring/netdata/restapi/mode/inodes.pm000066400000000000000000000123701417000230700262210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::netdata::restapi::mode::inodes; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'inodes', type => 1, cb_prefix_output => 'prefix_inodes_output', message_multiple => 'All inode partitions are ok' } ]; $self->{maps_counters}->{inodes} = [ { label => 'usage-prct', nlabel => 'storage.inodes.usage.percentage', set => { key_values => [ { name => 'prct_used' }, { name => 'display' } ], output_template => 'Used: %.2f %%', perfdatas => [ { template => '%d', unit => '%', min => 0, max => 100, label_extra_instance => 1, instance_use => 'display' }, ] } } ]; } sub prefix_inodes_output { my ($self, %options) = @_; return "Inodes partition '" . $options{instance_value}->{display} . "' "; } 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 => { 'chart-period:s' => { name => 'chart_period', default => '300' }, 'chart-statistics:s' => { name => 'chart_statistics', default => 'average' }, 'fs-name:s' => { name => 'fs_name' }, 'space-reservation' => { name => 'space_reservation'} }); return $self; } sub manage_selection { my ($self, %options) = @_; my $full_list = $options{custom}->list_charts(); foreach my $chart (values %{$full_list->{charts}}) { next if ($chart->{name} !~ 'disk_inodes._'); push @{$self->{fs_list}}, $chart->{name}; } foreach my $fs (@{$self->{fs_list}}) { my $result = $options{custom}->get_data( chart => $fs, dimensions => 'used,avail,reserved_for_root', points => $self->{option_results}->{chart_point}, after_period => $self->{option_results}->{chart_period}, group => $self->{option_results}->{chart_statistics} ); $fs =~ s/disk_inodes.//; $fs =~ s/_/\//g; next if (defined($self->{option_results}->{fs_name}) && $self->{option_results}->{fs_name} ne '' && $fs !~ /$self->{option_results}->{fs_name}/ ); foreach my $fs_value (@{$result->{data}}) { foreach my $fs_label (@{$result->{labels}}) { $self->{fs}->{$fs}->{$fs_label} = shift @{$fs_value}; } } my $reserved_space = defined($self->{option_results}->{space_reservation}) ? $self->{fs}->{$fs}->{"reserved for root"} : '0'; my $used = $self->{fs}->{$fs}->{used}; my $free = $self->{fs}->{$fs}->{avail}; my $total = $used + $free + $reserved_space; my $prct_used = $used * 100 / $total; my $prct_free = 100 - $prct_used; $self->{inodes}->{$fs} = { display => $fs, used => $used, total => $total, free => $free, prct_used => $prct_used, prct_free => $prct_free }; $self->{global}->{count}++; } if (scalar(keys %{$self->{inodes}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'Issue with disk path information (see details)'); $self->{output}->option_exit(); } }; 1; __END__ =head1 MODE Check disks FS inodes of *nix based servers using the Netdata agent RestAPI. Example: perl centreon_plugins.pl --plugin=apps::monitoring::netdata::restapi::plugin --mode=inodes --hostname=10.0.0.1 --chart-period=300 --chart-statistics=average --warning-usage-prct=80 --critical-usage-prct=90 --verbose More information on'https://learn.netdata.cloud/docs/agent/web/api'. =over 8 =item B<--chart-period> The period in seconds on which the values are calculated Default: 300 =item B<--chart-statistic> The statistic calculation method used to parse the collected data. Can be : average, sum, min, max Default: average =item B<--fs-name> Filter on one or more specific FS. Regexp can be used Example: --fs-name='(^/$|^/boot$)' =item B<--warning-usage-prct> Warning threshold on FS used Inodes (in %). =item B<--critical-usage-prct> Critical threshold on FS used Inodes (in %). =item B<--space-reservation> On specific systems, partitions can have reserved space/inodes (like ext4 for root). This option will consider this space in the calculation (like for the 'df' command). =back =cut centreon-plugins-20220113/apps/monitoring/netdata/restapi/mode/listcharts.pm000066400000000000000000000051371417000230700271230ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::netdata::restapi::mode::listcharts; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-chart:s' => { name => 'filter_chart' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my $result = $options{custom}->list_charts(); foreach my $chart (values %{$result->{charts}}) { next if (defined($self->{option_results}->{filter_chart}) && $self->{option_results}->{filter_chart} ne '' && $chart->{title} !~ /$self->{option_results}->{filter_chart}/); $self->{output}->output_add( long_msg => sprintf( "[name = %s][title = %s][units = %s]", $chart->{name}, $chart->{title}, $chart->{units}, ) ); } $self->{output}->output_add(severity => 'OK', short_msg => 'Netdata Available Charts:'); $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', 'title', 'units']); } sub disco_show { my ($self, %options) = @_; $self->run(%options); foreach my $chart (@{$self->{charts}}) { $self->{output}->add_disco_entry( name => $chart->{name}, title => $chart->{title}, units => $chart->{units}, ); } } 1; __END__ =head1 MODE List available Netdata charts. =over 8 =item B<--filter-chart> Filter on specific chart(s). Regexp can be used. =back =cut centreon-plugins-20220113/apps/monitoring/netdata/restapi/mode/listdisks.pm000066400000000000000000000044611417000230700267530ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::netdata::restapi::mode::listdisks; use strict; use warnings; use base qw(centreon::plugins::mode); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my $full_list = $options{custom}->list_charts(); foreach my $chart (values %{$full_list->{charts}}) { next if ($chart->{name} !~ 'disk_space._'); push @{$self->{fs_list}}, $chart->{name}; $chart->{name} =~s/disk_space.//; $chart->{name} =~ s/_/\//g; $self->{output}->output_add( long_msg => sprintf( "[name = %s][title = %s]", $chart->{name}, $chart->{title}, ) ); } $self->{output}->output_add(severity => 'OK', short_msg => 'Server 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 => [ 'name', 'title' ]); } sub disco_show { my ($self, %options) = @_; $self->run(%options); foreach my $fs (@{$self->{fs_list}}) { $self->{output}->add_disco_entry( name => $fs->{name}, status => $fs->{title}, ); } } 1; __END__ =head1 MODE List system disks using the Netdata agent Restapi. =back =cut centreon-plugins-20220113/apps/monitoring/netdata/restapi/mode/listinterfaces.pm000066400000000000000000000044451417000230700277630ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::netdata::restapi::mode::listinterfaces; use strict; use warnings; use base qw(centreon::plugins::mode); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my $full_list = $options{custom}->list_charts(); foreach my $chart (values %{$full_list->{charts}}) { next if ($chart->{name} !~ '^net\.'); push @{$self->{fs_list}}, $chart->{name}; $chart->{name} =~ s/net.//; $self->{output}->output_add( long_msg => sprintf( "[name = %s][title = %s]", $chart->{name}, $chart->{title}, ) ); } $self->{output}->output_add(severity => 'OK', short_msg => 'Server interfaces:'); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } sub disco_format { my ($self, %options) = @_; $self->{output}->add_disco_format(elements => [ 'name', 'title' ]); } sub disco_show { my ($self, %options) = @_; $self->run(%options); foreach my $interface (@{$self->{fs_list}}) { $self->{output}->add_disco_entry( name => $interface->{name}, status => $interface->{title}, ); } } 1; __END__ =head1 MODE List system interfaces using the Netdata agent Restapi. =back =cut centreon-plugins-20220113/apps/monitoring/netdata/restapi/mode/load.pm000066400000000000000000000100431417000230700256520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and alarm 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::monitoring::netdata::restapi::mode::load; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_load_output { my ($self, %options) = @_; return 'Load average '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'loadaverage', type => 0, skipped_code => { -10 => 1 }, cb_prefix_output => 'prefix_load_output' } ]; $self->{maps_counters}->{loadaverage} = [ { label => 'load1', nlabel => 'system.loadaverage.1m.value', set => { key_values => [ { name => 'load1' } ], output_template => '%.2f (1m)', perfdatas => [ { template => '%.2f', min => 0 } ] } }, { label => 'load5', nlabel => 'system.loadaverage.5m.value', set => { key_values => [ { name => 'load5' } ], output_template => '%.2f (5m)', perfdatas => [ { template => '%.2f', min => 0 } ] } }, { label => 'load15', nlabel => 'system.loadaverage.15m.value', set => { key_values => [ { name => 'load15' }, { name => 'load1' }, { name => 'load5' } ], output_template => '%.2f (15m)', perfdatas => [ { template => '%.2f', min => 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 => { 'chart-period:s' => { name => 'chart_period', default => '300' }, 'chart-statistics:s' => { name => 'chart_statistics', default => 'average' }, }); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->get_data( chart => 'system.load', points => $self->{option_results}->{chart_point}, after_period => $self->{option_results}->{chart_period}, group => $self->{option_results}->{chart_statistics} ); foreach my $load_value (@{$result->{data}}) { foreach my $load_label (@{$result->{labels}}) { $self->{load_data}->{$load_label} = shift @{$load_value}; } } $self->{loadaverage} = { load1 => $self->{load_data}->{load1}, load5 => $self->{load_data}->{load5}, load15 => $self->{load_data}->{load15} }; }; 1; __END__ =head1 MODE Check the average load of *nix based servers using the Netdata agent RestAPI. Example: perl centreon-plugins/centreon_plugins.pl --plugin=apps::monitoring::netdata::restapi::plugin --mode=load --hostname=10.0.0.1 --chart-period=300 --warning-load15='4' --critical-load15='5' --verbose More information on 'https://learn.netdata.cloud/docs/agent/web/api'. =over 8 =item B<--chart-period> The period in seconds on which the values are calculated. Default: 300 =item B<--chart-statistic> The statistic calculation method used to parse the collected data. Can be : average, sum, min, max. Default: average =item B<--warning-*> Warning threshold where '*' can be: load1, load5, load15 =item B<--critical-*> Critical threshold where '*' can be: load1, load5, load15 =back =cut centreon-plugins-20220113/apps/monitoring/netdata/restapi/mode/memory.pm000066400000000000000000000152601417000230700262510ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and alarm 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::monitoring::netdata::restapi::mode::memory; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_usage_output { my ($self, %options) = @_; return sprintf( 'Ram total: %s %s used (-buffers/cache): %s %s (%.2f%%) free: %s %s (%.2f%%)', $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}), $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}), $self->{result_values}->{prct_used}, $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}), $self->{result_values}->{prct_free} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'ram', type => 0, skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{ram} = [ { label => 'usage', nlabel => 'memory.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1 } ] } }, { label => 'usage-free', display_ok => 0, nlabel => 'memory.free.bytes', set => { key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1 } ] } }, { label => 'usage-prct', display_ok => 0, nlabel => 'memory.usage.percentage', set => { key_values => [ { name => 'prct_used' } ], output_template => 'Ram used : %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%' } ] } }, { label => 'buffer', nlabel => 'memory.buffer.bytes', set => { key_values => [ { name => 'buffers' } ], output_template => 'Buffer: %s %s', output_change_bytes => 1, perfdatas => [ { template => '%d', min => 0, unit => 'B' } ] } }, { label => 'cached', nlabel => 'memory.cached.bytes', set => { key_values => [ { name => 'cached' } ], output_template => 'Cached: %s %s', output_change_bytes => 1, perfdatas => [ { template => '%d', min => 0, unit => 'B' } ] } }, { label => 'shared', nlabel => 'memory.shared.bytes', set => { key_values => [ { name => 'memShared' } ], output_template => 'Shared: %s %s', output_change_bytes => 1, perfdatas => [ { template => '%d', min => 0, unit => 'B' } ] } } ]; } 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 => { 'chart-period:s' => { name => 'chart_period', default => '300' }, 'chart-statistics:s' => { name => 'chart_statistics', default => 'average' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->get_data( chart => 'system.ram', points => $self->{option_results}->{chart_point}, after_period => $self->{option_results}->{chart_period}, group => $self->{option_results}->{chart_statistics} ); foreach my $memory_value (@{$result->{data}}) { foreach my $memory_label (@{$result->{labels}}) { $self->{ram_data}->{$memory_label} = shift @{$memory_value}; } } my $total = $options{custom}->get_info(filter_info => 'ram_total'); my $used = $self->{ram_data}->{used} * 1024 * 1024; my $free = $self->{ram_data}->{free} * 1024 * 1024; my $prct_used = $used * 100 / $total; my $prct_free = 100 - $prct_used; my $cached = $self->{ram_data}->{cached} * 1024 * 1024; my $buffers = $self->{ram_data}->{buffers} * 1024 * 1024; $self->{ram} = { total => $total, used => $used, free => $free, prct_used => $prct_used, prct_free => $prct_free, cached => $cached, buffers => $buffers }; }; 1; __END__ =head1 MODE Check *nix based servers memory using the Netdata agent RestAPI. Example: perl centreon-plugins/centreon_plugins.pl --plugin=apps::monitoring::netdata::restapi::plugin --mode=memory --hostname=10.0.0.1 --chart-period=300 --warning-usage-prct=80 --critical-usage-prct=90 --verbose More information on 'https://learn.netdata.cloud/docs/agent/web/api'. =over 8 =item B<--chart-period> The period in seconds on which the values are calculated Default: 300 =item B<--chart-statistic> The statistic calculation method used to parse the collected data. Can be : average, sum, min, max Default: average =item B<--warning-usage> Warning threshold on used memory (in B). =item B<--critical-usage> Critical threshold on used memory (in B) =item B<--warning-usage-prct> Warning threshold on used memory (in %). =item B<--critical-usage-prct> Critical threshold on percentage used memory (in %) =item B<--warning-usage-free> Warning threshold on free memory (in B). =item B<--critical-usage-free> Critical threshold on free memory (in B) =item B<--warning-*> Warning threshold (in B) on other metrics where '*' can be: buffer,cached,shared =item B<--critical-*> Critical threshold (in B) on other metrics where '*' can be: buffer,cached,shared =back =cut centreon-plugins-20220113/apps/monitoring/netdata/restapi/mode/swap.pm000066400000000000000000000122701417000230700257110ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and alarm 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::monitoring::netdata::restapi::mode::swap; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_swap_output { my ($self, %options) = @_; return sprintf( 'Swap total: %s %s used: %s %s (%.2f%%) free: %s %s (%.2f%%)', $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}), $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}), $self->{result_values}->{prct_used}, $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}), $self->{result_values}->{prct_free} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'swap', type => 0, message_separator => ' - ', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{swap} = [ { label => 'usage', nlabel => 'swap.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_swap_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1 } ] } }, { label => 'usage-free', display_ok => 0, nlabel => 'swap.free.bytes', set => { key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_swap_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1 } ] } }, { label => 'usage-prct', display_ok => 0, nlabel => 'swap.usage.percentage', set => { key_values => [ { name => 'prct_used' } ], output_template => 'Swap used: %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'chart-period:s' => { name => 'chart_period', default => '300' }, 'chart-statistics:s' => { name => 'chart_statistics', default => 'average' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->get_data( chart => 'system.swap', points => $self->{option_results}->{chart_point}, after_period => $self->{option_results}->{chart_period}, group => $self->{option_results}->{chart_statistics} ); foreach my $swap_value (@{$result->{data}}) { foreach my $swap_label (@{$result->{labels}}) { $self->{swap_data}->{$swap_label} = shift @{$swap_value}; } } my $used = $self->{swap_data}->{used} * 1024 * 1024; my $free = $self->{swap_data}->{free} * 1024 * 1024; my $total = $used + $free; my $prct_used = $used * 100 / $total; my $prct_free = 100 - $prct_used; $self->{swap} = { total => $total, used => $used, free => $free, prct_used => $prct_used, prct_free => $prct_free }; }; 1; __END__ =head1 MODE Check *nix based servers CPU using the Netdata agent RestAPI. Example: perl centreon-plugins/centreon_plugins.pl --plugin=apps::monitoring::netdata::restapi::plugin --mode=swap --hostname=10.0.0.1 --chart-period=300 --warning-usage-prct=80 --critical-usage-prct=90 --verbose More information on 'https://learn.netdata.cloud/docs/agent/web/api'. =over 8 =item B<--chart-period> The period in seconds on which the values are calculated Default: 300 =item B<--chart-statistic> The statistic calculation method used to parse the collected data. Can be : average, sum, min, max Default: average =item B<--warning-usage> Warning threshold on used swap (in B). =item B<--critical-usage> Critical threshold on used swap (in B) =item B<--warning-usage-prct> Warning threshold on used swap (in %). =item B<--critical-usage-prct> Critical threshold on percentage used swap (in %) =item B<--warning-usage-free> Warning threshold on free swap (in B). =item B<--critical-usage-free> Critical threshold on free swap (in B) =back =cut centreon-plugins-20220113/apps/monitoring/netdata/restapi/mode/traffic.pm000066400000000000000000000134541417000230700263620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::netdata::restapi::mode::traffic; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_traffic_output { my ($self, %options) = @_; return "Interface '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'interfaces', type => 1, cb_prefix_output => 'prefix_traffic_output', message_multiple => 'All interfaces are ok' } ]; $self->{maps_counters}->{interfaces} = [ { label => 'traffic-in', nlabel => 'network.traffic.in.bitspersecond', set => { key_values => [ { name => 'traffic_in' }, { name => 'speed' }, { name => 'display' } ], output_template => 'traffic in: %.2f%s/s', output_change_bytes => 2, perfdatas => [ { template => '%d', min => 0, max => 'speed', unit => 'b/s', cast_int => 1, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'traffic-out', nlabel => 'network.traffic.out.bitspersecond', set => { key_values => [ { name => 'traffic_out' }, { name => 'speed' }, { name => 'display' } ], output_template => 'traffic out: %.2f%s/s', output_change_bytes => 2, perfdatas => [ { template => '%d', min => 0, max => 'speed', unit => 'b/s', cast_int => 1, label_extra_instance => 1, instance_use => 'display' } ] } } ]; } 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 => { 'chart-period:s' => { name => 'chart_period', default => '300' }, 'chart-statistics:s' => { name => 'chart_statistics', default => 'average' }, 'interface-name:s' => { name => 'interface_name' }, 'speed:s' => { name => 'speed' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $full_list = $options{custom}->list_charts(); my $interface_list = []; foreach my $chart (values %{$full_list->{charts}}) { next if ($chart->{name} !~ '^net\.'); push @$interface_list, { name => $chart->{name}, speed => $chart->{chart_variables}->{nic_speed_max} }; } $self->{interfaces} = {}; foreach my $int (@$interface_list) { my $result = $options{custom}->get_data( chart => $int->{name}, dimensions => 'received,sent', points => $self->{option_results}->{chart_point}, after_period => $self->{option_results}->{chart_period}, group => $self->{option_results}->{chart_statistics}, absolute => 1 ); $int->{name} =~ s/net.//; next if (defined($self->{option_results}->{interface_name}) && $self->{option_results}->{interface_name} ne '' && $int->{name} !~ /$self->{option_results}->{interface_name}/ ); my $count = 0; # In Kb/s my $metrics = { received => 0, sent => 0 }; foreach my $data (@{$result->{data}}) { while (my ($index, $label) = each(@{$result->{labels}})) { $metrics->{$label} += $data->[$index]; } $count++; } my $speed = defined($int->{speed}) ? $int->{speed} * 1000 * 1000 : ''; $speed = $self->{option_results}->{speed} if (defined($self->{option_results}->{speed}) && $self->{option_results}->{speed} ne ''); $self->{interfaces}->{ $int->{name} } = { display => $int->{name}, traffic_in => $metrics->{received} * 1000, traffic_out => $metrics->{sent} * 1000, speed => $speed }; } if (scalar(keys %{$self->{interfaces}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No interfaces found'); $self->{output}->option_exit(); } }; 1; __END__ =head1 MODE Check traffic on interfaces of *nix based servers using the Netdata agent RestAPI. Example: perl centreon_plugins.pl --plugin=apps::monitoring::netdata::restapi::plugin --mode=traffic --hostname=10.0.0.1 --chart-period=300 --warning-traffic-in='70000000' --critical-traffic-in='80000000' --verbose More information on 'https://learn.netdata.cloud/docs/agent/web/api'. =over 8 =item B<--chart-period> The period in seconds on which the values are calculated Default: 300 =item B<--chart-statistic> The statistic calculation method used to parse the collected data. Can be : average, sum, min, max Default: average =item B<--interface-name> Filter on a specific interface. Regexp can be used. Example: --interface-name='^eth0$' =item B<--speed> Set interfaces speed in b/s. Default: 1000000000 (1Gb/s). =item B<--warning-traffic-*> Warning threshold on interface traffic where '*' can be: in,out. =item B<--critical-traffic-*> Critical threshold on interface traffic where '*' can be: in,out. =back =cut centreon-plugins-20220113/apps/monitoring/netdata/restapi/plugin.pm000066400000000000000000000043641417000230700253160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::netdata::restapi::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} = '1.0'; $self->{modes} = { 'alarms' => 'apps::monitoring::netdata::restapi::mode::alarms', 'cpu' => 'apps::monitoring::netdata::restapi::mode::cpu', 'disks' => 'apps::monitoring::netdata::restapi::mode::disks', 'get-chart' => 'apps::monitoring::netdata::restapi::mode::getchart', 'inodes' => 'apps::monitoring::netdata::restapi::mode::inodes', 'list-charts' => 'apps::monitoring::netdata::restapi::mode::listcharts', 'list-disks' => 'apps::monitoring::netdata::restapi::mode::listdisks', 'list-interfaces' => 'apps::monitoring::netdata::restapi::mode::listinterfaces', 'load' => 'apps::monitoring::netdata::restapi::mode::load', 'memory' => 'apps::monitoring::netdata::restapi::mode::memory', 'swap' => 'apps::monitoring::netdata::restapi::mode::swap', 'traffic' => 'apps::monitoring::netdata::restapi::mode::traffic' }; $self->{custom_modes}->{restapi} = 'apps::monitoring::netdata::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check *nix based servers components using the Netdata agent RestAPI. =cut centreon-plugins-20220113/apps/monitoring/openmetrics/000077500000000000000000000000001417000230700227145ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/openmetrics/mode/000077500000000000000000000000001417000230700236405ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/openmetrics/mode/scrapemetrics.pm000066400000000000000000000177131417000230700270530ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::openmetrics::mode::scrapemetrics; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::misc; use centreon::common::monitoring::openmetrics::scrape; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-metrics:s' => { name => 'filter_metrics' }, "warning:s" => { name => 'warning', default => '' }, "critical:s" => { name => 'critical', default => '' }, 'instance:s' => { name => 'instance' }, 'subinstance:s' => { name => 'subinstance' }, 'filter-instance:s' => { name => 'filter_instance' }, 'filter-subinstance:s' => { name => 'filter_subinstance' }, 'new-perfdata' => { name => 'new_perfdata' }, }); 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) = @_; $self->{metrics} = centreon::common::monitoring::openmetrics::scrape::parse(%options); my @exits; my $short_msg = 'All metrics are ok'; my $nometrics = 1; foreach my $metric (keys %{$self->{metrics}}) { next if (defined($self->{option_results}->{filter_metrics}) && $self->{option_results}->{filter_metrics} ne '' && $metric !~ /$self->{option_results}->{filter_metrics}/); foreach my $data (@{$self->{metrics}->{$metric}->{data}}) { next if (defined($self->{option_results}->{instance}) && $self->{option_results}->{instance} ne '' && !defined($data->{dimensions}->{$self->{option_results}->{instance}}) || defined($self->{option_results}->{filter_instance}) && $self->{option_results}->{filter_instance} ne '' && $data->{dimensions}->{$self->{option_results}->{instance}} !~ /$self->{option_results}->{filter_instance}/); next if (defined($self->{option_results}->{subinstance}) && $self->{option_results}->{subinstance} ne '' && !defined($data->{dimensions}->{$self->{option_results}->{subinstance}}) || defined($self->{option_results}->{filter_subinstance}) && $self->{option_results}->{filter_subinstance} ne '' && $data->{dimensions}->{$self->{option_results}->{subinstance}} !~ /$self->{option_results}->{filter_subinstance}/); $nometrics = 0; my $label = $metric; $label =~ s/_/./g if (defined($self->{option_results}->{new_perfdata})); $label = $data->{dimensions}->{$self->{option_results}->{instance}} . '#' . $label if (defined($self->{option_results}->{instance}) && $self->{option_results}->{instance} ne '' && defined($data->{dimensions}->{$self->{option_results}->{instance}}) && !defined($self->{option_results}->{subinstance})); $label = $data->{dimensions}->{$self->{option_results}->{instance}} . '~' . $data->{dimensions}->{$self->{option_results}->{subinstance}} . '#' . $label if (defined($self->{option_results}->{instance}) && $self->{option_results}->{instance} ne '' && defined($data->{dimensions}->{$self->{option_results}->{instance}}) && defined($self->{option_results}->{subinstance}) && $self->{option_results}->{subinstance} ne '' && defined($data->{dimensions}->{$self->{option_results}->{subinstance}})); $label =~ s/'//g; push @exits, $self->{perfdata}->threshold_check( value => $data->{value}, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->perfdata_add( label => $label, value => $data->{value}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical') ); $self->{output}->output_add(long_msg => sprintf("Metric '%s' value is '%s' [Help: \"%s\"] [Type: '%s'] [Dimensions: \"%s\"]", $metric, $data->{value}, (defined($self->{metrics}->{$metric}->{help})) ? $self->{metrics}->{$metric}->{help} : '-', (defined($self->{metrics}->{$metric}->{type})) ? $self->{metrics}->{$metric}->{type} : '-', $data->{dimensions_string})); } } if ($nometrics == 1) { $self->{output}->add_option_msg(short_msg => "No metrics found."); $self->{output}->option_exit(); } my $exit = $self->{output}->get_most_critical(status => \@exits); $short_msg = 'Some metrics are not ok' if ($exit !~ /OK/i); $self->{output}->output_add(severity => $exit, short_msg => $short_msg); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Scrape metrics. Examples: # perl centreon_plugins.pl --plugin=apps::monitoring::openmetrics::plugin --mode=scrape-metrics --custommode=web --hostname=10.2.3.4 --port=9100 --verbose --filter-metrics='node_network_up' --critical='0:0' --instance='device' --new-perfdata # perl centreon_plugins.pl --plugin=apps::monitoring::openmetrics::plugin --mode=scrape-metrics --custommode=web --hostname=10.2.3.4 --port=9100 --verbose --filter-metrics='node_cpu_seconds_total' --instance='cpu' --subinstance='mode' --filter-subinstance='mode' # perl centreon_plugins.pl --plugin=apps::monitoring::openmetrics::plugin --mode=scrape-metrics --custommode=file --command-options='/tmp/metrics' --filter-metrics='cpu' --verbose # perl centreon_plugins.pl --plugin=apps::monitoring::openmetrics::plugin --mode=scrape-metrics --custommode=file --hostname=10.2.3.4 --ssh-option='-l=centreon-engine' --ssh-option='-p=52' --command-options='/my/app/path/metrics' --verbose =over 8 =item B<--filter-metrics> Only parse some metrics (regexp can be used). Example: --filter-metrics='^status$' =item B<--warning> Set warning threshold. =item B<--critical> Set critical threshold. =item B<--instance> Set the label from dimensions to get the instance value from. =item B<--filter-instance> Only display some instances. Example: --filter-instance='0' =item B<--subinstance> Set the label from dimensions to get the subinstance value from. =item B<--filter-subinstance> Only display some subinstances. Example: --filter-subinstance='idle' =item B<--new-perfdata> Replace the underscore symbol by a point in perfdata. =back =cut centreon-plugins-20220113/apps/monitoring/openmetrics/plugin.pm000066400000000000000000000026631417000230700245570ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::openmetrics::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}} = ( 'scrape-metrics' => 'apps::monitoring::openmetrics::mode::scrapemetrics', ); $self->{custom_modes}{web} = 'centreon::common::monitoring::openmetrics::custom::web'; $self->{custom_modes}{file} = 'centreon::common::monitoring::openmetrics::custom::file'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Scrapes metrics from openmetric endpoints. =cut centreon-plugins-20220113/apps/monitoring/quanta/000077500000000000000000000000001417000230700216555ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/quanta/restapi/000077500000000000000000000000001417000230700233245ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/quanta/restapi/custom/000077500000000000000000000000001417000230700246365ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/quanta/restapi/custom/api.pm000066400000000000000000000120121417000230700257410ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::quanta::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use DateTime; use JSON::XS; 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 => { 'hostname:s' => { name => 'hostname' }, 'url-path:s' => { name => 'url_path' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'api-token:s' => { name => 'api_token' }, 'timeout:s' => { name => 'timeout' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : 'app.quanta.io'; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{url_path} = (defined($self->{option_results}->{url_path})) ? $self->{option_results}->{url_path} : '/api'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{api_token} = (defined($self->{option_results}->{api_token})) ? $self->{option_results}->{api_token} : ''; if (!defined($self->{api_token}) || $self->{api_token} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-token option."); $self->{output}->option_exit(); } return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{url_path} = $self->{url_path}; $self->{option_results}->{warning_status} = ''; $self->{option_results}->{critical_status} = ''; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->set_options(%{$self->{option_results}}); } sub get_api_token { my ($self, %options) = @_; return $self->{api_token}; } sub request_api { my ($self, %options) = @_; $self->settings; $self->{output}->output_add(long_msg => "Query URL: '" . $self->{proto} . "://" . $self->{hostname} . $self->{url_path} . $options{url_path} . "'", debug => 1); my $content = $self->{http}->request(url_path => $self->{url_path} . $options{url_path}); my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } if (defined($decoded->{error})) { $self->{output}->add_option_msg(short_msg => "API returned error '" . $decoded->{error} . "'"); $self->{output}->option_exit(); } return $decoded; } 1; __END__ =head1 NAME Quanta Rest API =head1 SYNOPSIS Quanta Rest API custom mode =head1 REST API OPTIONS Quanta Rest API =over 8 =item B<--hostname> Quanta API hostname (Default: 'api.quanta.io') =item B<--port> API port (Default: 443) =item B<--proto> Specify https if needed (Default: 'https') =item B<--url-path> API URL path (Default: '/api') =item B<--api-token> API token. =item B<--timeout> Set HTTP timeout. =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/monitoring/quanta/restapi/mode/000077500000000000000000000000001417000230700242505ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/quanta/restapi/mode/webscenariosavailability.pm000066400000000000000000000116421417000230700316710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::quanta::restapi::mode::webscenariosavailability; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 1, cb_prefix_output => 'prefix_output' } ]; $self->{maps_counters}->{global} = [ { label => 'total-response-time', nlabel => 'total.response.time.seconds', set => { key_values => [ { name => 'response_time' }, { name => 'display' } ], output_template => 'Total Response Time: %.3fs', perfdatas => [ { value => 'response_time', template => '%.3f', min => 0, unit => 's', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'availability', nlabel => 'availability.percentage', set => { key_values => [ { name => 'availability' }, { name => 'display' } ], output_template => 'Availability: %.2f%%', perfdatas => [ { value => 'availability', template => '%s', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'step-response-time', nlabel => 'step.response.time.seconds', set => { key_values => [ { name => 'avg_step_response_time' }, { name => 'display' } ], output_template => 'Step Average Response Time: %.3fs', perfdatas => [ { value => 'avg_step_response_time', template => '%.3f', min => 0, unit => 's', label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub prefix_output { my ($self, %options) = @_; return "Scenario '" . $options{instance_value}->{display} . "' "; } 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 => { "scenario-id:s" => { name => 'scenario_id' }, "timeframe:s" => { name => 'timeframe', default => 900 }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{scenario_id}) || $self->{option_results}->{scenario_id} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --scenario-id option."); $self->{output}->option_exit(); } } sub manage_selection { my ($self, %options) = @_; $self->{global} = {}; my $from = DateTime->now->subtract(seconds => $self->{option_results}->{timeframe}); my $to = DateTime->now; my $from_epoch = $from->epoch; my $to_epoch = $to->epoch; my $url = '/partners/report/' . $options{custom}->get_api_token . '?scenario=' . $self->{option_results}->{scenario_id} . '&from=' . $from_epoch . '&to=' . $to_epoch; my $results = $options{custom}->request_api(url_path => $url); $self->{global}->{$results->{site}->{id}}->{display} = $results->{site}->{scenario}; $self->{global}->{$results->{site}->{id}}->{availability} = $results->{site}->{availability} * 100; $self->{global}->{$results->{site}->{id}}->{avg_step_response_time} = $results->{site}->{avg_step_response_time}; foreach my $response (@{$results->{site}->{scenario_response_times}}) { $self->{global}->{$results->{site}->{id}}->{response_time} += $response->{value}; } $self->{global}->{$results->{site}->{id}}->{response_time} /= scalar(@{$results->{site}->{scenario_response_times}}) if (scalar(@{$results->{site}->{scenario_response_times}}) > 0); } 1; __END__ =head1 MODE Check web scenario availability metrics. (Data are delayed by a minimum of 3 hours) =over 8 =item B<--scenario-id> Set ID of the scenario. =item B<--timeframe> Set timeframe in seconds (Default: 14400). =item B<--warning-*> B<--critical-*> Can be: 'total-response-time', 'availability', 'step-response-time'. =back =cut centreon-plugins-20220113/apps/monitoring/quanta/restapi/plugin.pm000066400000000000000000000025611417000230700251640ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::quanta::restapi::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}} = ( 'web-scenarios-availability' => 'apps::monitoring::quanta::restapi::mode::webscenariosavailability', ); $self->{custom_modes}{api} = 'apps::monitoring::quanta::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Quanta.io application probes results. =cut centreon-plugins-20220113/apps/monitoring/scom/000077500000000000000000000000001417000230700213255ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/scom/restapi/000077500000000000000000000000001417000230700227745ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/scom/restapi/custom/000077500000000000000000000000001417000230700243065ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/scom/restapi/custom/api.pm000066400000000000000000000207411417000230700254210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::scom::restapi::custom::api; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::http; use JSON::XS; 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 => { 'api-version:s' => { name => 'api_version' }, 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'basic' => { name => 'basic' }, 'ntlmv2' => { name => 'ntlmv2' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'timeout:s' => { name => 'timeout' }, 'unknown-http-status:s' => { name => 'unknown_http_status' }, 'warning-http-status:s' => { name => 'warning_http_status' }, 'critical-http-status:s' => { name => 'critical_http_status' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'CUSTOM MODE OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{api_version} = (defined($self->{option_results}->{api_version})) ? $self->{option_results}->{api_version} : 2016; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 80; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'http'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{username} = $self->{option_results}->{username}; $self->{password} = $self->{option_results}->{password}; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300' ; $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; $self->{basic} = $self->{option_results}->{basic}; $self->{ntlmv2} = $self->{option_results}->{ntlmv2}; if (!defined($self->{api_version}) || $self->{api_version} !~ /(2012|2016|1801)/) { $self->{output}->add_option_msg(short_msg => 'Need to specify valid --api-version.'); $self->{output}->option_exit(); } $self->{api_version} = $1; if (!defined($self->{hostname}) || $self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --hostname option.'); $self->{output}->option_exit(); } return 0; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub get_port { my ($self, %options) = @_; return $self->{port}; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; if (defined($self->{username}) && $self->{username} ne '') { $self->{option_results}->{credentials} = 1; $self->{option_results}->{basic} = 1 if (defined($self->{basic})); $self->{option_results}->{ntlmv2} = 1 if (defined($self->{ntlmv2})); $self->{option_results}->{username} = $self->{username}; $self->{option_results}->{password} = $self->{password}; } } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->set_options(%{$self->{option_results}}); } sub get_method { my ($self, %options) = @_; my $api = 2016; $api = 1801 if ($self->{api_version} == 1801); return $self->can($options{method} . '_' . $api); } my $map_severity = { 0 => 'information', 1 => 'warning', 2 => 'critical' }; my $map_resolution_state = { 0 => 'new', 255 => 'closed', 254 => 'resolved', 250 => 'scheduled', 247 => 'awaiting_evidence', 248 => 'assigned_to_engineering', 249 => 'acknowledge', }; sub get_alerts_2016 { my ($self, %options) = @_; $self->settings(); my ($status, $response) = $self->{http}->request( url_path => '/api/alerts', credentials => 1, header => [ 'Accept-Type: application/json; charset=utf-8', 'Content-Type: application/json; charset=utf-8', ], unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status}, ); my $entries; eval { $entries = JSON::XS->new->utf8->decode($response); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } my $results = {}; foreach (@$entries) { $results->{$_->{alertGenerated}->{id}} = { host => $_->{alertGenerated}->{monitoringObjectDisplayName}, monitoringobjectdisplayname => $_->{alertGenerated}->{monitoringObjectDisplayName}, resolutionstate => $map_resolution_state->{$_->{alertGenerated}->{resolutionState}}, name => $_->{alertGenerated}->{name}, severity => $map_severity->{$_->{alertGenerated}->{severity}}, timeraised => $_->{alertGenerated}->{timeRaised}, description => $_->{alertGenerated}->{description}, }; } return $results; } sub get_alerts_1801 { my ($self, %options) = @_; $self->{output}->add_option_msg(short_msg => "method 'get_alerts_1801' unsupported"); $self->{output}->option_exit(); } sub get_alerts { my ($self, %options) = @_; my $func = $self->get_method(method => 'get_alerts'); return $func->($self, %options); } 1; __END__ =head1 NAME SCOM Rest API =head1 CUSTOM MODE OPTIONS SCOM Rest API =over 8 =item B<--api-version> Set SCOM API version (default: 2016). Could be: 2012, 2016 or 1801. =item B<--hostname> Remote hostname or IP address. =item B<--port> Port used (Default: 80) =item B<--proto> Specify https if needed (Default: 'http') =item B<--username> Specify username for authentication =item B<--password> Specify password for authentication =item B<--basic> Specify this option if you access webpage over basic authentication and don't want a '401 UNAUTHORIZED' error to be logged on your webserver. Specify this option if you access webpage over hidden basic authentication or you'll get a '404 NOT FOUND' error. (Use with --credentials) =item B<--ntlmv2> Specify this option if you access webpage over ntlmv2 authentication (Use with --credentials and --port options) =item B<--timeout> Set timeout in seconds (Default: 10). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/monitoring/scom/restapi/mode/000077500000000000000000000000001417000230700237205ustar00rootroot00000000000000centreon-plugins-20220113/apps/monitoring/scom/restapi/mode/alerts.pm000066400000000000000000000146131417000230700255550ustar00rootroot00000000000000# # Copyright 2018 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::monitoring::scom::restapi::mode::alerts; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::statefile; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("alert [severity: %s] [host: %s] [name: %s] %s", $self->{result_values}->{severity}, $self->{result_values}->{host}, $self->{result_values}->{name}, $self->{result_values}->{timeraised}); return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }, { name => 'alarms', type => 2, message_multiple => '0 problem(s) detected', display_counter_problem => { nlabel => 'alerts.problems.current.count', min => 0 }, group => [ { name => 'alarm', skipped_code => { -11 => 1 } } ] } ]; $self->{maps_counters}->{global} = []; foreach ('new', 'closed', 'resolved', 'scheduled', 'awaiting_evidence', 'assigned_to_engineering', 'acknowledge') { my $label = $_; $label =~ s/_/-/g; push @{$self->{maps_counters}->{global}}, { label => $label, nlabel => 'alerts.resolution.' . $_ . '.count', display_ok => 0, set => { key_values => [ { name => $_ } ], output_template => $_ . ': %s', perfdatas => [ { value => $_ , template => '%s', min => 0 }, ], } }; } $self->{maps_counters}->{alarm} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'host' }, { name => 'name' }, { name => 'severity' }, { name => 'timeraised' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold, } }, ]; } sub prefix_global_output { my ($self, %options) = @_; return 'Resolution state '; } 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-host:s' => { name => 'filter_host' }, 'warning-status:s' => { name => 'warning_status', default => '%{severity} =~ /warning/i' }, 'critical-status:s' => { name => 'critical_status', default => '%{severity} =~ /critical/i' }, 'memory' => { name => 'memory' }, }); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->check_options(%options); } } sub manage_selection { my ($self, %options) = @_; $self->{global} = { 'new' => 0, 'closed' => 0, 'resolved' => 0, 'scheduled' => 0, 'awaiting_evidence' => 0, 'assigned_to_engineering' => 0, 'acknowledge' => 0, }; $self->{alarms}->{global} = { alarm => {} }; my $results = $options{custom}->get_alerts(); my $alerts_mem; if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->read(statefile => "cache_scom_" . $options{custom}->get_hostname() . '_' . $options{custom}->get_port(). '_' . $self->{mode}); $alerts_mem = $self->{statefile_cache}->get(name => 'alerts'); } foreach my $alert_id (keys %$results) { if (defined($self->{option_results}->{memory})) { if (defined($alerts_mem) && defined($alerts_mem->{$alert_id})) { $alerts_mem->{$alert_id} = 1; next; } $alerts_mem->{$alert_id} = 1; } if (defined($self->{option_results}->{filter_host}) && $self->{option_results}->{filter_host} ne '' && $results->{$alert_id}->{monitoringobjectdisplayname} !~ /$self->{option_results}->{filter_host}/) { $self->{output}->output_add(long_msg => "skipping '" . $results->{$alert_id}->{monitoringobjectdisplayname} . "': no matching filter.", debug => 1); next; } $self->{global}->{$results->{$alert_id}->{resolutionstate}}++; $self->{alarms}->{global}->{alarm}->{$alert_id} = { %{$results->{$alert_id}} }; } if (defined($alerts_mem)) { foreach (keys %$alerts_mem) { if (!defined($results->{$_})) { delete $alerts_mem->{$_}; } } } if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->write(data => { alerts => $alerts_mem }); } } 1; __END__ =head1 MODE Check alerts. =over 8 =item B<--filter-host> Filter by host name (can be a regexp). =item B<--warning-status> Set warning threshold for status (Default: '%{severity} =~ /warning/i') Can used special variables like: %{severity}, %{host}, %{name}, %{timeraised} =item B<--critical-status> Set critical threshold for status (Default: '%{severity} =~ /critical/i'). Can used special variables like: %{severity}, %{host}, %{name}, %{timeraised} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'new', 'closed', 'resolved', 'scheduled', 'awaiting-evidence', 'assigned-to-engineering', 'acknowledge'. =item B<--memory> Only check new alarms. =back =cut centreon-plugins-20220113/apps/monitoring/scom/restapi/plugin.pm000066400000000000000000000027341417000230700246360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::monitoring::scom::restapi::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} = '1.0'; %{$self->{modes}} = ( 'alerts' => 'apps::monitoring::scom::restapi::mode::alerts', ); $self->{custom_modes}{api} = 'apps::monitoring::scom::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check SCOM with Rest API. Compatible SCOM 2012 and 2016 with api: https://gallery.technet.microsoft.com/System-Center-Operations-5d88527c Not compatible SCOM 1801 (soon) =cut centreon-plugins-20220113/apps/mq/000077500000000000000000000000001417000230700166145ustar00rootroot00000000000000centreon-plugins-20220113/apps/mq/activemq/000077500000000000000000000000001417000230700204255ustar00rootroot00000000000000centreon-plugins-20220113/apps/mq/activemq/jmx/000077500000000000000000000000001417000230700212235ustar00rootroot00000000000000centreon-plugins-20220113/apps/mq/activemq/jmx/mode/000077500000000000000000000000001417000230700221475ustar00rootroot00000000000000centreon-plugins-20220113/apps/mq/activemq/jmx/mode/brokers.pm000066400000000000000000000325731417000230700241660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mq::activemq::jmx::mode::brokers; 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 => 'brokers', type => 3, cb_prefix_output => 'prefix_broker_output', cb_long_output => 'broker_long_output', indent_long_output => ' ', message_multiple => 'All brokers are ok', group => [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'queue', display_long => 1, cb_prefix_output => 'prefix_queue_output', message_multiple => 'All queues are ok', type => 1, skipped_code => { -10 => 1 } }, { name => 'topic', display_long => 1, cb_prefix_output => 'prefix_topic_output', message_multiple => 'All topics are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'store-usage', nlabel => 'broker.store.usage.percentage', set => { key_values => [ { name => 'StorePercentUsage' }, { name => 'display' } ], output_template => 'store usage: %.2f %%', perfdatas => [ { template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1 } ] } }, { label => 'temporary-usage', nlabel => 'broker.temporary.usage.percentage', set => { key_values => [ { name => 'TempPercentUsage' }, { name => 'display' } ], output_template => 'temporary usage: %.2f %%', perfdatas => [ { template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1 } ] } }, { label => 'memory-usage', nlabel => 'broker.memory.usage.percentage', set => { key_values => [ { name => 'MemoryPercentUsage' }, { name => 'display' } ], output_template => 'memory usage: %.2f %%', perfdatas => [ { template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1 } ] } } ]; foreach (('queue', 'topic')) { $self->{maps_counters}->{$_} = [ { label => $_ . '-average-enqueue-time', nlabel => 'broker.' . $_ . '.average.enqueue.time.milliseconds', set => { key_values => [ { name => 'AverageEnqueueTime' }, { name => 'display' } ], output_template => 'average time messages remained enqueued: %.3f ms', perfdatas => [ { template => '%.3f', unit => 'ms', min => 0, label_extra_instance => 1 } ] } }, { label => $_ . '-consumers-connected', nlabel => 'broker.' . $_ . '.consumers.connected.count', set => { key_values => [ { name => 'ConsumerCount' }, { name => 'display' } ], output_template => 'consumers connected: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } }, { label => $_ . '-producers-connected', nlabel => 'broker.' . $_ . '.producers.connected.count', display_ok => 0, set => { key_values => [ { name => 'ProducerCount' }, { name => 'display' } ], output_template => 'producers connected: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } }, { label => $_ . '-memory-usage', nlabel => 'broker.' . $_ . '.memory.usage.percentage', display_ok => 0, set => { key_values => [ { name => 'MemoryPercentUsage' }, { name => 'display' } ], output_template => 'memory usage: %.2f %%', perfdatas => [ { template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1 } ] } }, { label => $_ . '-size', nlabel => 'broker.' . $_ . '.size.count', set => { key_values => [ { name => 'QueueSize' }, { name => 'display' } ], output_template => 'queue size: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } }, { label => $_ . '-messages-enqueued', nlabel => 'broker.' . $_ . '.messages.enqueued.count', display_ok => 0, set => { key_values => [ { name => 'EnqueueCount', diff => 1 }, { name => 'display' } ], output_template => 'messages enqueued: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } }, { label => $_ . '-messages-dequeued', nlabel => 'broker.' . $_ . '.messages.dequeue.count', display_ok => 0, set => { key_values => [ { name => 'DequeueCount', diff => 1 }, { name => 'display' } ], output_template => 'messages dequeued: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } }, { label => $_ . '-messages-expired', nlabel => 'broker.' . $_ . '.messages.expired.count', display_ok => 0, set => { key_values => [ { name => 'ExpiredCount', diff => 1 }, { name => 'display' } ], output_template => 'messages expired: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } }, { label => $_ . '-messages-inflighted', nlabel => 'broker.' . $_ . '.messages.inflighted.count', display_ok => 0, set => { key_values => [ { name => 'InFlightCount', diff => 1 }, { name => 'display' } ], output_template => 'messages in-flighted: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } }, { label => $_ . '-messages-size-average', nlabel => 'broker.' . $_ . '.messages.size.average.bytes', display_ok => 0, set => { key_values => [ { name => 'AverageMessageSize' }, { name => 'display' } ], output_template => 'average messages size: %s %s', output_change_bytes => 1, perfdatas => [ { template => '%s', unit => 'B', min => 0, label_extra_instance => 1 } ] } } ]; } } sub broker_long_output { my ($self, %options) = @_; return "checking broker '" . $options{instance_value}->{display} . "'"; } sub prefix_broker_output { my ($self, %options) = @_; return "Broker '" . $options{instance_value}->{display} . "' "; } sub prefix_queue_output { my ($self, %options) = @_; return "queue '" . $options{instance_value}->{display} . "' "; } sub prefix_topic_output { my ($self, %options) = @_; return "topic '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-broker-name:s' => { name => 'filter_broker_name' }, 'filter-destination-name:s' => { name => 'filter_destination_name' }, 'filter-destination-type:s' => { name => 'filter_destination_type' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $request = [ { mbean => 'org.apache.activemq:brokerName=*,destinationName=*,destinationType=*,type=Broker', attributes => [ { name => 'AverageEnqueueTime' }, { name => 'ConsumerCount' }, { name => 'ProducerCount' }, { name => 'MemoryPercentUsage' }, { name => 'QueueSize' }, { name => 'EnqueueCount' }, { name => 'DequeueCount' }, { name => 'ExpiredCount' }, { name => 'InFlightCount' }, { name => 'AverageMessageSize' } ] }, { mbean => 'org.apache.activemq:brokerName=*,type=Broker', attributes => [ { name => 'StorePercentUsage' }, { name => 'TempPercentUsage' }, { name => 'MemoryPercentUsage' } ] } ]; my $result = $options{custom}->get_attributes(request => $request, nothing_quit => 1); $self->{cache_name} = 'activemq_' . $self->{mode} . '_' . md5_hex($options{custom}->get_connection_info()) . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_broker_name}) ? md5_hex($self->{option_results}->{filter_broker_name}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_destination_name}) ? md5_hex($self->{option_results}->{filter_destination_name}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_destination_type}) ? md5_hex($self->{option_results}->{filter_destination_type}) : md5_hex('all')); $self->{brokers} = {}; foreach my $mbean (keys %$result) { next if ($mbean !~ /org.apache.activemq:brokerName=(.*?),(?:destinationName=(.*?),destinationType=(.*?),|type=Broker)/); my ($broker_name, $destination_name, $destination_type) = ($1, $2, $3); if (defined($self->{option_results}->{filter_broker_name}) && $self->{option_results}->{filter_broker_name} ne '' && $broker_name !~ /$self->{option_results}->{filter_broker_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $broker_name . "': no matching filter.", debug => 1); next; } if (defined($self->{option_results}->{filter_destination_type}) && $self->{option_results}->{filter_destination_type} ne '' && $destination_type !~ /$self->{option_results}->{filter_destination_type}/) { $self->{output}->output_add(long_msg => "skipping '" . $broker_name . "': no matching filter.", debug => 1); next; } if (!defined($self->{brokers}->{$broker_name})) { $self->{brokers}->{$broker_name} = { display => $broker_name, queue => {}, topic => {} }; } if (defined($destination_name)) { my $type = lc($destination_type); next if ($type ne 'topic' && $type ne 'queue'); if (defined($self->{option_results}->{filter_destination_name}) && $self->{option_results}->{filter_destination_name} ne '' && $destination_name !~ /$self->{option_results}->{filter_destination_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $destination_name . "': no matching filter.", debug => 1); next; } $self->{brokers}->{$broker_name}->{$type}->{$destination_name} = { display => $destination_name, %{$result->{$mbean}} }; } else { $self->{brokers}->{$broker_name}->{global} = { display => $broker_name, %{$result->{$mbean}} }; } } if (scalar(keys %{$self->{brokers}}) <= 0) { $self->{output}->output_add(short_msg => 'no brokers found'); } } 1; __END__ =head1 MODE Check brokers. =over 8 =item B<--filter-broker-name> Filter broker name (Can be a regexp). =item B<--filter-destination-name> Filter destination name (Can be a regexp). =item B<--filter-destination-type> Filter destination type (Can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'store-usage' (%), 'temporary-usage' (%), 'memory-usage' (%), 'queue-average-enqueue-time' (ms), 'queue-consumers-connected', 'queue-producers-connected', 'queue-memory-usage' (%), 'queue-size', 'queue-messages-enqueued', 'queue-messages-dequeued', 'queue-messages-expired', 'queue-messages-inflighted', 'topic-average-enqueue-time' (ms), 'topic-consumers-connected', 'topic-producers-connected', 'topic-memory-usage' (%), 'topic-size', 'topic-messages-enqueued', 'topic-messages-dequeued', 'topic-messages-expired', 'topic-messages-inflighted'. =back =cut centreon-plugins-20220113/apps/mq/activemq/jmx/mode/listbrokers.pm000066400000000000000000000051311417000230700250500ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mq::activemq::jmx::mode::listbrokers; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; my $request = [ { mbean => 'org.apache.activemq:brokerName=*,type=Broker', attributes => [ { name => 'BrokerName' } ] } ]; my $datas = $options{custom}->get_attributes(request => $request); my $results = {}; foreach (keys %$datas) { $results->{$datas->{$_}->{BrokerName}} = { name => $datas->{$_}->{BrokerName} }; } return $results; } sub run { my ($self, %options) = @_; my $results = $self->manage_selection(custom => $options{custom}); foreach (sort keys %$results) { $self->{output}->output_add( long_msg => sprintf( '[name = %s]', $_ ) ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List brokers:' ); $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) = @_; my $results = $self->manage_selection(custom => $options{custom}); foreach (sort keys %$results) { $self->{output}->add_disco_entry( name => $_ ); } } 1; __END__ =head1 MODE List brokers. =over 8 =back =cut centreon-plugins-20220113/apps/mq/activemq/jmx/plugin.pm000066400000000000000000000026101417000230700230560ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mq::activemq::jmx::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}} = ( 'brokers' => 'apps::mq::activemq::jmx::mode::brokers', 'list-brokers' => 'apps::mq::activemq::jmx::mode::listbrokers' ); $self->{custom_modes}{jolokia} = 'centreon::common::protocols::jmx::custom::jolokia'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check ActiveMQ in JMX. Need Jolokia agent. =cut centreon-plugins-20220113/apps/mq/ibmmq/000077500000000000000000000000001417000230700177215ustar00rootroot00000000000000centreon-plugins-20220113/apps/mq/ibmmq/mqi/000077500000000000000000000000001417000230700205075ustar00rootroot00000000000000centreon-plugins-20220113/apps/mq/ibmmq/mqi/custom/000077500000000000000000000000001417000230700220215ustar00rootroot00000000000000centreon-plugins-20220113/apps/mq/ibmmq/mqi/custom/api.pm000066400000000000000000000136401417000230700231340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mq::ibmmq::mqi::custom::api; use base qw(centreon::plugins::mode); 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'channel:s' => { name => 'channel' }, 'timeout:s' => { name => 'timeout' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'CUSTOM MQI OPTIONS', once => 1); $self->{output} = $options{output}; centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'MQSeries::QueueManager', error_msg => "Cannot load module 'MQSeries::QueueManager'." ); centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'MQSeries::Command', error_msg => "Cannot load module 'MQSeries::Command'." ); $self->{connected} = 0; return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{channel} = (defined($self->{option_results}->{channel})) ? $self->{option_results}->{channel} : ''; $self->{port} = (defined($self->{option_results}->{port})) && $self->{option_results}->{port} =~ /(\d+)/ ? $1 : 1414; $self->{timeout} = (defined($self->{option_results}->{timeout})) && $self->{option_results}->{timeout} =~ /(\d+)/ ? $1 : 30; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --hostname option.'); $self->{output}->option_exit(); } if ($self->{channel} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --channel option.'); $self->{output}->option_exit(); } return 0; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub get_port { my ($self, %options) = @_; return $self->{port}; } sub get_qmgr_name { my ($self, %options) = @_; return $self->{qmgr_name}; } sub my_logger {} sub connect { my ($self, %options) = @_; return if ($self->{connected} == 1); my $reason; $self->{qmgr} = MQSeries::QueueManager->new( QueueManager => '', ConnectTimeout => $self->{timeout}, Carp => \&my_logger, Reason => \$reason, ClientConn => { 'ChannelName' => $self->{channel}, 'TransportType' => 'TCP', 'ConnectionName' => $self->{hostname} . '(' . $self->{port} . ')', 'MaxMsgLength' => 16 * 1024 * 1024 } ); if (!$self->{qmgr}) { $self->{output}->add_option_msg(short_msg => 'unable to connect to the queue manager: ' . MQSeries::MQReasonToText($reason)); $self->{output}->option_exit(); } $self->{mq_command} = MQSeries::Command->new(QueueManager => $self->{qmgr}, CommandVersion => eval('MQSeries::MQCFH_VERSION_3')); if (!$self->{mq_command}) { $self->{output}->add_option_msg(short_msg => 'unable to instantiate command object'); $self->{output}->option_exit(); } $self->{connected} = 1; my $results = $self->execute_command(command => 'InquireQueueManager'); $self->{qmgr_name} = $results->[0]->{QMgrName}; } sub execute_command { my ($self, %options) = @_; $self->connect(); my @results; if ($options{command} eq 'InquireQueueManager') { @results = $self->{mq_command}->InquireQueueManager(%{$options{attrs}}); } elsif ($options{command} eq 'InquireQueueManagerStatus') { @results = $self->{mq_command}->InquireQueueManagerStatus(%{$options{attrs}}); } elsif ($options{command} eq 'InquireChannelStatus') { @results = $self->{mq_command}->InquireChannelStatus(%{$options{attrs}}); } elsif ($options{command} eq 'InquireQueueStatus') { @results = $self->{mq_command}->InquireQueueStatus(%{$options{attrs}}); } elsif ($options{command} eq 'InquireChannel') { @results = $self->{mq_command}->InquireChannel(%{$options{attrs}}); } if (!@results) { $self->{output}->add_option_msg(short_msg => "method '$options{command}' issue: " . $self->{mq_command}->ReasonText()); $self->{output}->option_exit(); } return \@results; } 1; __END__ =head1 NAME IBM MQ MQI =head1 CUSTOM MQI OPTIONS IBM MQ MQI =over 8 =item B<--hostname> Hostname or IP address. =item B<--port> Port used (Default: 1414) =item B<--channel> Channel name. =item B<--timeout> Set timeout in seconds (Default: 30). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/mq/ibmmq/mqi/mode/000077500000000000000000000000001417000230700214335ustar00rootroot00000000000000centreon-plugins-20220113/apps/mq/ibmmq/mqi/mode/channels.pm000066400000000000000000000201141417000230700235620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mq::ibmmq::mqi::mode::channels; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); sub custom_status_output { my ($self, %options) = @_; return sprintf( 'status: %s [message channel agent: %s]', $self->{result_values}->{channel_status}, $self->{result_values}->{mca_status} ); } sub custom_traffic_in_perfdata { my ($self) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel}, unit => 'b/s', instances => [$self->{result_values}->{qmgr_name}, $self->{result_values}->{channel_name}], value => $self->{result_values}->{traffic_in}, 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_traffic_out_perfdata { my ($self) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel}, unit => 'b/s', instances => [$self->{result_values}->{qmgr_name}, $self->{result_values}->{channel_name}], value => $self->{result_values}->{traffic_out}, 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 prefix_channel_output { my ($self, %options) = @_; return "Channel '" . $options{instance_value}->{qmgr_name} . ':' . $options{instance_value}->{channel_name} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'channel', type => 1, cb_prefix_output => 'prefix_channel_output', message_multiple => 'All channels are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{channel} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'qmgr_name' }, { name => 'channel_name' }, { name => 'channel_status' }, { name => 'mca_status' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } }, { label => 'traffic-in', nlabel => 'channel.traffic.in.bitspersecond', set => { key_values => [ { name => 'traffic_in', per_second => 1 }, { name => 'qmgr_name' }, { name => 'channel_name' } ], output_template => 'traffic in: %s %s/s', output_change_bytes => 2, closure_custom_perfdata => $self->can('custom_traffic_in_perfdata') } }, { label => 'traffic-out', nlabel => 'channel.traffic.out.bitspersecond', set => { key_values => [ { name => 'traffic_out', per_second => 1 }, { name => 'qmgr_name' }, { name => 'channel_name' } ], output_template => 'traffic out: %s %s/s', output_change_bytes => 2, closure_custom_perfdata => $self->can('custom_traffic_out_perfdata') } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'filter-type:s' => { name => 'filter_type' }, 'unknown-status:s' => { name => 'unknown_status', default => '' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{channel_status} !~ /running|idle/i' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['unknown_status', 'warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->execute_command( command => 'InquireChannelStatus', attrs => { } ); my $names = $options{custom}->execute_command( command => 'InquireChannel', attrs => { } ); $self->{channel} = {}; foreach (@$result) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $_->{ChannelName} !~ /$self->{option_results}->{filter_name}/); next if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' && $_->{ChannelType} !~ /$self->{option_results}->{filter_type}/); $self->{channel}->{$_->{ChannelName}} = { qmgr_name => $options{custom}->get_qmgr_name(), channel_name => $_->{ChannelName}, channel_status => lc($_->{ChannelStatus}), channel_type => $_->{ChannelType}, mca_status => lc($_->{MCAStatus}), traffic_in => $_->{BytesReceived} * 8, traffic_out => $_->{BytesSent} * 8 }; } foreach (@$names) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $_->{ChannelName} !~ /$self->{option_results}->{filter_name}/); next if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' && $_->{ChannelType} !~ /$self->{option_results}->{filter_type}/i); if (!defined($self->{channel}->{$_->{ChannelName}})) { $self->{channel}->{$_->{ChannelName}} = { qmgr_name => $options{custom}->get_qmgr_name(), channel_name => $_->{ChannelName}, channel_status => 'idle', channel_type => $_->{ChannelType}, mca_status => '-', }; } } $self->{cache_name} = 'ibmmq_' . $self->{mode} . '_' . $options{custom}->get_hostname() . '_' . $options{custom}->get_port() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check channels. =over 8 =item B<--filter-name> Filter channel name (Can use regexp). =item B<--filter-type> Filter channel type (Can use regexp, insensitive search). Here is the IBM - Perl mapping about Channel types: SDR - Sender SVR - Server RCVR - Receiver RQSTR - Requester CLNTCONN - Clntconn SVRCONN - Svrconn CLUSSDR - ClusterSender CLUSRCVR - ClusterReceiver MQTT - Telemetry =item B<--unknown-status> Set unknown threshold for status (Default: ''). Can used special variables like: %{channel_status}, %{mca_status} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{channel_status}, %{mca_status} =item B<--critical-status> Set critical threshold for status (Default: '%{channel_status} !~ /running|idle/i'). Can used special variables like: %{channel_status}, %{mca_status} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'traffic-in', 'traffic-out'. =back =cut centreon-plugins-20220113/apps/mq/ibmmq/mqi/mode/listchannels.pm000066400000000000000000000047351417000230700244710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mq::ibmmq::mqi::mode::listchannels; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->execute_command( command => 'InquireChannel', attrs => {} ); $self->{channel} = {}; foreach (@$result) { $self->{channel}->{$_->{ChannelName}} = { name => $_->{ChannelName}, type => $_->{ChannelType} }; } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach (sort keys %{$self->{channel}}) { $self->{output}->output_add(long_msg => sprintf( '[name = %s][type = %s]', $self->{channel}->{$_}->{name}, $self->{channel}->{$_}->{type} ) ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List channels:' ); $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','type']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach (values %{$self->{channel}}) { $self->{output}->add_disco_entry(%$_); } } 1; __END__ =head1 MODE List channels. =over 8 =back =cutcentreon-plugins-20220113/apps/mq/ibmmq/mqi/mode/listqueues.pm000066400000000000000000000045671417000230700242100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mq::ibmmq::mqi::mode::listqueues; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->execute_command( command => 'InquireQueueStatus', attrs => { QStatusAttrs => ['QName'] } ); $self->{queue} = {}; foreach (@$result) { $self->{queue}->{$_->{QName}} = { name => $_->{QName} }; } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach (sort keys %{$self->{queue}}) { $self->{output}->output_add(long_msg => sprintf( '[name = %s]', $self->{queue}->{$_}->{name} ) ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List queues:' ); $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->manage_selection(%options); foreach (values %{$self->{queue}}) { $self->{output}->add_disco_entry(%$_); } } 1; __END__ =head1 MODE List queues. =over 8 =back =cut centreon-plugins-20220113/apps/mq/ibmmq/mqi/mode/queuemanager.pm000066400000000000000000000116761417000230700244630ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mq::ibmmq::mqi::mode::queuemanager; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); sub custom_status_output { my ($self, %options) = @_; return sprintf( 'status: %s [command server: %s] [channel initiator: %s]', $self->{result_values}->{mgr_status}, $self->{result_values}->{command_server_status}, $self->{result_values}->{channel_initiator_status} ); } sub custom_connections_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel}, instances => $self->{result_values}->{display}, value => $self->{result_values}->{connection_count}, 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 prefix_qmgr_output { my ($self, %options) = @_; return "Queue manager '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'qmgr', type => 0, cb_prefix_output => 'prefix_qmgr_output', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{qmgr} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'mgr_status' }, { name => 'channel_initiator_status' }, { name => 'command_server_status' }, { name => 'display' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } }, { label => 'connections', nlabel => 'queuemanager.connections.count', set => { key_values => [ { name => 'connection_count' }, { name => 'display' } ], output_template => 'current number of connections: %s', closure_custom_perfdata => $self->can('custom_connections_perfdata') } } ]; } 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 => { 'unknown-status:s' => { name => 'unknown_status', default => '' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{mgr_status} !~ /running/i' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['unknown_status', 'warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->execute_command( command => 'InquireQueueManagerStatus', attrs => { } ); $self->{qmgr} = { display => $options{custom}->get_qmgr_name(), channel_initiator_status => lc($result->[0]->{ChannelInitiatorStatus}), mgr_status => lc($result->[0]->{QMgrStatus}), command_server_status => lc($result->[0]->{CommandServerStatus}), connection_count => $result->[0]->{ConnectionCount} }; } 1; __END__ =head1 MODE Check queue manager. =over 8 =item B<--unknown-status> Set unknown threshold for status (Default: ''). Can used special variables like: %{mgr_status}, %{channel_initiator_status}, %{command_server_status} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{mgr_status}, %{channel_initiator_status}, %{command_server_status} =item B<--critical-status> Set critical threshold for status (Default: '%{mgr_status} !~ /running/i'). Can used special variables like: %{mgr_status}, %{channel_initiator_status}, %{command_server_status} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'connections'. =back =cut centreon-plugins-20220113/apps/mq/ibmmq/mqi/mode/queues.pm000066400000000000000000000133271417000230700233060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mq::ibmmq::mqi::mode::queues; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; sub custom_oldest_output { my ($self, %options) = @_; return sprintf( 'oldest message: %s', centreon::plugins::misc::change_seconds(value => $self->{result_values}->{oldest_msg_age}) ); } sub custom_connections_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel}, instances => [$self->{result_values}->{qmgr_name}, $self->{result_values}->{queue_name}], value => $self->{result_values}->{open_input_count}, 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_qdepth_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel}, instances => [$self->{result_values}->{qmgr_name}, $self->{result_values}->{queue_name}], value => $self->{result_values}->{current_qdepth}, 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_oldest_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel}, instances => [$self->{result_values}->{qmgr_name}, $self->{result_values}->{queue_name}], value => $self->{result_values}->{oldest_msg_age}, 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 prefix_queue_output { my ($self, %options) = @_; return "Queue '" . $options{instance_value}->{qmgr_name} . ':' . $options{instance_value}->{queue_name} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'queue', type => 1, cb_prefix_output => 'prefix_queue_output', message_multiple => 'All queues are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{queue} = [ { label => 'connections-input', nlabel => 'queue.connections.input.count', set => { key_values => [ { name => 'open_input_count' }, { name => 'qmgr_name' }, { name => 'queue_name' } ], output_template => 'current input connections: %s', closure_custom_perfdata => $self->can('custom_connections_perfdata') } }, { label => 'messages-depth', nlabel => 'queue.messages.depth.count', set => { key_values => [ { name => 'current_qdepth' }, { name => 'qmgr_name' }, { name => 'queue_name' } ], output_template => 'current messages depth: %s', closure_custom_perfdata => $self->can('custom_qdepth_perfdata') } }, { label => 'message-oldest', nlabel => 'queue.message.oldest.seconds', set => { key_values => [ { name => 'oldest_msg_age' }, { name => 'qmgr_name' }, { name => 'queue_name' } ], closure_custom_output => $self->can('custom_oldest_output'), closure_custom_perfdata => $self->can('custom_oldest_perfdata') } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->execute_command( command => 'InquireQueueStatus', attrs => { QStatusAttrs => ['QName', 'CurrentQDepth', 'OpenInputCount', 'OldestMsgAge'] } ); $self->{queue} = {}; foreach (@$result) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $_->{QName} !~ /$self->{option_results}->{filter_name}/); $self->{queue}->{$_->{QName}} = { qmgr_name => $options{custom}->get_qmgr_name(), queue_name => $_->{QName}, open_input_count => $_->{OpenInputCount}, current_qdepth => $_->{CurrentQDepth}, oldest_msg_age => $_->{OldestMsgAge} # in seconds }; } if (scalar(keys %{$self->{queue}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No queue found'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check queues. =over 8 =item B<--filter-name> Filter queue name (Can use regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'connections-input', 'messages-depth', 'message-oldest'. =back =cut centreon-plugins-20220113/apps/mq/ibmmq/mqi/plugin.pm000066400000000000000000000031251417000230700223440ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mq::ibmmq::mqi::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} = '1.0'; %{$self->{modes}} = ( 'channels' => 'apps::mq::ibmmq::mqi::mode::channels', 'list-channels' => 'apps::mq::ibmmq::mqi::mode::listchannels', 'list-queues' => 'apps::mq::ibmmq::mqi::mode::listqueues', 'queues' => 'apps::mq::ibmmq::mqi::mode::queues', 'queue-manager' => 'apps::mq::ibmmq::mqi::mode::queuemanager' ); $self->{custom_modes}{api} = 'apps::mq::ibmmq::mqi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check IBM MQ using middleware product API (work for version <= 7.5) =cut centreon-plugins-20220113/apps/mq/ibmmq/restapi/000077500000000000000000000000001417000230700213705ustar00rootroot00000000000000centreon-plugins-20220113/apps/mq/ibmmq/restapi/custom/000077500000000000000000000000001417000230700227025ustar00rootroot00000000000000centreon-plugins-20220113/apps/mq/ibmmq/restapi/custom/api.pm000066400000000000000000000147351417000230700240230ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mq::ibmmq::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use JSON::XS; 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 => { 'api-username:s' => { name => 'api_username' }, 'api-password:s' => { name => 'api_password' }, 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'timeout:s' => { name => 'timeout' }, 'url-path:s' => { name => 'url_path' }, 'unknown-http-status:s' => { name => 'unknown_http_status' }, 'warning-http-status:s' => { name => 'warning_http_status' }, 'critical-http-status:s' => { name => 'critical_http_status' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 9443; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{url_path} = (defined($self->{option_results}->{url_path})) ? $self->{option_results}->{url_path} : '/ibmmq/rest/v1/admin'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 50; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : ''; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : ''; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300'; $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } if ($self->{api_username} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-username option."); $self->{output}->option_exit(); } return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{credentials} = 1; $self->{option_results}->{basic} = 1; $self->{option_results}->{username} = $self->{api_username}; $self->{option_results}->{password} = $self->{api_password}; } sub settings { my ($self, %options) = @_; return if (defined($self->{settings_done})); $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->set_options(%{$self->{option_results}}); $self->{settings_done} = 1; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub request_api { my ($self, %options) = @_; $self->settings(); my $content = $self->{http}->request( url_path => $self->{url_path} . $options{endpoint}, unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status}, get_param => $options{get_param} ); if (!defined($content) || $content eq '') { $self->{output}->add_option_msg(short_msg => "API returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } return $decoded; } 1; __END__ =head1 NAME IBM MQ Rest API =head1 REST API OPTIONS IBM MQ Rest API =over 8 =item B<--hostname> Administrative server hostname. =item B<--port> Port used (Default: 9443) =item B<--proto> Specify https if needed (Default: 'https') =item B<--url-path> API url path (Default: '/ibmmq/rest/v1/admin') =item B<--api-username> API username. =item B<--api-password> API password. =item B<--timeout> Set timeout in seconds (Default: 50). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/mq/ibmmq/restapi/mode/000077500000000000000000000000001417000230700223145ustar00rootroot00000000000000centreon-plugins-20220113/apps/mq/ibmmq/restapi/mode/listqueuemanagers.pm000066400000000000000000000046451417000230700264210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mq::ibmmq::restapi::mode::listqueuemanagers; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; my $infos = $options{custom}->request_api( endpoint => '/qmgr/' ); my $results = {}; foreach my $entry (@{$infos->{qmgr}}) { $results->{ $entry->{name} } = $entry; } return $results; } sub run { my ($self, %options) = @_; my $results = $self->manage_selection(%options); foreach (sort keys %$results) { $self->{output}->output_add(long_msg => sprintf( '[name: %s][state: %s]', $results->{$_}->{name}, $results->{$_}->{state} ) ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List queue managers:' ); $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) = @_; my $results = $self->manage_selection(%options); foreach (sort keys %$results) { $self->{output}->add_disco_entry(%{$results->{$_}}); } } 1; __END__ =head1 MODE List queue managers. =over 8 =back =cut centreon-plugins-20220113/apps/mq/ibmmq/restapi/mode/listqueues.pm000066400000000000000000000054351417000230700250640ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mq::ibmmq::restapi::mode::listqueues; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; my $list_qmgr = $options{custom}->request_api( endpoint => '/qmgr/' ); my $results = {}; foreach my $qmgr (@{$list_qmgr->{qmgr}}) { my $queues = $options{custom}->request_api( endpoint => '/qmgr/' . $qmgr->{name} . '/queue' ); foreach my $queue (@{$queues->{queue}}) { $results->{ $qmgr->{name} . ':' . $queue->{name} } = { qmgr => $qmgr->{name}, name => $queue->{name}, type => $queue->{type} }; } } return $results; } sub run { my ($self, %options) = @_; my $results = $self->manage_selection(%options); foreach (sort keys %$results) { $self->{output}->output_add(long_msg => sprintf( '[qmgr: %s][name: %s][types: %s]', $results->{$_}->{qmgr}, $results->{$_}->{name}, $results->{$_}->{type} ) ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List queues:' ); $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 => ['qmgr', 'name', 'type']); } sub disco_show { my ($self, %options) = @_; my $results = $self->manage_selection(%options); foreach (sort keys %$results) { $self->{output}->add_disco_entry(%{$results->{$_}}); } } 1; __END__ =head1 MODE List queues. =over 8 =back =cut centreon-plugins-20220113/apps/mq/ibmmq/restapi/mode/queuemanagers.pm000066400000000000000000000117471417000230700255260ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mq::ibmmq::restapi::mode::queuemanagers; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf( 'status: %s [channel initiator: %s]', $self->{result_values}->{mgr_status}, $self->{result_values}->{channel_initiator_status} ); } sub prefix_qmgr_output { my ($self, %options) = @_; return "Queue manager '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'qmgr', type => 1, cb_prefix_output => 'prefix_qmgr_output', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{qmgr} = [ { label => 'status', type => 2, critical_default => '%{mgr_status} !~ /running/i', set => { key_values => [ { name => 'mgr_status' }, { name => 'channel_initiator_status' }, { name => 'display' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'connections', nlabel => 'queuemanager.connections.count', set => { key_values => [ { name => 'connection_count' } ], output_template => 'current number of connections: %s', perfdatas => [ { template => '%d', min => 0, label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'qmgr-name:s' => { name => 'qmgr_name' }, 'filter-qmgr-name:s' => { name => 'filter_qmgr_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my @lists = (); if (defined($self->{option_results}->{qmgr_name}) && $self->{option_results}->{qmgr_name} ne '') { @lists = ($self->{option_results}->{qmgr_name}); } else { my $names = $options{custom}->request_api( endpoint => '/qmgr/' ); foreach (@{$names->{qmgr}}) { push @lists, $_->{name}; } } $self->{qmgr} = {}; foreach my $name (@lists) { if (defined($self->{option_results}->{filter_qmgr_name}) && $self->{option_results}->{filter_qmgr_name} ne '' && $name !~ /$self->{option_results}->{filter_qmgr_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $name . "': no matching filter.", debug => 1); next; } my $infos = $options{custom}->request_api( endpoint => '/qmgr/' . $name, get_param => ['status=*'] ); $self->{qmgr}->{$name} = { display => $name, channel_initiator_status => lc($infos->{qmgr}->[0]->{status}->{channelInitiatorState}), mgr_status => lc($infos->{qmgr}->[0]->{state}), connection_count => $infos->{qmgr}->[0]->{status}->{connectionCount} }; } if (scalar(keys %{$self->{qmgr}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No queue managers found'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check queue managers. =over 8 =item B<--qmgr-name> Check exact queue manager (no API listing call). =item B<--filter-qmgr-name> Filter queue managers by name (can be a regexp). =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{mgr_status}, %{channel_initiator_status} =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{mgr_status}, %{channel_initiator_status} =item B<--critical-status> Set critical threshold for status (Default: '%{mgr_status} !~ /running/i'). Can used special variables like: %{mgr_status}, %{channel_initiator_status} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'connections'. =back =cut centreon-plugins-20220113/apps/mq/ibmmq/restapi/mode/queues.pm000066400000000000000000000145601417000230700241670ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mq::ibmmq::restapi::mode::queues; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; sub custom_oldest_output { my ($self, %options) = @_; return sprintf( 'oldest message: %s', centreon::plugins::misc::change_seconds(value => $self->{result_values}->{oldest_msg_age}) ); } sub qmgr_long_output { my ($self, %options) = @_; return "checking queue manager '" . $options{instance_value}->{name} . "'"; } sub prefix_qmgr_output { my ($self, %options) = @_; return "queue manager '" . $options{instance_value}->{name} . "' "; } sub prefix_queue_output { my ($self, %options) = @_; return "queue '" . $options{instance_value}->{name} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'qmgr', type => 3, cb_prefix_output => 'prefix_qmgr_output', cb_long_output => 'qmgr_long_output', indent_long_output => ' ', message_multiple => 'All queue managers are ok', group => [ { name => 'queues', display_long => 1, cb_prefix_output => 'prefix_queue_output', message_multiple => 'queues are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{queues} = [ { label => 'connections-input', nlabel => 'queue.connections.input.count', set => { key_values => [ { name => 'open_input_count' } ], output_template => 'current input connections: %s', perfdatas => [ { template => '%d', min => 0, label_extra_instance => 1 } ] } }, { label => 'messages-depth', nlabel => 'queue.messages.depth.count', set => { key_values => [ { name => 'current_qdepth' }], output_template => 'current messages depth: %s', perfdatas => [ { template => '%d', min => 0, label_extra_instance => 1 } ] } }, { label => 'message-oldest', nlabel => 'queue.message.oldest.seconds', set => { key_values => [ { name => 'oldest_msg_age' } ], closure_custom_output => $self->can('custom_oldest_output'), closure_custom_perfdata => $self->can('custom_oldest_perfdata') } } ]; } 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 => { 'qmgr-name:s' => { name => 'qmgr_name' }, 'queue-name:s' => { name => 'queue_name' }, 'filter-qmgr-name:s' => { name => 'filter_qmgr_name' }, 'filter-queue-name:s' => { name => 'filter_queue_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my @list_qmgr = (); if (defined($self->{option_results}->{qmgr_name}) && $self->{option_results}->{qmgr_name} ne '') { @list_qmgr = ($self->{option_results}->{qmgr_name}); } else { my $names = $options{custom}->request_api( endpoint => '/qmgr/' ); foreach (@{$names->{qmgr}}) { push @list_qmgr, $_->{name}; } } my $found = 0; $self->{qmgr} = {}; foreach my $qmgr_name (@list_qmgr) { if (defined($self->{option_results}->{filter_qmgr_name}) && $self->{option_results}->{filter_qmgr_name} ne '' && $qmgr_name !~ /$self->{option_results}->{filter_qmgr_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $qmgr_name . "': no matching filter.", debug => 1); next; } my $endpoint = '/qmgr/' . $qmgr_name . '/queue'; if (defined($self->{option_results}->{queue_name}) && $self->{option_results}->{queue_name} ne '') { $endpoint .= '/' . $self->{option_results}->{queue_name}; } my $queues = $options{custom}->request_api( endpoint => $endpoint, get_param => ['status=*'] ); foreach my $queue (@{$queues->{queue}}) { if (defined($self->{option_results}->{filter_queue_name}) && $self->{option_results}->{filter_queue_name} ne '' && $queue->{name} !~ /$self->{option_results}->{filter_queue_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $queue->{name} . "': no matching filter.", debug => 1); next; } unless (defined($self->{qmgr}->{$qmgr_name})) { $self->{qmgr}->{$qmgr_name} = { name => $qmgr_name, queues => {} }; } $self->{qmgr}->{$qmgr_name}->{queues}->{ $queue->{name} } = { name => $queue->{name}, open_input_count => $queue->{status}->{openInputCount}, current_qdepth => $queue->{status}->{currentDepth}, oldest_msg_age => $queue->{status}->{oldestMessageAge} }; $found = 1; } } unless ($found) { $self->{output}->add_option_msg(short_msg => 'No queue found'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check queues. =over 8 =item B<--qmgr-name> Check exact queue manager. =item B<--queue-name> Check exact queue. =item B<--filter-qmgr-name> Filter queue managers by name (can be a regexp). =item B<--filter-queue-name> Filter queues by name (can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'connections-input', 'messages-depth', 'message-oldest'. =back =cut centreon-plugins-20220113/apps/mq/ibmmq/restapi/plugin.pm000066400000000000000000000030421417000230700232230ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mq::ibmmq::restapi::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} = { 'list-queue-managers' => 'apps::mq::ibmmq::restapi::mode::listqueuemanagers', 'list-queues' => 'apps::mq::ibmmq::restapi::mode::listqueues', 'queues' => 'apps::mq::ibmmq::restapi::mode::queues', 'queue-managers' => 'apps::mq::ibmmq::restapi::mode::queuemanagers' }; $self->{custom_modes}->{api} = 'apps::mq::ibmmq::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check IBM MQ using Rest API. =cut centreon-plugins-20220113/apps/mq/rabbitmq/000077500000000000000000000000001417000230700204155ustar00rootroot00000000000000centreon-plugins-20220113/apps/mq/rabbitmq/restapi/000077500000000000000000000000001417000230700220645ustar00rootroot00000000000000centreon-plugins-20220113/apps/mq/rabbitmq/restapi/custom/000077500000000000000000000000001417000230700233765ustar00rootroot00000000000000centreon-plugins-20220113/apps/mq/rabbitmq/restapi/custom/api.pm000066400000000000000000000133061417000230700245100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mq::rabbitmq::restapi::custom::api; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::http; use JSON::XS; 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'timeout:s' => { name => 'timeout' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'CUSTOM MODE OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 15672; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'http'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{username} = (defined($self->{option_results}->{username})) ? $self->{option_results}->{username} : undef; $self->{password} = (defined($self->{option_results}->{password})) ? $self->{option_results}->{password} : undef; if (!defined($self->{hostname}) || $self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --hostname option.'); $self->{output}->option_exit(); } return 0; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub get_port { my ($self, %options) = @_; return $self->{port}; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; if (defined($self->{username}) && $self->{username} ne '') { $self->{option_results}->{credentials} = 1; $self->{option_results}->{basic} = 1; $self->{option_results}->{username} = $self->{username}; $self->{option_results}->{password} = $self->{password}; } } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->set_options(%{$self->{option_results}}); } sub request { my ($self, %options) = @_; $self->settings(); $self->{output}->output_add(long_msg => "URL: '" . $self->{proto} . '://' . $self->{hostname} . ':' . $self->{port} . $options{url_path} . "'", debug => 1); $self->{output}->output_add(long_msg => "Parameters: '" . join(', ', @{$options{post_param}}) . "'", debug => 1) if (defined($options{post_param})); my $content = $self->{http}->request( %options, unknown_status => '%{http_code} < 200 or %{http_code} >= 300', critical_status => '', ); if (!defined($content) || $content eq '') { $self->{output}->add_option_msg(short_msg => "API returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->output_add(long_msg => $content, debug => 1); $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } return $decoded; } sub query { my ($self, %options) = @_; return $self->request(url_path => $options{url_path}); } 1; __END__ =head1 NAME RabbitMQ Rest API =head1 CUSTOM MODE OPTIONS RabbitMQ Rest API =over 8 =item B<--hostname> Remote hostname or IP address. =item B<--port> Port used (Default: 15672) =item B<--proto> Specify https if needed (Default: 'http') =item B<--username> Specify username for authentication =item B<--password> Specify password for authentication =item B<--timeout> Set timeout in seconds (Default: 10). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/mq/rabbitmq/restapi/mode/000077500000000000000000000000001417000230700230105ustar00rootroot00000000000000centreon-plugins-20220113/apps/mq/rabbitmq/restapi/mode/listnodes.pm000066400000000000000000000046241417000230700253600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mq::rabbitmq::restapi::mode::listnodes; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->query(url_path => '/api/nodes/?columns=name,running'); $self->{node} = {}; foreach (@$result) { $self->{node}->{$_->{name}} = { name => $_->{name}, status => $_->{running} ? 'running' : 'notrunning', }; } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach (sort keys %{$self->{node}}) { $self->{output}->output_add(long_msg => sprintf( "[name = %s][status = %s]", $self->{node}->{$_}->{name}, $self->{node}->{$_}->{status}) ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List nodes:' ); $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', 'status']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach (values %{$self->{node}}) { $self->{output}->add_disco_entry(%$_); } } 1; __END__ =head1 MODE List nodes. =over 8 =back =cut centreon-plugins-20220113/apps/mq/rabbitmq/restapi/mode/listqueues.pm000066400000000000000000000047531417000230700255620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mq::rabbitmq::restapi::mode::listqueues; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->query(url_path => '/api/queues/?columns=vhost,name,state'); $self->{queue} = {}; foreach (@$result) { $self->{queue}->{$_->{vhost} . ':' . $_->{name}} = { vhost => $_->{vhost}, name => $_->{name}, state => $_->{state}, }; } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach (sort keys %{$self->{queue}}) { $self->{output}->output_add(long_msg => sprintf( "[name = %s][vhost = %s][state = %s]", $self->{queue}->{$_}->{name}, $self->{queue}->{$_}->{vhost}, $self->{queue}->{$_}->{state}) ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List queues:' ); $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', 'vhost', 'state']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach (values %{$self->{queue}}) { $self->{output}->add_disco_entry(%$_); } } 1; __END__ =head1 MODE List queues. =over 8 =back =cut centreon-plugins-20220113/apps/mq/rabbitmq/restapi/mode/listvhosts.pm000066400000000000000000000050741417000230700255760ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mq::rabbitmq::restapi::mode::listvhosts; use base qw(centreon::plugins::mode); use strict; use warnings; use URI::Encode; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; my $uri = URI::Encode->new({encode_reserved => 1}); my $result = $options{custom}->query(url_path => '/api/vhosts/?columns=name'); $self->{vhost} = {}; foreach (@$result) { my $result_alive = $options{custom}->query(url_path => '/api/aliveness-test/' . $uri->encode($_->{name})); $self->{vhost}->{$_->{name}} = { name => $_->{name}, status => $result_alive->{status} }; } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach (sort keys %{$self->{vhost}}) { $self->{output}->output_add(long_msg => sprintf( "[name = %s][status = %s]", $self->{vhost}->{$_}->{name}, $self->{vhost}->{$_}->{status}) ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List vhosts:' ); $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', 'status']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach (values %{$self->{vhost}}) { $self->{output}->add_disco_entry(%$_); } } 1; __END__ =head1 MODE List vhosts. =over 8 =back =cut centreon-plugins-20220113/apps/mq/rabbitmq/restapi/mode/nodeusage.pm000066400000000000000000000124131417000230700253210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mq::rabbitmq::restapi::mode::nodeusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); sub custom_status_output { my ($self, %options) = @_; my $msg = "status: '" . $self->{result_values}->{status} . "'"; return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'node', type => 1, cb_prefix_output => 'prefix_node_output', message_multiple => 'All nodes are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{node} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'display' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold, } }, { label => 'read', nlabel => 'node.io.read.usage.bytespersecond', set => { key_values => [ { name => 'io_read_bytes', per_second => 1 }, { name => 'display' } ], output_template => 'read i/o : %s %s/s', output_change_bytes => 1, perfdatas => [ { template => '%d', unit => 'B/s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'write', nlabel => 'node.io.write.usage.bytespersecond', set => { key_values => [ { name => 'io_write_bytes', per_second => 1 }, { name => 'display' } ], output_template => 'write i/o : %s %s/s', output_change_bytes => 1, perfdatas => [ { template => '%d', unit => 'B/s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub prefix_node_output { my ($self, %options) = @_; return "Node '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{status} ne "running"' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->query(url_path => '/api/nodes/?columns=name,running,io_write_bytes,io_read_bytes'); $self->{node} = {}; foreach (@$result) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $_->{name} !~ /$self->{option_results}->{filter_name}/); $self->{node}->{$_->{name}} = { display => $_->{name}, io_write_bytes => $_->{io_write_bytes}, io_read_bytes => $_->{io_read_bytes}, status => $_->{running} ? 'running' : 'notrunning', }; } if (scalar(keys %{$self->{node}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No node found'); $self->{output}->option_exit(); } $self->{cache_name} = "rabbitmq_" . $self->{mode} . '_' . $options{custom}->get_hostname() . '_' . $options{custom}->get_port() . '_' . (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check node usage. =over 8 =item B<--filter-name> Filter node name (Can use regexp). =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{display} =item B<--critical-status> Set critical threshold for status (Default: '%{status} ne "running"'). Can used special variables like: %{status}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'read', 'write'. =back =cut centreon-plugins-20220113/apps/mq/rabbitmq/restapi/mode/queueusage.pm000066400000000000000000000125201417000230700255170ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mq::rabbitmq::restapi::mode::queueusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); sub custom_status_output { my ($self, %options) = @_; my $msg = "state: '" . $self->{result_values}->{state} . "'"; return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'queue', type => 1, cb_prefix_output => 'prefix_queue_output', message_multiple => 'All queues are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{queue} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'state' }, { name => 'display' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold, } }, { label => 'queue-msg', nlabel => 'queue.messages.count', set => { key_values => [ { name => 'queue_messages' }, { name => 'display' } ], output_template => 'current queue messages : %s', perfdatas => [ { label => 'queue_msg', value => 'queue_messages', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'queue-msg-ready', nlabel => 'queue.messages.ready.count', set => { key_values => [ { name => 'queue_messages_ready' }, { name => 'display' } ], output_template => 'current queue messages ready : %s', perfdatas => [ { label => 'queue_msg_ready', value => 'queue_messages_ready', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub prefix_queue_output { my ($self, %options) = @_; return "Queue '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{state} ne "running"' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->query(url_path => '/api/queues/?columns=vhost,name,state,messages,messages_ready'); $self->{queue} = {}; foreach (@$result) { my $name = $_->{vhost} . ':' . $_->{name}; next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $_->{name} !~ /$self->{option_results}->{filter_name}/); $self->{queue}->{$name} = { display => $name, queue_messages_ready => $_->{messages_ready}, queue_messages => $_->{messages}, state => $_->{state}, }; } if (scalar(keys %{$self->{queue}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No queue found'); $self->{output}->option_exit(); } $self->{cache_name} = "rabbitmq_" . $self->{mode} . '_' . $options{custom}->get_hostname() . '_' . $options{custom}->get_port() . '_' . (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check queue usage. =over 8 =item B<--filter-name> Filter queue name (Can use regexp). =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{state}, %{display} =item B<--critical-status> Set critical threshold for status (Default: '%{state} ne "running"'). Can used special variables like: %{state}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'queue-msg', 'queue-msg-ready'. =back =cut centreon-plugins-20220113/apps/mq/rabbitmq/restapi/mode/systemusage.pm000066400000000000000000000100701417000230700257150ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mq::rabbitmq::restapi::mode::systemusage; 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 => 'global', type => 0, skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ { label => 'queue-msg', nlabel => 'system.queue.messages.count', set => { key_values => [ { name => 'queue_messages' } ], output_template => 'current queue messages : %s', perfdatas => [ { template => '%d', min => 0 } ] } }, { label => 'queue-msg-ready', nlabel => 'system.queue.messages.ready.count', set => { key_values => [ { name => 'queue_messages_ready' } ], output_template => 'current queue messages ready : %s', perfdatas => [ { template => '%d', min => 0 } ] } }, { label => 'db-event-queue', nlabel => 'system.db.event.queue.count', set => { key_values => [ { name => 'db_event_queue' } ], output_template => 'db event queue : %s', perfdatas => [ { template => '%d', min => 0 } ] } }, { label => 'disk-read-iops', nlabel => 'system.disk.read.usage.iops', set => { key_values => [ { name => 'disk_reads', per_second => 1 } ], output_template => 'disk reads iops : %s', perfdatas => [ { template => '%d', unit => 'iops', min => 0 } ] } }, { label => 'disk-write-iops', nlabel => 'system.disk.write.usage.iops', set => { key_values => [ { name => 'disk_writes', per_second => 1 } ], output_template => 'disk writes iops : %s', perfdatas => [ { template => '%d', unit => 'iops', min => 0 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->query(url_path => '/api/overview'); $self->{global} = { disk_reads => $result->{message_stats}->{disk_reads}, disk_writes => $result->{message_stats}->{disk_writes}, queue_messages_ready => $result->{queue_totals}->{messages_ready}, queue_messages => $result->{queue_totals}->{messages}, db_event_queue => $result->{statistics_db_event_queue}, }; $self->{cache_name} = "rabbitmq_" . $self->{mode} . '_' . $options{custom}->get_hostname() . '_' . $options{custom}->get_port() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check global system statistics =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'disk-read-iops', 'disk-write-iops', 'queue-msg-ready', 'queue-msg', 'db-event-queue'. =back =cut centreon-plugins-20220113/apps/mq/rabbitmq/restapi/mode/vhostusage.pm000066400000000000000000000120301417000230700255320ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mq::rabbitmq::restapi::mode::vhostusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use URI::Encode; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); sub custom_status_output { my ($self, %options) = @_; my $msg = 'status: ' . $self->{result_values}->{status}; return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'vhost', type => 1, cb_prefix_output => 'prefix_vhost_output', message_multiple => 'All vhosts are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{vhost} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'display' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold, } }, { label => 'queue-msg', nlabel => 'vhost.queue.messages.count', set => { key_values => [ { name => 'queue_messages' }, { name => 'display' } ], output_template => 'current queue messages : %s', perfdatas => [ { label => 'queue_msg', value => 'queue_messages', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'queue-msg-ready', nlabel => 'vhost.queue.messages.ready.count', set => { key_values => [ { name => 'queue_messages_ready' }, { name => 'display' } ], output_template => 'current queue messages ready : %s', perfdatas => [ { label => 'queue_msg_ready', value => 'queue_messages_ready', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub prefix_vhost_output { my ($self, %options) = @_; return "Vhost '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{status} ne "ok"' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->query(url_path => '/api/vhosts'); my $uri = URI::Encode->new({encode_reserved => 1}); $self->{vhost} = {}; foreach (@$result) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $_->{name} !~ /$self->{option_results}->{filter_name}/); my $result_alive = $options{custom}->query(url_path => '/api/aliveness-test/' . $uri->encode($_->{name})); $self->{vhost}->{$_->{name}} = { display => $_->{name}, queue_messages_ready => $_->{messages_ready}, queue_messages => $_->{messages}, status => $result_alive->{status} }; } if (scalar(keys %{$self->{vhost}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No vhost found'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check vhost usage. =over 8 =item B<--filter-name> Filter vhost name (Can use regexp). =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{display} =item B<--critical-status> Set critical threshold for status (Default: '%{status} ne "ok"'). Can used special variables like: %{status}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'queue-msg-ready', 'queue-msg'. =back =cut centreon-plugins-20220113/apps/mq/rabbitmq/restapi/plugin.pm000066400000000000000000000034221417000230700237210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mq::rabbitmq::restapi::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} = '1.0'; %{$self->{modes}} = ( 'list-nodes' => 'apps::mq::rabbitmq::restapi::mode::listnodes', 'list-queues' => 'apps::mq::rabbitmq::restapi::mode::listqueues', 'list-vhosts' => 'apps::mq::rabbitmq::restapi::mode::listvhosts', 'node-usage' => 'apps::mq::rabbitmq::restapi::mode::nodeusage', 'queue-usage' => 'apps::mq::rabbitmq::restapi::mode::queueusage', 'system-usage' => 'apps::mq::rabbitmq::restapi::mode::systemusage', 'vhost-usage' => 'apps::mq::rabbitmq::restapi::mode::vhostusage', ); $self->{custom_modes}{api} = 'apps::mq::rabbitmq::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check RabbitMQ with Rest API. =cut centreon-plugins-20220113/apps/mq/vernemq/000077500000000000000000000000001417000230700202715ustar00rootroot00000000000000centreon-plugins-20220113/apps/mq/vernemq/restapi/000077500000000000000000000000001417000230700217405ustar00rootroot00000000000000centreon-plugins-20220113/apps/mq/vernemq/restapi/custom/000077500000000000000000000000001417000230700232525ustar00rootroot00000000000000centreon-plugins-20220113/apps/mq/vernemq/restapi/custom/api.pm000066400000000000000000000137221417000230700243660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mq::vernemq::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use JSON::XS; 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 => { 'api-key:s' => { name => 'api_key' }, 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'timeout:s' => { name => 'timeout' }, 'unknown-http-status:s' => { name => 'unknown_http_status' }, 'warning-http-status:s' => { name => 'warning_http_status' }, 'critical-http-status:s' => { name => 'critical_http_status' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 8888; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'http'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{api_key} = (defined($self->{option_results}->{api_key})) ? $self->{option_results}->{api_key} : undef; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300'; $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; if (!defined($self->{hostname}) || $self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } if (!defined($self->{api_key}) || $self->{api_key} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-key option."); $self->{output}->option_exit(); } return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{api_key} . '@' . $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; } sub settings { my ($self, %options) = @_; return if (defined($self->{settings_done})); $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->add_header(key => 'Content-Type', value => 'application/json'); $self->{http}->set_options(%{$self->{option_results}}); $self->{settings_done} = 1; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub get_port { my ($self, %options) = @_; return $self->{port}; } sub request_api { my ($self, %options) = @_; $self->settings(); my $content = $self->{http}->request( method => defined($options{method}) ? $options{method} : 'GET', url_path => '/api/v1' . $options{endpoint}, unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status} ); if (!defined($content) || $content eq '') { $self->{output}->add_option_msg(short_msg => "API returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } return $decoded; } 1; __END__ =head1 NAME VerneMQ Rest API =head1 REST API OPTIONS VerneMQ Rest API =over 8 =item B<--hostname> Set hostname. =item B<--port> Port used (Default: 8888) =item B<--proto> Specify https if needed (Default: 'http') =item B<--api-key> VerneMQ API Token. =item B<--timeout> Set timeout in seconds (Default: 10). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/mq/vernemq/restapi/mode/000077500000000000000000000000001417000230700226645ustar00rootroot00000000000000centreon-plugins-20220113/apps/mq/vernemq/restapi/mode/clusters.pm000066400000000000000000000121201417000230700250620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mq::vernemq::restapi::mode::clusters; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); sub custom_status_output { my ($self, %options) = @_; return 'status: ' . $self->{result_values}->{status}; } sub prefix_cluster_output { my ($self, %options) = @_; return "Cluster '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'clusters', type => 1, cb_prefix_output => 'prefix_cluster_output', message_multiple => 'All clusters are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ { label => 'running', nlabel => 'clusters.running.count', display_ok => 0, set => { key_values => [ { name => 'running' } ], output_template => 'current clusters running: %s', perfdatas => [ { value => 'running', template => '%s', min => 0 } ] } }, { label => 'notrunning', nlabel => 'clusters.notrunning.count', display_ok => 0, set => { key_values => [ { name => 'notrunning' } ], output_template => 'current clusters not running: %s', perfdatas => [ { value => 'notrunning', template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{clusters} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'display' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_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 => { 'filter-name:s' => { name => 'filter_name' }, 'unknown-status:s' => { name => 'unknown_status', default => '' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{status} eq "notRunning"' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status', 'unknown_status']); } sub manage_selection { my ($self, %options) = @_; my $clusters = $options{custom}->request_api(endpoint => '/cluster/show'); $self->{global} = { running => 0, notrunning => 0 }; $self->{clusters} = {}; foreach (@{$clusters->{table}}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $_->{Node} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping cluster '" . $_->{Node} . "': no matching filter.", debug => 1); next; } $_->{Running} ? $self->{global}->{running}++ : $self->{global}->{notrunning}++; $self->{clusters}->{$_->{Node}} = { display => $_->{Node}, status => $_->{Running} ? 'running' : 'notRunning' }; } if (scalar(keys %{$self->{clusters}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No cluster found"); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check clusters. =over 8 =item B<--filter-name> Filter cluster name (can be a regexp). =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{status}, %{display} =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 (Default: '%{status} eq "notRunning"'). Can used special variables like: %{status}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'running', 'notrunning'. =back =cut centreon-plugins-20220113/apps/mq/vernemq/restapi/mode/listeners.pm000066400000000000000000000121221417000230700252300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mq::vernemq::restapi::mode::listeners; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); sub custom_status_output { my ($self, %options) = @_; return 'status: ' . $self->{result_values}->{status}; } sub prefix_listener_output { my ($self, %options) = @_; return "Listener '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'listeners', type => 1, cb_prefix_output => 'prefix_listener_output', message_multiple => 'All listeners are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ { label => 'running', nlabel => 'listeners.running.count', display_ok => 0, set => { key_values => [ { name => 'running' } ], output_template => 'current listeners running: %s', perfdatas => [ { value => 'running', template => '%s', min => 0 } ] } }, { label => 'notrunning', nlabel => 'listeners.notrunning.count', display_ok => 0, set => { key_values => [ { name => 'notrunning' } ], output_template => 'current listeners not running: %s', perfdatas => [ { value => 'notrunning', template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{listeners} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'display' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_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 => { 'filter-type:s' => { name => 'filter_type' }, 'unknown-status:s' => { name => 'unknown_status', default => '' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{status} ne "running"' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status', 'unknown_status']); } sub manage_selection { my ($self, %options) = @_; my $clusters = $options{custom}->request_api(endpoint => '/listener/show'); $self->{global} = { running => 0, notrunning => 0 }; $self->{listeners} = {}; foreach (@{$clusters->{table}}) { if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' && $_->{type} !~ /$self->{option_results}->{filter_type}/) { $self->{output}->output_add(long_msg => "skipping listeners '" . $_->{type} . "': no matching filter.", debug => 1); next; } $_->{status} eq 'running' ? $self->{global}->{running}++ : $self->{global}->{notrunning}++; $self->{listeners}->{$_->{type}} = { display => $_->{type}, status => $_->{status} }; } if (scalar(keys %{$self->{listeners}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No listener found"); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check listeners. =over 8 =item B<--filter-type> Filter listener type (can be a regexp). =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{status}, %{display} =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 (Default: '%{status} ne "running"'). Can used special variables like: %{status}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'running', 'notrunning'. =back =cut centreon-plugins-20220113/apps/mq/vernemq/restapi/mode/plugins.pm000066400000000000000000000050751417000230700247120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mq::vernemq::restapi::mode::plugins; 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, skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'total', nlabel => 'plugins.total.count', set => { key_values => [ { name => 'total' } ], output_template => 'current total plugins: %s', perfdatas => [ { value => 'total', template => '%s', min => 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-name:s' => { name => 'filter_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $plugins = $options{custom}->request_api( endpoint => '/plugin/show' ); $self->{global} = { total => 0 }; foreach (@{$plugins->{table}}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $_->{Plugin} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping plugin '" . $_->{Plugin} . "': no matching filter.", debug => 1); next; } $self->{output}->output_add(long_msg => "plugin '" . $_->{Plugin} . "'"); $self->{global}->{total}++; } } 1; __END__ =head1 MODE Check plugins. =over 8 =item B<--filter-name> Filter plugin name (can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'total'. =back =cut centreon-plugins-20220113/apps/mq/vernemq/restapi/mode/sessions.pm000066400000000000000000000050741417000230700250760ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mq::vernemq::restapi::mode::sessions; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_session_output { my ($self, %options) = @_; return 'Sessions '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_session_output', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'online', nlabel => 'sessions.online.count', set => { key_values => [ { name => 'online' } ], output_template => 'current online: %s', perfdatas => [ { value => 'online', template => '%s', min => 0 } ] } }, { label => 'total', nlabel => 'sessions.total.count', set => { key_values => [ { name => 'total' } ], output_template => 'current total: %s', perfdatas => [ { value => 'total', template => '%s', min => 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 => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $sessions = $options{custom}->request_api( endpoint => '/session/show' ); $self->{global} = { total => 0, online => 0 }; foreach (@{$sessions->{table}}) { $self->{global}->{online}++ if ($_->{is_online}); $self->{global}->{total}++; } } 1; __END__ =head1 MODE Check sessions. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'total', 'online'. =back =cut centreon-plugins-20220113/apps/mq/vernemq/restapi/plugin.pm000066400000000000000000000027741417000230700236060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mq::vernemq::restapi::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} } = ( 'clusters' => 'apps::mq::vernemq::restapi::mode::clusters', 'listeners' => 'apps::mq::vernemq::restapi::mode::listeners', 'plugins' => 'apps::mq::vernemq::restapi::mode::plugins', 'sessions' => 'apps::mq::vernemq::restapi::mode::sessions' ); $self->{custom_modes}{api} = 'apps::mq::vernemq::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check VerneMQ using Rest API. =cut centreon-plugins-20220113/apps/mulesoft/000077500000000000000000000000001417000230700200355ustar00rootroot00000000000000centreon-plugins-20220113/apps/mulesoft/restapi/000077500000000000000000000000001417000230700215045ustar00rootroot00000000000000centreon-plugins-20220113/apps/mulesoft/restapi/custom/000077500000000000000000000000001417000230700230165ustar00rootroot00000000000000centreon-plugins-20220113/apps/mulesoft/restapi/custom/api.pm000066400000000000000000000302431417000230700241270ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mulesoft::restapi::custom::api; use strict; use warnings; use DateTime; use centreon::plugins::http; use centreon::plugins::statefile; use JSON::XS; use URI::Encode; use Digest::MD5 qw(md5_hex); 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 => { 'api-username:s' => { name => 'api_username' }, 'api-password:s' => { name => 'api_password' }, 'environment-id:s' => { name => 'environment_id' }, 'organization-id:s' => { name => 'organization_id' }, 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'timeout:s' => { name => 'timeout' }, 'reload-cache-time:s' => { name => 'reload_cache_time' }, 'authent-endpoint:s' => { name => 'authent_endpoint' }, 'monitoring-endpoint:s' => { name => 'monitoring_endpoint' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); $self->{cache} = centreon::plugins::statefile->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : 'eu1.anypoint.mulesoft.com'; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{authent_endpoint} = (defined($self->{option_results}->{authent_endpoint})) ? $self->{option_results}->{authent_endpoint} : '/accounts/login'; $self->{monitoring_endpoint}->{arm} = (defined($self->{option_results}->{monitoring_endpoint})) ? $self->{option_results}->{monitoring_endpoint} : '/hybrid/api/v1'; $self->{monitoring_endpoint}->{mq_admin} = (defined($self->{option_results}->{monitoring_endpoint})) ? $self->{option_results}->{monitoring_endpoint} : '/mq/admin/api/v1'; $self->{monitoring_endpoint}->{mq_stats} = (defined($self->{option_results}->{monitoring_endpoint})) ? $self->{option_results}->{monitoring_endpoint} : '/mq/stats/api/v1'; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : ''; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : ''; $self->{environment_id} = (defined($self->{option_results}->{environment_id})) ? $self->{option_results}->{environment_id} : ''; $self->{organization_id} = (defined($self->{option_results}->{organization_id})) ? $self->{option_results}->{organization_id} : ''; $self->{reload_cache_time} = (defined($self->{option_results}->{reload_cache_time})) ? $self->{option_results}->{reload_cache_time} : 180; $self->{cache}->check_options(option_results => $self->{option_results}); if ($self->{environment_id} eq '' || $self->{organization_id} eq '' ) { $self->{output}->add_option_msg(short_msg => "--environment-id and --organization-id must be set"); $self->{output}->option_exit(); } if ($self->{api_username} eq '' || $self->{api_password} eq '' ) { $self->{output}->add_option_msg(short_msg => "--api-username and --api-password must be set"); $self->{output}->option_exit(); } return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{warning_status} = ''; $self->{option_results}->{critical_status} = ''; $self->{option_results}->{unknown_status} = '%{http_code} < 200 or %{http_code} > 400'; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->add_header(key => 'Authorization', value => 'Bearer ' . $self->{access_token}) if (defined($self->{access_token})); $self->{http}->add_header(key => 'X-ANYPNT-ENV-ID', value => $self->{environment_id}) if (defined $options{environment_header}); $self->{http}->add_header(key => 'X-ANYPNT-ORG-ID', value => $self->{organization_id}) if (defined $options{organization_header}); $self->{http}->set_options(%{$self->{option_results}}); } sub get_access_token { my ($self, %options) = @_; my $has_cache_file = $options{statefile}->read(statefile => 'mulesoft_api_' . md5_hex($self->{hostname}) . '_' . md5_hex($self->{api_username})); my $expires_on = $options{statefile}->get(name => 'expires_on'); my $access_token = $options{statefile}->get(name => 'access_token'); if ( $has_cache_file == 0 || !defined($access_token) || (($expires_on - time()) < 10) ) { my $login = { username => $self->{api_username}, password => $self->{api_password} }; my $post_json = JSON::XS->new->utf8->encode($login); $self->settings(); my $content = $self->{http}->request( method => 'POST', header => ['Content-type: application/json'], query_form_post => $post_json, url_path => $self->{authent_endpoint} ); if (!defined($content) || $content eq '') { $self->{output}->add_option_msg(short_msg => "Authentication endpoint returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->output_add(long_msg => $content, debug => 1); $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } if (defined($decoded->{error_code})) { $self->{output}->output_add(long_msg => "Error message : " . $decoded->{error}, debug => 1); $self->{output}->add_option_msg(short_msg => "Authentication endpoint returns error code '" . $decoded->{error_code} . "' (add --debug option for detailed message)"); $self->{output}->option_exit(); } $access_token = $decoded->{access_token}; my $datas = { last_timestamp => time(), access_token => $decoded->{access_token}, expires_on => time() + 3600 }; $options{statefile}->write(data => $datas); } return $access_token; } sub request_api { my ($self, %options) = @_; if (!defined($self->{access_token})) { $self->{access_token} = $self->get_access_token(statefile => $self->{cache}); } $self->settings(environment_header => 1, organization_header => 1); my $content = $self->{http}->request(%options); if (!defined($content) || $content eq '') { $self->{output}->add_option_msg(short_msg => "API returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } return $decoded; } sub list_objects { my ($self, %options) = @_; if ($options{api_type} eq 'arm') { my $url_path = $self->{monitoring_endpoint}->{arm} . $options{endpoint}; my $response = $self->request_api(method => 'GET', url_path => $url_path); return $response->{data}; }; if ($options{api_type} eq 'mq') { my $url_path = $self->{monitoring_endpoint}->{mq_admin} . '/organizations/' . $self->{organization_id} . '/environments/' . $self->{environment_id} . '/regions/' . $options{region_id} . $options{endpoint}; my $response = $self->request_api(method => 'GET', url_path => $url_path); return $response; }; } sub get_objects_status { my ($self, %options) = @_; if ($options{api_type} eq 'arm') { my $url_path = $self->{monitoring_endpoint}->{arm} . $options{endpoint} . $options{object_id}; my $response = $self->request_api(method => 'GET', url_path => $url_path); return $response->{data}; }; if ($options{api_type} eq 'mq') { my $url_path = $self->{monitoring_endpoint}->{mq_stats} . '/organizations/' . $self->{organization_id} . '/environments/' . $self->{environment_id} . '/regions/' . $options{region_id} . $options{endpoint} . '/' . $options{object_id}; my $response = $self->request_api(method => 'GET', url_path => $url_path, get_param => $options{get_param}); return $response; }; } sub cache_hosts { my ($self, %options) = @_; $self->{cache_hosts} = centreon::plugins::statefile->new(%options); $self->{cache_hosts}->check_options(option_results => $self->{option_results}); my $has_cache_file = $self->{cache_hosts}->read(statefile => 'cache_ovirt_hosts_' . md5_hex($self->{hostname}) . '_' . md5_hex($self->{api_username})); my $timestamp_cache = $self->{cache_hosts}->get(name => 'last_timestamp'); my $hosts = $self->{cache_hosts}->get(name => 'hosts'); if ($has_cache_file == 0 || !defined($timestamp_cache) || ((time() - $timestamp_cache) > (($self->{reload_cache_time}) * 60))) { $hosts = []; my $datas = { last_timestamp => time(), hosts => $hosts }; my $list = $self->list_hosts(); foreach (@{$list}) { push @{$hosts}, { id => $_->{id}, name => $_->{name} }; } $self->{cache_hosts}->write(data => $datas); } return $hosts; } 1; __END__ =head1 NAME Mulesoft Rest API =head1 REST API OPTIONS Mulesoft Rest API =over 8 =item B<--hostname> Mulesoft API hostname (Default: anypoint.mulesoft.com). =item B<--port> Port used (Default: 443) =item B<--proto> Specify https if needed (Default: 'https') =item B<--api-username> Mulesoft API username (mandatory). =item B<--api-password> Mulesoft API password (mandatory). =item B<--environment-id> Mulesoft API Environment ID (mandatory). =item B<--organization-id> Mulesoft API Organization ID (mandatory). =item B<--timeout> Set timeout in seconds (Default: 10). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/mulesoft/restapi/mode/000077500000000000000000000000001417000230700224305ustar00rootroot00000000000000centreon-plugins-20220113/apps/mulesoft/restapi/mode/applications.pm000066400000000000000000000144071417000230700254620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mulesoft::restapi::mode::applications; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; return sprintf('Id: %s, Status: %s', $self->{result_values}->{id}, $self->{result_values}->{status}); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }, { name => 'applications', type => 1, cb_prefix_output => 'prefix_application_output', message_multiple => 'All applications are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'total', nlabel => 'mulesoft.applications.total.count', set => { key_values => [ { name => 'total' } ], output_template => "Total : %s", perfdatas => [ { template => '%d', min => 0 } ] } }, { label => 'started', nlabel => 'mulesoft.applications.status.started.count', set => { key_values => [ { name => 'started' } ], output_template => "Started : %s", perfdatas => [ { template => '%d', min => 0 } ] } }, { label => 'stopped', nlabel => 'mulesoft.applications.status.stopped.count', set => { key_values => [ { name => 'stopped' } ], output_template => "Stopped : %s", perfdatas => [ { template => '%d', min => 0 } ] } }, { label => 'failed', nlabel => 'mulesoft.applications.status.failed.count', set => { key_values => [ { name => 'failed' } ], output_template => "Failed : %s", perfdatas => [ { template => '%d', min => 0 } ] } } ]; $self->{maps_counters}->{applications} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'id' }, { name => 'status' }, { name => 'name'}, { name => 'display' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_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 => { '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); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub prefix_global_output { my ($self, %options) = @_; return "Total applications "; } sub prefix_application_output { my ($self, %options) = @_; return "Application '" . $options{instance_value}->{name} . "' "; } sub manage_selection { my ($self, %options) = @_; $self->{global} = { started => 0, stopped => 0, failed => 0 }; $self->{applications} = {}; my $result = $options{custom}->list_objects(api_type => 'arm', endpoint => '/applications'); foreach ('started', 'stopped', 'failed') { $self->{global}->{$_} = 0; }; foreach my $application (@{$result}) { next if ( defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $application->{name} !~ /$self->{option_results}->{filter_name}/ ); $self->{applications}->{$application} = { display => $application, id => $application->{id}, name => $application->{name}, status => $application->{lastReportedStatus}, }; $self->{global}->{started}++ if $application->{lastReportedStatus} =~ m/STARTED/; $self->{global}->{stopped}++ if $application->{lastReportedStatus} =~ m/STOPPED/; $self->{global}->{failed}++ if $application->{lastReportedStatus} =~ m/FAILED/; } if (scalar(keys %{$self->{applications}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No application found."); $self->{output}->option_exit(); } $self->{global}->{total} = scalar (keys %{$self->{applications}}); } 1; __END__ =head1 MODE Check Mulesoft Anypoint Applications status. Example: perl centreon_plugins.pl --plugin=apps::mulesoft::restapi::plugin --mode=applications --environment-id='1234abc-56de-78fg-90hi-1234abcdefg' --organization-id='1234abcd-56ef-78fg-90hi-1234abcdefg' --api-username='myapiuser' --api-password='myapipassword' --verbose More information on'https://anypoint.mulesoft.com/exchange/portals/anypoint-platform/'. =over 8 =item B<--filter-name> Filter by application name (Regexp can be used). Example: --filter-name='^application1$' =item B<--warning-status> Set warning threshold for status (Default: ''). Threshold can be matched on %{name}, %{id} or %{status} and Regexp can be used. Typical syntax: --warning-status='%{status} ne "STARTED"' =item B<--critical-status> Set warning threshold for status (Default: ''). Threshold can be matched on %{name}, %{id} or %{status} and Regexp can be used. Typical syntax: --critical-status='%{status} =~ m/FAILED/' =back =cut centreon-plugins-20220113/apps/mulesoft/restapi/mode/clusters.pm000066400000000000000000000134201417000230700246320ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and cluster 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::mulesoft::restapi::mode::clusters; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; return my $msg = sprintf('Id: %s, Status: %s', $self->{result_values}->{id}, $self->{result_values}->{status}); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }, { name => 'clusters', type => 1, cb_prefix_output => 'prefix_cluster_output', message_multiple => 'All clusters are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'total', nlabel => 'mulesoft.clusters.total.count', set => { key_values => [ { name => 'total' } ], output_template => "Total : %s", perfdatas => [ { template => '%d', min => 0 } ] } }, { label => 'running', nlabel => 'mulesoft.clusters.status.running.count', set => { key_values => [ { name => 'running' } ], output_template => "Running : %s", perfdatas => [ { template => '%d', min => 0 } ] } }, { label => 'disconnected', nlabel => 'mulesoft.clusters.status.disconnected.count', set => { key_values => [ { name => 'disconnected' } ], output_template => "Disconnected : %s", perfdatas => [ { template => '%d', min => 0 } ] } } ]; $self->{maps_counters}->{clusters} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'id' }, { name => 'status' }, { name => 'name'}, { name => 'display' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_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 => { '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); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub prefix_global_output { my ($self, %options) = @_; return "Total clusters "; } sub prefix_cluster_output { my ($self, %options) = @_; return "cluster '" . $options{instance_value}->{name} . "' "; } sub manage_selection { my ($self, %options) = @_; $self->{global} = { started => 0, stopped => 0, failed => 0 }; $self->{clusters} = {}; my $result = $options{custom}->list_objects(api_type => 'arm', endpoint => '/clusters'); foreach ('running', 'disconnected') { $self->{global}->{$_} = 0; }; foreach my $cluster (@{$result}) { next if ( defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $cluster->{name} !~ /$self->{option_results}->{filter_name}/ ); $self->{clusters}->{$cluster} = { display => $cluster, id => $cluster->{id}, name => $cluster->{name}, status => $cluster->{status}, }; $self->{global}->{running}++ if $cluster->{status} =~ m/RUNNING/; $self->{global}->{disconnected}++ if $cluster->{status} =~ m/DISCONNECTED/; } if (scalar(keys %{$self->{clusters}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No cluster found."); $self->{output}->option_exit(); } $self->{global}->{total} = scalar (keys %{$self->{clusters}}); } 1; __END__ =head1 MODE Check Mulesoft Anypoint clusters status. Example: perl centreon_plugins.pl --plugin=apps::mulesoft::restapi::plugin --mode=clusters --environment-id='1234abc-56de-78fg-90hi-1234abcdefg' --organization-id='1234abcd-56ef-78fg-90hi-1234abcdefg' --api-username='myapiuser' --api-password='myapipassword' --verbose More information on'https://anypoint.mulesoft.com/exchange/portals/anypoint-platform/'. =over 8 =item B<--filter-name> Filter by cluster name (Regexp can be used). Example: --filter-name='^cluster1$' =item B<--warning-status> Set warning threshold for status (Default: ''). Threshold can be matched on %{name}, %{id} or %{status} and Regexp can be used. Typical syntax: --warning-status='%{status} ne "RUNNING"' =item B<--critical-status> Set warning threshold for status (Default: ''). Threshold can be matched on %{name}, %{id} or %{status} and Regexp can be used. Typical syntax: --critical-status='%{status} =~ m/DISCONNECTED/' =back =cut centreon-plugins-20220113/apps/mulesoft/restapi/mode/listapplications.pm000066400000000000000000000056661417000230700263650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mulesoft::restapi::mode::listapplications; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my $result = $options{custom}->list_objects(api_type => 'arm', endpoint => '/applications'); foreach my $application (@{$result}) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $application->{name} !~ /$self->{option_results}->{filter_name}/); $self->{output}->output_add( long_msg => sprintf( "[id = %s][name = %s][status = %s]", $application->{id}, $application->{name}, $application->{lastReportedStatus} ) ); } $self->{output}->output_add(severity => 'OK', short_msg => 'Mulesoft Anypoint Applications:'); $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 => ['id', 'name', 'status']); } sub disco_show { my ($self, %options) = @_; my $result = $options{custom}->list_objects(api_type => 'arm', endpoint => '/applications'); foreach my $application (@{$result}) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $application->{name} !~ /$self->{option_results}->{filter_name}/); $self->{output}->add_disco_entry( id => $application->{id}, name => $application->{name}, status => $application->{lastReportedStatus}, ); } } 1; __END__ =head1 MODE List Mulesoft Anypoint applications. =over 8 =item B<--filter-name> Filter application name (Can be a regexp). =back =cut centreon-plugins-20220113/apps/mulesoft/restapi/mode/listqueues.pm000066400000000000000000000063361417000230700252010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mulesoft::restapi::mode::listqueues; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'region-id:s' => { name => 'region_id' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{region_id}) || $self->{option_results}->{region_id} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --region-id option."); $self->{output}->option_exit(); } } sub run { my ($self, %options) = @_; my $result = $options{custom}->list_objects( api_type => 'mq', endpoint => '/destinations', region_id => $self->{option_results}->{region_id}, ); foreach my $queue (@{$result}) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $queue->{queueId} !~ /$self->{option_results}->{filter_name}/); $self->{output}->output_add( long_msg => sprintf( "[name = %s]", $queue->{queueId} ) ); } $self->{output}->output_add(severity => 'OK', short_msg => 'Mulesoft Anypoint Message Qeues:'); $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) = @_; my $result = $options{custom}->list_objects( api_type => 'mq', endpoint => '/destinations', region_id => $self->{option_results}->{region_id}, ); foreach my $queue (@{$result}) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $queue->{queueId} !~ /$self->{option_results}->{filter_name}/); $self->{output}->add_disco_entry(name => $queue->{queueId}); } } 1; __END__ =head1 MODE List Mulesoft Anypoint Messages Queues. =over 8 =item B<--filter-name> Filter on queue name (Can be a regexp). =item B<--region-id> Specify the queue region ID (Mandatory). Example: --region-id='eu-central-1' =back =cut centreon-plugins-20220113/apps/mulesoft/restapi/mode/listservers.pm000066400000000000000000000055071417000230700253620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and server 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::mulesoft::restapi::mode::listservers; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my $result = $options{custom}->list_objects(api_type => 'arm', endpoint => '/servers'); foreach my $server (@{$result}) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $server->{name} !~ /$self->{option_results}->{filter_name}/); $self->{output}->output_add( long_msg => sprintf( "[id = %s][name = %s][status = %s]", $server->{id}, $server->{name}, $server->{status} ) ); } $self->{output}->output_add(severity => 'OK', short_msg => 'Mulesoft Anypoint 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 => ['id', 'name', 'status']); } sub disco_show { my ($self, %options) = @_; my $result = $options{custom}->list_objects(api_type => 'arm', endpoint => '/servers'); foreach my $server (@{$result}) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $server->{name} !~ /$self->{option_results}->{filter_name}/); $self->{output}->add_disco_entry( id => $server->{id}, name => $server->{name}, status => $server->{status}, ); } } 1; __END__ =head1 MODE List Mulesoft Anypoint Servers. =over 8 =item B<--filter-name> Filter server name (Can be a regexp). =back =cut centreon-plugins-20220113/apps/mulesoft/restapi/mode/messages.pm000066400000000000000000000202661417000230700246030ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mulesoft::restapi::mode::messages; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use POSIX; use base qw(centreon::plugins::templates::counter); sub prefix_queue_output { my ($self, %options) = @_; return "Queue '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'queues', type => 1, cb_prefix_output => 'prefix_queue_output', message_multiple => 'All queues are ok' } ]; $self->{maps_counters}->{queues} = [ { label => 'total', nlabel => 'mulesoft.mq.messages.total.count', set => { key_values => [ { name => 'total' }, { name => 'display' } ], output_template => 'total: %s', perfdatas => [ { template => '%d', min => 0, cast_int => 1, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'inflight', nlabel => 'mulesoft.mq.inflight.count', set => { key_values => [ { name => 'inflight' }, { name => 'display' } ], output_template => 'inflight: %s', perfdatas => [ { template => '%d', min => 0, cast_int => 1, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'received', nlabel => 'mulesoft.mq.received.count', set => { key_values => [ { name => 'received' }, { name => 'display' } ], output_template => 'received: %s', perfdatas => [ { template => '%d', min => 0, cast_int => 1, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'sent', nlabel => 'mulesoft.mq.sent.count', set => { key_values => [ { name => 'sent' }, { name => 'display' } ], output_template => 'sent: %s', perfdatas => [ { template => '%d', min => 0, cast_int => 1, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'visible', nlabel => 'mulesoft.mq.visible.count', set => { key_values => [ { name => 'visible' }, { name => 'display' } ], output_template => 'visible: %s', perfdatas => [ { template => '%d', min => 0, cast_int => 1, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'acked', nlabel => 'mulesoft.mq.acked.count', set => { key_values => [ { name => 'acked' }, { name => 'display' } ], output_template => 'acked: %s', perfdatas => [ { template => '%d', min => 0, cast_int => 1, label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'region-id:s' => { name => 'region_id' }, 'timeframe:s' => { name => 'timeframe', default => '600' }, 'period:s' => { name => 'period', default => '60' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{region_id}) || $self->{option_results}->{region_id} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --region-id option."); $self->{output}->option_exit(); } } sub manage_selection { my ($self, %options) = @_; POSIX::setlocale(LC_ALL, "C"); my $time = time(); my $end_time = POSIX::strftime('%a, %d %b %Y %H:%M:%S', gmtime()) . ' GMT'; my $start_time = POSIX::strftime('%a, %d %b %Y %H:%M:%S', gmtime($time - $self->{option_results}->{timeframe})) . ' GMT'; my $destinations = $options{custom}->list_objects( api_type => 'mq', endpoint => '/destinations', region_id => $self->{option_results}->{region_id}, ); my $get_param = [ 'startDate=' . $start_time, 'endDate=' . $end_time, 'period=' . $self->{option_results}->{period} ]; foreach my $queue (@{$destinations}) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $queue->{queueId} !~ /$self->{option_results}->{filter_name}/ ); my $queue_stats = $options{custom}->get_objects_status( api_type => 'mq', endpoint => '/queues', region_id => $self->{option_results}->{region_id}, object_id => $queue->{queueId}, get_param => $get_param ); my $message_type = {}; my $total_value; foreach my $message_type (keys %$queue_stats) { next if ($message_type =~ 'destination'); foreach my $values (@{$queue_stats->{$message_type}} ) { push @{$self->{raw_results}->{$queue->{queueId}}->{$message_type}}, $values->{value}; $total_value += $values->{value}; } if ($self->{raw_results}->{$queue->{queueId}}->{$message_type}) { my $points = scalar(@{$self->{raw_results}->{$queue->{queueId}}->{$message_type}}); $self->{raw_results}->{$queue->{queueId}}{$message_type} = $total_value / $points; } } $self->{queues}->{$queue->{queueId}} = { display => $queue->{queueId}, total => $self->{raw_results}->{$queue->{queueId}}{messages}, inflight => $self->{raw_results}->{$queue->{queueId}}{inflightMessages}, received => $self->{raw_results}->{$queue->{queueId}}{messagesReceived}, sent => $self->{raw_results}->{$queue->{queueId}}{messagesSent}, visible => $self->{raw_results}->{$queue->{queueId}}{messagesVisible}, acked => $self->{raw_results}->{$queue->{queueId}}{messagesAcked} } } if (scalar(keys %{$self->{queues}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No queues found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check Mulesoft Messages Queues (MQ). Example: perl centreon_plugins.pl --plugin=apps::mulesoft::restapi::plugin --mode=messages --environment-id='1234abc-56de-78fg-90hi-1234abcdefg' --organization-id='1234abcd-56ef-78fg-90hi-1234abcdefg' --api-username='myapiuser' --api-password='myapipassword' --warning-total=900 --critical-total=1000 --verbose More information on 'https://anypoint.mulesoft.com/exchange/portals/anypoint-platform/f1e97bc6-315a-4490-82a7-23abe036327a.anypoint-platform/anypoint-mq-stats/'. =over 8 =item B<--filter-name> Filter by queue name (Regexp can be used). Example: --filter-name='^mymessagequeue1$' =item B<--region-id> Specify the queue region ID (Mandatory). Example: --region-id='eu-central-1' =item B<--timeframe> Specify the time window in seconds on which to collect the data. Default: 600 (5 min) =item B<--period> Specify the data granularity in seconds. Default: 60 (1 value/minute) =item B<--warning-*> Warning threshold for queue messages count, by message type where * can be: total, inflight, received, sent, visible, acked. =item B<--critical-*> Critical threshold for queue messages count, by message type where * can be: total, inflight, received, sent, visible, acked. =back =cut centreon-plugins-20220113/apps/mulesoft/restapi/mode/servers.pm000066400000000000000000000133321417000230700244610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and server 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::mulesoft::restapi::mode::servers; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; return sprintf('Id: %s, Status: %s', $self->{result_values}->{id}, $self->{result_values}->{status}); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }, { name => 'servers', type => 1, cb_prefix_output => 'prefix_server_output', message_multiple => 'All servers are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'total', nlabel => 'mulesoft.servers.total.count', set => { key_values => [ { name => 'total' } ], output_template => '%s', perfdatas => [ { template => '%d', min => 0 } ] } }, { label => 'running', nlabel => 'mulesoft.servers.status.running.count', set => { key_values => [ { name => 'running' } ], output_template => 'running : %s', perfdatas => [ { template => '%d', min => 0 } ] } }, { label => 'disconnected', nlabel => 'mulesoft.servers.status.disconnected.count', set => { key_values => [ { name => 'disconnected' } ], output_template => 'disconnected : %s', perfdatas => [ { template => '%d', min => 0 } ] } } ]; $self->{maps_counters}->{servers} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'id' }, { name => 'status' }, { name => 'name'}, { name => 'display' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_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 => { '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); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub prefix_global_output { my ($self, %options) = @_; return 'Total servers :'; } sub prefix_server_output { my ($self, %options) = @_; return "Server '" . $options{instance_value}->{name} . "' "; } sub manage_selection { my ($self, %options) = @_; $self->{global} = { started => 0, stopped => 0, failed => 0 }; $self->{servers} = {}; my $result = $options{custom}->list_objects(api_type => 'arm', endpoint => '/servers'); foreach ('running', 'disconnected') { $self->{global}->{$_} = 0; }; foreach my $server (@{$result}) { next if ( defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $server->{name} !~ /$self->{option_results}->{filter_name}/ ); $self->{servers}->{$server} = { display => $server, id => $server->{id}, name => $server->{name}, status => $server->{status}, }; $self->{global}->{running}++ if $server->{status} =~ m/RUNNING/; $self->{global}->{disconnected}++ if $server->{status} =~ m/DISCONNECTED/; } if (scalar(keys %{$self->{servers}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No server found."); $self->{output}->option_exit(); } $self->{global}->{total} = scalar (keys %{$self->{servers}}); } 1; __END__ =head1 MODE Check Mulesoft Anypoint Servers status. Example: perl centreon_plugins.pl --plugin=apps::mulesoft::restapi::plugin --mode=servers --environment-id='1234abc-56de-78fg-90hi-1234abcdefg' --organization-id='1234abcd-56ef-78fg-90hi-1234abcdefg' --api-username='myapiuser' --api-password='myapipassword' --verbose More information on'https://anypoint.mulesoft.com/exchange/portals/anypoint-platform/'. =over 8 =item B<--filter-name> Filter by server name (Regexp can be used). Example: --filter-name='^server1$' =item B<--warning-status> Set warning threshold for status (Default: ''). Threshold can be matched on %{name}, %{id} or %{status} and Regexp can be used. Typical syntax: --warning-status='%{status} ne "RUNNING"' =item B<--critical-status> Set warning threshold for status (Default: ''). Threshold can be matched on %{name}, %{id} or %{status} and Regexp can be used. Typical syntax: --critical-status='%{status} =~ m/DISCONNECTED/' =back =cut centreon-plugins-20220113/apps/mulesoft/restapi/plugin.pm000066400000000000000000000033761417000230700233510ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::mulesoft::restapi::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} = '1.0'; $self->{modes} = { 'applications' => 'apps::mulesoft::restapi::mode::applications', 'clusters' => 'apps::mulesoft::restapi::mode::clusters', 'list-applications' => 'apps::mulesoft::restapi::mode::listapplications', 'list-queues' => 'apps::mulesoft::restapi::mode::listqueues', 'list-servers' => 'apps::mulesoft::restapi::mode::listservers', 'messages' => 'apps::mulesoft::restapi::mode::messages', 'servers' => 'apps::mulesoft::restapi::mode::servers' }; $self->{custom_modes}->{restapi} = 'apps::mulesoft::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Mulesoft components using API. =cut centreon-plugins-20220113/apps/nginx/000077500000000000000000000000001417000230700173225ustar00rootroot00000000000000centreon-plugins-20220113/apps/nginx/nginxplus/000077500000000000000000000000001417000230700213515ustar00rootroot00000000000000centreon-plugins-20220113/apps/nginx/nginxplus/restapi/000077500000000000000000000000001417000230700230205ustar00rootroot00000000000000centreon-plugins-20220113/apps/nginx/nginxplus/restapi/custom/000077500000000000000000000000001417000230700243325ustar00rootroot00000000000000centreon-plugins-20220113/apps/nginx/nginxplus/restapi/custom/api.pm000066400000000000000000000145721417000230700254520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::nginx::nginxplus::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use JSON::XS; 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 => { 'api-username:s' => { name => 'api_username' }, 'api-password:s' => { name => 'api_password' }, 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'timeout:s' => { name => 'timeout' }, 'api-path:s' => { name => 'api_path' }, 'unknown-http-status:s' => { name => 'unknown_http_status' }, 'warning-http-status:s' => { name => 'warning_http_status' }, 'critical-http-status:s' => { name => 'critical_http_status' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 30; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : ''; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : ''; $self->{api_path} = (defined($self->{option_results}->{api_path})) ? $self->{option_results}->{api_path} : '/api/6'; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '(%{http_code} < 200 or %{http_code} >= 300) and %{http_code} != 424'; $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --hostname option.'); $self->{output}->option_exit(); } return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; if ($self->{api_username} ne '') { $self->{option_results}->{credentials} = 1; $self->{option_results}->{basic} = 1; $self->{option_results}->{username} = $self->{api_username}; $self->{option_results}->{password} = $self->{api_password}; } } sub settings { my ($self, %options) = @_; return if (defined($self->{settings_done})); $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->add_header(key => 'Content-Type', value => 'application/json'); $self->{http}->set_options(%{$self->{option_results}}); $self->{settings_done} = 1; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub request_api { my ($self, %options) = @_; $self->settings(); my $content = $self->{http}->request( url_path => $self->{api_path} . $options{endpoint}, unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status} ); if (!defined($content) || $content eq '') { $self->{output}->add_option_msg(short_msg => "API returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } return $decoded; } 1; __END__ =head1 NAME Nginx Plus Rest API =head1 REST API OPTIONS Nginx Plus Rest API =over 8 =item B<--hostname> Nginx hostname. =item B<--port> Port used (Default: 443) =item B<--proto> Specify https if needed (Default: 'https') =item B<--api-username> Nginx basic username. =item B<--api-password> Nginx basic password. =item B<--api-path> Specify api path (Default: '/api/6') =item B<--timeout> Set timeout in seconds (Default: 30). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/nginx/nginxplus/restapi/mode/000077500000000000000000000000001417000230700237445ustar00rootroot00000000000000centreon-plugins-20220113/apps/nginx/nginxplus/restapi/mode/connections.pm000066400000000000000000000070251417000230700266300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::nginx::nginxplus::restapi::mode::connections; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); sub prefix_connection_output { my ($self, %options) = @_; return 'Connections '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'connection', type => 0, cb_prefix_output => 'prefix_connection_output' } ]; $self->{maps_counters}->{connection} = [ { label => 'active', nlabel => 'connections.active.count', set => { key_values => [ { name => 'active' } ], output_template => 'active: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'idle', nlabel => 'connections.idle.count', set => { key_values => [ { name => 'idle' } ], output_template => 'idle: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'accepted', nlabel => 'connections.accepted.count', display_ok => 0, set => { key_values => [ { name => 'accepted', diff => 1 } ], output_template => 'accepted: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'dropped', nlabel => 'connections.dropped.count', display_ok => 0, set => { key_values => [ { name => 'dropped', diff => 1 } ], output_template => 'dropped: %s', perfdatas => [ { template => '%s', min => 0 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->request_api( endpoint => '/connections' ); $self->{connection} = {}; foreach (keys %$result) { $self->{connection}->{$_} = $result->{$_}; } $self->{cache_name} = 'nginx_nginxplus_' . $options{custom}->get_hostname() . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check connections. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='accepted' =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'active', 'idle', 'accepted', 'dropped'. =back =cut centreon-plugins-20220113/apps/nginx/nginxplus/restapi/mode/httpzones.pm000066400000000000000000000173521417000230700263500ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::nginx::nginxplus::restapi::mode::httpzones; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); sub prefix_server_zone_output { my ($self, %options) = @_; return "Server zone '" . $options{instance_value}->{display} . "' "; } sub prefix_location_zone_output { my ($self, %options) = @_; return "Location zone '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'server_zones', type => 1, cb_prefix_output => 'prefix_server_zone_output', message_multiple => 'All server zones are ok', skipped_code => { -10 => 1 } }, { name => 'location_zones', type => 1, cb_prefix_output => 'prefix_location_zone_output', message_multiple => 'All location zones are ok', skipped_code => { -10 => 1 } } ]; foreach my $name (('server', 'location')) { $self->{maps_counters}->{$name . '_zones'} = [ { label => $name . 'zone-requests', nlabel => 'http.' . $name . 'zone.requests.persecond', set => { key_values => [ { name => 'requests', per_second => 1 } ], output_template => 'requests: %.2f/s', perfdatas => [ { template => '%.2f', min => 0, unit => '/s', label_extra_instance => 1 } ] } }, { label => $name . 'zone-requests-discarded', nlabel => 'http.' . $name . 'zone.requests.discarded.count', set => { key_values => [ { name => 'discarded' } ], output_template => 'discarded: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } }, { label => $name . 'zone-traffic-in', nlabel => 'http.' . $name . 'zone.traffic.in.bitspersecond', set => { key_values => [ { name => 'received', per_second => 1 } ], output_template => 'traffic in: %s %s/s', output_change_bytes => 2, perfdatas => [ { template => '%s', min => 0, unit => 'b/s', label_extra_instance => 1 } ] } }, { label => $name . 'zone-traffic-out', nlabel => 'http.' . $name . 'zone.traffic.out.bitspersecond', set => { key_values => [ { name => 'sent', per_second => 1 } ], output_template => 'traffic out: %s %s/s', output_change_bytes => 2, perfdatas => [ { template => '%s', min => 0, unit => 'b/s', label_extra_instance => 1 } ] } }, { label => $name . 'zone-responses-total', nlabel => 'http.' . $name . 'zone.responses.total.count', set => { key_values => [ { name => 'responses_total', diff => 1 } ], output_template => 'responses total: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } } ]; foreach (('1xx', '2xx', '3xx', '4xx', '5xx')) { push @{$self->{maps_counters}->{$name . '_zones'}}, { label => $name . 'zone-responses-' . $_, nlabel => 'http.' . $name . 'zone.responses.' . $_ . '.count', display_ok => 0, set => { key_values => [ { name => 'responses_' . $_, diff => 1 } ], output_template => 'responses ' . $_ . ': %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } }; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-server-name:s' => { name => 'filter_server_name' }, 'filter-location-name:s' => { name => 'filter_location_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; foreach my $name (('server', 'location')) { my $results = $options{custom}->request_api( endpoint => '/http/' . $name . '_zones/' ); $self->{$name . '_zones'} = {}; foreach (keys %$results) { if (defined($self->{option_results}->{'filter_' . $name . '_name'}) && $self->{option_results}->{'filter_' . $name . '_name'} ne '' && $_ !~ /$self->{option_results}->{'filter_' . $name . '_name'}/) { $self->{output}->output_add(long_msg => "skipping $name zone '" . $_ . "': no matching filter.", debug => 1); next; } $self->{$name . '_zones'}->{$_} = { display => $_, discarded => $results->{ $_ }->{discarded}, requests => $results->{ $_ }->{requests}, received => $results->{ $_ }->{received} * 8, sent => $results->{ $_ }->{sent} * 8, responses_total => $results->{ $_ }->{responses}->{total}, responses_1xx => $results->{ $_ }->{responses}->{'1xx'}, responses_2xx => $results->{ $_ }->{responses}->{'2xx'}, responses_3xx => $results->{ $_ }->{responses}->{'3xx'}, responses_4xx => $results->{ $_ }->{responses}->{'4xx'}, responses_5xx => $results->{ $_ }->{responses}->{'5xx'} }; } } $self->{cache_name} = 'nginx_nginxplus_' . $options{custom}->get_hostname() . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_server_name}) ? md5_hex($self->{option_results}->{filter_server_name}) : md5_hex('all')); } 1; __END__ =head1 MODE Check http zones. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='serverzone' =item B<--filter-server-name> Filter server zone name (can be a regexp). =item B<--filter-location-name> Filter location zone name (can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'serverzone-requests', 'serverzone-requests-discarded', 'serverzone-traffic-in', 'serverzone-traffic-out', 'serverzone-responses-total', 'serverzone-responses-1xx', 'serverzone-responses-2xx', 'serverzone-responses-3xx', 'serverzone-responses-4xx', 'serverzone-responses-5xx', 'locationzone-requests', 'locationzone-requests-discarded', 'locationzone-traffic-in', 'locationzone-traffic-out', 'locationzone-responses-total', 'locationzone-responses-1xx', 'locationzone-responses-2xx', 'locationzone-responses-3xx', 'locationzone-responses-4xx', 'locationzone-responses-5xx'. =back =cut centreon-plugins-20220113/apps/nginx/nginxplus/restapi/mode/ssl.pm000066400000000000000000000064021417000230700251050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::nginx::nginxplus::restapi::mode::ssl; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); sub prefix_ssl_output { my ($self, %options) = @_; return 'Ssl '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'ssl', type => 0, cb_prefix_output => 'prefix_ssl_output' } ]; $self->{maps_counters}->{ssl} = [ { label => 'handshakes-succeeded', nlabel => 'ssl.handshakes.succeeded.count', set => { key_values => [ { name => 'handshakes', diff => 1 } ], output_template => 'handshakes succeeded: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'handshakes-failed', nlabel => 'ssl.handshakes.failed.count', set => { key_values => [ { name => 'handshakes_failed', diff => 1 } ], output_template => 'handshakes failed: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'sessions-reuses', nlabel => 'ssl.sessions.reuses.count', set => { key_values => [ { name => 'session_reuses', diff => 1 } ], output_template => 'session reuses: %s', perfdatas => [ { template => '%s', min => 0 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->request_api( endpoint => '/ssl' ); $self->{ssl} = {}; foreach (keys %$result) { $self->{ssl}->{$_} = $result->{$_}; } $self->{cache_name} = 'nginx_nginxplus_' . $options{custom}->get_hostname() . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check ssl statistics. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='failed' =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'handshakes-succeeded', 'handshakes-failed', 'sessions-reuses'. =back =cut centreon-plugins-20220113/apps/nginx/nginxplus/restapi/plugin.pm000066400000000000000000000027521417000230700246620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::nginx::nginxplus::restapi::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} = { 'connections' => 'apps::nginx::nginxplus::restapi::mode::connections', 'http-zones' => 'apps::nginx::nginxplus::restapi::mode::httpzones', 'ssl' => 'apps::nginx::nginxplus::restapi::mode::ssl' }; $self->{custom_modes}->{api} = 'apps::nginx::nginxplus::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Nginx Web Servers through Nginx Plus Rest API. =cut centreon-plugins-20220113/apps/nginx/serverstatus/000077500000000000000000000000001417000230700220745ustar00rootroot00000000000000centreon-plugins-20220113/apps/nginx/serverstatus/custom/000077500000000000000000000000001417000230700234065ustar00rootroot00000000000000centreon-plugins-20220113/apps/nginx/serverstatus/custom/api.pm000066400000000000000000000131201417000230700245120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::nginx::serverstatus::custom::api; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::http; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port'}, 'proto:s' => { name => 'proto' }, 'endpoint:s' => { name => 'endpoint', default => '/nginx_status' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'timeout:s' => { name => 'timeout', default => 30 }, 'unknown-http-status:s' => { name => 'unknown_http_status' }, 'warning-http-status:s' => { name => 'warning_http_status' }, 'critical-http-status:s' => { name => 'critical_http_status' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'NGINX OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 80; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'http'; $self->{endpoint} = (defined($self->{option_results}->{endpoint}) && $self->{option_results}->{endpoint} ne '') ? $self->{option_results}->{endpoint} : '/nginx_status'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 30; $self->{username} = (defined($self->{option_results}->{username})) ? $self->{option_results}->{username} : ''; $self->{password} = (defined($self->{option_results}->{password})) ? $self->{option_results}->{password} : ''; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300'; $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; if ($self->{username} ne '') { $self->{option_results}->{credentials} = 1; $self->{option_results}->{basic} = 1; $self->{option_results}->{username} = $self->{username}; $self->{option_results}->{password} = $self->{password}; } } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->set_options(%{$self->{option_results}}); } sub get_connection_info { my ($self, %options) = @_; return $self->{hostname} . ":" . $self->{port}; } sub get_status { my ($self, %options) = @_; $self->settings(); my ($content) = $self->{http}->request( url_path => $self->{endpoint}, unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status} ); return $content; } 1; __END__ =head1 NAME Nginx server-status =head1 NGINX OPTIONS =over 8 =item B<--hostname> IP Addr/FQDN of the webserver host =item B<--port> Port used by the webserver (Default: 80) =item B<--proto> Specify https if needed =item B<--endpoint> Set path to get server-status page (Default: '/nginx_status') =item B<--username> Specify username for basic authentication. =item B<--password> Specify password for basic authentication =item B<--timeout> HTTP timeout =back =cut centreon-plugins-20220113/apps/nginx/serverstatus/mode/000077500000000000000000000000001417000230700230205ustar00rootroot00000000000000centreon-plugins-20220113/apps/nginx/serverstatus/mode/connections.pm000066400000000000000000000056021417000230700257030ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::nginx::serverstatus::mode::connections; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_global_output { my ($self, %options) = @_; return 'Connections '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', cb_prefix_output => 'prefix_global_output', type => 0 } ]; $self->{maps_counters}->{global} = []; foreach (('active', 'reading', 'writing', 'waiting')) { push @{$self->{maps_counters}->{global}}, { label => 'connections-' . $_, nlabel => 'server.connections.' . $_ . '.count', set => { key_values => [ { name => $_ }, { name => 'total' } ], output_template => $_ . ': %d', perfdatas => [ { template => '%d', min => 0, max => 'total' } ] } }; } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $content = $options{custom}->get_status(); $self->{global} = {}; $self->{global}->{active} = $1 if ($content =~ /Active connections:\s*(\d+)/msi); $self->{global}->{reading} = $1 if ($content =~ /Reading:\s*(\d+)/msi); $self->{global}->{writing} = $1 if ($content =~ /Writing:\s*(\d+)/msi); $self->{global}->{waiting} = $1 if ($content =~ /Waiting:\s*(\d+)/msi); if (!defined($self->{global}->{active})) { $self->{output}->add_option_msg(short_msg => 'Cannot find connection informations.'); $self->{output}->option_exit(); } my $total = 0; $total += $self->{global}->{$_} foreach (keys %{$self->{global}}); $self->{global}->{total} = $total; } 1; __END__ =head1 MODE Check current connections. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'connections-active', 'connections-waiting', 'connections-writing', 'connections-reading'. =back =cut centreon-plugins-20220113/apps/nginx/serverstatus/mode/requests.pm000066400000000000000000000146001417000230700252320ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::nginx::serverstatus::mode::requests; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use POSIX; use Digest::MD5 qw(md5_hex); sub custom_requests_perfdata { my ($self, %options) = @_; my $nlabel = $self->{nlabel}; if (defined($self->{instance_mode}->{option_results}->{per_minute})) { $nlabel =~ s/persecond/perminute/; } $self->{output}->perfdata_add( nlabel => $nlabel, value => sprintf('%.2f', $self->{result_values}->{value}), 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_requests_calc { my ($self, %options) = @_; my $diff_value = ($options{new_datas}->{ $self->{instance} . '_' . $options{extra_options}->{metric} } - $options{old_datas}->{ $self->{instance} . '_' . $options{extra_options}->{metric} }); $self->{result_values}->{value} = $diff_value / $options{delta_time}; if (defined($self->{instance_mode}->{option_results}->{per_minute})) { $self->{result_values}->{value} = $diff_value / ceil($options{delta_time} / 60); } $self->{result_values}->{output_str} = sprintf( $options{extra_options}->{output_str} . (defined($self->{instance_mode}->{option_results}->{per_minute}) ? '/min' : '/s'), $self->{result_values}->{value} ); return 0; } sub custom_dropped_calc { my ($self, %options) = @_; $self->{result_values}->{dropped} = ($options{new_datas}->{ $self->{instance} . '_accepts' } - $options{old_datas}->{ $self->{instance} . '_accepts' }) - ($options{new_datas}->{ $self->{instance} . '_handled' } - $options{old_datas}->{ $self->{instance} . '_handled' }); return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, message_separator => ' - ' } ]; $self->{maps_counters}->{global} = [ { label => 'connections-accepted', nlabel => 'server.connections.accepted.persecond', set => { key_values => [ { name => 'accepts', diff => 1 } ], closure_custom_calc => $self->can('custom_requests_calc'), closure_custom_calc_extra_options => { metric => 'accepts', output_str => 'connections accepted: %.2f' }, output_template => '%s', output_use => 'output_str', threshold_use => 'value', closure_custom_perfdata => $self->can('custom_requests_perfdata') } }, { label => 'connections-handled', nlabel => 'server.connections.handled.persecond', set => { key_values => [ { name => 'handled', diff => 1 } ], closure_custom_calc => $self->can('custom_requests_calc'), closure_custom_calc_extra_options => { metric => 'handled', output_str => 'connections handled: %.2f' }, output_template => '%s', output_use => 'output_str', threshold_use => 'value', closure_custom_perfdata => $self->can('custom_requests_perfdata') } }, { label => 'connections-dropped', nlabel => 'server.connections.dropped.count', set => { key_values => [ { name => 'accepts', diff => 1 }, { name => 'handled', diff => 1 } ], closure_custom_calc => $self->can('custom_dropped_calc'), output_template => 'connections dropped: %d', output_use => 'dropped', threshold_use => 'dropped', perfdatas => [ { value => 'dropped', template => '%d', min => 0 } ] } }, { label => 'requests', nlabel => 'server.requests.persecond', set => { key_values => [ { name => 'requests', diff => 1 } ], closure_custom_calc => $self->can('custom_requests_calc'), closure_custom_calc_extra_options => { metric => 'requests', output_str => 'requests: %.2f' }, output_template => '%s', output_use => 'output_str', threshold_use => 'value', closure_custom_perfdata => $self->can('custom_requests_perfdata') } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'per-minute' => { name => 'per_minute' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->{maps_counters}->{global}->[0]->{nlabel} = 'toto'; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; my $content = $options{custom}->get_status(); if ($content !~ /server accepts handled requests.*?(\d+)\s+(\d+)\s+(\d+)/msi) { $self->{output}->add_option_msg(short_msg => 'Cannot find request informations.'); $self->{output}->option_exit(); } $self->{global} = { accepts => $1, handled => $2, requests => $3 }; $self->{cache_name} = 'nginx_' . $self->{mode} . '_' . md5_hex($options{custom}->get_connection_info()) . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check Nginx request statistics. =over 8 =item B<--per-minute> Per second metrics are computed per minute. =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'connections-accepted', 'connections-handled', 'requests'. =back =cut centreon-plugins-20220113/apps/nginx/serverstatus/plugin.pm000066400000000000000000000026161417000230700237350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::nginx::serverstatus::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} = { 'connections' => 'apps::nginx::serverstatus::mode::connections', 'requests' => 'apps::nginx::serverstatus::mode::requests' }; $self->{custom_modes}->{api} = 'apps::nginx::serverstatus::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Nginx Web Servers through HttpStubStatusModule Module =cut centreon-plugins-20220113/apps/nmap/000077500000000000000000000000001417000230700171325ustar00rootroot00000000000000centreon-plugins-20220113/apps/nmap/cli/000077500000000000000000000000001417000230700177015ustar00rootroot00000000000000centreon-plugins-20220113/apps/nmap/cli/mode/000077500000000000000000000000001417000230700206255ustar00rootroot00000000000000centreon-plugins-20220113/apps/nmap/cli/mode/discovery.pm000066400000000000000000000155161417000230700232020ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::nmap::cli::mode::discovery; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; use XML::Simple; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'subnet:s' => { name => 'subnet' }, 'nmap-options:s' => { name => 'nmap_options', default => '-sS -sU -R -O --osscan-limit --osscan-guess -p U:161,162,T:21-25,80,139,443,3306,8080,8443 -oX - ' }, 'prettify' => { name => 'prettify' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{subnet}) || $self->{option_results}->{subnet} !~ /(\d+)\.(\d+)\.(\d+)\.(\d+)\/(\d+)/) { $self->{output}->add_option_msg(short_msg => "Need to specify --subnet option (/)."); $self->{output}->option_exit(); } } my $lookup_type = [ { type => 'cisco standard', re => qr/Cisco/i }, { type => 'emc data domain', re => qr/Data Domain/i }, { type => 'sonicwall', re => qr/SonicWALL/i }, { type => 'silverpeak', re => qr/Silver Peak/i }, { type => 'stonesoft', re => qr/Forcepoint/i }, { type => 'redback', re => qr/Redback/i }, { type => 'palo alto', re => qr/Palo Alto/i }, { type => 'hp procurve', re => qr/HP ProCurve/i }, { type => 'hp standard', re => qr/HPE Comware/i }, { type => 'hp msl', re => qr/HP MSL/i }, { type => 'mrv optiswitch', re => qr/OptiSwitch/i }, { type => 'netapp', re => qr/Netapp/i }, { type => 'linux', re => qr/linux/i }, { type => 'windows', re => qr/windows/i }, { type => 'macos', re => qr/Darwin/i }, { type => 'hp-ux', re => qr/HP-UX/i }, { type => 'freebsd', re => qr/FreeBSD/i }, { type => 'synology', re => qr/Synology/i } ]; sub define_type { my ($self, %options) = @_; return "unknown" unless (defined($options{desc}) && $options{desc} ne ''); foreach (@$lookup_type) { if (defined($options{vendor}) && $options{vendor} =~ /$_->{re}/) { return $_->{type}; } if (defined($options{desc}) && $options{desc} =~ /$_->{re}/) { return $_->{type}; } } return "unknown"; } sub decode_xml_response { my ($self, %options) = @_; my $content; eval { $content = XMLin($options{response}, ForceArray => $options{ForceArray}, KeyAttr => []); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode xml response: $@"); $self->{output}->option_exit(); } return $content; } sub run { my ($self, %options) = @_; my @disco_data; my $disco_stats; $disco_stats->{start_time} = time(); my ($stdout) = $options{custom}->execute_command( command => 'nmap', command_options => $self->{option_results}->{nmap_options}, command_options_suffix => $self->{option_results}->{subnet}, timeout => 120 ); my $results = $self->decode_xml_response( response => $stdout, ForceArray => ['host', 'port', 'address', 'hostname', 'osmatch'] ); foreach my $entry (@{$results->{host}}) { my %host; $host{status} = $entry->{status}->{state}; $host{os} = $entry->{os}->{osmatch}[0]->{name}; $host{os_accuracy} = $entry->{os}->{osmatch}[0]->{accuracy}; $host{ip} = undef; $host{addresses} = undef; $host{hostname} = undef; $host{hostnames} = undef; $host{vendor} = undef; $host{services} = undef; foreach my $hostname (@{$entry->{hostnames}->{hostname}}) { push @{$host{hostnames}}, { name => $hostname->{name}, type => $hostname->{type} }; $host{hostname} = $hostname->{name} if (!defined($host{hostname})); } foreach my $address (@{$entry->{address}}) { push @{$host{addresses}}, { address => $address->{addr}, type => $address->{addrtype} }; $host{ip} = $address->{addr} if (!defined($host{ip}) && $address->{addrtype} =~ /^ipv/); $host{vendor} = $address->{vendor} if (!defined($host{vendor}) && defined($address->{vendor})); } foreach my $port (@{$entry->{ports}->{port}}) { next if ($port->{state}->{state} !~ /open/); push @{$host{services}}, { port => $port->{portid} . '/' . $port->{protocol}, name => $port->{service}->{name} }; } $host{type} = $self->define_type(vendor => $host{vendor}, desc => $host{os}); push @disco_data, \%host; } $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; $disco_stats->{discovered_items} = @disco_data; $disco_stats->{results} = \@disco_data; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE Resources discovery. Default command used: nmap -sS -sU -R -O --osscan-limit --osscan-guess -p U:161,162,T:21-25,80,139,443,3306,8080,8443 -oX - __SUBNET_OPTION__ Timeout defaults to 120 seconds. =over 8 =item B<--subnet> Specify subnet from which discover resources (Must be / format) (Mandatory). =item B<--nmap-options> Specify the options to use with Nmap. Default value: -sS -sU -R -O --osscan-limit --osscan-guess -p U:161,162,T:21-25,80,139,443,3306,8080,8443 -oX - __SUBNET_OPTION__ Note that -oX - are mandatory when using the Plugin in Centreon Host Discovery =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/apps/nmap/cli/plugin.pm000066400000000000000000000024451417000230700215420ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::nmap::cli::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} = { 'discovery' => 'apps::nmap::cli::mode::discovery', }; $self->{custom_modes}->{cli} = 'centreon::plugins::script_custom::cli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Nmap Plugin to discover assets on your networks =cut centreon-plugins-20220113/apps/nsclient/000077500000000000000000000000001417000230700200165ustar00rootroot00000000000000centreon-plugins-20220113/apps/nsclient/restapi/000077500000000000000000000000001417000230700214655ustar00rootroot00000000000000centreon-plugins-20220113/apps/nsclient/restapi/mode/000077500000000000000000000000001417000230700224115ustar00rootroot00000000000000centreon-plugins-20220113/apps/nsclient/restapi/mode/query.pm000066400000000000000000000202541417000230700241170ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::nsclient::restapi::mode::query; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::http; use JSON; use URI::Encode; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port', default => 8443 }, 'proto:s' => { name => 'proto', default => 'https' }, 'credentials' => { name => 'credentials' }, 'basic' => { name => 'basic' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'legacy-password:s' => { name => 'legacy_password' }, 'timeout:s' => { name => 'timeout' }, 'command:s' => { name => 'command' }, 'arg:s@' => { name => 'arg' }, 'unknown-status:s' => { name => 'unknown_status', default => '%{http_code} < 200 or %{http_code} >= 300' }, 'warning-status:s' => { name => 'warning_status' }, 'critical-status:s' => { name => 'critical_status', default => '' } }); $self->{http} = centreon::plugins::http->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{command}) || $self->{option_results}->{command} eq '') { $self->{output}->add_option_msg(short_msg => 'Please set command option'); $self->{output}->option_exit(); } if (defined($self->{option_results}->{legacy_password}) && $self->{option_results}->{legacy_password} ne '') { $self->{http}->add_header(key => 'password', value => $self->{option_results}->{legacy_password}); } $self->{http}->set_options(%{$self->{option_results}}); } # Three kind of outputs. # 1- # { # "header":{"source_id":""}, # "payload":[ # { # "command":"check_centreon_plugins","lines":[{"message":"OK: Reboot Pending : False | 'value1'=10;;;; 'value2'=10;;;;\r\nlong1\r\nlong2"}], # "result":"OK" # } # ] # } # 2- # { # "header":{"max_supported_version":"VERSION_1","version":"VERSION_1"}, # "payload":[ # {"command":"check_centreon_plugin","message":"Unknown command(s): check_centreon_plugin","result":"UNKNOWN"} # ] # } # 3- Can be also "int_value". # { # "header":{"source_id":""}, # "payload": [ # { # "command":"check_drivesize", # "lines": [ # { # "message":"OK All 1 drive(s) are ok", # "perf":[ # {"alias":"C:\\ used", # "float_value": { # "critical":44.690621566027403, # "maximum":49.656246185302734, # "minimum":0.00000000000000000, # "unit":"GB", # "value":21.684593200683594, # "warning":39.724996947683394} # }, # {"alias":"C:\\ used %","float_value":{"critical":90.000000000000000,"maximum":100.00000000000000,"minimum":0.00000000000000000,"unit":"%","value":44.000000000000000,"warning":80.000000000000000}} # ] # } # ], # "result":"OK" # } # ] # } sub nscp_output_perf { my ($self, %options) = @_; $self->{output}->output_add( severity => $options{result}, short_msg => $options{data}->{message} ); foreach (@{$options{data}->{perf}}) { my $perf = defined($_->{float_value}) ? $_->{float_value} : $_->{int_value}; my $printf_format = '%d'; $printf_format = '%.3f' if (defined($_->{float_value})); $self->{output}->perfdata_add( label => $_->{alias}, unit => $perf->{unit}, value => sprintf($printf_format, $perf->{value}), warning => defined($perf->{warning}) ? sprintf($printf_format, $perf->{warning}) : undef, critical => defined($perf->{critical}) ? sprintf($printf_format, $perf->{critical}) : undef, min => defined($perf->{minimum}) ? sprintf($printf_format, $perf->{minimum}) : undef, max => defined($perf->{maximum}) ? sprintf($printf_format, $perf->{maximum}) : undef ); } } sub nscp_output_noperf { my ($self, %options) = @_; $self->{output}->output_add( severity => $options{result}, short_msg => $options{data}->{message} ); } sub check_nscp_result { my ($self, %options) = @_; my $decoded; eval { $decoded = decode_json($options{content}); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } my $entry = $decoded->{payload}->[0]; my $data = $entry; if (defined($entry->{lines})) { $data = $entry->{lines}->[0]; $entry->{lines}->[0]->{message} =~ s/\r//msg; } elsif (defined($entry->{message})) { $entry->{message} =~ s/\r//msg; } if (defined($entry->{lines}->[0]->{perf})) { $self->nscp_output_perf(result => $entry->{result}, data => $data); $self->{output}->display(nolabel => 1); } else { $self->nscp_output_noperf(result => $entry->{result}, data => $data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); } } sub run { my ($self, %options) = @_; my $uri = URI::Encode->new({encode_reserved => 1}); my ($encoded_args, $append) = ('', ''); if (defined($self->{option_results}->{arg})) { foreach (@{$self->{option_results}->{arg}}) { $encoded_args .= $append . $uri->encode($_); $append = '&'; } } my ($content) = $self->{http}->request(url_path => '/query/' . $self->{option_results}->{command} . '?' . $encoded_args); $self->check_nscp_result(content => $content); $self->{output}->exit(); } 1; __END__ =head1 MODE Query NSClient Legacy API. =over 8 =item B<--hostname> IP Addr/FQDN of the host =item B<--port> Port used (Default: 8443) =item B<--proto> Specify https if needed (Default: 'https') =item B<--credentials> Specify this option if you access webpage with authentication =item B<--username> Specify username for authentication (Mandatory if --credentials is specified) =item B<--password> Specify password for authentication (Mandatory if --credentials is specified) =item B<--basic> Specify this option if you access webpage over basic authentication and don't want a '401 UNAUTHORIZED' error to be logged on your webserver. Specify this option if you access webpage over hidden basic authentication or you'll get a '404 NOT FOUND' error. (Use with --credentials) =item B<--legacy-password> Specify password for old authentification system. =item B<--timeout> Threshold for HTTP timeout (Default: 5) =item B<--command> Set command. =item B<--arg> Set arguments (Multiple option. Example: --arg='arg1') =item B<--unknown-status> Threshold warning for http response code. (Default: '%{http_code} < 200 or %{http_code} >= 300') =item B<--warning-status> Threshold warning for http response code. =item B<--critical-status> Threshold critical for http response code. =back =cut centreon-plugins-20220113/apps/nsclient/restapi/plugin.pm000066400000000000000000000022721417000230700233240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::nsclient::restapi::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} = '0.1'; %{$self->{modes}} = ( 'query' => 'apps::nsclient::restapi::mode::query', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check nsclient Rest API. =cut centreon-plugins-20220113/apps/openldap/000077500000000000000000000000001417000230700200015ustar00rootroot00000000000000centreon-plugins-20220113/apps/openldap/ldap/000077500000000000000000000000001417000230700207215ustar00rootroot00000000000000centreon-plugins-20220113/apps/openldap/ldap/mode/000077500000000000000000000000001417000230700216455ustar00rootroot00000000000000centreon-plugins-20220113/apps/openldap/ldap/mode/systemusage.pm000066400000000000000000000217001417000230700245540ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::openldap::ldap::mode::systemusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use centreon::common::protocols::ldap::lib::ldap; sub prefix_operation_output { my ($self, %options) = @_; return 'Operation completed '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, message_separator => ' - ', skipped_code => { -10 => 1 } }, { name => 'operation', type => 0, cb_prefix_output => 'prefix_operation_output', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{operation} = []; foreach ('search', 'add', 'bind', 'unbind', 'delete') { push @{$self->{maps_counters}->{operation}}, { label => 'op-' . $_, nlabel => 'system.operations.' . $_ . '.completed.count', set => { key_values => [ { name => 'operations_completed_' . $_, diff => 1 } ], output_template => $_ . ' %s', perfdatas => [ { template => '%.2f', min => 0 } ] } }; } $self->{maps_counters}->{global} = [ { label => 'con-current', nlabel => 'system.connections.current.count', set => { key_values => [ { name => 'connections_current' } ], output_template => 'Current connections %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'con-total', nlabel => 'system.connections.total.count', set => { key_values => [ { name => 'connections_total', diff => 1 } ], output_template => 'Total connections %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'threads-active', nlabel => 'system.threads.active.percentage', set => { key_values => [ { name => 'threads_active_prct' } ], output_template => 'Current active threads %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%' } ] } }, { label => 'traffic', nlabel => 'system.traffic.bytespersecond', set => { key_values => [ { name => 'traffic', per_second => 1 } ], output_template => 'traffic %s %s/s', output_change_bytes => 1, perfdatas => [ { template => '%s', min => 0, unit => 'B/s', cast_int => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'hostname:s' => { name => 'hostname' }, 'search-base:s' => { name => 'search_base', default => 'cn=monitor' }, 'ldap-connect-options:s@' => { name => 'ldap_connect_options' }, 'ldap-starttls-options:s@' => { name => 'ldap_starttls_options' }, 'ldap-bind-options:s@' => { name => 'ldap_bind_options' }, 'tls' => { name => 'use_tls' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'timeout:s' => { name => 'timeout', default => '30' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{hostname})) { $self->{output}->add_option_msg(short_msg => 'Please set the hostname option'); $self->{output}->option_exit(); } if (defined($self->{option_results}->{username}) && $self->{option_results}->{username} ne '' && !defined($self->{option_results}->{password})) { $self->{output}->add_option_msg(short_msg => "Please set --password option."); $self->{output}->option_exit(); } } sub ldap_error { my ($self, %options) = @_; if ($options{code} == 1) { $self->{output}->output_add( severity => 'unknown', short_msg => $options{err_msg} ); $self->{output}->display(); $self->{output}->exit(); } } sub search_monitor { my ($self, %options) = @_; my ($ldap_handle, $code, $err_msg) = centreon::common::protocols::ldap::lib::ldap::connect( hostname => $self->{option_results}->{hostname}, username => $self->{option_results}->{username}, password => $self->{option_results}->{password}, timeout => $self->{option_results}->{timeout}, ldap_connect_options => $self->{option_results}->{ldap_connect_options}, use_tls => $self->{option_results}->{use_tls}, ldap_starttls_options => $self->{option_results}->{ldap_starttls_options}, ldap_bind_options => $self->{option_results}->{ldap_bind_options}, ); $self->ldap_error(code => $code, err_msg => $err_msg); (my $search_result, $code, $err_msg) = centreon::common::protocols::ldap::lib::ldap::search( ldap_handle => $ldap_handle, search_base => $self->{option_results}->{search_base}, search_filter => '(objectclass=*)', ldap_search_options => ['attrs=monitoredInfo', 'attrs=monitorCounter', 'attrs=MonitorOpCompleted'], ); $self->ldap_error(code => $code, err_msg => $err_msg); centreon::common::protocols::ldap::lib::ldap::quit(ldap_handle => $ldap_handle); return $search_result; } sub manage_selection { my ($self, %options) = @_; $self->{operation} = {}; $self->{global} = {}; my $search_result = $self->search_monitor(); foreach my $entry ($search_result->entries()) { my $dn = $entry->dn(); if ($dn =~ /cn=(Current|Total),cn=Connections/i) { $self->{global}->{'connections_' . lc($1)} = $entry->get_value('monitorCounter'); } elsif ($dn =~ /cn=(.*?),cn=Operations/i) { $self->{operation}->{'operations_completed_' . lc($1)} = $entry->get_value('MonitorOpCompleted'); } elsif ($dn =~ /cn=(Max|Active),cn=Threads/i) { $self->{global}->{'threads_' . lc($1)} = $entry->get_value('monitoredInfo'); } elsif ($dn =~ /cn=Bytes,cn=Statistics/i) { $self->{global}->{traffic} = $entry->get_value('monitorCounter'); } } if (scalar(keys %{$self->{global}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'cannot get informations from OpenLDAP monitor backend'); $self->{output}->option_exit(); } $self->{global}->{threads_active_prct} = $self->{global}->{threads_active} * 100 / $self->{global}->{threads_max} if (defined($self->{global}->{threads_max}) && $self->{global}->{threads_max} > 0); $self->{cache_name} = 'openldap_' . $self->{mode} . '_' . $self->{option_results}->{hostname} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check system usage (connections, threads, requests). =over 8 =item B<--hostname> IP Addr/FQDN of the openldap host (required). =item B<--search-base> Set the DN that is the base object entry relative to the backend monitor (Default: cn=monitor). =item B<--ldap-connect-options> Add custom ldap connect options: =over 16 =item B --ldap-connect-options='scheme=ldaps' =item B --ldap-connect-options='version=2' =back =item B<--ldap-starttls-options> Add custom start tls options (need --tls option): =over 16 =item B --ldap-starttls-options='verify=none' =back =item B<--ldap-bind-options> Add custom bind options (can force noauth) (not really useful now). =item B<--username> Specify username for authentification (can be a DN) =item B<--password> Specify password for authentification =item B<--timeout> Connection timeout in seconds (Default: 30) =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'con-current', 'con-total', 'threads-active', 'traffic', 'op-add', 'op-search', 'op-bind', 'op-unbind', 'op-delete'. =back =cut centreon-plugins-20220113/apps/openldap/ldap/plugin.pm000066400000000000000000000023461417000230700225620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::openldap::ldap::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} = '0.1'; %{$self->{modes}} = ( 'system-usage' => 'apps::openldap::ldap::mode::systemusage', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check OpenLDAP through the monitor backend. =cut centreon-plugins-20220113/apps/openvpn/000077500000000000000000000000001417000230700176645ustar00rootroot00000000000000centreon-plugins-20220113/apps/openvpn/omi/000077500000000000000000000000001417000230700204505ustar00rootroot00000000000000centreon-plugins-20220113/apps/openvpn/omi/custom/000077500000000000000000000000001417000230700217625ustar00rootroot00000000000000centreon-plugins-20220113/apps/openvpn/omi/custom/api.pm000066400000000000000000000150531417000230700230750ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::openvpn::omi::custom::api; use strict; use warnings; use IO::Socket::INET; use IO::Select; 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 => { 'omi-hostname:s@' => { name => 'omi_hostname' }, 'omi-port:s@' => { name => 'omi_port' }, 'omi-password:s@' => { name => 'omi_password' }, 'timeout:s@' => { name => 'timeout' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'MANAGEMENT API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{cnx_omi} = undef; return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{omi_hostname} = (defined($self->{option_results}->{omi_hostname})) ? shift(@{$self->{option_results}->{omi_hostname}}) : undef; $self->{omi_password} = (defined($self->{option_results}->{omi_password})) ? shift(@{$self->{option_results}->{omi_password}}) : undef; $self->{omi_port} = (defined($self->{option_results}->{omi_port})) ? shift(@{$self->{option_results}->{omi_port}}) : 7505; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? shift(@{$self->{option_results}->{timeout}}) : 10; if (!defined($self->{omi_hostname})) { $self->{output}->add_option_msg(short_msg => "Need to specify --omi-hostname option."); $self->{output}->option_exit(); } if (!defined($self->{omi_hostname}) || scalar(@{$self->{option_results}->{omi_hostname}}) == 0) { return 0; } return 1; } sub get_connect_info { my ($self, %options) = @_; return $self->{omi_hostname} . '_' . $self->{omi_port}; } sub write_omi_protocol { my ($self, %options) = @_; $self->{cnx_omi}->send($options{cmd}); } sub read_omi_protocol { my ($self, %options) = @_; my $select = IO::Select->new($self->{cnx_omi}); my $read_msg; my $message = ''; while (1) { if (!$select->can_read(10)) { $self->{output}->output_add(long_msg => $message, debug => 1); $self->{output}->add_option_msg(short_msg => "Communication issue [Timeout or unexpected protocol]"); $self->{output}->option_exit(); } my $status = $self->{cnx_omi}->recv($read_msg, 4096); $message .= $read_msg; last if ($message =~ /$options{expected}/ms); } $self->{output}->output_add(long_msg => $message, debug => 1); $message =~ s/\r//msg; #if ($response !~ /Success|Follows/) { # $message =~ s/\n+$//msg; # $message =~ s/\n/ -- /msg; # $self->{output}->add_option_msg(short_msg => "Communication issue [" . $message . "]"); # $self->{output}->option_exit(); #} return $message; } sub command_omi_protocol { my ($self, %options) = @_; # Three types of message: # CMD1 # SUCCESS: nclients=5,bytesin=7761549522,bytesout=18417469629 # # CMD1 # ERROR: unknown command, enter 'help' for more options # # CMD1 # ... # END $self->write_omi_protocol(cmd => "$options{cmd} "); my $message = $self->read_omi_protocol(expected => '^(END[^\n]*?|SUCCESS:[^\n]*?|ERROR:[^\n]*?)\n'); if ($message =~ /^ERROR:(.*)/m) { $self->{output}->add_option_msg(short_msg => "Protocol error [" . $message . "]"); $self->{output}->option_exit(); } return $message; } sub login { my ($self, %options) = @_; my $message = $self->read_omi_protocol(expected => '^(>INFO:OpenVPN.*|ENTER\s+PASSWORD:)'); if ($message =~ /PASSWORD/) { if (!defined($self->{omi_password}) || $self->{omi_password} eq '') { $self->{output}->add_option_msg(short_msg => "Openvpn management interface require a password. please set --omi-password option"); $self->{output}->option_exit(); } $self->write_omi_protocol(cmd => $self->{omi_password} . "\n"); $message = $self->read_omi_protocol(expected => '^(SUCCESS|ERROR):[^\n]*?\n'); if ($message =~ /^ERROR:(.*)/m) { $self->{output}->add_option_msg(short_msg => "Password error [" . $1 . "]"); $self->{output}->option_exit(); } } } sub connect { my ($self, %options) = @_; $self->{cnx_omi} = IO::Socket::INET->new( PeerAddr => $self->{omi_hostname}, PeerPort => $self->{omi_port}, Proto => 'tcp', Timeout => $self->{timeout}, ); if (!defined($self->{cnx_omi})) { $self->{output}->add_option_msg(short_msg => "Can't bind : $@"); $self->{output}->option_exit(); } $self->{cnx_omi}->autoflush(1); $self->login(); } sub command { my ($self, %options) = @_; if (!defined($self->{cnx_omi})) { $self->connect(); } return $self->command_omi_protocol(%options); } sub DESTROY { my $self = shift; if (defined($self->{cnx_omi})) { $self->{cnx_omi}->close(); } } 1; __END__ =head1 NAME Openvpn Management interface =head1 SYNOPSIS Openvpn Management interface custom mode =head1 MANAGEMENT API OPTIONS =over 8 =item B<--omi-hostname> OMI hostname. =item B<--omi-port> OMI port (Default: 7505). =item B<--omi-password> OMI password. =item B<--timeout> Set TCP timeout =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/openvpn/omi/mode/000077500000000000000000000000001417000230700213745ustar00rootroot00000000000000centreon-plugins-20220113/apps/openvpn/omi/mode/serverusage.pm000066400000000000000000000107101417000230700242640ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::openvpn::omi::mode::serverusage; 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 => 'global', type => 0 } ]; $self->{maps_counters}->{global} = [ { label => 'num-clients', nlabel => 'clients.current.count',set => { key_values => [ { name => 'num_clients' } ], output_template => 'Current Clients: %s', perfdatas => [ { label => 'num_clients', template => '%s', min => 0 } ] } }, { label => 'traffic-in', nlabel => 'server.traffic.in.bitspersecond',set => { key_values => [ { name => 'traffic_in', per_second => 1 } ], output_change_bytes => 2, output_template => 'Traffic In: %s %s/s', perfdatas => [ { label => 'traffic_in', template => '%.2f', min => 0, unit => 'b/s' } ] } }, { label => 'traffic-out', nlabel => 'server.traffic.out.bitspersecond', set => { key_values => [ { name => 'traffic_out', per_second => 1 } ], output_change_bytes => 2, output_template => 'Traffic Out: %s %s/s', perfdatas => [ { label => 'traffic_out', template => '%.2f', min => 0, unit => 'b/s' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->command(cmd => 'load-stats'); # SUCCESS: nclients=6,bytesin=7765329961,bytesout=18435500727 $self->{global} = { num_clients => 0, traffic_in => 0, traffic_out => 0 }; if ($result =~ /nclients=(\d+),bytesin=(\d+),bytesout=(\d+)/) { $self->{global} = { num_clients => $1, traffic_in => $2 * 8, traffic_out => $3 * 8 }; } #status #OpenVPN CLIENT LIST #Updated,Thu Jan 10 16:05:32 2019 #Common Name,Real Address,Bytes Received,Bytes Sent,Connected Since #plop1,xxxx.xxx.xxx.xxxx:56702,104525967,29529209,Thu Jan 10 08:53:46 2019 #plop2,xxx.xxxx.xxx.xxx:39374,1814536,8630412,Thu Jan 10 15:27:13 2019 #plop3,xxx.xxxx.xxxx.xxxx:62866,8208936,85352252,Thu Jan 10 08:14:49 2019 #ROUTING TABLE #Virtual Address,Common Name,Real Address,Last Ref #10.8.1.xxx,plop1,xxx.xx.xx.xxx:53725,Thu Jan 10 16:05:31 2019 #... #GLOBAL STATS #Max bcast/mcast queue length,9 #END if ($self->{output}->is_verbose()) { $result = $options{custom}->command(cmd => 'status'); if ($result =~ /OpenVPN CLIENT LIST\n(.*?)ROUTING TABLE/ms) { my @users = split /\n/, $1; splice @users, 0, 2; foreach (@users) { my ($user) = split /,/; $self->{output}->add_option_msg(long_msg => "user '$user' connected"); } } } $self->{cache_name} = 'openvpn_' . $self->{mode} . '_' . $options{custom}->get_connect_info() . '_' . (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 server usage. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'num-clients', 'traffic-in', 'traffic-out'. =back =cut centreon-plugins-20220113/apps/openvpn/omi/plugin.pm000066400000000000000000000024451417000230700223110ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::openvpn::omi::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} = '1.0'; $self->{modes} = { 'server-usage' => 'apps::openvpn::omi::mode::serverusage', }; $self->{custom_modes}->{api} = 'apps::openvpn::omi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Openvpn through management interface. =cut centreon-plugins-20220113/apps/openweathermap/000077500000000000000000000000001417000230700212165ustar00rootroot00000000000000centreon-plugins-20220113/apps/openweathermap/restapi/000077500000000000000000000000001417000230700226655ustar00rootroot00000000000000centreon-plugins-20220113/apps/openweathermap/restapi/custom/000077500000000000000000000000001417000230700241775ustar00rootroot00000000000000centreon-plugins-20220113/apps/openweathermap/restapi/custom/api.pm000066400000000000000000000123331417000230700253100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::openweathermap::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use JSON::XS; 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 => { 'hostname:s' => { name => 'hostname' }, 'url-path:s' => { name => 'url_path' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'api-token:s' => { name => 'api_token' }, 'timeout:s' => { name => 'timeout' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : 'api.openweathermap.org'; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{url_path} = (defined($self->{option_results}->{url_path})) ? $self->{option_results}->{url_path} : '/data/2.5'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{api_token} = (defined($self->{option_results}->{api_token})) ? $self->{option_results}->{api_token} : ''; if (!defined($self->{api_token}) || $self->{api_token} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-token option."); $self->{output}->option_exit(); } return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{url_path} = $self->{url_path}; $self->{option_results}->{warning_status} = ''; $self->{option_results}->{critical_status} = ''; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->set_options(%{$self->{option_results}}); } sub set_token { my ($self, %options) = @_; push @{$self->{get_param}}, 'APPID=' . $self->{api_token}; } sub request_api { my ($self, %options) = @_; $self->set_token(); $self->settings; foreach my $get_param (@{$options{get_param}}) { push @{$self->{get_param}}, $get_param; } my $content = $self->{http}->request( url_path => $self->{url_path} . $options{url_path}, get_param => \@{$self->{get_param}} ); my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } if (!defined($decoded->{cod}) || $decoded->{cod} != 200) { $self->{output}->output_add(long_msg => "Error message : " . $decoded->{errorDetails}, debug => 1); $self->{output}->add_option_msg(short_msg => "API return error code '" . $decoded->{result} . "' (add --debug option for detailed message)"); $self->{output}->option_exit(); } return $decoded; } 1; __END__ =head1 NAME OpenWeatherMap Rest API =head1 SYNOPSIS OpenWeatherMap Rest API custom mode =head1 REST API OPTIONS OpenWeatherMap Rest API =over 8 =item B<--hostname> OpenWeatherMap API hostname (Default: 'api.openweathermap.org') =item B<--port> API port (Default: 443) =item B<--proto> Specify https if needed (Default: 'https') =item B<--url-path> API URL path (Default: '/data/2.5') =item B<--timeout> Set HTTP timeout =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/openweathermap/restapi/mode/000077500000000000000000000000001417000230700236115ustar00rootroot00000000000000centreon-plugins-20220113/apps/openweathermap/restapi/mode/cityweather.pm000066400000000000000000000126521417000230700265050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::openweathermap::restapi::mode::cityweather; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; return sprintf("Weather: '%s'", $self->{result_values}->{weather}); } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{weather} = $options{new_datas}->{$self->{instance} . '_weather'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'city', type => 0, cb_prefix_output => 'prefix_city_output' } ]; $self->{maps_counters}->{city} = [ { label => 'weather', set => { key_values => [ { name => 'weather' } ], 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 => \&catalog_status_threshold, } }, { label => 'temperature', nlabel => 'temperature.celsius', set => { key_values => [ { name => 'temperature' } ], output_template => 'Temperature: %d C', perfdatas => [ { label => 'temperature', value => 'temperature', template => '%d', unit => 'C' } ], } }, { label => 'humidity', nlabel => 'humidity.percentage', set => { key_values => [ { name => 'humidity' } ], output_template => 'Humidity: %.2f%%', perfdatas => [ { label => 'humidity', value => 'humidity', template => '%.1f', min => 0, max => 100, unit => '%' } ], } }, { label => 'clouds', nlabel => 'clouds.percentage', set => { key_values => [ { name => 'clouds' } ], output_template => 'Clouds: %.2f%%', perfdatas => [ { label => 'clouds', value => 'clouds', template => '%.1f', min => 0, max => 100, unit => '%' } ], } }, { label => 'wind', nlabel => 'wind.speed.meterspersecond', set => { key_values => [ { name => 'wind' } ], output_template => 'Wind: %.2f m/s', perfdatas => [ { label => 'wind', value => 'wind', template => '%.1f', min => 0, unit => 'm/s' } ], } } ]; } sub prefix_city_output { my ($self, %options) = @_; return $self->{option_results}->{city_name} . " "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "city-name:s" => { name => 'city_name' }, "warning-weather:s" => { name => 'warning_weather', default => '' }, "critical-weather:s" => { name => 'critical_weather', default => '' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_weather', 'critical_weather']); } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->request_api( url_path => "/weather?", get_param => ["q=" . $self->{option_results}->{city_name}] ); $self->{city} = { wind => $results->{wind}->{speed}, humidity => $results->{main}->{humidity}, temperature => $results->{main}->{temp} - 273.15, clouds => $results->{clouds}->{all}, weather => @{$results->{weather}->[0]}{main} }; } 1; __END__ =head1 MODE Check city weather =over 8 =item B<--city-name> City name (e.g London or ISO 3166 code like London,uk) =item B<--warning-weather> Set warning threshold for weather string desc (Default: ''). Can used special variables like: %{weather} =item B<--critical-weather> Set critical threshold for weather string desc (Default: ''). Can used special variables like: %{weather} Example : --critical-weather='%{weather} eq "Clouds' =item B<--warning-*> Set warning threshold for each metric gathered Can be : - temperature (Celsius) - humidity (%) - clouds (% coverage) - wind (speed m/s) =item B<--critical-*> Set critical threshold for each metric gathered Can be : - temperature (Celsius) - humidity (%) - clouds (% coverage) - wind (speed m/s) =back =cut centreon-plugins-20220113/apps/openweathermap/restapi/plugin.pm000066400000000000000000000024651417000230700245300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::openweathermap::restapi::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}} = ( 'city-weather' => 'apps::openweathermap::restapi::mode::cityweather', ); $self->{custom_modes}{api} = 'apps::openweathermap::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Openweathermap data =cut centreon-plugins-20220113/apps/oracle/000077500000000000000000000000001417000230700174445ustar00rootroot00000000000000centreon-plugins-20220113/apps/oracle/gg/000077500000000000000000000000001417000230700200415ustar00rootroot00000000000000centreon-plugins-20220113/apps/oracle/gg/local/000077500000000000000000000000001417000230700211335ustar00rootroot00000000000000centreon-plugins-20220113/apps/oracle/gg/local/custom/000077500000000000000000000000001417000230700224455ustar00rootroot00000000000000centreon-plugins-20220113/apps/oracle/gg/local/custom/cli.pm000066400000000000000000000176261417000230700235660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::oracle::gg::local::custom::cli; use strict; use warnings; use centreon::plugins::ssh; 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 => { 'hostname:s' => { name => 'hostname' }, 'timeout:s' => { name => 'timeout' }, 'command:s' => { name => 'command' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options' }, 'sudo:s' => { name => 'sudo' }, 'ggs-home:s' => { name => 'ggs_home' }, 'oracle-home:s' => { name => 'oracle_home' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'CLI OPTIONS', once => 1); $self->{output} = $options{output}; $self->{ssh} = centreon::plugins::ssh->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; if (defined($self->{option_results}->{timeout}) && $self->{option_results}->{timeout} =~ /(\d+)/) { $self->{timeout} = $1; } if (defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '') { $self->{ssh}->check_options(option_results => $self->{option_results}); } return 0; } sub get_identifier { my ($self, %options) = @_; my $id = defined($self->{option_results}->{hostname}) ? $self->{option_results}->{hostname} : 'me'; if (defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '') { $id .= ':' . $self->{ssh}->get_port(); } return $id; } sub set_local_environment { my ($self, %options) = @_; if (!defined($ENV{GGS_HOME}) || $ENV{GGS_HOME} eq '') { if (!defined($self->{option_results}->{ggs_home}) || $self->{option_results}->{ggs_home} eq '') { $self->{output}->add_option_msg(short_msg => "Please set option --ggs-home."); $self->{output}->option_exit(); } $ENV{GGS_HOME} = $self->{option_results}->{ggs_home}; } if (!defined($ENV{ORACLE_HOME}) || $ENV{ORACLE_HOME} eq '') { if (!defined($self->{option_results}->{oracle_home_home}) || $self->{option_results}->{oracle_home} eq '') { $self->{output}->add_option_msg(short_msg => "Please set option --oracle-home."); $self->{output}->option_exit(); } $ENV{ORACLE_HOME} = $self->{option_results}->{oracle_home}; $ENV{LD_LIBRARY_PATH} = $ENV{GGS_HOME} . ':' . $ENV{ORACLE_HOME} . '/lib'; } } sub set_ssh_command { my ($self, %options) = @_; my $env_vars = ''; my $command = 'ggsci'; if (!defined($self->{option_results}->{ggs_home})) { $self->{output}->add_option_msg(short_msg => "Please set option --ggs-home."); $self->{output}->option_exit(); } if ($self->{option_results}->{ggs_home} ne '') { $command = '"' . $self->{option_results}->{ggs_home} . '/ggsci"'; } if (!defined($self->{option_results}->{oracle_home})) { $self->{output}->add_option_msg(short_msg => "Please set option --oracle-home."); $self->{output}->option_exit(); } if ($self->{option_results}->{oracle_home} ne '') { $env_vars = 'export ORACLE_HOME="' . $self->{option_results}->{oracle_home} . '"; '; $env_vars .= 'export LD_LIBRARY_PATH="' . $self->{option_results}->{oracle_home} . '/lib"; '; } return $env_vars . 'echo "' . $options{commands} . '" | ' . $command; } sub execute_command { my ($self, %options) = @_; my $timeout = $self->{timeout}; if (!defined($timeout)) { $timeout = defined($options{timeout}) ? $options{timeout} : 45; } my $command_override = 0; if (defined($self->{option_results}->{command}) && $self->{option_results}->{command} ne '') { $command_override = 1; } my $command_options = defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne '' ? $self->{option_results}->{command_options} : $options{command_options}; my $command = $self->{option_results}->{command}; my ($stdout, $exit_code); if (defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '') { if ($command_override == 0) { $command = $self->set_ssh_command(commands => $options{commands}); } ($stdout, $exit_code) = $self->{ssh}->execute( hostname => $self->{option_results}->{hostname}, sudo => $self->{option_results}->{sudo}, command => $command, command_path => defined($self->{option_results}->{command_path}) && $self->{option_results}->{command_path} ne '' ? $self->{option_results}->{command_path} : $options{command_path}, command_options => $command_options, timeout => $timeout, no_quit => $options{no_quit} ); } else { if ($command_override == 0) { $self->set_local_environment(); $command = 'echo "' . $options{commands} . '" | "' . $ENV{GGS_HOME} . '/ggsci"'; } ($stdout, $exit_code) = centreon::plugins::misc::execute( output => $self->{output}, sudo => $self->{option_results}->{sudo}, options => { timeout => $timeout }, command => $command, command_path => defined($self->{option_results}->{command_path}) && $self->{option_results}->{command_path} ne '' ? $self->{option_results}->{command_path} : $options{command_path}, command_options => $command_options, no_quit => $options{no_quit} ); } $self->{output}->output_add(long_msg => "command response: $stdout", debug => 1); return ($stdout, $exit_code); } 1; __END__ =head1 NAME ggsci cli =head1 SYNOPSIS ggsci cli =head1 CLI OPTIONS =over 8 =item B<--hostname> Hostname to query. =item B<--timeout> Timeout in seconds for the command (Default: 45). Default value can be override by the mode. =item B<--command> Command to get information. Used it you have output in a file. =item B<--command-path> Command path. =item B<--command-options> Command options. =item B<--sudo> sudo command. =item B<--ggs-home> Directory with ggsci command line. Mandatory in ssh (you can set it empty if you have an user with GGS_HOME set in PATH environment) Mandatory in local if GSS_HOME environment variable is not. =item B<--oracle-home> Oracle home directory. Mandatory in ssh (you can set it empty if you have an user with ORACLE_HOME set in environment) Mandatory in local if ORACLE_HOME environment variable is not set. =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/oracle/gg/local/mode/000077500000000000000000000000001417000230700220575ustar00rootroot00000000000000centreon-plugins-20220113/apps/oracle/gg/local/mode/processes.pm000066400000000000000000000153241417000230700244300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::oracle::gg::local::mode::processes; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf('status: %s', $self->{result_values}->{status} ); } sub prefix_process_output { my ($self, %options) = @_; return sprintf( "Process '%s' ", $options{instance_value}->{name} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'processes', type => 1, cb_prefix_output => 'prefix_process_output', message_multiple => 'All processes are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{processes} = [ { label => 'status', type => 2, critical_default => '%{status} =~ /ABENDED/i', set => { key_values => [ { name => 'status' }, { name => 'group' }, { name => 'type' }, { name => 'name' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'lag', nlabel => 'process.lag.seconds', set => { key_values => [ { name => 'lag_secs' }, { name => 'lag_human' } ], output_template => 'lag: %s', output_use => 'lag_human', perfdatas => [ { template => '%s', min => 0, unit => 's', label_extra_instance => 1 } ] } }, { label => 'time-checkpoint', nlabel => 'process.time.checkpoint.seconds', set => { key_values => [ { name => 'time_secs' }, { name => 'time_human' } ], output_template => 'time since checkpoint: %s', output_use => 'time_human', perfdatas => [ { template => '%s', min => 0, unit => 's', label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'filter-group:s' => { name => 'filter_group' }, 'filter-type:s' => { name => 'filter_type' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my ($stdout) = $options{custom}->execute_command( commands => 'INFO ALL' ); $self->{processes} = {}; while ($stdout =~ /^(MANAGER|EXTRACT|REPLICAT)\s+(\S+)(.*?)(?:\n|\Z)/msig) { my ($type, $status, $data) = ($1, $2, $3); if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' && $type !~ /$self->{option_results}->{filter_type}/) { $self->{output}->output_add(long_msg => "skipping process '" . $type . "': no matching filter.", debug => 1); next; } if ($type eq 'MANAGER') { $self->{processes}->{$type} = { status => $status, name => $type, type => $type, group => '-' }; next; } next if ($data !~ /\s*(\S+)\s*(?:(\d+:\d+:\d+)\s+(\d+:\d+:\d+))?/); my ($group, $lag, $time) = ($1, $2, $3); my $name = $type . ':' . $group; if (defined($self->{option_results}->{filter_group}) && $self->{option_results}->{filter_group} ne '' && $group !~ /$self->{option_results}->{filter_group}/) { $self->{output}->output_add(long_msg => "skipping process '" . $group . "': no matching filter.", debug => 1); next; } 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 process '" . $group . "': no matching filter.", debug => 1); next; } $self->{processes}->{$name} = { status => $status, name => $name, type => $type, group => $group }; next if ($status eq 'STOPPED'); if (defined($lag)) { my ($hour, $min, $sec) = split(/:/, $lag); my $lag_secs = ($hour * 3600) + ($min * 60) + $sec; $self->{processes}->{$name}->{lag_secs} = $lag_secs; $self->{processes}->{$name}->{lag_human} = centreon::plugins::misc::change_seconds(value => $self->{processes}->{$name}->{lag_secs}); } if (defined($time)) { my ($hour, $min, $sec) = split(/:/, $time); my $time_secs = ($hour * 3600) + ($min * 60) + $sec; $self->{processes}->{$name}->{time_secs} = $time_secs; $self->{processes}->{$name}->{time_human} = centreon::plugins::misc::change_seconds(value => $self->{processes}->{$name}->{time_secs}); } } } 1; __END__ =head1 MODE Check processes. =over 8 =item B<--filter-name> Filter processes by name (can be a regexp). name is the following concatenation: type:group (eg.: EXTRACT:DB_test) =item B<--filter-group> Filter processes by group (can be a regexp). =item B<--filter-type> Filter processes by type (can be a regexp). =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{status}, %{name}, %{group}, %{type} =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{status}, %{name}, %{group}, %{type} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /ABENDED/i'). Can used special variables like: %{status}, %{name}, %{group}, %{type} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'lag' (s), 'time-checkpoint' (s). =back =cut centreon-plugins-20220113/apps/oracle/gg/local/plugin.pm000066400000000000000000000024631417000230700227740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::oracle::gg::local::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} = { 'processes' => 'apps::oracle::gg::local::mode::processes' }; $self->{custom_modes}->{cli} = 'apps::oracle::gg::local::custom::cli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Oracle GoldenGate with ggsci command line. =cut centreon-plugins-20220113/apps/oracle/ovm/000077500000000000000000000000001417000230700202455ustar00rootroot00000000000000centreon-plugins-20220113/apps/oracle/ovm/api/000077500000000000000000000000001417000230700210165ustar00rootroot00000000000000centreon-plugins-20220113/apps/oracle/ovm/api/custom/000077500000000000000000000000001417000230700223305ustar00rootroot00000000000000centreon-plugins-20220113/apps/oracle/ovm/api/custom/rest.pm000066400000000000000000000142051417000230700236450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::oracle::ovm::api::custom::rest; use strict; use warnings; use centreon::plugins::http; use JSON::XS; 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 => { 'api-username:s' => { name => 'api_username' }, 'api-password:s' => { name => 'api_password' }, 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'timeout:s' => { name => 'timeout' }, 'unknown-http-status:s' => { name => 'unknown_http_status' }, 'warning-http-status:s' => { name => 'warning_http_status' }, 'critical-http-status:s' => { name => 'critical_http_status' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{option_results}->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 7002; $self->{option_results}->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{option_results}->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 30; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : ''; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : ''; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300'; $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; if (!defined($self->{option_results}->{hostname}) || $self->{option_results}->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --hostname option.'); $self->{output}->option_exit(); } if ($self->{api_username} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --api-username option.'); $self->{output}->option_exit(); } if ($self->{api_password} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --api-password option.'); $self->{output}->option_exit(); } return 0; } sub settings { my ($self, %options) = @_; return if (defined($self->{settings_done})); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->add_header(key => 'Content-Type', value => 'application/json'); $self->{option_results}->{credentials} = 1; $self->{option_results}->{basic} = 1; $self->{option_results}->{username} = $self->{api_username}; $self->{option_results}->{password} = $self->{api_password}; $self->{http}->set_options(%{$self->{option_results}}); $self->{settings_done} = 1; } sub get_connection_info { my ($self, %options) = @_; return $self->{option_results}->{hostname} . ":" . $self->{option_results}->{port}; } sub request_api { my ($self, %options) = @_; $self->settings(); my ($content) = $self->{http}->request( url_path => '/ovm/core/wsapi/rest' . $options{endpoint}, unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status}, get_param => $options{get_param} ); if (!defined($content) || $content eq '') { $self->{output}->add_option_msg(short_msg => "API returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded; eval { $decoded = JSON::XS->new->allow_nonref(1)->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } return $decoded; } 1; __END__ =head1 NAME Oracle OVM Rest API =head1 REST API OPTIONS Oracle OVM Rest API =over 8 =item B<--hostname> Set hostname. =item B<--port> Port used (Default: 7002) =item B<--proto> Specify https if needed (Default: 'https') =item B<--api-username> API username. =item B<--api-password> API password. =item B<--timeout> Set timeout in seconds (Default: 30). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/oracle/ovm/api/mode/000077500000000000000000000000001417000230700217425ustar00rootroot00000000000000centreon-plugins-20220113/apps/oracle/ovm/api/mode/discovery.pm000066400000000000000000000107221417000230700243110ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::oracle::ovm::api::mode::discovery; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'resource-type:s' => { name => 'resource_type' }, 'prettify' => { name => 'prettify' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{resource_type}) || $self->{option_results}->{resource_type} eq '') { $self->{option_results}->{resource_type} = 'server'; } if ($self->{option_results}->{resource_type} !~ /^server|vm$/) { $self->{output}->add_option_msg(short_msg => 'unknown resource type'); $self->{output}->option_exit(); } } sub discovery_vm { my ($self, %options) = @_; my $vms = $options{custom}->request_api(endpoint => '/Vm'); my $disco_data = []; foreach my $vm (@$vms) { my $node = {}; $node->{uuid} = $vm->{id}->{value}; $node->{name} = $vm->{name}; $node->{description} = $vm->{description}; $node->{running_state} = lc($vm->{vmRunState}); $node->{os_type} = $vm->{osType}; $node->{server_pool_uuid} = $vm->{serverPoolId}->{value}; $node->{server_pool_name} = $vm->{serverPoolId}->{name}; $node->{server_uuid} = $vm->{serverId}->{value}; $node->{server_name} = $vm->{serverId}->{name}; push @$disco_data, $node; } return $disco_data; } sub discovery_server { my ($self, %options) = @_; my $servers = $options{custom}->request_api(endpoint => '/Server'); my $disco_data = []; foreach my $server (@$servers) { my $node = {}; $node->{uuid} = $server->{id}->{value}; $node->{name} = $server->{name}; $node->{description} = $server->{description}; $node->{running_state} = lc($server->{serverRunState}); $node->{ip_address} = $server->{ipAddress}; $node->{hostname} = $server->{hostname}; $node->{serial_number} = $server->{serialNumber}; $node->{server_pool_uuid} = $server->{serverPoolId}->{value}; $node->{server_pool_name} = $server->{serverPoolId}->{name}; push @$disco_data, $node; } return $disco_data; } sub run { my ($self, %options) = @_; my $disco_stats; $disco_stats->{start_time} = time(); my $results = []; if ($self->{option_results}->{resource_type} eq 'vm') { $results = $self->discovery_vm( custom => $options{custom} ); } else { $results = $self->discovery_server( custom => $options{custom} ); } $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; $disco_stats->{discovered_items} = scalar(@$results); $disco_stats->{results} = $results; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE Resources discovery. =over 8 =item B<--resource-type> Choose the type of resources to discover (Can be: 'vm', 'server'). =back =cut centreon-plugins-20220113/apps/oracle/ovm/api/mode/fileservers.pm000066400000000000000000000173061417000230700246400ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::oracle::ovm::api::mode::fileservers; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_usage_output { my ($self, %options) = @_; my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total_space}); my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used_space}); my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free_space}); return sprintf( 'space usage total: %s used: %s (%.2f%%) free: %s (%.2f%%)', $total_size_value . " " . $total_size_unit, $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used_space}, $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free_space} ); } sub fileserver_long_output { my ($self, %options) = @_; return "checking file server '" . $options{instance_value}->{name} . "'"; } sub prefix_fileserver_output { my ($self, %options) = @_; return "File server '" . $options{instance_value}->{name} . "' "; } sub prefix_fs_output { my ($self, %options) = @_; return "filesystem '" . $options{instance_value}->{name} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'fileservers', type => 3, cb_prefix_output => 'prefix_fileserver_output', cb_long_output => 'fileserver_long_output', indent_long_output => ' ', message_multiple => 'All file servers are ok', group => [ { name => 'filesystems', type => 1, display_long => 1, cb_prefix_output => 'prefix_fs_output', message_multiple => 'filesystems are ok', skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{filesystems} = [ { label => 'space-usage', nlabel => 'serverpool.space.usage.bytes', set => { key_values => [ { name => 'used_space' }, { name => 'free_space' }, { name => 'prct_used_space' }, { name => 'prct_free_space' }, { name => 'total_space' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total_space', unit => 'B', cast_int => 1, label_extra_instance => 1 } ] } }, { label => 'space-usage-free', nlabel => 'serverpool.space.free.bytes', display_ok => 0, set => { key_values => [ { name => 'free_space' }, { name => 'used_space' }, { name => 'prct_used_space' }, { name => 'prct_free_space' }, { name => 'total_space' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total_space', unit => 'B', cast_int => 1, label_extra_instance => 1 } ] } }, { label => 'space-usage-prct', nlabel => 'serverpool.space.usage.percentage', display_ok => 0, set => { key_values => [ { name => 'prct_used_space' }, { name => 'used_space' }, { name => 'free_space' }, { name => 'prct_free_space' }, { name => 'total_space' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-fileserver-name:s' => { name => 'filter_fileserver_name' }, 'filter-filesystem-name:s' => { name => 'filter_filesystem_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $manager = $options{custom}->request_api(endpoint => '/Manager'); if ($manager->[0]->{managerRunState} ne 'RUNNING') { $self->{output}->add_option_msg(short_msg => 'manager is not running.'); $self->{output}->option_exit(); } my $fileservers = $options{custom}->request_api(endpoint => '/FileServer'); my $filesystems = $options{custom}->request_api(endpoint => '/FileSystem'); $self->{fileservers} = {}; foreach my $fileserver (@$fileservers) { my $name = $fileserver->{id}->{value}; $name = $fileserver->{name} if (defined($fileserver->{name}) && $fileserver->{name} ne ''); if (defined($self->{option_results}->{filter_fileserver_name}) && $self->{option_results}->{filter_fileserver_name} ne '' && $name !~ /$self->{option_results}->{filter_fileserver_name}/) { $self->{output}->output_add(long_msg => "skipping file server '" . $name . "': no matching filter.", debug => 1); next; } $self->{fileservers}->{$name} = { name => $name, filesystems => {} }; foreach my $filesystem (@{$fileserver->{fileSystemIds}}) { foreach my $target (@$filesystems) { if ($filesystem->{value} eq $target->{id}->{value}) { my $fs_name = $target->{id}->{value}; $fs_name = $target->{name} if (defined($target->{name}) && $target->{name} ne ''); if (defined($self->{option_results}->{filter_filesystem_name}) && $self->{option_results}->{filter_filesystem_name} ne '' && $fs_name !~ /$self->{option_results}->{filter_filesystem_name}/) { $self->{output}->output_add(long_msg => "skipping file system '" . $fs_name . "': no matching filter.", debug => 1); next; } my $total_space = $target->{size}; my $usable_space = $target->{freeSize}; $self->{fileservers}->{$name}->{filesystems}->{$fs_name} = { name => $fs_name, total_space => $total_space, used_space => $total_space - $usable_space, free_space => $usable_space, prct_used_space => ($total_space - $usable_space) * 100 / $total_space, prct_free_space => $usable_space * 100 / $total_space }; last; } } } } } 1; __END__ =head1 MODE Check file servers. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^space-usage$' =item B<--filter-fileserver-name> Filter file servers by name (can be a regexp). =item B<--filter-filesystem-name> Filter file systems by name (can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'space-usage' (B), 'space-usage-free' (B), 'space-usage-prct' (%). =back =cut centreon-plugins-20220113/apps/oracle/ovm/api/mode/manager.pm000066400000000000000000000106761417000230700237240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::oracle::ovm::api::mode::manager; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return 'status: ' . $self->{result_values}->{status}; } sub prefix_manager_output { my ($self, %options) = @_; return "Manager '" . $options{instance_value}->{name} . "' "; } sub prefix_jobs_output { my ($self, %options) = @_; return 'Jobs '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'manager', type => 0, cb_prefix_output => 'prefix_manager_output', skipped_code => { -10 => 1 } }, { name => 'jobs', type => 0, cb_prefix_output => 'prefix_jobs_output', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{manager} = [ { label => 'status', type => 2, critical_default => '%{status} !~ /running/i', set => { key_values => [ { name => 'status' }, { name => 'name' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{jobs} = [ { label => 'jobs-succeeded', nlabel => 'manager.jobs.succeeded.count', set => { key_values => [ { name => 'success' }, { name => 'name' } ], output_template => 'succeeded: %s', perfdatas => [ { template => '%d', min => 0, label_extra_instance => 1, instance_use => 'name' } ] } }, { label => 'jobs-failed', nlabel => 'manager.jobs.failed.count', set => { key_values => [ { name => 'failure' }, { name => 'name' } ], output_template => 'failed: %s', perfdatas => [ { template => '%d', min => 0, label_extra_instance => 1, instance_use => 'name' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $manager = $options{custom}->request_api(endpoint => '/Manager'); my $jobs = $options{custom}->request_api(endpoint => '/Job'); my $name = $manager->[0]->{id}->{value}; $name = $manager->[0]->{name} if (defined($manager->[0]->{name}) && $manager->[0]->{name} ne ''); $self->{manager} = { name => $name, status => lc($manager->[0]->{managerRunState}) }; $self->{jobs} = { name => $name, success => 0, failure => 0 }; foreach (@$jobs) { $self->{jobs}->{ lc($_->{jobSummaryState}) }++ if (defined($self->{jobs}->{ lc($_->{jobSummaryState}) })); } } 1; __END__ =head1 MODE Check manager. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='status' =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{status}, %{name} =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{status}, %{name} =item B<--critical-status> Set critical threshold for status (Default: '%{status} !~ /running/i'). Can used special variables like: %{status}, %{name} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'jobs-succeeded', 'jobs-failed'. =back =cut centreon-plugins-20220113/apps/oracle/ovm/api/mode/serverpools.pm000066400000000000000000000232611417000230700246670ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::oracle::ovm::api::mode::serverpools; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_usage_output { my ($self, %options) = @_; my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total_memory}); my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used_memory}); my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free_memory}); return sprintf( 'memory usage total: %s used: %s (%.2f%%) free: %s (%.2f%%)', $total_size_value . " " . $total_size_unit, $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used_memory}, $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free_memory} ); } sub pool_long_output { my ($self, %options) = @_; return "checking server pool '" . $options{instance_value}->{name} . "'"; } sub prefix_pool_output { my ($self, %options) = @_; return "Server pool '" . $options{instance_value}->{name} . "' "; } sub prefix_servers_output { my ($self, %options) = @_; return 'servers '; } sub prefix_vm_output { my ($self, %options) = @_; return 'virtual machines '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'pools', type => 3, cb_prefix_output => 'prefix_pool_output', cb_long_output => 'pool_long_output', indent_long_output => ' ', message_multiple => 'All server pools are ok', group => [ { name => 'servers', type => 0, cb_prefix_output => 'prefix_servers_output' }, { name => 'vm', type => 0, cb_prefix_output => 'prefix_vm_output' }, { name => 'memory', type => 0 } ] } ]; $self->{maps_counters}->{servers} = [ { label => 'servers-running', nlabel => 'serverpool.servers.running.count', set => { key_values => [ { name => 'running' }, { name => 'total' } ], output_template => 'running: %d', perfdatas => [ { template => '%d', min => 0, max => 'total', label_extra_instance => 1 } ] } }, { label => 'servers-stopped', nlabel => 'serverpool.servers.stopped.count', set => { key_values => [ { name => 'stopped' }, { name => 'total' } ], output_template => 'stopped: %d', perfdatas => [ { template => '%d', min => 0, max => 'total', label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{vm} = [ { label => 'vm-running', nlabel => 'serverpool.vm.running.count', set => { key_values => [ { name => 'running' }, { name => 'total' } ], output_template => 'running: %d', perfdatas => [ { template => '%d', min => 0, max => 'total', label_extra_instance => 1 } ] } }, { label => 'vm-stopped', nlabel => 'serverpool.vm.stopped.count', set => { key_values => [ { name => 'stopped' }, { name => 'total' } ], output_template => 'stopped: %d', perfdatas => [ { template => '%d', min => 0, max => 'total', label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{memory} = [ { label => 'memory-usage', nlabel => 'serverpool.memory.usage.bytes', set => { key_values => [ { name => 'used_memory' }, { name => 'free_memory' }, { name => 'prct_used_memory' }, { name => 'prct_free_memory' }, { name => 'total_memory' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total_memory', unit => 'B', cast_int => 1, label_extra_instance => 1 } ] } }, { label => 'memory-usage-free', nlabel => 'serverpool.memory.free.bytes', display_ok => 0, set => { key_values => [ { name => 'free_memory' }, { name => 'used_memory' }, { name => 'prct_used_memory' }, { name => 'prct_free_memory' }, { name => 'total_memory' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total_memory', unit => 'B', cast_int => 1, label_extra_instance => 1 } ] } }, { label => 'memory-usage-prct', nlabel => 'serverpool.memory.usage.percentage', display_ok => 0, set => { key_values => [ { name => 'prct_used_memory' }, { name => 'used_memory' }, { name => 'free_memory' }, { name => 'prct_free_memory' }, { name => 'total_memory' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-server-pool-name:s' => { name => 'filter_server_pool_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $manager = $options{custom}->request_api(endpoint => '/Manager'); if ($manager->[0]->{managerRunState} ne 'RUNNING') { $self->{output}->add_option_msg(short_msg => 'manager is not running.'); $self->{output}->option_exit(); } my $pools = $options{custom}->request_api(endpoint => '/ServerPool'); my $vms = $options{custom}->request_api(endpoint => '/Vm'); my $servers = $options{custom}->request_api(endpoint => '/Server'); $self->{pools} = {}; foreach (@$pools) { my $name = $_->{id}->{value}; $name = $_->{name} if (defined($_->{name}) && $_->{name} ne ''); if (defined($self->{option_results}->{filter_server_pool_name}) && $self->{option_results}->{filter_server_pool_name} ne '' && $name !~ /$self->{option_results}->{filter_server_pool_name}/) { $self->{output}->output_add(long_msg => "skipping server pool '" . $name . "': no matching filter.", debug => 1); next; } $self->{pools}->{$name} = { name => $name, memory => { total_memory => 0, free_memory => 0 }, servers => { total => 0, running => 0, stopped => 0 }, vm => { total => 0, running => 0, stopped => 0 } }; foreach my $server (@{$_->{serverIds}}) { foreach my $target (@$servers) { if ($server->{value} eq $target->{id}->{value}) { $self->{pools}->{$name}->{memory}->{total_memory} += ($target->{memory} * 1024 * 1024); $self->{pools}->{$name}->{memory}->{free_memory} += ($target->{usableMemory} * 1024 * 1024); $self->{pools}->{$name}->{servers}->{ lc($target->{serverRunState}) }++ if (defined($self->{pools}->{$name}->{servers}->{ lc($target->{serverRunState}) })); $self->{pools}->{$name}->{servers}->{total}++; last; } } } foreach my $vm (@{$_->{vmIds}}) { foreach my $target (@$vms) { if ($vm->{value} eq $target->{id}->{value}) { $self->{pools}->{$name}->{vm}->{ lc($target->{vmRunState}) }++ if (defined($self->{pools}->{$name}->{vm}->{ lc($target->{vmRunState}) })); $self->{pools}->{$name}->{vm}->{total}++; last; } } } $self->{pools}->{$name}->{memory}->{used_memory} = $self->{pools}->{$name}->{memory}->{total_memory} - $self->{pools}->{$name}->{memory}->{free_memory}; $self->{pools}->{$name}->{memory}->{prct_used_memory} = $self->{pools}->{$name}->{memory}->{used_memory} * 100 / $self->{pools}->{$name}->{memory}->{total_memory}; $self->{pools}->{$name}->{memory}->{prct_free_memory} = 100 - $self->{pools}->{$name}->{memory}->{prct_used_memory}; } } 1; __END__ =head1 MODE Check servers. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^memory-usage$' =item B<--filter-server-pool-name> Filter server pools by name (can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'servers-running', 'servers-stopped', 'vm-running', 'vm-stopped', 'memory-usage' (B), 'memory-usage-free' (B), 'memory-usage-prct' (%). =back =cut centreon-plugins-20220113/apps/oracle/ovm/api/mode/servers.pm000066400000000000000000000206351417000230700237770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::oracle::ovm::api::mode::servers; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf( 'running state: %s [up2date: %s][maintenance: %s]', $self->{result_values}->{running_state}, $self->{result_values}->{up2date}, $self->{result_values}->{is_maintenance} ); } sub custom_usage_output { my ($self, %options) = @_; my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total_memory}); my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used_memory}); my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free_memory}); return sprintf( 'memory usage total: %s used: %s (%.2f%%) free: %s (%.2f%%)', $total_size_value . " " . $total_size_unit, $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used_memory}, $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free_memory} ); } sub prefix_server_output { my ($self, %options) = @_; return "Server '" . $options{instance_value}->{name} . "' "; } sub prefix_global_output { my ($self, %options) = @_; return 'Servers '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }, { name => 'servers', type => 1, cb_prefix_output => 'prefix_server_output', message_multiple => 'All servers are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'servers-running', nlabel => 'servers.running.count', display_ok => 0, set => { key_values => [ { name => 'running' }, { name => 'total' } ], output_template => 'running: %d', perfdatas => [ { template => '%d', min => 0, max => 'total' } ] } }, { label => 'servers-stopped', nlabel => 'servers.stopped.count', display_ok => 0, set => { key_values => [ { name => 'stopped' }, { name => 'total' } ], output_template => 'stopped: %d', perfdatas => [ { template => '%d', min => 0, max => 'total' } ] } } ]; $self->{maps_counters}->{servers} = [ { label => 'status', threshold => 2, set => { key_values => [ { name => 'running_state' }, { name => 'up2date' }, { name => 'is_maintenance' },{ name => 'name' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'memory-usage', nlabel => 'server.memory.usage.bytes', set => { key_values => [ { name => 'used_memory' }, { name => 'free_memory' }, { name => 'prct_used_memory' }, { name => 'prct_free_memory' }, { name => 'total_memory' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total_memory', unit => 'B', cast_int => 1, label_extra_instance => 1 } ] } }, { label => 'memory-usage-free', nlabel => 'server.memory.free.bytes', display_ok => 0, set => { key_values => [ { name => 'free_memory' }, { name => 'used_memory' }, { name => 'prct_used_memory' }, { name => 'prct_free_memory' }, { name => 'total_memory' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total_memory', unit => 'B', cast_int => 1, label_extra_instance => 1 } ] } }, { label => 'memory-usage-prct', nlabel => 'server.memory.usage.percentage', display_ok => 0, set => { key_values => [ { name => 'prct_used_memory' }, { name => 'used_memory' }, { name => 'free_memory' }, { name => 'prct_free_memory' }, { name => 'total_memory' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $manager = $options{custom}->request_api(endpoint => '/Manager'); if ($manager->[0]->{managerRunState} ne 'RUNNING') { $self->{output}->add_option_msg(short_msg => 'manager is not running.'); $self->{output}->option_exit(); } my $servers = $options{custom}->request_api(endpoint => '/Server'); $self->{global} = { running => 0, stopped => 0, total => 0 }; $self->{servers} = {}; foreach (@$servers) { my $name = $_->{id}->{value}; $name = $_->{name} if (defined($_->{name}) && $_->{name} ne ''); 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 server '" . $name . "': no matching filter.", debug => 1); next; } my $total_memory = $_->{memory} * 1024 * 1024; my $usable_memory = $_->{usableMemory} * 1024 * 1024; $self->{servers}->{$name} = { name => $name, running_state => lc($_->{serverRunState}), is_maintenance => $_->{maintenanceMode} =~ /True|1/i ? 'yes' : 'no', up2date => $_->{serverUpToDate} =~ /True|1/i ? 'yes' : 'no', total_memory => $total_memory, used_memory => $total_memory - $usable_memory, free_memory => $usable_memory, prct_used_memory => ($total_memory - $usable_memory) * 100 / $total_memory, prct_free_memory => $usable_memory * 100 / $total_memory }; $self->{global}->{ lc($_->{serverRunState}) }++ if (defined($self->{global}->{ lc($_->{serverRunState}) })); $self->{global}->{total}++; } } 1; __END__ =head1 MODE Check servers. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^memory-usage$' =item B<--filter-name> Filter servers by name (can be a regexp). =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{running_status}, %{is_maintenance}, %{up2date}, %{name} =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{running_status}, %{is_maintenance}, %{up2date}, %{name} =item B<--critical-status> Set critical threshold for status. Can used special variables like: %{running_status}, %{is_maintenance}, %{up2date}, %{name} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'servers-running', 'servers-stopped', 'memory-usage' (B), 'memory-usage-free' (B), 'memory-usage-prct' (%). =back =cut centreon-plugins-20220113/apps/oracle/ovm/api/mode/vm.pm000066400000000000000000000121361417000230700227250ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::oracle::ovm::api::mode::vm; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf( 'running state: %s', $self->{result_values}->{running_state} ); } sub prefix_vm_output { my ($self, %options) = @_; return "Virtual machine '" . $options{instance_value}->{name} . "' "; } sub prefix_global_output { my ($self, %options) = @_; return 'Virtual machines '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }, { name => 'vm', type => 1, cb_prefix_output => 'prefix_vm_output', message_multiple => 'All virtual machines are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'vm-running', nlabel => 'virtualmachines.running.count', display_ok => 0, set => { key_values => [ { name => 'running' }, { name => 'total' } ], output_template => 'running: %d', perfdatas => [ { template => '%d', min => 0, max => 'total' } ] } }, { label => 'vm-stopped', nlabel => 'virtualmachines.stopped.count', display_ok => 0, set => { key_values => [ { name => 'stopped' }, { name => 'total' } ], output_template => 'stopped: %d', perfdatas => [ { template => '%d', min => 0, max => 'total' } ] } } ]; $self->{maps_counters}->{vm} = [ { label => 'status', threshold => 2, set => { key_values => [ { name => 'running_state' }, { name => 'name' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $manager = $options{custom}->request_api(endpoint => '/Manager'); if ($manager->[0]->{managerRunState} ne 'RUNNING') { $self->{output}->add_option_msg(short_msg => 'manager is not running.'); $self->{output}->option_exit(); } my $vms = $options{custom}->request_api(endpoint => '/Vm'); $self->{global} = { running => 0, stopped => 0, total => 0 }; $self->{vm} = {}; foreach (@$vms) { my $name = $_->{id}->{value}; $name = $_->{name} if (defined($_->{name}) && $_->{name} ne ''); 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 virtual machine '" . $name . "': no matching filter.", debug => 1); next; } $self->{vm}->{$name} = { name => $name, running_state => lc($_->{vmRunState}) }; $self->{global}->{ lc($_->{vmRunState}) }++ if (defined($self->{global}->{ lc($_->{vmRunState}) })); $self->{global}->{total}++; } } 1; __END__ =head1 MODE Check virtual machines. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='status' =item B<--filter-name> Filter virtual machines by name (can be a regexp). =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{running_status}, %{name} =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{running_status}, %{name} =item B<--critical-status> Set critical threshold for status. Can used special variables like: %{running_status}, %{name} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'vm-running', 'vm-stopped'. =back =cut centreon-plugins-20220113/apps/oracle/ovm/api/plugin.pm000066400000000000000000000031731417000230700226560ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::oracle::ovm::api::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} = { 'discovery' => 'apps::oracle::ovm::api::mode::discovery', 'file-servers' => 'apps::oracle::ovm::api::mode::fileservers', 'manager' => 'apps::oracle::ovm::api::mode::manager', 'server-pools' => 'apps::oracle::ovm::api::mode::serverpools', 'servers' => 'apps::oracle::ovm::api::mode::servers', 'vm' => 'apps::oracle::ovm::api::mode::vm' }; $self->{custom_modes}->{rest} = 'apps::oracle::ovm::api::custom::rest'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Oracle VM Manager using API. =cut centreon-plugins-20220113/apps/pacemaker/000077500000000000000000000000001417000230700201275ustar00rootroot00000000000000centreon-plugins-20220113/apps/pacemaker/local/000077500000000000000000000000001417000230700212215ustar00rootroot00000000000000centreon-plugins-20220113/apps/pacemaker/local/mode/000077500000000000000000000000001417000230700221455ustar00rootroot00000000000000centreon-plugins-20220113/apps/pacemaker/local/mode/clustat.pm000066400000000000000000000115431417000230700241660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::pacemaker::local::mode::clustat; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use XML::Simple; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); my %map_node_state = ( 0 => 'down', 1 => 'up', 2 => 'clean' ); sub custom_state_output { my ($self, %options) = @_; return sprintf("state is '%s'", $self->{result_values}->{state}); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'nodes', type => 1, cb_prefix_output => 'prefix_node_output', message_multiple => 'All nodes are ok' }, { name => 'groups', type => 1, cb_prefix_output => 'prefix_group_output', message_multiple => 'All groups/resources are ok' } ]; $self->{maps_counters}->{nodes} = [ { label => 'node', type => 2, critical_default => '%{state} !~ /up|clean/', set => { key_values => [ { name => 'state' }, { name => 'display' } ], closure_custom_output => $self->can('custom_state_output'), closure_custom_threshold_check => \&catalog_status_threshold_ng, closure_custom_perfdata => sub { return 0; } } } ]; $self->{maps_counters}->{groups} = [ { label => 'group', type => 2, critical_default => '%{state} !~ /starting|started/', set => { key_values => [ { name => 'state' }, { name => 'display' } ], closure_custom_output => $self->can('custom_state_output'), closure_custom_threshold_check => \&catalog_status_threshold_ng, closure_custom_perfdata => sub { return 0; } } } ]; } sub prefix_node_output { my ($self, %options) = @_; return "Node: '" . $options{instance_value}->{display} . "' "; } sub prefix_group_output { my ($self, %options) = @_; return "Resource group: '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-node:s' => { name => 'filter_node' }, 'filter-groups:s' => { name => 'filter_groups' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my ($stdout) = $options{custom}->execute_command( command => 'clustat', command_path => '/usr/sbin', command_options => '-x 2>&1' ); my $clustat_hash = XMLin($stdout); foreach my $node (keys %{$clustat_hash->{nodes}->{node}}) { if (defined($self->{option_results}->{filter_node}) && $self->{option_results}->{filter_node} ne '' && $node !~ /$self->{option_results}->{filter_node}/) { $self->{output}->output_add(long_msg => "skipping peer '" . $node . "': no matching filter.", debug => 1); next; } $self->{nodes}->{$node} = { display => $node, state => $map_node_state{$clustat_hash->{nodes}->{node}->{$node}->{state}} }; } foreach my $group_name (keys %{$clustat_hash->{groups}->{group}}) { if (defined($self->{option_results}->{filter_group}) && $self->{option_results}->{filter_group} ne '' && $group_name !~ /$self->{option_results}->{filter_group}/) { $self->{output}->output_add(long_msg => "skipping peer '" . $group_name . "': no matching filter.", debug => 1); next; } $self->{groups}->{$group_name} = { display => $group_name, state => $clustat_hash->{groups}->{group}->{$group_name}->{state_str} }; } } 1; __END__ =head1 MODE Check Cluster Resource Manager (need 'clustat' command). Should be executed on a cluster node. Command used: /usr/sbin/clustat -x 2>&1 =over 8 =item B<--warning-*> Can be ('group','node') Warning threshold for status. =item B<--critical-*> Can be ('group','node') Critical threshold for status. (Default: --critical-node '%{state} !~ /up|clean/' --critical-group '%{state} !~ /started|starting/') =back =cut centreon-plugins-20220113/apps/pacemaker/local/mode/constraints.pm000066400000000000000000000072651417000230700250640ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::pacemaker::local::mode::constraints; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'resource:s' => { name => 'resource' }, 'warning' => { name => 'warning' } }); $self->{threshold} = 'CRITICAL'; return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => "Please set the resource name with --resource option"); $self->{output}->option_exit(); } $self->{threshold} = 'WARNING' if (defined $self->{option_results}->{warning}); } sub parse_output { my ($self, %options) = @_; $self->{output}->output_add( severity => 'OK', short_msg => sprintf("Resource '%s' constraint location is OK", $self->{option_results}->{resource}) ); if ($options{output} =~ /Connection to cluster failed\:(.*)/i ) { $self->{output}->output_add( severity => 'CRITICAL', short_msg => "Connection to cluster FAILED: $1" ); return ; } my @lines = split /\n/, $options{output}; foreach my $line (@lines) { next if $line !~ /^\s+:\sNode/; if ($line =~ /^\s+:\sNode/) { $self->{output}->output_add(long_msg => sprintf('Processed %s', $line), debug => 1); $line =~ /^\s+:\sNode\s([a-zA-Z0-9-_]+)\s+\(score=([a-zA-Z0-9-_]+),\sid=([a-zA-Z0-9-_]+)/; my ($node, $score, $rule) = ($1, $2, $3); if ($score eq '-INFINITY' && $rule =~ /^cli-ban/) { $self->{output}->output_add( severity => $self->{threshold}, short_msg => sprintf("Resource '%s' is locked on node '%s' ('%s')", $self->{option_results}->{resource}, $node, $rule) ); } } else { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => "ERROR: $line" ); } } } sub run { my ($self, %options) = @_; my ($stdout) = $options{custom}->execute_command( command => 'crm_resource', command_path => '/usr/sbin', command_options => '--constraints -r ' . $self->{option_results}->{resource} ); $self->parse_output(output => $stdout); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check that a resource has no location constraint (migrate without unmigrate) Can be executed from any cluster node. Command used: /usr/sbin/crm_resource --constraints -r resource_name =over 8 =item B<--resource> Set the resource name you want to check =item B<--warning> Return a warning instead of a critical =back =cut centreon-plugins-20220113/apps/pacemaker/local/mode/crm.pm000066400000000000000000000502371417000230700232730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::pacemaker::local::mode::crm; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_resource_threshold { my ($self, %options) = @_; my $status = catalog_status_threshold_ng($self, %options); if (defined($self->{instance_mode}->{resources_check}->{ $self->{result_values}->{name} }) && $self->{instance_mode}->{resources_check}->{ $self->{result_values}->{name} } ne $self->{result_values}->{node}) { return $self->{output}->get_most_critical(status => [ $status, 'warning' ]); } return $status; } sub custom_connection_status_output { my ($self, %options) = @_; return sprintf( 'connection status: %s [error: %s]', $self->{result_values}->{connection_status}, $self->{result_values}->{connection_error} ); } sub custom_quorum_status_output { my ($self, %options) = @_; return sprintf( 'quorum status: %s', $self->{result_values}->{quorum_status} ); } sub custom_nodes_online_output { my ($self, %options) = @_; return sprintf( 'online: %s [%s]', $self->{result_values}->{online}, $self->{result_values}->{online_names} ); } sub custom_nodes_offline_output { my ($self, %options) = @_; return sprintf( 'offline: %s [%s]', $self->{result_values}->{offline}, $self->{result_values}->{offline_names} ); } sub custom_nodes_standby_output { my ($self, %options) = @_; return sprintf( 'standby: %s [%s]', $self->{result_values}->{standby}, $self->{result_values}->{standby_names} ); } sub custom_resource_status_output { my ($self, %options) = @_; return sprintf( 'status: %s [node: %s] [unmanaged: %s]', $self->{result_values}->{status}, $self->{result_values}->{node}, $self->{result_values}->{is_unmanaged} ); } sub custom_clone_resource_status_output { my ($self, %options) = @_; return sprintf( 'status: %s [masters: %s] [slaves: %s] [unmanaged: %s]', $self->{result_values}->{status}, $self->{result_values}->{masters_nodes_name}, $self->{result_values}->{slaves_nodes_name}, $self->{result_values}->{is_unmanaged} ); } sub prefix_rsc_output { my ($self, %options) = @_; return "resource '" . $options{instance_value}->{name} . "' "; } sub prefix_clone_rsc_output { my ($self, %options) = @_; return "clone resource '" . $options{instance_value}->{name} . "' "; } sub prefix_nodes_output { my ($self, %options) = @_; return 'nodes '; } sub cluster_long_output { my ($self, %options) = @_; return 'checking cluster'; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'cluster', type => 3, cb_long_output => 'cluster_long_output', indent_long_output => ' ', group => [ { name => 'connection', type => 0, display_short => 0, skipped_code => { -10 => 1 } }, { name => 'quorum', type => 0, display_short => 0, skipped_code => { -10 => 1 } }, { name => 'nodes', type => 0, display_short => 0, cb_prefix_output => 'prefix_nodes_output', skipped_code => { -10 => 1 } }, { name => 'actions', type => 0, display_short => 0, skipped_code => { -10 => 1 } }, ] }, { name => 'resources', type => 1, display_short => 0, cb_prefix_output => 'prefix_rsc_output', skipped_code => { -10 => 1 } }, { name => 'clone_resources', type => 1, display_short => 0, cb_prefix_output => 'prefix_clone_rsc_output', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{connection} = [ { label => 'connection-status', type => 2, critical_default => '%{connection_status} =~ /failed/i', set => { key_values => [ { name => 'connection_status' }, { name => 'connection_error' } ], closure_custom_output => $self->can('custom_connection_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{quorum} = [ { label => 'quorum-status', type => 2, critical_default => '%{quorum_status} =~ /noQuorum/i', set => { key_values => [ { name => 'quorum_status' } ], closure_custom_output => $self->can('custom_quorum_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{nodes} = [ { label => 'nodes-online', nlabel => 'cluster.nodes.online.count', set => { key_values => [ { name => 'online' }, { name => 'online_names' } ], closure_custom_output => $self->can('custom_nodes_online_output'), perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'nodes-offline', nlabel => 'cluster.nodes.offline.count', set => { key_values => [ { name => 'offline' }, { name => 'offline_names' } ], closure_custom_output => $self->can('custom_nodes_offline_output'), perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'nodes-standby', nlabel => 'cluster.nodes.standby.count', set => { key_values => [ { name => 'standby' }, { name => 'standby_names' } ], closure_custom_output => $self->can('custom_nodes_standby_output'), perfdatas => [ { template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{actions} = [ { label => 'cluster-actions-failed', nlabel => 'cluster.actions.failed.count', set => { key_values => [ { name => 'failed' } ], output_template => 'actions failed: %s', perfdatas => [ { template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{resources} = [ { label => 'resource-status', type => 2, critical_default => '%{status} =~ /stopped|failed/i', set => { key_values => [ { name => 'status' }, { name => 'is_unmanaged' }, { name => 'node' }, { name => 'name' } ], closure_custom_output => $self->can('custom_resource_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => $self->can('custom_resource_threshold') } }, { label => 'resource-actions-failed', nlabel => 'resource.actions.failed.count', set => { key_values => [ { name => 'failed_actions' } ], output_template => 'actions failed: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } }, { label => 'resource-migration-failed', nlabel => 'resource.migration.failed.count', set => { key_values => [ { name => 'failed_migration' } ], output_template => 'migration failed: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{clone_resources} = [ { label => 'clone-resource-status', type => 2, critical_default => '%{status} =~ /failed/i', set => { key_values => [ { name => 'name' }, { name => 'status' }, { name => 'is_unmanaged' }, { name => 'masters_nodes_name' }, { name => 'slaves_nodes_name' } ], closure_custom_output => $self->can('custom_clone_resource_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'clone-resource-actions-failed', nlabel => 'clone_resource.actions.failed.count', set => { key_values => [ { name => 'failed_actions' } ], output_template => 'actions failed: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } }, { label => 'clone-resource-migration-failed', nlabel => 'clone_resource.migration.failed.count', set => { key_values => [ { name => 'failed_migration' } ], output_template => 'migration failed: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-resource-name:s' => { name => 'filter_resource_name' }, 'resources:s' => { name => 'resources' }, # legacy 'ignore-failed-actions:s@' => { name => 'ignore_failed_actions' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (defined($self->{option_results}->{resources})) { foreach (split(/,/, $self->{option_results}->{resources})) { my ($rsc_name, $node) = split(/:/, $_); if (defined($rsc_name) && $rsc_name ne '' && defined($node) && $node ne '') { $self->{resources_check}->{$rsc_name} = $node; } } } } sub parse_crm { my ($self, %options) = @_; $self->{cluster} = { global => { connection => { connection_status => 'ok', connection_error => '-', }, quorum => { quorum_status => '-' }, nodes => { online => 0, online_names => '', offline => 0, offline_names => '', standby => 0, standby_names => '', }, actions => { failed => 0 } } }; $self->{resources} = {}; $self->{clone_resources} = {}; my @lines = split /\n/, $options{crm_out}; my $num_lines = scalar(@lines); for (my $i = 0; $i < $num_lines; $i++) { if ($lines[$i] =~ /Connection to cluster failed\:(.*)/i ) { $self->{cluster}->{global}->{connection}->{connection_status} = 'failed'; $self->{cluster}->{global}->{connection}->{connection_error} = $1; } elsif ($lines[$i] =~ /Current DC:/) { $self->{cluster}->{global}->{quorum}->{quorum_status} = 'ok'; if ($lines[$i] !~ /partition with quorum$/) { $self->{cluster}->{global}->{quorum}->{quorum_status} = 'noQuorum'; } } elsif ($lines[$i] =~ /^(?:(?:\s*\*\s*)?(offline|online)):\s*\[\s*(.*?)\s*\]/i) { my @nodes = split(/\s+/, $2); $self->{cluster}->{global}->{nodes}->{lc($1)} = scalar(@nodes); $self->{cluster}->{global}->{nodes}->{lc($1) . '_names'} = join(' ', @nodes); } elsif ($lines[$i] =~ /^node\s+(\S+?):\s*standby/i) { $self->{cluster}->{global}->{nodes}->{standby}++; $self->{cluster}->{global}->{nodes}->{standby_names} .= ' ' . $1; } elsif ($lines[$i] =~ /\s*([0-9a-zA-Z_\-]+)\s+\(\S+\)\:\s+Started\s+([0-9a-zA-Z_\-]+)/) { my ($name, $node) = ($1, $2); if (defined($self->{option_results}->{filter_resource_name}) && $self->{option_results}->{filter_resource_name} ne '' && $name !~ /$self->{option_results}->{filter_resource_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $name . "': no matching filter.", debug => 1); next; } $self->{resources}->{$name} = { name => $name, failed_actions => 0, failed_migration => 0, status => 'started', node => $node, is_unmanaged => 'no' }; $self->{resources}->{$name}->{is_unmanaged} = 'yes' if ($lines[$i] =~ /unmanaged/); $self->{resources}->{$name}->{status} = 'failed' if ($lines[$i] =~ /FAILED/i); } elsif ($lines[$i] =~ /\s*([0-9a-zA-Z_\-]+)\s+\(\S+\)\:\s+Stopped/ || $lines[$i] =~ /\s*([0-9a-zA-Z_\-]+)\s+\(\S+\)\:\s+\(\S+\)\s+Stopped/) { my $name = $1; if (defined($self->{option_results}->{filter_resource_name}) && $self->{option_results}->{filter_resource_name} ne '' && $name !~ /$self->{option_results}->{filter_resource_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $name . "': no matching filter.", debug => 1); next; } $self->{resources}->{$name} = { name => $name, failed_actions => 0, failed_migration => 0, status => 'stopped', node => '-', is_unmanaged => 'no' }; $self->{resources}->{$name}->{is_unmanaged} = 'yes' if ($lines[$i] =~ /unmanaged/); $self->{resources}->{$name}->{status} = 'failed' if ($lines[$i] =~ /FAILED/i); } elsif ($lines[$i] =~ /Master\/Slave.*\[(.*)\]/i) { #Master/Slave Set: ms_mysql-master [ms_mysql] # ms_mysql (ocf::heartbeat:mysql-centreon): FAILED node-db-passive # Masters: [ node-db-active ] # Stopped: [ node-map-active node-map-passive ] #Master/Slave Set: ms_mysql-master [ms_mysql] # Masters: [ node-db-active ] # Slaves: [ node-db-passive ] # Stopped: [ node-map-active node-map-passive ] #Master/Slave Set: ms_mysql-master [ms_mysql] # ms_mysql (ocf::heartbeat:mysql-centreon): Master node-db-active (unmanaged) # ms_mysql (ocf::heartbeat:mysql-centreon): Slave node-db-passive (unmanaged) # Stopped: [ cps-map-active cps-map-passive ] my $name = $1; if (defined($self->{option_results}->{filter_resource_name}) && $self->{option_results}->{filter_resource_name} ne '' && $name !~ /$self->{option_results}->{filter_resource_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $name . "': no matching filter.", debug => 1); next; } $self->{clone_resources}->{$name} = { name => $name, failed_actions => 0, failed_migration => 0, status => 'ok', is_unmanaged => 'no', masters_nodes_name => '', slaves_nodes => 0, slaves_nodes_name => '', stopped_nodes => 0, stopped_nodes_name => '' }; for (; $i < $num_lines; $i++) { if ($lines[$i + 1] =~ /^\s+(masters|slaves|stopped):\s*\[\s*(.*?)\s*\]/i) { my $type = lc($1); my @nodes = split(/\s+/, $2); $self->{clone_resources}->{$name}->{$type . '_nodes'} = scalar(@nodes); $self->{clone_resources}->{$name}->{$type . '_nodes_name'} = join(' ', @nodes); } elsif ($lines[$i + 1] =~ /^\s+$name\s+.*unmanaged/) { $self->{clone_resources}->{$name}->{is_unmanaged} = 'yes'; } elsif ($lines[$i + 1] =~ /^\s+$name\s+.*FAILED/i) { $self->{clone_resources}->{$name}->{status} = 'failed'; } else { last; } } } elsif ($lines[$i] =~ /^Failed\s+(?:(Resource|Fencing)\s+)?actions:/i) { for (; $i < $num_lines; $i++) { last if ($lines[$i + 1] !~ /^\*\s+/); my $skip = 0; foreach (@{$self->{option_results}->{ignore_failed_actions}}) { if ($lines[$i + 1] =~ /$_/) { $skip = 1; last; } } next if ($skip == 1); if ($lines[$i + 1] =~ /^\*\s+(\S+?)_(start|stop|status|monitor|promote|demote)_/) { $self->{clone_resources}->{$1}->{failed_actions}++ if (defined($self->{clone_resources}->{$1})); $self->{resources}->{$1}->{failed_actions}++ if (defined($self->{resources}->{$1})); } $self->{cluster}->{global}->{actions}->{failed}++; } } elsif ($lines[$i] =~ /\s*(\S+?):.*migration.*fail-count=(\d+)/i) { $self->{clone_resources}->{$1}->{failed_migration} += $2 if (defined($self->{clone_resources}->{$1})); $self->{resources}->{$1}->{failed_migration} += $2 if (defined($self->{resources}->{$1})); } } } sub manage_selection { my ($self, %options) = @_; my ($stdout) = $options{custom}->execute_command( command => 'crm_mon', command_path => '/usr/sbin', command_options => '-1 -r -f 2>&1' ); $self->parse_crm(crm_out => $stdout); $self->{output}->output_add(short_msg => 'Cluster is ok'); } 1; __END__ =head1 MODE Check cluster resource manager (need 'crm_mon' command). Should be executed on a cluster node. Command used: /usr/sbin/crm_mon -1 -r -f 2>&1 =over 8 =item B<--filter-resource-name> Filter resource (also clone resource) by name (can be a regexp). =item B<--warning-connection-status> Set warning threshold for status. Can used special variables like: %{connection_status}, %{connection_error} =item B<--critical-connection-status> Set critical threshold for status (Default: '%{connection_status} =~ /failed/i'). Can used special variables like: %{connection_status}, %{connection_error} =item B<--warning-quorum-status> Set warning threshold for status. Can used special variables like: %{quorum_status} =item B<--critical-quorum-status> Set critical threshold for status (Default: '%{quorum_status} =~ /noQuorum/i'). Can used special variables like: %{quorum_status} =item B<--warning-resource-status> Set warning threshold for status. Can used special variables like: %{name}, %{status}, %{node}, %{is_unmanaged} =item B<--critical-resource-status> Set critical threshold for status (Default: '%{status} =~ /stopped|failed/i'). Can used special variables like: %{name}, %{status}, %{node}, %{is_unmanaged} =item B<--warning-clone-resource-status> Set warning threshold for status. Can used special variables like: %{name}, %{status}, %{masters_nodes_name}, %{slaves_nodes_name}, %{is_unmanaged} =item B<--critical-clone-resource-status> Set critical threshold for status (Default: '%{status} =~ /failed/i'). Can used special variables like: %{name}, %{status}, %{masters_nodes_name}, %{slaves_nodes_name}, %{is_unmanaged} =item B<--ignore-failed-actions> Failed actions errors (that match) are skipped. =item B<--resources> If resources not started on the node specified, send a warning message: (format: :,:,...) =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'cluster-actions-failed', 'clone-resource-actions-failed', 'clone-resource-migration-failed', 'nodes-online', 'nodes-offline', 'nodes-standby', 'resource-actions-failed', 'resource-migration-failed'. =back =cut centreon-plugins-20220113/apps/pacemaker/local/plugin.pm000066400000000000000000000027121417000230700230570ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::pacemaker::local::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} = { 'clustat' => 'apps::pacemaker::local::mode::clustat', 'constraints' => 'apps::pacemaker::local::mode::constraints', 'crm' => 'apps::pacemaker::local::mode::crm' }; $self->{custom_modes}->{cli} = 'centreon::plugins::script_custom::cli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Pacemaker through local commands (the plugin can use SSH). =cut centreon-plugins-20220113/apps/pfsense/000077500000000000000000000000001417000230700176425ustar00rootroot00000000000000centreon-plugins-20220113/apps/pfsense/fauxapi/000077500000000000000000000000001417000230700212775ustar00rootroot00000000000000centreon-plugins-20220113/apps/pfsense/fauxapi/custom/000077500000000000000000000000001417000230700226115ustar00rootroot00000000000000centreon-plugins-20220113/apps/pfsense/fauxapi/custom/api.pm000066400000000000000000000155041417000230700237250ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::pfsense::fauxapi::custom::api; use strict; use warnings; use centreon::plugins::http; use POSIX; use JSON::XS; use Digest::SHA; 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 => { 'api-key:s' => { name => 'api_key' }, 'api-secret:s' => { name => 'api_secret' }, 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'timeout:s' => { name => 'timeout' }, 'unknown-http-status:s' => { name => 'unknown_http_status' }, 'warning-http-status:s' => { name => 'warning_http_status' }, 'critical-http-status:s' => { name => 'critical_http_status' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{api_key} = (defined($self->{option_results}->{api_key})) ? $self->{option_results}->{api_key} : ''; $self->{api_secret} = (defined($self->{option_results}->{api_secret})) ? $self->{option_results}->{api_secret} : ''; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300'; $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; if (!defined($self->{hostname}) || $self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } if ($self->{api_key} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-key option."); $self->{output}->option_exit(); } if ($self->{api_secret} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-secret option."); $self->{output}->option_exit(); } return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; } sub build_fauxapi_header { my ($self, %options) = @_; my $timestamp = POSIX::strftime('%Y%m%dZ%H%M%S', gmtime()); my $nonce = sprintf('%08X', rand(0xFFFFFFFF)); my $hash = Digest::SHA::sha256_hex($self->{api_secret} . $timestamp . $nonce); return sprintf( '%s:%s:%s:%s', $self->{api_key}, $timestamp, $nonce, $hash ); } sub settings { my ($self, %options) = @_; return if (defined($self->{settings_done})); $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->add_header(key => 'Content-Type', value => 'application/json'); $self->{http}->set_options(%{$self->{option_results}}); $self->{settings_done} = 1; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub get_port { my ($self, %options) = @_; return $self->{port}; } sub request_api { my ($self, %options) = @_; $self->settings(); my $fauxapi_auth = $self->build_fauxapi_header(); my $content = $self->{http}->request( url_path => '/fauxapi/v1/?action=' . $options{action}, unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status}, curl_backend_options => { header => ['fauxapi-auth:: ' . $fauxapi_auth] }, lwp_backend_options => { header => [':fauxapi-auth: ' . $fauxapi_auth] } ); if (!defined($content) || $content eq '') { $self->{output}->add_option_msg(short_msg => "API returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } return $decoded; } 1; __END__ =head1 NAME pfsense FauxAPI =head1 REST API OPTIONS pfsense FauxAPI =over 8 =item B<--hostname> pfsense hostname. =item B<--port> Port used (Default: 443) =item B<--proto> Specify https if needed (Default: 'https') =item B<--api-key> API key. =item B<--api-secret> API secret. =item B<--timeout> Set timeout in seconds (Default: 10). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/pfsense/fauxapi/mode/000077500000000000000000000000001417000230700222235ustar00rootroot00000000000000centreon-plugins-20220113/apps/pfsense/fauxapi/mode/backupfiles.pm000066400000000000000000000066461417000230700250650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::pfsense::fauxapi::mode::backupfiles; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use POSIX; use DateTime; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'total', nlabel => 'backups.total.count', set => { key_values => [ { name => 'total' } ], output_template => 'number of backups: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'time-last', nlabel => 'backups.time.last.seconds', set => { key_values => [ { name => 'since' }, { name => 'readable_since' } ], output_template => 'last backup time: %s', output_use => 'readable_since', perfdatas => [ { template => '%s', min => 0, unit => 'ms' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->request_api(action => 'config_backup_list'); $self->{global} = { total => 0 }; my $recent_time = 0; if (defined($results->{data}->{backup_files})) { foreach (@{$results->{data}->{backup_files}}) { # 20200511Z094516 return if ($_->{timestamp} !~ /^\s*(\d{4})(\d{2})(\d{2})Z(\d{2})(\d{2})(\d{2})/); my $dt = DateTime->new( year => $1, month => $2, day => $3, hour => $4, minute => $5, second => $6, time_zone => 'GMT' ); my $time = $dt->epoch(); $recent_time = $time if ($recent_time < $time); $self->{global}->{total}++; } } if ($recent_time > 0) { $self->{global}->{since} = POSIX::strftime('%s', gmtime()) - $recent_time; $self->{global}->{readable_since} = centreon::plugins::misc::change_seconds(value => $self->{global}->{since}); } } 1; __END__ =head1 MODE Check backup files. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='total' =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'total', 'time-last'. =back =cut centreon-plugins-20220113/apps/pfsense/fauxapi/mode/gateways.pm000066400000000000000000000126171417000230700244140ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::pfsense::fauxapi::mode::gateways; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf('status: ' . $self->{result_values}->{status}); } sub prefix_gateway_output { my ($self, %options) = @_; return "Gateway '" . $options{instance_value}->{display} . "' packets "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'gateways', type => 1, cb_prefix_output => 'prefix_gateway_output', message_multiple => 'All gateways are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{gateways} = [ { label => 'status', type => 2, critical_default => '%{status} !~ /none/i', set => { key_values => [ { name => 'status' }, { name => 'display' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'packets-delay', nlabel => 'gateway.packets.delay.milliseconds', set => { key_values => [ { name => 'delay' }, { name => 'display' } ], output_template => 'delay: %.2f ms', perfdatas => [ { template => '%.2f', min => 0, unit => 'ms', label_extra_instance => 1 } ] } }, { label => 'packets-loss', nlabel => 'gateway.packets.loss.percentage', set => { key_values => [ { name => 'loss' }, { name => 'display' } ], output_template => 'loss: %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 } ] } }, { label => 'packets-stddev', nlabel => 'gateway.packets.stddev.milliseconds', set => { key_values => [ { name => 'stddev' }, { name => 'display' } ], output_template => 'stddev: %.2f ms', perfdatas => [ { template => '%.2f', min => 0, unit => 'ms', label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->request_api(action => 'gateway_status'); $self->{gateways} = {}; if (defined($results->{data}->{gateway_status})) { foreach (values %{$results->{data}->{gateway_status}}) { 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 gateway '" . $_->{name} . "': no matching filter.", debug => 1); next; } my $delay = $_->{delay} =~ /([0-9\.]+)/ ? $1 : undef; my $stddev = $_->{stddev} =~ /([0-9\.]+)/ ? $1 : undef; my $loss = $_->{loss} =~ /([0-9\.]+)/ ? $1 : undef; $self->{gateways}->{ $_->{name} } = { display => $_->{name}, status => $_->{status}, delay => $delay, stddev => $stddev, loss => $loss }; } } if (scalar(keys %{$self->{gateways}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'no gateway found'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check gateways. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='status' =item B<--filter-name> Filter gateway name (can be a regexp). =item B<--unknown-status> Set unknon threshold for status (Default: ''). Can used special variables like: %{status}, %{display} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{display} =item B<--critical-status> Set critical threshold for status (Default: '%{status} !~ /none/i'). Can used special variables like: %{status}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'packets-delay' (ms), 'packets-loss' (%), 'packets-stddev' (ms). =back =cut centreon-plugins-20220113/apps/pfsense/fauxapi/mode/rules.pm000066400000000000000000000100421417000230700237100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::pfsense::fauxapi::mode::rules; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); sub prefix_rule_output { my ($self, %options) = @_; return "Rule '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'rules', type => 1, cb_prefix_output => 'prefix_rule_output', message_multiple => 'All rules are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'total', nlabel => 'rules.total.count', set => { key_values => [ { name => 'total' } ], output_template => 'number of rules: %s', perfdatas => [ { template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{rules} = [ { label => 'traffic', nlabel => 'rule.traffic.bitspersecond', set => { key_values => [ { name => 'traffic', per_second => 1 }, { name => 'display' } ], output_template => 'traffic: %s %s/s', output_change_bytes => 2, perfdatas => [ { template => '%s', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->request_api(action => 'rule_get'); $self->{global} = { total => 0 }; $self->{rules} = {}; if (defined($results->{data}->{rules})) { foreach (@{$results->{data}->{rules}}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $_->{rule} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping rule '" . $_->{name} . "': no matching filter.", debug => 1); next; } $self->{rules}->{ $_->{number} } = { display => $_->{rule}, traffic => $_->{bytes} * 8 }; $self->{global}->{total}++; } } $self->{cache_name} = 'pfsense_fauxapi_' . $options{custom}->get_hostname() . '_' . $options{custom}->get_port() . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')); } 1; __END__ =head1 MODE Check rules. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='traffic' =item B<--filter-name> Filter rule name (can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'traffic' (b/s). =back =cut centreon-plugins-20220113/apps/pfsense/fauxapi/mode/system.pm000066400000000000000000000102531417000230700241060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::pfsense::fauxapi::mode::system; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_tcp_usage_output { my ($self, %options) = @_; my $msg = sprintf( 'tcp connections total: %s used: %s (%.2f%%) free: %s (%.2f%%)', $self->{result_values}->{tcp_conn_total}, $self->{result_values}->{tcp_conn_used}, $self->{result_values}->{tcp_conn_used_prct}, $self->{result_values}->{tcp_conn_free}, $self->{result_values}->{tcp_conn_free_prct} ); return $msg; } sub prefix_global_output { my ($self, %options) = @_; return 'System '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'connections-tcp-usage', nlabel => 'system.connections.tcp.usage.count', set => { key_values => [ { name => 'tcp_conn_used' }, { name => 'tcp_conn_total' }, { name => 'tcp_conn_free' }, { name => 'tcp_conn_used_prct' }, { name => 'tcp_conn_free_prct' } ], closure_custom_output => $self->can('custom_tcp_usage_output'), perfdatas => [ { template => '%s', min => 0, max => 'tcp_conn_total' } ] } }, { label => 'connections-tcp-usage-prct', nlabel => 'system.connections.tcp.usage.percentage', display_ok => 0, set => { key_values => [ { name => 'tcp_conn_used_prct' } ], output_template => 'tcp connections used: %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%' } ] } }, { label => 'temperature', nlabel => 'system.temperature.celsius', set => { key_values => [ { name => 'temperature' } ], output_template => 'temperature: %s C', perfdatas => [ { template => '%s', unit => 'C' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->request_api(action => 'system_stats'); $self->{global} = {}; if (defined($results->{data}->{stats})) { if ($results->{data}->{stats}->{pfstate} =~ /^(\d+)\/(\d+)/) { $self->{global}->{tcp_conn_used} = $1; $self->{global}->{tcp_conn_total} = $2; $self->{global}->{tcp_conn_free} = $2 - $1; $self->{global}->{tcp_conn_used_prct} = $1 * 100 / $2; $self->{global}->{tcp_conn_free_prct} = 100 - $self->{global}->{tcp_conn_used_prct}; } $self->{global}->{temperature} = $results->{data}->{stats}->{temp}; } } 1; __END__ =head1 MODE Check system. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='temperature' =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'temperature' (C), 'connections-tcp-usage', 'connections-tcp-usage-prct' (%). =back =cut centreon-plugins-20220113/apps/pfsense/fauxapi/plugin.pm000066400000000000000000000027471417000230700231450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::pfsense::fauxapi::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} = { 'backup-files' => 'apps::pfsense::fauxapi::mode::backupfiles', 'gateways' => 'apps::pfsense::fauxapi::mode::gateways', 'system' => 'apps::pfsense::fauxapi::mode::system', 'rules' => 'apps::pfsense::fauxapi::mode::rules' }; $self->{custom_modes}{api} = 'apps::pfsense::fauxapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check pfsense with FauxAPI. =cut centreon-plugins-20220113/apps/pfsense/snmp/000077500000000000000000000000001417000230700206175ustar00rootroot00000000000000centreon-plugins-20220113/apps/pfsense/snmp/mode/000077500000000000000000000000001417000230700215435ustar00rootroot00000000000000centreon-plugins-20220113/apps/pfsense/snmp/mode/listpfinterfaces.pm000066400000000000000000000056121417000230700254520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::pfsense::snmp::mode::listpfinterfaces; use base qw(centreon::plugins::mode); use strict; use warnings; my $oid_pfInterfacesIfDescr = '.1.3.6.1.4.1.12325.1.200.1.8.2.1.2'; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $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_pfInterfacesIfDescr, nothing_quit => 1); $self->{pfint} = {}; 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 pfInteface '" . $snmp_result->{$oid} . "'.", debug => 1); next; } $self->{pfint}->{$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->{pfint}}) { $self->{output}->output_add(long_msg => "'" . $name . "'"); } $self->{output}->output_add(severity => 'OK', short_msg => 'List pfIntefaces:'); $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->{pfint}}) { $self->{output}->add_disco_entry(name => $name); } } 1; __END__ =head1 MODE List pfInteface. =over 8 =item B<--filter-name> Filter by pfinterface name. =back =cut centreon-plugins-20220113/apps/pfsense/snmp/mode/packetstats.pm000066400000000000000000000123021417000230700244250ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::pfsense::snmp::mode::packetstats; 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 => 'global', type => 0, message_separator => ' - ' } ]; $self->{maps_counters}->{global} = [ { label => 'match', nlabel => 'packets.matched.persecond', set => { key_values => [ { name => 'pfCounterMatch', per_second => 1 } ], output_template => 'Packets Matched Filter Rule : %.2f/s', perfdatas => [ { label => 'match', template => '%.2f', unit => '/s', min => 0 } ] } }, { label => 'badoffset', nlabel => 'packets.badoffset.persecond', set => { key_values => [ { name => 'pfCounterBadOffset', per_second => 1 } ], output_template => 'Bad Offset Packets : %.2f/s', perfdatas => [ { label => 'bad_offset', template => '%.2f', unit => '/s', min => 0 } ] } }, { label => 'fragment', nlabel => 'packets.fragmented.persecond', set => { key_values => [ { name => 'pfCounterFragment', per_second => 1 } ], output_template => 'Fragmented Packets : %.2f/s', perfdatas => [ { label => 'fragment', template => '%.2f', unit => '/s', min => 0 } ] } }, { label => 'short', nlabel => 'packets.short.persecond', set => { key_values => [ { name => 'pfCounterShort', per_second => 1 } ], output_template => 'Short Packets : %.2f/s', perfdatas => [ { label => 'short', template => '%.2f', unit => '/s', min => 0 } ] } }, { label => 'normalize', nlabel => 'packets.normalized.persecond',set => { key_values => [ { name => 'pfCounterNormalize', per_second => 1 } ], output_template => 'Normalized Packets : %.2f/s', perfdatas => [ { label => 'normalize', template => '%.2f', unit => '/s', min => 0 }, ], } }, { label => 'memdrop', nlabel => 'packets.memorydropped.persecond',set => { key_values => [ { name => 'pfCounterMemDrop', per_second => 1 } ], output_template => 'Dropped Packets Due To Memory : %.2f/s', perfdatas => [ { label => 'memdrop', template => '%.2f', unit => '/s', min => 0 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; if ($options{snmp}->is_snmpv1()) { $self->{output}->add_option_msg(short_msg => "Can't check SNMP 64 bits counters with SNMPv1."); $self->{output}->option_exit(); } my %oids = ( pfCounterMatch => '.1.3.6.1.4.1.12325.1.200.1.2.1.0', pfCounterBadOffset => '.1.3.6.1.4.1.12325.1.200.1.2.2.0', pfCounterFragment => '.1.3.6.1.4.1.12325.1.200.1.2.3.0', pfCounterShort => '.1.3.6.1.4.1.12325.1.200.1.2.4.0', pfCounterNormalize => '.1.3.6.1.4.1.12325.1.200.1.2.5.0', pfCounterMemDrop => '.1.3.6.1.4.1.12325.1.200.1.2.6.0' ); my $snmp_result = $options{snmp}->get_leef(oids => [values %oids], nothing_quit => 1); $self->{global} = {}; foreach (keys %oids) { $self->{global}->{$_} = $snmp_result->{$oids{$_}}; } $self->{cache_name} = "pfsense_" . $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')); } 1; __END__ =head1 MODE Check global packet statistics. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^match$' =item B<--warning-*> Threshold warning. Can be: 'match', 'badoffset', 'fragment', 'short', 'normalize', 'memdrop'. =item B<--critical-*> Threshold critical. Can be: 'match', 'badoffset', 'fragment', 'short', 'normalize', 'memdrop'. =back =cut centreon-plugins-20220113/apps/pfsense/snmp/mode/pfinterfaces.pm000066400000000000000000000155271417000230700245640ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::pfsense::snmp::mode::pfinterfaces; 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 => 'pfint', type => 1, cb_prefix_output => 'prefix_pfint_output', message_multiple => 'All pfInterfaes are ok' } ]; $self->{maps_counters}->{pfint} = [ { label => 'traffic-in-pass', nlabel => 'pfinterface.pass.traffic.in.bitspersecond', set => { key_values => [ { name => 'pfInterfacesIf4BytesInPass', per_second => 1 }, { name => 'display' } ], output_change_bytes => 2, output_template => 'Traffic In Pass : %s %s/s', perfdatas => [ { label => 'traffic_in_pass', template => '%.2f', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'traffic-out-pass', nlabel => 'pfinterface.pass.traffic.out.bitspersecond', set => { key_values => [ { name => 'pfInterfacesIf4BytesOutPass', per_second => 1 }, { name => 'display' } ], output_change_bytes => 2, output_template => 'Traffic Out Pass : %s %s/s', perfdatas => [ { label => 'traffic_out_pass', template => '%.2f', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'traffic-in-block', nlabel => 'pfinterface.block.traffic.in.bitspersecond', set => { key_values => [ { name => 'pfInterfacesIf4BytesInBlock', per_second => 1 }, { name => 'display' } ], output_change_bytes => 2, output_template => 'Traffic In Block : %s %s/s', perfdatas => [ { label => 'traffic_in_block', template => '%.2f', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'traffic-out-block', nlabel => 'pfinterface.block.traffic.out.bitspersecond', set => { key_values => [ { name => 'pfInterfacesIf4BytesOutBlock', per_second => 1 }, { name => 'display' } ], output_change_bytes => 2, output_template => 'Traffic Out Block : %s %s/s', perfdatas => [ { label => 'traffic_out_block', template => '%.2f', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub prefix_pfint_output { my ($self, %options) = @_; return "pfInterface '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } my $oid_pfInterfacesIfDescr = '.1.3.6.1.4.1.12325.1.200.1.8.2.1.2'; my $mapping = { pfInterfacesIf4BytesInPass => { oid => '.1.3.6.1.4.1.12325.1.200.1.8.2.1.7' }, pfInterfacesIf4BytesInBlock => { oid => '.1.3.6.1.4.1.12325.1.200.1.8.2.1.8' }, pfInterfacesIf4BytesOutPass => { oid => '.1.3.6.1.4.1.12325.1.200.1.8.2.1.9' }, pfInterfacesIf4BytesOutBlock => { oid => '.1.3.6.1.4.1.12325.1.200.1.8.2.1.10' } }; sub manage_selection { my ($self, %options) = @_; if ($options{snmp}->is_snmpv1()) { $self->{output}->add_option_msg(short_msg => "Can't check SNMP 64 bits counters with SNMPv1."); $self->{output}->option_exit(); } my $snmp_result = $options{snmp}->get_table(oid => $oid_pfInterfacesIfDescr, nothing_quit => 1); $self->{pfint} = {}; foreach my $oid (keys %{$snmp_result}) { $oid =~ /^$oid_pfInterfacesIfDescr\.(.*)$/; my $instance = $1; my $name = $snmp_result->{$oid}; 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 pfInterface '" . $name . "'.", debug => 1); next; } $self->{pfint}->{$instance} = { display => $name }; } $options{snmp}->load( oids => [ $mapping->{pfInterfacesIf4BytesInPass}->{oid}, $mapping->{pfInterfacesIf4BytesOutPass}->{oid}, $mapping->{pfInterfacesIf4BytesInBlock}->{oid}, $mapping->{pfInterfacesIf4BytesOutBlock}->{oid}, ], instances => [keys %{$self->{pfint}}], instance_regexp => '^(.*)$' ); $snmp_result = $options{snmp}->get_leef(nothing_quit => 1); foreach my $instance (keys %{$self->{pfint}}) { my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); foreach (keys %$mapping) { $self->{pfint}->{$instance}->{$_} = $result->{$_} * 8; } } if (scalar(keys %{$self->{pfint}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No pfInterface found."); $self->{output}->option_exit(); } $self->{cache_name} = 'pfsense_' . $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 pfInterfaces. =over 8 =item B<--warning-*> Threshold warning. Can be: 'traffic-in-pass', 'traffic-out-pass', 'traffic-in-block', 'traffic-out-block'. =item B<--critical-*> Threshold critical. Can be: 'traffic-in-pass', 'traffic-out-pass', 'traffic-in-block', 'traffic-out-block'. =item B<--filter-name> Filter by interface name (can be a regexp). =back =cut centreon-plugins-20220113/apps/pfsense/snmp/mode/runtime.pm000066400000000000000000000101371417000230700235660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::pfsense::snmp::mode::runtime; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::misc; use POSIX; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $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) = @_; $self->{snmp} = $options{snmp}; my $oid_pfsenseStatus = '.1.3.6.1.4.1.12325.1.200.1.1.1.0'; my $oid_pfsenseRuntime = '.1.3.6.1.4.1.12325.1.200.1.1.2.0'; my ($result, $valueStatus, $valueRuntime); $result = $self->{snmp}->get_leef(oids => [ $oid_pfsenseStatus, $oid_pfsenseRuntime ], nothing_quit => 1); $valueStatus = $result->{$oid_pfsenseStatus}; $valueRuntime = $result->{$oid_pfsenseRuntime}; if ($valueStatus == 1) { my $exit_code = $self->{perfdata}->threshold_check(value => $valueRuntime, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->perfdata_add(label => 'runtime', unit => 's', value => floor($valueRuntime / 100), 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("PfSense running since : %s", centreon::plugins::misc::change_seconds(value => floor($valueRuntime / 100)))); } else { $self->{output}->perfdata_add(label => 'runtime', unit => 's', value => 0, 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 => 'critical', short_msg => 'PfSense not running'); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check pfSense runtime. =over 8 =item B<--warning> Threshold warning in seconds. =item B<--critical> Threshold critical in seconds. =back =cut centreon-plugins-20220113/apps/pfsense/snmp/plugin.pm000066400000000000000000000026531417000230700224610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::pfsense::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} = { 'list-pfinterfaces' => 'apps::pfsense::snmp::mode::listpfinterfaces', 'packet-stats' => 'apps::pfsense::snmp::mode::packetstats', 'pfinterfaces' => 'apps::pfsense::snmp::mode::pfinterfaces', 'runtime' => 'apps::pfsense::snmp::mode::runtime' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check pfSense in SNMP. =cut centreon-plugins-20220113/apps/php/000077500000000000000000000000001417000230700167665ustar00rootroot00000000000000centreon-plugins-20220113/apps/php/apc/000077500000000000000000000000001417000230700175315ustar00rootroot00000000000000centreon-plugins-20220113/apps/php/apc/web/000077500000000000000000000000001417000230700203065ustar00rootroot00000000000000centreon-plugins-20220113/apps/php/apc/web/mode/000077500000000000000000000000001417000230700212325ustar00rootroot00000000000000centreon-plugins-20220113/apps/php/apc/web/mode/filecache.pm000066400000000000000000000255121417000230700235000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::php::apc::web::mode::filecache; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::http; use Digest::MD5 qw(md5_hex); sub custom_rr_calc { my ($self, %options) = @_; my $total = ($options{new_datas}->{$self->{instance} . '_hits'} - $options{old_datas}->{$self->{instance} . '_hits'}) + ($options{new_datas}->{$self->{instance} . '_misses'} - $options{old_datas}->{$self->{instance} . '_misses'}); if ($total == 0) { $self->{error_msg} = "skipped"; return -2; } $self->{result_values}->{rr_now} = $total / $options{delta_time}; return 0; } sub custom_hr_calc { my ($self, %options) = @_; my $total = ($options{new_datas}->{$self->{instance} . '_hits'} - $options{old_datas}->{$self->{instance} . '_hits'}); if ($total == 0) { $self->{error_msg} = "skipped"; return -2; } $self->{result_values}->{hr_now} = $total / $options{delta_time}; return 0; } sub custom_mr_calc { my ($self, %options) = @_; my $total = ($options{new_datas}->{$self->{instance} . '_misses'} - $options{old_datas}->{$self->{instance} . '_misses'}); if ($total == 0) { $self->{error_msg} = "skipped"; return -2; } $self->{result_values}->{mr_now} = $total / $options{delta_time}; return 0; } sub custom_hit_percent_now_calc { my ($self, %options) = @_; my $hits = ($options{new_datas}->{$self->{instance} . '_hits'} - $options{old_datas}->{$self->{instance} . '_hits'}); my $total = $hits + ($options{new_datas}->{$self->{instance} . '_misses'} - $options{old_datas}->{$self->{instance} . '_misses'}); if ($total == 0) { $self->{error_msg} = "skipped"; return -2; } $self->{result_values}->{hit_ratio_now} = $hits * 100 / $total; return 0; } sub custom_hit_percent_calc { my ($self, %options) = @_; my $hits = ($options{new_datas}->{$self->{instance} . '_hits'}); my $total = $hits + ($options{new_datas}->{$self->{instance} . '_misses'}); if ($total == 0) { $self->{error_msg} = "skipped"; return -2; } $self->{result_values}->{hit_ratio} = $hits * 100 / $total; return 0; } sub prefix_output { my ($self, %options) = @_; return 'Apc File Cache Information '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'fcache', type => 0, cb_prefix_output => 'prefix_output' } ]; $self->{maps_counters}->{fcache} = [ { label => 'request-rate', nlabel => 'filecache.requests.persecond', set => { key_values => [ { name => 'rr' } ], output_template => 'Request Rate (global): %.2f', perfdatas => [ { label => 'request_rate', template => '%.2f', unit => 'r/s', min => 0 } ] } }, { label => 'request-rate-now', nlabel => 'filecache.requests.now.persecond', set => { key_values => [ { name => 'hits', diff => 1 }, { name => 'misses', diff => 1 } ], closure_custom_calc => $self->can('custom_rr_calc'), output_template => 'Request Rate : %.2f', output_error_template => 'Request Rate : %s', output_use => 'rr_now', threshold_use => 'rr_now', perfdatas => [ { label => 'request_rate_now', template => '%.2f', unit => 'r/s', min => 0 } ] } }, { label => 'hit-rate', nlabel => 'filecache.hits.persecond', set => { key_values => [ { name => 'hr' } ], output_template => 'Hit Rate (global): %.2f', perfdatas => [ { label => 'hit_rate',template => '%.2f', unit => 'r/s', min => 0 } ] } }, { label => 'hit-rate-now', nlabel => 'filecache.hits.now.persecond', set => { key_values => [ { name => 'hits', diff => 1 } ], closure_custom_calc => $self->can('custom_hr_calc'), output_template => 'Hit Rate : %.2f', output_error_template => 'Hit Rate : %s', output_use => 'hr_now', threshold_use => 'hr_now', perfdatas => [ { label => 'hit_rate_now', template => '%.2f', unit => 'r/s', min => 0 } ] } }, { label => 'miss-rate', nlabel => 'filecache.misses.persecond', set => { key_values => [ { name => 'mr' } ], output_template => 'Miss Rate (global): %.2f', perfdatas => [ { label => 'miss_rate',template => '%.2f', unit => 'r/s', min => 0 } ] } }, { label => 'miss-rate-now', nlabel => 'filecache.misses.now.persecond', set => { key_values => [ { name => 'misses', diff => 1 } ], closure_custom_calc => $self->can('custom_mr_calc'), output_template => 'Miss Rate : %.2f', output_error_template => 'Miss Rate : %s', output_use => 'mr_now', threshold_use => 'mr_now', perfdatas => [ { label => 'miss_rate_now', value => 'mr_now', template => '%.2f', unit => 'r/s', min => 0 } ] } }, { label => 'hit-percent', nlabel => 'filecache.hits.percentage', set => { key_values => [ { name => 'hits' }, { name => 'misses' } ], closure_custom_calc => $self->can('custom_hit_percent_calc'), output_template => 'Hit Ratio (global) : %.2f %%', output_error_template => 'Hit Ratio (global): %s', output_use => 'hit_ratio', threshold_use => 'hit_ratio', perfdatas => [ { label => 'hit_ratio', value => 'hit_ratio', template => '%.2f', unit => '%', min => 0, max => 100 } ] } }, { label => 'hit-percent-now', nlabel => 'filecache.hits.now.percentage', set => { key_values => [ { name => 'hits', diff => 1 }, { name => 'misses', diff => 1 } ], closure_custom_calc => $self->can('custom_hit_percent_now_calc'), output_template => 'Hit Ratio : %.2f %%', output_error_template => 'Hit Ratio : %s', output_use => 'hit_ratio_now', threshold_use => 'hit_ratio_now', perfdatas => [ { label => 'hit_ratio_now', value => 'hit_ratio_now', template => '%.2f', unit => '%', min => 0, max => 100 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port', }, 'proto:s' => { name => 'proto' }, 'urlpath:s' => { name => 'url_path', default => "/apc.php" }, 'credentials' => { name => 'credentials' }, 'basic' => { name => 'basic' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'timeout:s' => { name => 'timeout', default => 30 } }); $self->{http} = centreon::plugins::http->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{http}->set_options(%{$self->{option_results}}); } sub manage_selection { my ($self, %options) = @_; my $webcontent = $self->{http}->request(); $self->{fcache} = {}; $self->{fcache}->{hits} = $webcontent =~ /File Cache Information.*?Hits.*?(\d+)/msi ? $1 : undef; $self->{fcache}->{misses} = $webcontent =~ /File Cache Information.*?Misses.*?(\d+)/msi ? $1 : undef; $self->{fcache}->{rr} = $webcontent =~ /File Cache Information.*?Request Rate.*?([0-9\.]+)/msi ? $1 : undef; $self->{fcache}->{hr} = $webcontent =~ /File Cache Information.*?Hit Rate.*?([0-9\.]+)/msi ? $1 : undef; $self->{fcache}->{mr} = $webcontent =~ /File Cache Information.*?Miss Rate.*?([0-9\.]+)/msi ? $1 : undef; $self->{fcache}->{ir} = $webcontent =~ /File Cache Information.*?Insert Rate.*?([0-9\.]+)/msi ? $1 : undef; $self->{cache_name} = 'apc_' . $self->{mode} . '_' . $self->{option_results}->{hostname} . '_' . $self->{http}->get_port() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check file cache informations. =over 8 =item B<--hostname> IP Addr/FQDN of the webserver host =item B<--port> Port used by web server =item B<--proto> Specify https if needed =item B<--urlpath> Set path to get server-status page in auto mode (Default: '/apc.php') =item B<--credentials> Specify this option if you access server-status page with authentication =item B<--username> Specify username for authentication (Mandatory if --credentials is specified) =item B<--password> Specify password for authentication (Mandatory if --credentials is specified) =item B<--basic> Specify this option if you access server-status page over basic authentication and don't want a '401 UNAUTHORIZED' error to be logged on your webserver. Specify this option if you access server-status page over hidden basic authentication or you'll get a '404 NOT FOUND' error. (Use with --credentials) =item B<--timeout> Threshold for HTTP timeout (Default: 30) =item B<--warning-*> Threshold warning. Can be: 'request-rate', 'request-rate-now', 'hit-rate', 'hit-rate-now', 'miss-rate', 'miss-rate-now', 'hit-percent', 'hit-percent-now'. '*-now' are rate between two calls. =item B<--critical-*> Threshold critical. Can be: 'request-rate', 'request-rate-now', 'hit-rate', 'hit-rate-now', 'miss-rate', 'miss-rate-now', 'hit-percent', 'hit-percent-now'. '*-now' are rate between two calls. =back =cut centreon-plugins-20220113/apps/php/apc/web/mode/memory.pm000066400000000000000000000145011417000230700231010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::php::apc::web::mode::memory; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::http; use centreon::plugins::misc; sub custom_used_calc { my ($self, %options) = @_; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_free'} + $options{new_datas}->{$self->{instance} . '_used'}; $self->{result_values}->{free} = $options{new_datas}->{$self->{instance} . '_free'}; $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_used'}; $self->{result_values}->{free_prct} = $self->{result_values}->{free} * 100 / $self->{result_values}->{total}; $self->{result_values}->{used_prct} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; return 0; } sub custom_used_output { my ($self, %options) = @_; my ($total_value, $total_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); my ($used_value, $used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); my ($free_value, $free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); return sprintf( "Memory Usage Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", $total_value . " " . $total_unit, $used_value . " " . $used_unit, $self->{result_values}->{used_prct}, $free_value . " " . $free_unit, $self->{result_values}->{free_prct} ); } sub prefix_output { my ($self, %options) = @_; return "Apc "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'mem', type => 0, cb_prefix_output => 'prefix_output' } ]; $self->{maps_counters}->{mem} = [ { label => 'used', nlabel => 'memory.usage.bytes', set => { key_values => [ { name => 'free' }, { name => 'free' } ], closure_custom_calc => $self->can('custom_used_calc'), closure_custom_output => $self->can('custom_used_output'), threshold_use => 'used_prct', output_error_template => 'Memory Usage: %s', perfdatas => [ { label => 'used', template => '%d', unit => 'B', min => 0, max => 'total', threshold_total => 'total' } ] } }, { label => 'fragmentation', nlabel => 'memory.fragmentation.percentage', set => { key_values => [ { name => 'fragmentation' } ], output_template => 'Memory Fragmentation: %.2f %%', output_error_template => 'Memory Fragmentation: %s', output_use => 'fragmentation', threshold_use => 'fragmentation', perfdatas => [ { label => 'fragmentation', template => '%.2f', unit => '%', min => 0, max => 100 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port', }, 'proto:s' => { name => 'proto' }, 'urlpath:s' => { name => 'url_path', default => "/apc.php" }, 'credentials' => { name => 'credentials' }, 'basic' => { name => 'basic' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'timeout:s' => { name => 'timeout', default => 30 }, }); $self->{http} = centreon::plugins::http->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{http}->set_options(%{$self->{option_results}}); } sub manage_selection { my ($self, %options) = @_; my $webcontent = $self->{http}->request(); my ($free, $used); if ($webcontent =~ /Memory Usage.*?Free:.*?([0-9\.]+)\s*(\S*)/msi) { $free = centreon::plugins::misc::convert_bytes(value => $1, unit => $2); } if ($webcontent =~ /Memory Usage.*?Used:.*?([0-9\.]+)\s*(\S*)/msi) { $used = centreon::plugins::misc::convert_bytes(value => $1, unit => $2); } $self->{mem} = {}; $self->{mem}->{free} = $free; $self->{mem}->{used} = $used; $self->{mem}->{fragmentation} = $webcontent =~ /Fragmentation:.*?([0-9\.]+)/msi ? $1 : undef; } 1; __END__ =head1 MODE Check memory usage. =over 8 =item B<--hostname> IP Addr/FQDN of the webserver host =item B<--port> Port used by web server =item B<--proto> Specify https if needed =item B<--urlpath> Set path to get server-status page in auto mode (Default: '/apc.php') =item B<--credentials> Specify this option if you access server-status page with authentication =item B<--username> Specify username for authentication (Mandatory if --credentials is specified) =item B<--password> Specify password for authentication (Mandatory if --credentials is specified) =item B<--basic> Specify this option if you access server-status page over basic authentication and don't want a '401 UNAUTHORIZED' error to be logged on your webserver. Specify this option if you access server-status page over hidden basic authentication or you'll get a '404 NOT FOUND' error. (Use with --credentials) =item B<--timeout> Threshold for HTTP timeout (Default: 30) =item B<--warning-*> Threshold warning. Can be: 'used' (in percent), 'fragmentation' (in percent). =item B<--critical-*> Threshold critical. Can be: 'used' (in percent), 'fragmentation' (in percent). =back =cut centreon-plugins-20220113/apps/php/apc/web/plugin.pm000066400000000000000000000024261417000230700221460ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::php::apc::web::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} = '0.1'; $self->{modes} = { 'file-cache' => 'apps::php::apc::web::mode::filecache', 'memory' => 'apps::php::apc::web::mode::memory' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check apc php module through the webpage =cut centreon-plugins-20220113/apps/php/fpm/000077500000000000000000000000001417000230700175505ustar00rootroot00000000000000centreon-plugins-20220113/apps/php/fpm/web/000077500000000000000000000000001417000230700203255ustar00rootroot00000000000000centreon-plugins-20220113/apps/php/fpm/web/mode/000077500000000000000000000000001417000230700212515ustar00rootroot00000000000000centreon-plugins-20220113/apps/php/fpm/web/mode/usage.pm000066400000000000000000000203401417000230700227120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::php::fpm::web::mode::usage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::http; use Digest::MD5 qw(md5_hex); sub custom_active_calc { my ($self, %options) = @_; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_total'}; $self->{result_values}->{active} = $options{new_datas}->{$self->{instance} . '_active'}; $self->{result_values}->{active_prct} = $self->{result_values}->{active} * 100 / $self->{result_values}->{total}; return 0; } sub custom_active_output { my ($self, %options) = @_; return sprintf( 'active processes: %s (%.2f%%)', $self->{result_values}->{active}, $self->{result_values}->{active_prct} ); } sub custom_active_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => 'active', nlabel => $self->{nlabel}, value => $self->{result_values}->{active}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), min => 0, max => $self->{result_values}->{total} ); } sub custom_idle_calc { my ($self, %options) = @_; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_total'}; $self->{result_values}->{idle} = $options{new_datas}->{$self->{instance} . '_idle'}; $self->{result_values}->{idle_prct} = $self->{result_values}->{idle} * 100 / $self->{result_values}->{total}; return 0; } sub custom_idle_output { my ($self, %options) = @_; return sprintf( 'idle processes: %s (%.2f%%)', $self->{result_values}->{idle}, $self->{result_values}->{idle_prct} ); } sub custom_idle_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => 'idle', nlabel => $self->{nlabel}, value => $self->{result_values}->{idle}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), min => 0, max => $self->{result_values}->{total} ); } sub prefix_output { my ($self, %options) = @_; return 'php-fpm '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'fpm', type => 0, cb_prefix_output => 'prefix_output', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{fpm} = [ { label => 'active-processes', nlabel => 'fpm.processes.active.count', set => { key_values => [ { name => 'active' }, { name => 'total' } ], closure_custom_calc => $self->can('custom_active_calc'), closure_custom_output => $self->can('custom_active_output'), threshold_use => 'active_prct', closure_custom_perfdata => => $self->can('custom_active_perfdata') } }, { label => 'idle-processes', nlabel => 'fpm.processes.idle.count', set => { key_values => [ { name => 'idle' }, { name => 'total' } ], closure_custom_calc => $self->can('custom_idle_calc'), closure_custom_output => $self->can('custom_idle_output'), threshold_use => 'idle_prct', closure_custom_perfdata => => $self->can('custom_idle_perfdata') } }, { label => 'listen-queue', nlabel => 'fpm.queue.listen.count', set => { key_values => [ { name => 'listen_queue' }, { name => 'max_listen_queue' } ], output_template => 'listen queue: %s', output_use => 'listen_queue', threshold_use => 'listen_queue', perfdatas => [ { label => 'listen_queue', template => '%s', min => 0, max => 'max_listen_queue' } ] } }, { label => 'requests', nlabel => 'fpm.requests.persecond', set => { key_values => [ { name => 'request', per_second => 1 } ], output_template => 'requests: %.2f/s', perfdatas => [ { label => 'requests', template => '%.2f', unit => '/s', min => 0 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port', }, 'proto:s' => { name => 'proto' }, 'urlpath:s' => { name => 'url_path', default => "/fpm-status" }, 'credentials' => { name => 'credentials' }, 'basic' => { name => 'basic' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'timeout:s' => { name => 'timeout', default => 5 } }); $self->{http} = centreon::plugins::http->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{http}->set_options(%{$self->{option_results}}); } sub manage_selection { my ($self, %options) = @_; my $webcontent = $self->{http}->request(); $self->{fpm} = {}; $self->{fpm}->{request} = $1 if ($webcontent =~ /accepted\s+conn:\s+(\d+)/msi); $self->{fpm}->{listen_queue} = $1 if ($webcontent =~ /listen\s+queue:\s+(\d+)/msi); $self->{fpm}->{max_listen_queue} = $1 if ($webcontent =~ /max\s+listen\s+queue:\s+(\d+)/msi); $self->{fpm}->{idle} = $1 if ($webcontent =~ /idle\s+processes:\s+(\d+)/msi); $self->{fpm}->{active} = $1 if ($webcontent =~ /active\s+processes:\s+(\d+)/msi); $self->{fpm}->{total} = $1 if ($webcontent =~ /total\s+processes:\s+(\d+)/msi); $self->{cache_name} = 'php_fpm_' . $self->{mode} . '_' . $self->{option_results}->{hostname} . '_' . $self->{http}->get_port() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check php-fpm usage. =over 8 =item B<--hostname> IP Addr/FQDN of the webserver host =item B<--port> Port used by web server =item B<--proto> Specify https if needed =item B<--urlpath> Set path to get server-status page in auto mode (Default: '/fpm-status') =item B<--credentials> Specify this option if you access server-status page with authentication =item B<--username> Specify username for authentication (Mandatory if --credentials is specified) =item B<--password> Specify password for authentication (Mandatory if --credentials is specified) =item B<--basic> Specify this option if you access server-status page over basic authentication and don't want a '401 UNAUTHORIZED' error to be logged on your webserver. Specify this option if you access server-status page over hidden basic authentication or you'll get a '404 NOT FOUND' error. (Use with --credentials) =item B<--timeout> Threshold for HTTP timeout (Default: 5) =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'active-processes' (%), 'idle-processes' (%), 'listen-queue', 'requests'. =back =cut centreon-plugins-20220113/apps/php/fpm/web/plugin.pm000066400000000000000000000023211417000230700221570ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::php::fpm::web::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} = '0.1'; $self->{modes} = { 'usage' => 'apps::php::fpm::web::mode::usage' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check php-fpm module through the webpage. =cut centreon-plugins-20220113/apps/pineapp/000077500000000000000000000000001417000230700176335ustar00rootroot00000000000000centreon-plugins-20220113/apps/pineapp/securemail/000077500000000000000000000000001417000230700217645ustar00rootroot00000000000000centreon-plugins-20220113/apps/pineapp/securemail/snmp/000077500000000000000000000000001417000230700227415ustar00rootroot00000000000000centreon-plugins-20220113/apps/pineapp/securemail/snmp/mode/000077500000000000000000000000001417000230700236655ustar00rootroot00000000000000centreon-plugins-20220113/apps/pineapp/securemail/snmp/mode/system.pm000066400000000000000000000245301417000230700255530ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::pineapp::securemail::snmp::mode::system; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); use Digest::MD5 qw(md5_hex); sub custom_status_output { my ($self, %options) = @_; my $msg = 'status is ' . $self->{result_values}->{status}; return $msg; } sub custom_storage_status_output { my ($self, %options) = @_; my $msg = 'Storage status is ' . $self->{result_values}->{status}; return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global_load', type => 0, cb_prefix_output => 'prefix_load_output', skipped_code => { -10 => 1 } }, { name => 'global', type => 0, message_separator => ' - ', skipped_code => { -10 => 1 } }, { name => 'service', type => 1, cb_prefix_output => 'prefix_service_output', message_multiple => 'All services are ok' }, ]; $self->{maps_counters}->{global_load} = []; foreach ('1', '5', '15') { push @{$self->{maps_counters}->{global_load}}, { label => 'load-' . $_ . 'm', nlabel => 'system.load.' . $_ . 'm.count', set => { key_values => [ { name => 'cpuload' . $_ . 'minavg' } ], output_template => '%s (' . $_ . 'm)', perfdatas => [ { value => 'cpuload' . $_ . 'minavg', template => '%s', min => 0 }, ], } }; } $self->{maps_counters}->{global} = [ { label => 'storage-status', threshold => 0, set => { key_values => [ { name => 'status' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_storage_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold, } }, { label => 'messages-queue-inbound', nlabel => 'system.messages.queue.inbound.count', display_ok => 0, set => { key_values => [ { name => 'mailsysteminboundqueue' } ], output_template => 'messages inbound queue: %s', perfdatas => [ { value => 'mailsysteminboundqueue', template => '%s', min => 0 }, ], } }, { label => 'messages-queue-outbound', nlabel => 'system.messages.queue.outbound.count', display_ok => 0, set => { key_values => [ { name => 'mailsystemoutboundqueue' } ], output_template => 'messages outbound queue: %s', perfdatas => [ { value => 'mailsystemoutboundqueue', template => '%s', min => 0 }, ], } }, { label => 'messages-priority-high', nlabel => 'system.messages.priority.high.count', display_ok => 0, set => { key_values => [ { name => 'mailQueueHigh' } ], output_template => 'messages high priority: %s', perfdatas => [ { value => 'mailQueueHigh', template => '%s', min => 0 }, ], } }, { label => 'messages-priority-normal', nlabel => 'system.messages.priority.normal.count', display_ok => 0, set => { key_values => [ { name => 'mailQueueNormal' } ], output_template => 'messages normal priority: %s', perfdatas => [ { value => 'mailQueueNormal', template => '%s', min => 0 }, ], } }, { label => 'messages-priority-low', nlabel => 'system.messages.priority.low.count', display_ok => 0, set => { key_values => [ { name => 'mailQueueLow' } ], output_template => 'messages low priority: %s', perfdatas => [ { value => 'mailQueueLow', template => '%s', min => 0 }, ], } }, { label => 'messages-queue-total', nlabel => 'system.messages.queue.total.count', display_ok => 0, set => { key_values => [ { name => 'mailQueueTotal' } ], output_template => 'messages queue total: %s', perfdatas => [ { value => 'mailQueueTotal', template => '%s', min => 0 }, ], } }, ]; $self->{maps_counters}->{service} = [ { label => 'service-status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'display' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold, } }, ]; } sub prefix_load_output { my ($self, %options) = @_; return 'Load average: '; } sub prefix_service_output { my ($self, %options) = @_; return "Service '" . $options{instance_value}->{display} . "' "; } 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 => { 'unknown-service-status:s' => { name => 'unknown_service_status', default => '' }, 'warning-service-status:s' => { name => 'warning_service_status', default => '' }, 'critical-service-status:s' => { name => 'critical_service_status', default => '%{status} !~ /running/i' }, 'unknown-storage-status:s' => { name => 'unknown_storage_status', default => '' }, 'warning-storage-status:s' => { name => 'warning_storage_status', default => '' }, 'critical-storage-status:s' => { name => 'critical_storage_status', default => '%{status} !~ /ok/i' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros( macros => [ 'unknown_service_status', 'warning_service_status', 'critical_service_status', 'unknown_storage_status', 'warning_storage_status', 'critical_storage_status', ] ); } my $map_sc_status = { 0 => 'stopped', 1 => 'running' }; my $mapping = { cpuload1minavg => { oid => '.1.3.6.1.4.1.19801.1.1.3.1' }, cpuload5minavg => { oid => '.1.3.6.1.4.1.19801.1.1.3.2' }, cpuload15minavg => { oid => '.1.3.6.1.4.1.19801.1.1.3.3' }, storage => { oid => '.1.3.6.1.4.1.19801.1.4' }, smtpservicestatus => { oid => '.1.3.6.1.4.1.19801.2.1.1', map => $map_sc_status }, pop3servicestatus => { oid => '.1.3.6.1.4.1.19801.2.1.2', map => $map_sc_status }, imap4servicestatus => { oid => '.1.3.6.1.4.1.19801.2.1.3', map => $map_sc_status }, mailsysteminboundqueue => { oid => '.1.3.6.1.4.1.19801.2.1.10.1' }, mailsystemoutboundqueue => { oid => '.1.3.6.1.4.1.19801.2.1.10.2' }, mailQueueHigh => { oid => '.1.3.6.1.4.1.19801.2.1.10.3.1' }, mailQueueNormal => { oid => '.1.3.6.1.4.1.19801.2.1.10.3.2' }, mailQueueLow => { oid => '.1.3.6.1.4.1.19801.2.1.10.3.3' }, mailQueueTotal => { oid => '.1.3.6.1.4.1.19801.2.1.10.3.4' }, antivirusservicestatus => { oid => '.1.3.6.1.4.1.19801.2.5.1', map => $map_sc_status }, }; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_leef( oids => [ map($_->{oid} . '.0', values(%$mapping)) ], nothing_quit => 1 ); my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => '0'); $self->{service} = { smtp => { status => $result->{smtpservicestatus}, display => 'smtp' }, pop3 => { status => $result->{pop3servicestatus}, display => 'pop3' }, imap4 => { status => $result->{imap4servicestatus}, display => 'imap4' }, antivirus => { status => $result->{antivirusservicestatus}, display => 'antivirus' }, }; $self->{global_load} = { %$result }; $self->{global} = { status => $result->{storage}, mailsysteminboundqueue => $result->{mailsysteminboundqueue}, mailsystemoutboundqueue => $result->{mailsystemoutboundqueue}, mailQueueHigh => $result->{mailQueueHigh}, mailQueueNormal => $result->{mailQueueNormal}, mailQueueLow => $result->{mailQueueLow}, mailQueueTotal => $result->{mailQueueTotal}, }; } 1; __END__ =head1 MODE Check system usage. =over 8 =item B<--unknown-service-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{display} =item B<--warning-service-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{display} =item B<--critical-service-status> Set critical threshold for status (Default: '%{status} !~ /running/i'). Can used special variables like: %{status}, %{display} =item B<--unknown-storage-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status} =item B<--warning-storage-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status} =item B<--critical-storage-status> Set critical threshold for status (Default: '%{status} !~ /ok/i'). Can used special variables like: %{status} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'load-1m', 'load-5m', 'load-15m', 'messages-priority-high', 'messages-priority-medium', 'messages-priority-low', 'messages-queue-inbound', 'messages-queue-outbound', 'messages-queue-total'. =back =cut centreon-plugins-20220113/apps/pineapp/securemail/snmp/plugin.pm000066400000000000000000000023451417000230700246010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::pineapp::securemail::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}} = ( 'system' => 'apps::pineapp::securemail::snmp::mode::system', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check PineApp SecureMail in SNMP. =cut centreon-plugins-20220113/apps/protocols/000077500000000000000000000000001417000230700202235ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/bgp/000077500000000000000000000000001417000230700207735ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/bgp/4/000077500000000000000000000000001417000230700211365ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/bgp/4/mode/000077500000000000000000000000001417000230700220625ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/bgp/4/mode/bgppeerstate.pm000066400000000000000000000174661417000230700251230ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::bgp::4::mode::bgppeerstate; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = "AS:'" . $self->{result_values}->{as} . "'"; $msg .= " Local: '" . $self->{result_values}->{local} . "'"; $msg .= " Remote: '" . $self->{result_values}->{remote} . "'"; $msg .= " Peer State: '" . $self->{result_values}->{peerstate} . "'"; $msg .= " Admin State: '" . $self->{result_values}->{adminstate} . "'"; return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{adminstate} = $options{new_datas}->{$self->{instance} . '_adminstate'}; $self->{result_values}->{peerstate} = $options{new_datas}->{$self->{instance} . '_peerstate'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{local} = $options{new_datas}->{$self->{instance} . '_local'}; $self->{result_values}->{remote} = $options{new_datas}->{$self->{instance} . '_remote'}; $self->{result_values}->{as} = $options{new_datas}->{$self->{instance} . '_as'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'peers', type => 1, cb_prefix_output => 'prefix_peers_output', message_multiple => 'All BGP peers are ok' }, ]; $self->{maps_counters}->{peers} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'adminstate' }, { name => 'peerstate' }, { name => 'display' }, { name => 'local' }, { name => 'remote' }, { name => 'as' } ], 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 => \&catalog_status_threshold, } }, { label => 'updates', nlabel => 'bgppeer.update.seconds', set => { key_values => [ { name => 'seconds' }, { name => 'display' } ], output_template => 'Last update : %ss', perfdatas => [ { label => 'seconds', value => 'seconds', template => '%s', unit => 's', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub prefix_peers_output { my ($self, %options) = @_; return "Peer '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-peer:s" => { name => 'filter_peer' }, "filter-as:s" => { name => 'filter_as' }, "warning-status:s" => { name => 'warning_status', default => '' }, "critical-status:s" => { name => 'critical_status', default => '%{adminstate} =~ /start/ && %{peerstate} !~ /established/' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } my %map_peer_state = ( 1 => 'idle', 2 => 'connect', 3 => 'active', 4 => 'opensent', 5 => 'openconfirm', 6 => 'established', ); my %map_admin_state = ( 1 => 'stop', 2 => 'start', ); my $oid_bgpPeerTable = '.1.3.6.1.2.1.15.3'; my $mapping = { bgpPeerState => { oid => '.1.3.6.1.2.1.15.3.1.2', map => \%map_peer_state }, bgpPeerAdminStatus => { oid => '.1.3.6.1.2.1.15.3.1.3', map => \%map_admin_state }, bgpPeerRemoteAs => { oid => '.1.3.6.1.2.1.15.3.1.9' }, bgpPeerLocalAddr => { oid => '.1.3.6.1.2.1.15.3.1.5' }, bgpPeerLocalPort => { oid => '.1.3.6.1.2.1.15.3.1.6' }, bgpPeerRemoteAddr => { oid => '.1.3.6.1.2.1.15.3.1.7' }, bgpPeerRemotePort => { oid => '.1.3.6.1.2.1.15.3.1.8' }, bgpPeerInUpdateElpasedTime => { oid => '.1.3.6.1.2.1.15.3.1.24' }, }; sub manage_selection { my ($self, %options) = @_; $self->{peers} = {}; my $result = $options{snmp}->get_table(oid => $oid_bgpPeerTable, nothing_quit => 1); foreach my $oid (keys %{$result}) { next if ($oid !~ /^$mapping->{bgpPeerState}->{oid}\.(.*)$/); my $instance = $1; my $mapped_value = $options{snmp}->map_instance( mapping => $mapping, results => $result, instance => $instance ); my $local_addr = $mapped_value->{bgpPeerLocalAddr} . ':' . $mapped_value->{bgpPeerLocalPort}; my $remote_addr = $mapped_value->{bgpPeerRemoteAddr} . ':' . $mapped_value->{bgpPeerRemotePort}; if (defined($self->{option_results}->{filter_peer}) && $self->{option_results}->{filter_peer} ne '' && $instance !~ /$self->{option_results}->{filter_peer}/) { $self->{output}->output_add( long_msg => "skipping peer '" . $instance . "': no matching filter.", debug => 1 ); next; } if (defined($self->{option_results}->{filter_as}) && $self->{option_results}->{filter_as} ne '' && $mapped_value->{bgpPeerRemoteAs} !~ /$self->{option_results}->{filter_as}/) { $self->{output}->output_add( long_msg => "skipping AS '" . $mapped_value->{bgpPeerRemoteAs} . "': no matching filter.", debug => 1 ); next; } $self->{peers}->{$instance} = { adminstate => $mapped_value->{bgpPeerAdminStatus}, local => $local_addr, peerstate => $mapped_value->{bgpPeerState}, remote => $remote_addr, seconds => $mapped_value->{bgpPeerInUpdateElpasedTime}, as => $mapped_value->{bgpPeerRemoteAs}, display => $instance }; } if (scalar(keys %{$self->{peers}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No peers found'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check BGP peer state (BGP4-MIB.mib and rfc4273) =over 8 =item B<--filter-as> Filter based on AS number (regexp allowed) =item B<--filter-peer> Filter based on IP of peers (regexp allowed) =item B<--warning-updates> Warning threshold on last update (seconds) =item B<--critical-updates> Critical threshold on last update (seconds) =item B<--warning-status> Specify admin and peer state that trigger a warning. Can use special variables like %{adminstate}, %{peerstate}, %{local}, %{remote}, %{as}, %{display} (Default: '') =item B<--critical-status> Specify admin and peer state that trigger a critical. Can use special variables like %{adminstate}, %{peerstate}, %{local}, %{remote}, %{as}, %{display} (Default: '%{adminstate} =~ /start/ && %{peerstate} !~ /established/') =back =cut centreon-plugins-20220113/apps/protocols/bgp/4/plugin.pm000066400000000000000000000023471417000230700230000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::bgp::4::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}} = ( 'bgppeerstate' => 'apps::protocols::bgp::4::mode::bgppeerstate', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check BGP protocol in SNMP. =cut centreon-plugins-20220113/apps/protocols/dhcp/000077500000000000000000000000001417000230700211415ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/dhcp/mode/000077500000000000000000000000001417000230700220655ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/dhcp/mode/connection.pm000066400000000000000000000216261417000230700245710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::dhcp::mode::connection; use base qw(centreon::plugins::mode); use strict; use warnings; use Time::HiRes qw(gettimeofday tv_interval); use IO::Socket; use IO::Select; use Net::DHCP::Packet; use Net::DHCP::Constants; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "serverip:s@" => { name => 'serverip' }, "out-first-valid" => { name => 'out_first_valid' }, "timeout:s" => { name => 'timeout', default => 15 }, "macaddr:s" => { name => 'macaddr', default => '999999100000'}, "interface:s" => { name => 'interface', default => 'eth0' }, "cidr-match:s@" => { name => 'cidr_match' }, }); $self->{unicast} = 0; return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (defined($self->{option_results}->{serverip}) && scalar(@{$self->{option_results}->{serverip}}) > 0) { $self->{unicast} = 1; } $self->{subnet_matcher} = undef; if (defined($self->{option_results}->{cidr_match}) && scalar(@{$self->{option_results}->{cidr_match}}) > 0) { centreon::plugins::misc::mymodule_load(output => $self->{output}, module => 'Net::Subnet', error_msg => "Cannot load module 'Net::Subnet'."); $self->{subnet_matcher} = Net::Subnet::subnet_matcher(@{$self->{option_results}->{cidr_match}}); } } sub send_discover { my ($self, %options) = @_; $self->{random_number} = int(rand(0xFFFFFFFF)); #Create DHCP Discover Packet my $discover = Net::DHCP::Packet->new( Xid => $self->{random_number}, Flags => $self->{unicast} == 1 ? 0 : 0x8000, Chaddr => $self->{option_results}->{macaddr}, Giaddr => $self->{my_ip}, Hops => $self->{unicast} == 1 ? 1 : 0, DHO_HOST_NAME() => 'centreon', DHO_VENDOR_CLASS_IDENTIFIER() => 'foo', DHO_DHCP_MESSAGE_TYPE() => DHCPDISCOVER(), ); my $str = $discover->serialize(); #Send UDP Packet $self->{timing0} = [gettimeofday]; if ($self->{unicast} == 0) { my $remoteipaddr = sockaddr_in(67, INADDR_BROADCAST); send($self->{socket}, $str, 0, $remoteipaddr); } else { foreach my $server_ip (@{$self->{option_results}->{serverip}}) { my $remoteipaddr = sockaddr_in(67, inet_aton($server_ip)); send($self->{socket}, $str, 0, $remoteipaddr); } } } sub create_socket { my ($self, %options) = @_; #Create UDP Socket socket($self->{socket}, AF_INET, SOCK_DGRAM, getprotobyname('udp')); setsockopt($self->{socket}, SOL_SOCKET, SO_REUSEADDR, 1); if ($self->{unicast} == 0) { setsockopt($self->{socket}, SOL_SOCKET, SO_BROADCAST, 1); } $self->{my_ip} = undef; if ($self->{unicast} == 1) { $self->{my_ip} = $self->get_interface_address(interface => $self->{option_results}->{interface}); } my $port = $self->{unicast} == 1 ? '67' : '68'; my $addr = $self->{unicast} == 1 ? inet_aton($self->{my_ip}) : INADDR_ANY; my $binding = bind($self->{socket}, sockaddr_in($port, $addr)); } sub get_interface_address { my ($self, %options) = @_; require 'sys/ioctl.ph'; my $socket; if (!socket($socket, PF_INET, SOCK_STREAM, (getprotobyname('tcp'))[2])) { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => "cannot get interface address: $!"); $self->{output}->display(); $self->{output}->exit(); } my $buf = pack('a256', $options{interface}); if (ioctl($socket, SIOCGIFADDR(), $buf) && (my @address = unpack('x20 C4', $buf))) { return join('.', @address); } $self->{output}->output_add(severity => 'UNKNOWN', short_msg => "cannot get interface address: $!"); $self->{output}->display(); $self->{output}->exit(); } sub get_offer { my ($self, %options) = @_; $self->{discresponse} = []; #Wait DHCP OFFER Packet my $wait = IO::Select->new($self->{socket}); my $timeout = $self->{option_results}->{timeout}; my $time = time(); $self->{random_number} = sprintf("%x", $self->{random_number}); while (my ($found) = $wait->can_read($timeout)) { $timeout -= time() - $time; $time = time(); my $srcpaddr = recv($self->{socket}, my $data, 4096, 0); my $response = new Net::DHCP::Packet($data); my $response_readable = $response->toString(); # Need to get same Xid and MacAddr in response. Otherwise not for me if ($response_readable =~ /^xid\s+=\s+$self->{random_number}/mi && $response_readable =~ /^chaddr\s+=\s+$self->{option_results}->{macaddr}/mi) { $self->{timeelapsed} = tv_interval($self->{timing0}, [gettimeofday]); push @{$self->{discresponse}}, $response_readable; last if (defined($self->{option_results}->{out_first_valid})); } } close $self->{socket}; } sub check_results { my ($self, %options) = @_; foreach my $response (@{$self->{discresponse}}) { $response =~ /DHO_DHCP_LEASE_TIME.*?=\s+(.*?)\n/m; my $lease_time = $1; my $yiaddr; if ($response =~ /^yiaddr\s+=\s+(.*?)\n/m) { $yiaddr = $1; } $response =~ /^siaddr\s+=\s+(.*?)\n/m; my $siaddr = $1; $self->{output}->output_add(long_msg => sprintf("Response from %s : offer address %s (lease time: %s)", $siaddr, $yiaddr, $lease_time)); if (defined($self->{subnet_matcher})) { if (!$self->{subnet_matcher}->($yiaddr)) { $self->{output}->output_add(severity => 'CRITICAL', short_msg => sprintf("Offer address %s not matching (from: %s)", $yiaddr, $siaddr)); } } else { if (!defined($yiaddr) || $yiaddr eq '' || $yiaddr eq '0.0.0.0' ) { $self->{output}->output_add(severity => 'CRITICAL', short_msg => sprintf("No free lease from %s server", $siaddr)); } } } } sub result { my ($self, %options) = @_; $self->{output}->output_add(severity => 'OK', short_msg => sprintf("DHCP Server found with free lease")); if (scalar(@{$self->{discresponse}}) == 0) { $self->{output}->output_add(severity => 'CRITICAL', short_msg => sprintf("No DHCPOFFERs were received")); } elsif ($self->{unicast} == 1) { if (scalar(@{$self->{discresponse}}) != scalar(@{$self->{option_results}->{serverip}})) { $self->{output}->output_add(severity => 'CRITICAL', short_msg => sprintf("%d of %d requested servers responded", scalar(@{$self->{discresponse}}), scalar(@{$self->{option_results}->{serverip}}))); } } $self->check_results(); $self->{output}->perfdata_add(label => "time", unit => 'ms', value => sprintf('%.3f', $self->{timeelapsed})) if (defined($self->{timeelapsed})); } sub run { my ($self, %options) = @_; $self->create_socket(); $self->send_discover(); $self->get_offer(); $self->result(); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check DHCP server availability =over 8 =item B<--serverip> IP Addr of the DHCP server to query (do a unicast mode) =item B<--timeout> How much time to check dhcp responses (Default: 15 seconds) =item B<--out-first-valid> Stop after first valid dhcp response =item B<--macaddr> MAC address to use in the DHCP request =item B<--interface> Interface to to use for listening (Default: eth0) =item B<--cidr-match> Match ip addresses offered (can be used multiple times). Returns critical for each ip addresses with no match. =back =cut centreon-plugins-20220113/apps/protocols/dhcp/plugin.pm000066400000000000000000000023201417000230700227720ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::dhcp::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}} = ( 'connection' => 'apps::protocols::dhcp::mode::connection', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check a DHCP server. =cut centreon-plugins-20220113/apps/protocols/dns/000077500000000000000000000000001417000230700210075ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/dns/lib/000077500000000000000000000000001417000230700215555ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/dns/lib/dns.pm000066400000000000000000000057121417000230700227040ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::dns::lib::dns; use strict; use warnings; use Net::DNS; my $handle; sub search { my ($self, %options) = @_; my $map_search_field = { MX => 'exchange', SOA => 'mname', NS => 'nsdname', A => 'address', PTR => 'name', CNAME => 'cname', TXT => 'txtdata' }; my @results = (); my $search_type = $self->{option_results}->{search_type}; if (defined($search_type) && !defined($map_search_field->{$search_type})) { $self->{output}->add_option_msg(short_msg => "search-type '$search_type' is unknown or unsupported"); $self->{output}->option_exit(); } $map_search_field->{PTR} = 'ptrdname' if (defined($self->{option_results}->{use_ptr_fqdn})); my $error_quit = defined($options{error_quit}) ? $options{error_quit} : undef; my $reply = $handle->search($self->{option_results}->{search}, $search_type); if ($reply) { foreach my $rr ($reply->answer) { my $type = defined($search_type) ? $search_type : $rr->type; next if ($type ne $rr->type); my $attr = $map_search_field->{$type}; push @results, $rr->$attr; } } else { if (defined($error_quit)) { $self->{output}->output_add( severity => $error_quit, short_msg => sprintf('DNS query failed: %s', $handle->errorstring) ); $self->{output}->display(); $self->{output}->exit(); } } return sort @results; } sub connect { my ($self, %options) = @_; my %dns_options = (); my $nameservers = []; if (defined($self->{option_results}->{nameservers})) { $nameservers = [@{$self->{option_results}->{nameservers}}]; } my $searchlist = []; if (defined($self->{option_results}->{searchlist})) { $searchlist = [@{$self->{option_results}->{searchlist}}]; } foreach my $option (@{$self->{option_results}->{dns_options}}) { next if ($option !~ /^(.+?)=(.+)$/); $dns_options{$1} = $2; } $handle = Net::DNS::Resolver->new( nameservers => $nameservers, searchlist => $searchlist, %dns_options ); } 1; centreon-plugins-20220113/apps/protocols/dns/mode/000077500000000000000000000000001417000230700217335ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/dns/mode/request.pm000066400000000000000000000155431417000230700237710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::dns::mode::request; use base qw(centreon::plugins::mode); use strict; use warnings; use Time::HiRes qw(gettimeofday tv_interval); use apps::protocols::dns::lib::dns; use centreon::plugins::statefile; use Digest::MD5 qw(md5_hex); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'nameservers:s@' => { name => 'nameservers' }, 'searchlist:s@' => { name => 'searchlist' }, 'dns-options:s@' => { name => 'dns_options' }, 'search:s' => { name => 'search' }, 'search-type:s' => { name => 'search_type' }, 'use-ptr-fqdn' => { name => 'use_ptr_fqdn' }, 'expected-answer:s' => { name => 'expected_answer' }, 'warning:s' => { name => 'warning' }, 'critical:s' => { name => 'critical' }, 'memory' => { name => 'memory' } }); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); 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}->{search}) || $self->{option_results}->{search} eq '') { $self->{output}->add_option_msg(short_msg => "Please set the search option"); $self->{output}->option_exit(); } if (defined($self->{option_results}->{memory})) { $self->{cache_filename} = $self->{option_results}->{search}; foreach (('search_type', 'search', 'nameservers')) { $self->{cache_filename} .= '_'; if (defined($self->{option_results}->{$_})) { if (ref($self->{option_results}->{$_}) eq 'ARRAY') { $self->{cache_filename} .= join('-', @{$self->{option_results}->{$_}}); } else { $self->{cache_filename} .= $self->{option_results}->{$_}; } } } $self->{statefile_cache}->check_options(%options); } } sub run { my ($self, %options) = @_; my $timing0 = [gettimeofday]; apps::protocols::dns::lib::dns::connect($self); my @results = apps::protocols::dns::lib::dns::search($self, error_quit => 'critical'); my $timeelapsed = tv_interval ($timing0, [gettimeofday]); my $result_str = join(', ', @results); my $exit = $self->{perfdata}->threshold_check( value => $timeelapsed, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ] ); $self->{output}->output_add( severity => $exit, short_msg => sprintf("Response time %.3f second(s) (answer: %s)", $timeelapsed, $result_str) ); $self->{output}->perfdata_add( label => "time", unit => 's', value => sprintf('%.3f', $timeelapsed), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical') ); if (defined($self->{option_results}->{expected_answer}) && $self->{option_results}->{expected_answer} ne '') { my $match = 0; foreach (@results) { if (/$self->{option_results}->{expected_answer}/) { $match = 1; } } if ($match == 0) { $self->{output}->output_add( severity => 'CRITICAL', short_msg => sprintf("No result values match expected answer (answer: %s)", $result_str ) ); } } if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->read(statefile => 'cache_dns_' . md5_hex($self->{cache_filename})); my $datas = { result => $result_str }; my $old_result = $self->{statefile_cache}->get(name => "result"); if (defined($old_result)) { if ($old_result ne $result_str) { $self->{output}->output_add( severity => 'CRITICAL', short_msg => sprintf("Result has changed [answer: %s] [old answer: %s]", $result_str, $old_result) ); } } else { $self->{output}->output_add(long_msg => 'cache file created.'); } $self->{statefile_cache}->write(data => $datas); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check requests to a DNS Server. Example: perl centreon_plugins.pl --plugin=apps::protocols::dns::plugin --mode=request --search=google.com --search-type=MX =over 8 =item B<--nameservers> Set nameserver to query (can be multiple). The system configuration is used by default. =item B<--searchlist> Set domains to search for unqualified names (can be multiple). The system configuration is used by default. =item B<--search> Set the search value (required). =item B<--search-type> Set the search type. Can be: 'MX', 'SOA', 'NS', 'A', 'CNAME' or 'PTR'. 'A' or 'PTR' is used by default (depends if an IP or not). =item B<--use-ptr-fqdn> Search is done on conical names for PTR type. =item B<--expected-answer> What the server must answer (can be a regexp). =item B<--dns-options> Add custom dns options. Example: --dns-options='debug=1' --dns-options='retry=2' --dns-options='port=972' --dns-options='recurse=0' ... =item B<--memory> Critical threshold if the answer changed between two checks. =item B<--warning> Threshold warning in seconds. =item B<--critical> Threshold critical in seconds. =back =cut centreon-plugins-20220113/apps/protocols/dns/plugin.pm000066400000000000000000000023101417000230700226370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::dns::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} = '0.1'; %{$self->{modes}} = ( 'request' => 'apps::protocols::dns::mode::request', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check an DNS server. =cut centreon-plugins-20220113/apps/protocols/ftp/000077500000000000000000000000001417000230700210145ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/ftp/lib/000077500000000000000000000000001417000230700215625ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/ftp/lib/ftp.pm000066400000000000000000000066731417000230700227250ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::ftp::lib::ftp; use strict; use warnings; use centreon::plugins::misc; use Net::FTP; my $ftp_handle; sub quit { $ftp_handle->quit; } sub message { return $ftp_handle->message; } sub execute { my ($self, %options) = @_; my $command = $options{command}; return $ftp_handle->$command(@{$options{command_args}}); } sub connect { my ($self, %options) = @_; my %ftp_options = (); my $ftp_class = 'Net::FTP'; if (defined($self->{option_results}->{use_ssl})) { centreon::plugins::misc::mymodule_load(output => $self->{output}, module => 'Net::FTPSSL', error_msg => "Cannot load module 'Net::FTPSSL'."); $ftp_class = 'Net::FTPSSL'; } my $connection_exit = defined($options{connection_exit}) ? $options{connection_exit} : 'unknown'; $ftp_options{Port} = $self->{option_results}->{port} if (defined($self->{option_results}->{port})); $ftp_options{Timeout} = $self->{option_results}->{timeout} if (defined($self->{option_results}->{timeout})); foreach my $option (@{$self->{option_results}->{ftp_options}}) { my ($key, $value) = split /=/, $option; if (defined($key) && defined($value)) { $ftp_options{$key} = $value; } } if (defined($self->{option_results}->{username}) && $self->{option_results}->{username} ne '' && !defined($self->{option_results}->{password})) { $self->{output}->add_option_msg(short_msg => "Please set --password option."); $self->{output}->option_exit(); } $ftp_handle = $ftp_class->new($self->{option_results}->{hostname}, %ftp_options ); if (!defined($ftp_handle)) { if (defined($self->{option_results}->{use_ssl})) { $self->{output}->output_add(severity => $connection_exit, short_msg => 'Unable to connect to FTP: ' . $Net::FTPSSL::ERRSTR); } else { $self->{output}->output_add(severity => $connection_exit, short_msg => 'Unable to connect to FTP: ' . $@); } $self->{output}->display(); $self->{output}->exit(); } if (defined($self->{option_results}->{username}) && $self->{option_results}->{username} ne '') { if (!$ftp_handle->login($self->{option_results}->{username}, $self->{option_results}->{password})) { $self->{output}->output_add(severity => $connection_exit, short_msg => 'Login failed: ' . $ftp_handle->message); quit(); $self->{output}->display(); $self->{output}->exit(); } } } 1; centreon-plugins-20220113/apps/protocols/ftp/mode/000077500000000000000000000000001417000230700217405ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/ftp/mode/commands.pm000066400000000000000000000170221417000230700241010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::ftp::mode::commands; use base qw(centreon::plugins::mode); use strict; use warnings; use Time::HiRes qw(gettimeofday tv_interval); use apps::protocols::ftp::lib::ftp; # How much arguments i need and commands manages my %map_commands = ( binary => { ssl => { name => 'binary', num => 0 }, nossl => { name => 'binary', num => 0 } }, ascii => { ssl => { name => 'ascii', num => 0 }, nossl => { name => 'ascii', num => 0 } }, cwd => { ssl => { name => 'cwd', num => 1 }, nossl => { name => 'cwd', num => 0 } }, rmdir => { ssl => { name => 'rmdir', num => 1 }, nossl => { name => 'rmdir', num => 1 } }, mkdir => { ssl => { name => 'mkdir', num => 1 }, nossl => { name => 'mkdir', num => 1 } }, ls => { ssl => { name => 'nlst', num => 0 }, nossl => { name => 'ls', num => 0 } }, rename => { ssl => { name => 'rename', num => 2 }, nossl => { name => 'rename', num => 2 } }, delete => { ssl => { name => 'delete', num => 1 }, nossl => { name => 'delete', num => 1 } }, get => { ssl => { name => 'get', num => 1 }, nossl => { name => 'get', num => 1 } }, put => { ssl => { name => 'put', num => 1 }, nossl => { name => 'put', num => 1 } }, ); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "hostname:s" => { name => 'hostname' }, "port:s" => { name => 'port', }, "ssl" => { name => 'use_ssl' }, "ftp-options:s@" => { name => 'ftp_options' }, "ftp-command:s@" => { name => 'ftp_command' }, "username:s" => { name => 'username' }, "password:s" => { name => 'password' }, "warning:s" => { name => 'warning' }, "critical:s" => { name => 'critical' }, "timeout:s" => { name => 'timeout', default => '30' }, }); $self->{commands} = []; 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}->{hostname})) { $self->{output}->add_option_msg(short_msg => "Please set the hostname option"); $self->{output}->option_exit(); } foreach (@{$self->{option_results}->{ftp_command}}) { my ($command, @args) = split /,/; if (!defined($map_commands{$command})) { $self->{output}->add_option_msg(short_msg => "Command '$command' doesn't exist or is not supported."); $self->{output}->option_exit(); } my $ssl_or_not = $map_commands{$command}->{nossl}; if (defined($self->{option_results}->{use_ssl})) { $ssl_or_not = $map_commands{$command}->{ssl}; } if (scalar(@args) < $ssl_or_not->{num}) { $self->{output}->add_option_msg(short_msg => "Some arguments are missing for the command: '$command'."); $self->{output}->option_exit(); } push @{$self->{commands}}, { name => $ssl_or_not->{name}, args => \@args}; } } sub run { my ($self, %options) = @_; my $timing0 = [gettimeofday]; apps::protocols::ftp::lib::ftp::connect($self); foreach my $command (@{$self->{commands}}) { if (!defined(apps::protocols::ftp::lib::ftp::execute($self, command => $command->{name}, command_args => \@{$command->{args}}))) { $self->{output}->output_add(severity => 'CRITICAL', short_msg => sprintf("Command '$command->{name}' issue: %s", apps::protocols::ftp::lib::ftp::message())); apps::protocols::ftp::lib::ftp::quit(); $self->{output}->display(); $self->{output}->exit(); } } apps::protocols::ftp::lib::ftp::quit(); my $timeelapsed = tv_interval ($timing0, [gettimeofday]); my $exit = $self->{perfdata}->threshold_check(value => $timeelapsed, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit, short_msg => sprintf("Response time %.3f ", $timeelapsed)); $self->{output}->perfdata_add(label => "time", value => sprintf('%.3f', $timeelapsed), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical')); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check if commands succeed to an FTP Server. =over 8 =item B<--hostname> IP Addr/FQDN of the ftp host =item B<--port> Port used =item B<--ssl> Use SSL connection Need Perl 'Net::FTPSSL' module =item B<--ftp-options> Add custom ftp options. Example: --ftp-options='Debug=1" --ftp-options='useSSL=1' =item B<--username> Specify username for authentification =item B<--password> Specify password for authentification =item B<--timeout> Connection timeout in seconds (Default: 30) =item B<--warning> Threshold warning in seconds =item B<--critical> Threshold critical in seconds =item B<--ftp-command> Set command to test (can be multiple). It will be executed in the order and stop on first command problem. Following commands can be used: =over 16 =item binary Transfer file in binary mode. =item ascii Transfer file in ascii mode. =item cwd,DIR Attempt to change directory to the directory given in DIR. If no directory is given then an attempt is made to change the directory to the root directory. =item rmdir,DIR Remove the directory with the name DIR. =item mkdir,DIR Create a new directory with the name DIR. =item ls,DIR Get a directory listing of DIR, or the current directory. =item rename,OLDNAME,NEWNAME Rename a file on the remote FTP server from OLDNAME to NEWNAME. =item delete,FILENAME Send a request to the server to delete FILENAME. =item get,REMOTE_FILE,LOCAL_FILE Get REMOTE_FILE from the server and store locally. =item put,LOCAL_FILE,REMOTE_FILE Put a file on the remote server. =back =back =cut centreon-plugins-20220113/apps/protocols/ftp/mode/date.pm000066400000000000000000000200641417000230700232150ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::ftp::mode::date; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::misc; use apps::protocols::ftp::lib::ftp; # How much arguments i need and commands manages my %map_commands = ( mdtm => { ssl => { name => '_mdtm' }, nossl => { name => 'mdtm' } }, ls => { ssl => { name => 'nlst' }, nossl => { name => 'ls'} }, ); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "hostname:s" => { name => 'hostname' }, "port:s" => { name => 'port', }, "ssl" => { name => 'use_ssl' }, "ftp-options:s@" => { name => 'ftp_options' }, "directory:s@" => { name => 'directory' }, "file:s@" => { name => 'file' }, "username:s" => { name => 'username' }, "password:s" => { name => 'password' }, "warning:s" => { name => 'warning' }, "critical:s" => { name => 'critical' }, "timeout:s" => { name => 'timeout', default => '30' }, "timezone:s" => { name => 'timezone' }, }); 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}->{hostname})) { $self->{output}->add_option_msg(short_msg => "Please set the hostname option"); $self->{output}->option_exit(); } $self->{ssl_or_not} = 'nossl'; if (defined($self->{option_results}->{use_ssl})) { $self->{ssl_or_not} = 'ssl'; } if (defined($self->{option_results}->{timezone}) && $self->{option_results}->{timezone} ne '') { centreon::plugins::misc::mymodule_load(module => 'DateTime', error_msg => "Cannot load module 'DateTime'."); } } sub run { my ($self, %options) = @_; my %file_times = (); apps::protocols::ftp::lib::ftp::connect($self); my $current_time = time(); my $dirs = ['.']; if (defined($self->{option_results}->{directory}) && scalar(@{$self->{option_results}->{directory}}) != 0) { $dirs = $self->{option_results}->{directory}; } foreach my $dir (@$dirs) { my @files; if (!(@files = apps::protocols::ftp::lib::ftp::execute($self, command => $map_commands{ls}->{$self->{ssl_or_not}}->{name}, command_args => [$dir]))) { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => sprintf("Command '$map_commands{ls}->{$self->{ssl_or_not}}->{name}' issue for directory '$dir': %s", apps::protocols::ftp::lib::ftp::message())); apps::protocols::ftp::lib::ftp::quit(); $self->{output}->display(); $self->{output}->exit(); } foreach my $file (@files) { my $time_result; $file = $dir . '/' . $file if ($file !~ /^$dir/); # some ftp only give filename (not the complete path) if (!($time_result = apps::protocols::ftp::lib::ftp::execute($self, command => $map_commands{mdtm}->{$self->{ssl_or_not}}->{name}, command_args => [$file]))) { # Sometime we can't have mtime for a directory next; } $file_times{$file} = $time_result; } } foreach my $file (@{$self->{option_results}->{file}}) { my $time_result; if (!($time_result = apps::protocols::ftp::lib::ftp::execute($self, command => $map_commands{mdtm}->{$self->{ssl_or_not}}->{name}, command_args => [$file]))) { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => sprintf("Command '$map_commands{mdtm}->{$self->{ssl_or_not}}->{name}' issue for file '$file': %s", apps::protocols::ftp::lib::ftp::message())); apps::protocols::ftp::lib::ftp::quit(); $self->{output}->display(); $self->{output}->exit(); } $file_times{$file} = $time_result; } apps::protocols::ftp::lib::ftp::quit(); $self->{output}->output_add(severity => 'OK', short_msg => "All file times are ok."); my $tz = centreon::plugins::misc::set_timezone(name => $self->{option_results}->{timezone}); foreach my $name (sort keys %file_times) { my $diff_time = $current_time - $file_times{$name}; my $exit_code = $self->{perfdata}->threshold_check(value => $diff_time, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); my $display_date = scalar(localtime($file_times{$name})); if (defined($self->{option_results}->{timezone}) && $self->{option_results}->{timezone} ne '') { $display_date = DateTime->from_epoch(epoch => $file_times{$name}, %$tz)->datetime() } $self->{output}->output_add(long_msg => sprintf("%s: %s seconds (time: %s)", $name, $diff_time, $display_date)); if (!$self->{output}->is_status(litteral => 1, value => $exit_code, compare => 'ok')) { $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("%s: %s seconds (time: %s)", $name, $diff_time, $display_date)); } $self->{output}->perfdata_add(label => $name, unit => 's', value => $diff_time, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), ); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check modified time of files. =over 8 =item B<--hostname> IP Addr/FQDN of the ftp host =item B<--port> Port used =item B<--ssl> Use SSL connection Need Perl 'Net::FTPSSL' module =item B<--ftp-options> Add custom ftp options. Example: --ftp-options='Debug=1" --ftp-options='useSSL=1' =item B<--username> Specify username for authentification =item B<--password> Specify password for authentification =item B<--timeout> Connection timeout in seconds (Default: 30) =item B<--warning> Threshold warning in seconds for each files (diff time) =item B<--critical> Threshold critical in seconds for each files (diff time) =item B<--directory> Check files in the directory (no recursive) (Multiple option) =item B<--file> Check file (Multiple option) =item B<--timezone> Set the timezone of display date. Can use format: 'Europe/London' or '+0100'. =back =cut centreon-plugins-20220113/apps/protocols/ftp/mode/filescount.pm000066400000000000000000000157701417000230700244630ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::ftp::mode::filescount; use base qw(centreon::plugins::mode); use strict; use warnings; use apps::protocols::ftp::lib::ftp; use File::Basename; # How much arguments i need and commands manages my %map_commands = ( ls => { ssl => { name => 'list' }, nossl => { name => 'dir'} }, ); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "hostname:s" => { name => 'hostname' }, "port:s" => { name => 'port', }, "ssl" => { name => 'use_ssl' }, "ftp-options:s@" => { name => 'ftp_options' }, "directory:s@" => { name => 'directory' }, "max-depth:s" => { name => 'max_depth', default => 0 }, "username:s" => { name => 'username' }, "password:s" => { name => 'password' }, "warning:s" => { name => 'warning' }, "critical:s" => { name => 'critical' }, "filter-file:s" => { name => 'filter_file' }, "timeout:s" => { name => 'timeout', default => '30' }, }); 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}->{hostname})) { $self->{output}->add_option_msg(short_msg => "Please set the hostname option"); $self->{output}->option_exit(); } $self->{ssl_or_not} = 'nossl'; if (defined($self->{option_results}->{use_ssl})) { $self->{ssl_or_not} = 'ssl'; } } sub run { my ($self, %options) = @_; my $cpt; my @files; my @array; apps::protocols::ftp::lib::ftp::connect($self); my $count = $self->countFiles(); apps::protocols::ftp::lib::ftp::quit(); my $exit_code = $self->{perfdata}->threshold_check(value => $count, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("Number of files : %s", $count)); $self->{output}->perfdata_add(label => 'files', value => $count, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0); $self->{output}->display(); $self->{output}->exit(); } sub countFiles { my ($self) = @_; my @listings; my $count = 0; if (!defined($self->{option_results}->{directory}) || scalar(@{$self->{option_results}->{directory}}) == 0) { push @listings, [ { name => '.', level => 0 } ]; } else { foreach my $dir (@{$self->{option_results}->{directory}}) { push @listings, [ { name => $dir, level => 0 } ]; } } my @build_name = (); foreach my $list (@listings) { while (@$list) { my @files; my $hash = pop @$list; my $dir = $hash->{name}; my $level = $hash->{level}; if (!(@files = apps::protocols::ftp::lib::ftp::execute($self, command => $map_commands{ls}->{$self->{ssl_or_not}}->{name}, command_args => [$dir]))) { # Cannot list we skip next; } foreach my $line (@files) { # IIS: 05-13-15 10:59AM 1184403 test.jpg next if ($line !~ /(\S+)\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+(.*)/ && $line !~ /^\s*\S+\s*\S+\s*(\S+)\s+(.*)/); my ($rights, $filename) = ($1, $2); my $bname = basename($filename); next if ($bname eq '.' || $bname eq '..'); my $name = $dir . '/' . $bname; if (defined($self->{option_results}->{filter_file}) && $self->{option_results}->{filter_file} ne '' && $name !~ /$self->{option_results}->{filter_file}/) { $self->{output}->output_add(long_msg => sprintf("Skipping '%s'", $name)); next; } if ($rights =~ /^(d|)/i) { if (defined($self->{option_results}->{max_depth}) && $level + 1 <= $self->{option_results}->{max_depth}) { push @$list, { name => $name, level => $level + 1}; } } else { $self->{output}->output_add(long_msg => sprintf("Match '%s'", $name)); $count++; } } } } return $count; } 1; __END__ =head1 MODE Count files in an FTP directory (can be recursive). =over 8 =item B<--hostname> IP Addr/FQDN of the ftp host =item B<--port> Port used =item B<--ssl> Use SSL connection Need Perl 'Net::FTPSSL' module =item B<--ftp-options> Add custom ftp options. Example: --ftp-options='Debug=1" --ftp-options='useSSL=1' =item B<--username> Specify username for authentification =item B<--password> Specify password for authentification =item B<--timeout> Connection timeout in seconds (Default: 30) =item B<--warning> Threshold warning (number of files) =item B<--critical> Threshold critical (number of files) =item B<--directory> Check files in the directory (Multiple option) =item B<--max-depth> Don't check fewer levels (Default: '0'. Means current dir only). =item B<--filter-file> Filter files (can be a regexp. Directory is in the name). =back =cut centreon-plugins-20220113/apps/protocols/ftp/mode/login.pm000066400000000000000000000102511417000230700234050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::ftp::mode::login; use base qw(centreon::plugins::mode); use strict; use warnings; use Time::HiRes qw(gettimeofday tv_interval); use apps::protocols::ftp::lib::ftp; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "hostname:s" => { name => 'hostname' }, "port:s" => { name => 'port', }, "ssl" => { name => 'use_ssl' }, "ftp-options:s@" => { name => 'ftp_options' }, "username:s" => { name => 'username' }, "password:s" => { name => 'password' }, "warning:s" => { name => 'warning' }, "critical:s" => { name => 'critical' }, "timeout:s" => { name => 'timeout', default => '30' }, }); 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}->{hostname})) { $self->{output}->add_option_msg(short_msg => "Please set the hostname option"); $self->{output}->option_exit(); } } sub run { my ($self, %options) = @_; my $timing0 = [gettimeofday]; apps::protocols::ftp::lib::ftp::connect($self, connection_exit => 'critical'); apps::protocols::ftp::lib::ftp::quit(); my $timeelapsed = tv_interval ($timing0, [gettimeofday]); my $exit = $self->{perfdata}->threshold_check(value => $timeelapsed, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit, short_msg => sprintf("Response time %.3f ", $timeelapsed)); $self->{output}->perfdata_add(label => "time", value => sprintf('%.3f', $timeelapsed), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical')); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check Connection (also login) to an FTP Server. =over 8 =item B<--hostname> IP Addr/FQDN of the ftp host =item B<--port> Port used =item B<--ssl> Use SSL connection Need Perl 'Net::FTPSSL' module =item B<--ftp-options> Add custom ftp options. Example: --ftp-options='Debug=1" --ftp-options='useSSL=1' =item B<--username> Specify username for authentification =item B<--password> Specify password for authentification =item B<--timeout> Connection timeout in seconds (Default: 30) =item B<--warning> Threshold warning in seconds =item B<--critical> Threshold critical in seconds =back =cut centreon-plugins-20220113/apps/protocols/ftp/plugin.pm000066400000000000000000000026211417000230700226510ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::ftp::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} = '0.1'; %{$self->{modes}} = ( 'commands' => 'apps::protocols::ftp::mode::commands', 'date' => 'apps::protocols::ftp::mode::date', 'filescount' => 'apps::protocols::ftp::mode::filescount', 'login' => 'apps::protocols::ftp::mode::login', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check an FTP server. =cut centreon-plugins-20220113/apps/protocols/http/000077500000000000000000000000001417000230700212025ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/http/mode/000077500000000000000000000000001417000230700221265ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/http/mode/expectedcontent.pm000066400000000000000000000265741417000230700256760ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::http::mode::expectedcontent; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::http; use Time::HiRes qw(gettimeofday tv_interval); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_content_threshold { my ($self, %options) = @_; $self->{instance_mode}->{content_status} = catalog_status_threshold_ng($self, %options); return $self->{instance_mode}->{content_status}; } sub custom_content_output { my ($self, %options) = @_; my $msg = 'HTTP test(s)'; if (!$self->{output}->is_status(value => $self->{instance_mode}->{content_status}, compare => 'ok', litteral => 1)) { my $filter = $self->{instance_mode}->{option_results}->{lc($self->{instance_mode}->{content_status}) . '-content'}; $filter =~ s/\$values->/%/g; $filter =~ s/%\{expected_string\}/$self->{result_values}->{expected_string}/g; $msg = sprintf("Content test [filter: '%s']", $filter); } return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'content', type => 2, set => { key_values => [ { name => 'content' }, { name => 'code' }, { name => 'first_header' }, { name => 'header' }, { name => 'expected_string' } ], closure_custom_output => $self->can('custom_content_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => $self->can('custom_content_threshold') } }, { label => 'size', nlabel => 'http.content.size.bytes', display_ok => 0, set => { key_values => [ { name => 'size' } ], output_template => 'Content size : %s', perfdatas => [ { label => 'size', template => '%s', min => 0, unit => 'B' } ] } }, { label => 'time', nlabel => 'http.response.time.seconds', display_ok => 0, set => { key_values => [ { name => 'time' } ], output_template => 'Response time : %.3fs', perfdatas => [ { label => 'time', template => '%.3f', min => 0, unit => 's' } ] } }, { label => 'extracted', nlabel => 'http.extracted.value.count', display_ok => 0, set => { key_values => [ { name => 'extracted' } ], output_template => 'Extracted value : %s', perfdatas => [ { label => 'value', template => '%s' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port', }, 'method:s' => { name => 'method' }, 'proto:s' => { name => 'proto' }, 'urlpath:s' => { name => 'url_path' }, 'credentials' => { name => 'credentials' }, 'basic' => { name => 'basic' }, 'ntlmv2' => { name => 'ntlmv2' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'expected-string:s' => { name => 'expected_string' }, 'extracted-pattern:s' => { name => 'extracted_pattern' }, 'timeout:s' => { name => 'timeout' }, 'no-follow' => { name => 'no_follow', }, 'cert-file:s' => { name => 'cert_file' }, 'key-file:s' => { name => 'key_file' }, 'cacert-file:s' => { name => 'cacert_file' }, 'cert-pwd:s' => { name => 'cert_pwd' }, 'cert-pkcs12' => { name => 'cert_pkcs12' }, 'data:s' => { name => 'data' }, 'header:s@' => { name => 'header' }, 'get-param:s@' => { name => 'get_param' }, 'post-param:s@' => { name => 'post_param' }, 'cookies-file:s' => { name => 'cookies_file' }, 'unknown-status:s' => { name => 'unknown_status' }, 'warning-status:s' => { name => 'warning_status' }, 'critical-status:s' => { name => 'critical_status' } }); $self->{http} = centreon::plugins::http->new(%options); return $self; } sub load_request { my ($self, %options) = @_; $self->{options_request} = {}; if (defined($self->{option_results}->{data}) && $self->{option_results}->{data} ne '') { $self->{option_results}->{method} = defined($self->{option_results}->{method}) && $self->{option_results}->{method} ne '' ? $self->{option_results}->{method} : 'POST'; if (-f $self->{option_results}->{data} and -r $self->{option_results}->{data}) { local $/ = undef; my $fh; if (!open($fh, "<", $self->{option_results}->{data})) { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => sprintf("Could not read file '%s': %s", $self->{option_results}->{data}, $!) ); $self->{output}->display(); $self->{output}->exit(); } $self->{options_request}->{query_form_post} = <$fh>; close $fh; } else { $self->{options_request}->{query_form_post} = $self->{option_results}->{data}; } } } sub check_options { my ($self, %options) = @_; # Legacy compat if (defined($options{option_results}->{expected_string}) && $options{option_results}->{expected_string} ne '') { $options{option_results}->{'critical-content'} = "%{content} !~ /%{expected_string}/mi"; } $self->SUPER::check_options(%options); $self->load_request(); $self->{http}->set_options(%{$self->{option_results}}); } sub manage_selection { my ($self, %options) = @_; my $timing0 = [gettimeofday]; my $webcontent = $self->{http}->request(%{$self->{options_request}}); my $timeelapsed = tv_interval($timing0, [gettimeofday]); $self->{global} = { time => $timeelapsed, content => $webcontent, code => $self->{http}->get_code(), header => $self->{http}->get_header(), first_header => $self->{http}->get_first_header(), expected_string => defined($self->{option_results}->{expected_string}) ? $self->{option_results}->{expected_string} : '' }; if (defined($self->{option_results}->{extracted_pattern}) && $self->{option_results}->{extracted_pattern} ne '' && $webcontent =~ /$self->{option_results}->{extracted_pattern}/mi) { my $extracted = $1; if (defined($extracted) && $extracted =~ /(\d+([\.,]\d+)?)/) { $extracted =~ s/,/\./; $self->{global}->{extracted} = $extracted, } } $self->{output}->output_add(long_msg => $webcontent); # Size check { require bytes; $self->{global}->{size} = bytes::length($webcontent); } } 1; __END__ =head1 MODE Check Webpage content =over 8 =item B<--hostname> IP Addr/FQDN of the Webserver host =item B<--port> Port used by Webserver =item B<--method> Specify http method used (Default: 'GET') =item B<--proto> Specify https if needed (Default: 'http') =item B<--urlpath> Set path to get Webpage (Default: '/') =item B<--credentials> Specify this option if you access webpage with authentication =item B<--username> Specify username for authentication (Mandatory if --credentials is specified) =item B<--password> Specify password for authentication (Mandatory if --credentials is specified) =item B<--basic> Specify this option if you access webpage over basic authentication and don't want a '401 UNAUTHORIZED' error to be logged on your webserver. Specify this option if you access webpage over hidden basic authentication or you'll get a '404 NOT FOUND' error. (Use with --credentials) =item B<--ntlmv2> Specify this option if you access webpage over ntlmv2 authentication (Use with --credentials and --port options) =item B<--timeout> Threshold for HTTP timeout (Default: 5) =item B<--no-follow> Do not follow http redirect =item B<--cert-file> Specify certificate to send to the webserver =item B<--key-file> Specify key to send to the webserver =item B<--cacert-file> Specify root certificate to send to the webserver =item B<--cert-pwd> Specify certificate's password =item B<--cert-pkcs12> Specify type of certificate (PKCS12) =item B<--data> Set POST data request (For a JSON data, add following option: --header='Content-Type: application/json') =item B<--header> Set HTTP headers (Multiple option) =item B<--get-param> Set GET params (Multiple option. Example: --get-param='key=value') =item B<--post-param> Set POST params (Multiple option. Example: --post-param='key=value') =item B<--cookies-file> Save cookies in a file (Example: '/tmp/lwp_cookies.dat') =item B<--extracted-pattern> Set pattern to extracted a number (used --warning-extracted and --critical-extracted option). =item B<--expected-string> --expected-string='toto' is a shortcut for --critical-content='%{content} !~ /toto/mi' Recommend to use directly --critical-content. =item B<--unknown-status> Threshold warning for http response code (Default: '%{http_code} < 200 or %{http_code} >= 300') =item B<--warning-status> Threshold warning for http response code =item B<--critical-status> Threshold critical for http response code =item B<--warning-time> Threshold warning in seconds (Webpage response time) =item B<--critical-time> Threshold critical in seconds (Webpage response time) =item B<--warning-size> Threshold warning for content size =item B<--critical-size> Threshold critical for content size =item B<--warning-extracted> Threshold warning for extracted value =item B<--critical-extracted> Threshold critical for extracted value =item B<--unknown-content> Set warning threshold for content page (Default: ''). Can used special variables like: %{content}, %{header}, %{first_header}, %{code} =item B<--warning-content> Set warning threshold for status (Default: ''). Can used special variables like: %{content}, %{header}, %{first_header}, %{code} =item B<--critical-content> Set critical threshold for content page (Default: ''). Can used special variables like: %{content}, %{header}, %{first_header}, %{code} =back =cut centreon-plugins-20220113/apps/protocols/http/mode/jsoncontent.pm000066400000000000000000000471621417000230700250420ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::http::mode::jsoncontent; use base qw(centreon::plugins::mode); use strict; use warnings; use Time::HiRes qw(gettimeofday tv_interval); use centreon::plugins::http; use centreon::plugins::misc; use JSON::Path; use JSON; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'hostname:s' => { name => 'hostname' }, 'vhost:s' => { name => 'vhost' }, 'port:s' => { name => 'port', }, 'proto:s' => { name => 'proto' }, 'urlpath:s' => { name => 'url_path' }, 'credentials' => { name => 'credentials' }, 'basic' => { name => 'basic' }, 'ntlmv2' => { name => 'ntlmv2' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'header:s@' => { name => 'header' }, 'get-param:s@' => { name => 'get_param' }, 'timeout:s' => { name => 'timeout', default => 10 }, 'cert-file:s' => { name => 'cert_file' }, 'key-file:s' => { name => 'key_file' }, 'cacert-file:s' => { name => 'cacert_file' }, 'cert-pwd:s' => { name => 'cert_pwd' }, 'cert-pkcs12' => { name => 'cert_pkcs12' }, 'unknown-status:s' => { name => 'unknown_status' }, 'warning-status:s' => { name => 'warning_status' }, 'critical-status:s' => { name => 'critical_status' }, 'warning-numeric:s' => { name => 'warning_numeric' }, 'critical-numeric:s' => { name => 'critical_numeric' }, 'warning-string:s' => { name => 'warning_string' }, 'critical-string:s' => { name => 'critical_string' }, 'unknown-string:s' => { name => 'unknown_string' }, 'warning-time:s' => { name => 'warning_time' }, 'critical-time:s' => { name => 'critical_time' }, 'threshold-value:s' => { name => 'threshold_value', default => 'count' }, 'format-ok:s' => { name => 'format_ok', default => '%{count} element(s) found' }, 'format-warning:s' => { name => 'format_warning', default => '%{count} element(s) found' }, 'format-critical:s' => { name => 'format_critical', default => '%{count} element(s) found' }, 'format-unknown:s' => { name => 'format_unknown', default => '%{count} element(s) found' }, 'format-lookup:s' => { name => 'format_lookup'}, 'values-separator:s' => { name => 'values_separator', default => ', ' }, 'lookup-perfdatas-nagios:s' => { name => 'lookup_perfdatas_nagios'}, 'data:s' => { name => 'data' }, 'lookup:s@' => { name => 'lookup' } }); $self->{count} = 0; $self->{count_ok} = 0; $self->{count_warning} = 0; $self->{count_critical} = 0; $self->{values_ok} = []; $self->{values_warning} = []; $self->{values_critical} = []; $self->{values_unknown} = []; $self->{values_string_ok} = []; $self->{values_string_warning} = []; $self->{values_string_critical} = []; $self->{values_string_unknown} = []; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{threshold_value}) || $self->{option_results}->{threshold_value} !~ /^(count|values)$/) { $self->{option_results}->{threshold_value} = 'count'; } if (($self->{perfdata}->threshold_validate(label => 'warning-numeric', value => $self->{option_results}->{warning_numeric})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning-numeric threshold '" . $self->{option_results}->{warning_numeric} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'critical-numeric', value => $self->{option_results}->{critical_numeric})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical-numeric threshold '" . $self->{option_results}->{critical_numeric} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'warning-time', value => $self->{option_results}->{warning_time})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning-time threshold '" . $self->{option_results}->{warning_time} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'critical-time', value => $self->{option_results}->{critical_time})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical-time threshold '" . $self->{option_results}->{critical_time} . "'."); $self->{output}->option_exit(); } $self->{http}->set_options(%{$self->{option_results}}); } sub load_request { my ($self, %options) = @_; $self->{method} = 'GET'; if (defined($self->{option_results}->{data}) && $self->{option_results}->{data} ne '') { $self->{method} = 'POST'; if (-f $self->{option_results}->{data} and -r $self->{option_results}->{data}) { local $/ = undef; my $fh; if (!open($fh, "<:encoding(UTF-8)", $self->{option_results}->{data})) { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => sprintf("Could not read file '%s': %s", $self->{option_results}->{data}, $!)); $self->{output}->display(); $self->{output}->exit(); } my $file_content = <$fh>; close $fh; $/ = "\n"; chomp $file_content; $self->{json_request} = $file_content; } else { $self->{json_request} = $self->{option_results}->{data}; } } } sub display_output { my ($self, %options) = @_; foreach my $severity (('ok', 'warning', 'critical', 'unknown')) { next if (scalar(@{$self->{'values_' . $severity}}) == 0 && scalar(@{$self->{'values_string_' . $severity}}) == 0); my $format = ''; if(defined($self->{option_results}->{format_lookup}) && $self->{option_results}->{format_lookup} ne '') { $format = $self->{format_from_json}; } else { $format = $self->{option_results}->{'format_' . $severity}; } while ($format =~ /%\{(.*?)\}/g) { my $replace = ''; if (ref($self->{$1}) eq 'ARRAY') { $replace = join($self->{option_results}->{values_separator}, @{$self->{$1}}); } else { $replace = defined($self->{$1}) ? $self->{$1} : ''; } $format =~ s/%\{$1\}/$replace/g; } $self->{output}->output_add( severity => $severity, short_msg => $format ); } } sub decode_json_response { my ($self, %options) = @_; return if (defined($self->{json_response_decoded})); my $json = JSON->new; eval { $self->{json_response_decoded} = $json->decode($self->{json_response}); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response"); $self->{output}->option_exit(); } } sub lookup { my ($self, %options) = @_; my ($xpath, @values); $self->decode_json_response(); foreach my $xpath_find (@{$self->{option_results}->{lookup}}) { eval { my $jpath = JSON::Path->new($xpath_find); @values = $jpath->values($self->{json_response_decoded}); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot lookup: $@"); $self->{output}->option_exit(); } $self->{output}->output_add(long_msg => "Lookup XPath $xpath_find:"); foreach my $value (@values) { $self->{count}++; $self->{output}->output_add(long_msg => ' Node value: ' . $value); push @{$self->{values}}, $value; } } if ($self->{option_results}->{threshold_value} eq 'count') { my $exit = lc( $self->{perfdata}->threshold_check( value => $self->{count}, threshold => [ { label => 'critical-numeric', exit_litteral => 'critical' }, { label => 'warning-numeric', exit_litteral => 'warning' } ] ) ); push @{$self->{'values_' . $exit}}, $self->{count}; $self->{'count_' . $exit}++; } $self->{output}->perfdata_add( label => 'count', nlabel => 'json.match.total.count', value => $self->{count}, warning => $self->{option_results}->{threshold_value} eq 'count' ? $self->{perfdata}->get_perfdata_for_output(label => 'warning-numeric') : undef, critical => $self->{option_results}->{threshold_value} eq 'count' ? $self->{perfdata}->get_perfdata_for_output(label => 'critical-numeric') : undef, min => 0 ); my $count = 0; foreach my $value (@{$self->{values}}) { $count++; if ($value =~ /^(?:[0-9]+(?:\.[0-9]+)?|([0-9.]*)e([-+]?)(\d*))$/) { my $value_expand = centreon::plugins::misc::expand_exponential(value => $value); if ($self->{option_results}->{threshold_value} eq 'values') { my $exit = lc( $self->{perfdata}->threshold_check( value => $value_expand, threshold => [ { label => 'critical-numeric', exit_litteral => 'critical' }, { label => 'warning-numeric', exit_litteral => 'warning' } ] ) ); push @{$self->{'values_' . $exit}}, $value; $self->{'count_' . $exit}++ } $self->{output}->perfdata_add( label => 'element_' . $count, nlabel => 'json.match.element.' . $count . '.count', value => $value_expand, warning => $self->{option_results}->{threshold_value} eq 'values' ? $self->{perfdata}->get_perfdata_for_output(label => 'warning-numeric') : undef, critical => $self->{option_results}->{threshold_value} eq 'values' ? $self->{perfdata}->get_perfdata_for_output(label => 'critical-numeric') : undef ); } else { if (defined($self->{option_results}->{critical_string}) && $self->{option_results}->{critical_string} ne '' && $value =~ /$self->{option_results}->{critical_string}/) { push @{$self->{values_string_critical}}, $value; } elsif (defined($self->{option_results}->{warning_string}) && $self->{option_results}->{warning_string} ne '' && $value =~ /$self->{option_results}->{warning_string}/) { push @{$self->{values_string_warning}}, $value; } elsif (defined($self->{option_results}->{unknown_string}) && $self->{option_results}->{unknown_string} ne '' && $value =~ /$self->{option_results}->{unknown_string}/) { push @{$self->{values_string_unknown}}, $value; } else { push @{$self->{values_string_ok}}, $value; } } } if (defined($self->{option_results}->{format_lookup}) && $self->{option_results}->{format_lookup} ne '') { my $xpath_find = $self->{option_results}->{format_lookup}; eval { my $jpath = JSON::Path->new($xpath_find); $self->{format_from_json} = $jpath->value($self->{json_response_decoded}); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot lookup output message: $@"); $self->{output}->option_exit(); } $self->{output}->output_add(long_msg => "Lookup perfdatas XPath $xpath_find:"); } $self->display_output(); } sub lookup_perfdata_nagios { my ($self, %options) = @_; return if (!defined($self->{option_results}->{lookup_perfdatas_nagios}) || $self->{option_results}->{lookup_perfdatas_nagios} eq ''); $self->decode_json_response(); my $perfdata_string; my $xpath_find = $self->{option_results}->{lookup_perfdatas_nagios}; eval { my $jpath = JSON::Path->new($xpath_find); $perfdata_string = $jpath->value($self->{json_response_decoded}); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot lookup perfdatas: $@"); $self->{output}->option_exit(); } $self->{output}->output_add(long_msg => "Lookup perfdatas XPath $xpath_find:"); my @metrics = split(/ /, $perfdata_string); foreach my $single_metric (@metrics) { my ($label, $perfdatas) = split(/=/, $single_metric); my ($value_w_unit, $warn, $crit, $min, $max) = split(/;/, $perfdatas); # separate the value from the unit my ($value, $unit) = $value_w_unit =~ /(^[0-9]+\.*\,*[0-9]*)(.*)/g; $self->{output}->perfdata_add( label => $label, nlabel => $label, unit => $unit, value => $value, warning => $warn, critical => $crit, min => $min, max => $max ); } } sub run { my ($self, %options) = @_; $self->load_request(); my $timing0 = [gettimeofday]; $self->{json_response} = $self->{http}->request(method => $self->{method}, query_form_post => $self->{json_request}); my $timeelapsed = tv_interval ($timing0, [gettimeofday]); $self->{output}->output_add(long_msg => $self->{json_response}, debug => 1); if (!defined($self->{option_results}->{lookup}) || scalar(@{$self->{option_results}->{lookup}}) == 0) { $self->{output}->output_add( severity => 'OK', short_msg => "JSON webservice request success" ); } else { $self->lookup(); } my $exit = $self->{perfdata}->threshold_check( value => $timeelapsed, threshold => [ { label => 'critical-time', exit_litteral => 'critical' }, { label => 'warning-time', exit_litteral => 'warning' } ] ); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Response time %.3fs", $timeelapsed) ); } else { $self->{output}->output_add(long_msg => sprintf("Response time %.3fs", $timeelapsed)); } $self->{output}->perfdata_add( label => 'time', nlabel => 'http.response.time.seconds', unit => 's', value => sprintf('%.3f', $timeelapsed), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-time'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-time'), min => 0 ); $self->lookup_perfdata_nagios(); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check JSON webservice. Can send the json request with option '--data'. Example: centreon_plugins.pl --plugin=apps::protocols::http::plugin --mode=json-content --data='/home/user/request.json' --hostname='myws.site.com' --urlpath='/get/payment' --lookup='$..expiration' --header='Content-Type: application/json' JSON OPTIONS: =over 8 =item B<--data> Set file with JSON request =item B<--lookup> What to lookup in JSON response (JSON XPath string) (can be multiple) See: http://goessner.net/articles/JsonPath/ =item B<--lookup-perfdatas-nagios> Take perfdatas from the JSON response (JSON XPath string) Chain must be formated in Nagios format. Ex : "rta=10.752ms;50.000;100.000;0; pl=0%;20;40;; rtmax=10.802ms;;;;" =back FORMAT OPTIONS: =over 8 =item B<--format-lookup> Take the output message from the JSON response (JSON XPath string) Override all the format options but substitute are still applied. =item B<--format-ok> Output format (Default: '%{count} element(s) found') Can used: '%{values}' = display all values (also text string) '%{values_ok}' = values from attributes and text node only (seperated by option values-separator) '%{values_warning}' and '%{values_critical}' =item B<--format-warning> Output warning format (Default: %{count} element(s) found') =item B<--format-critical> Output critical format (Default: %{count} element(s) found') =item B<--format-unknown> Output unknown format (Default: %{count} element(s) found') =item B<--values-separator> Separator used for values in format option (Default: ', ') =back THRESHOLD OPTIONS: =over 8 =item B<--warning-numeric> Threshold warning (Default: on total matching elements) =item B<--critical-numeric> Threshold critical (Default: on total matching elements) =item B<--threshold-value> Which value to use (Default: 'count') Can be: 'values' (only check numeric values) =item B<--warning-string> Threshold warning if the string match =item B<--critical-string> Threshold critical if the string match =item B<--unknown-string> Threshold unknown if the string match =item B<--warning-time> Threshold warning in seconds of webservice response time =item B<--critical-time> Threshold critical in seconds of webservice response time =back HTTP OPTIONS: =over 8 =item B<--hostname> IP Addr/FQDN of the Webserver host =item B<--port> Port used by Webserver =item B<--proto> Specify https if needed =item B<--urlpath> Set path to get Webpage (Default: '/') =item B<--credentials> Specify this option if you access webpage with authentication =item B<--username> Specify username for authentication (Mandatory if --credentials is specified) =item B<--password> Specify password for authentication (Mandatory if --credentials is specified) =item B<--basic> Specify this option if you access webpage over basic authentication and don't want a '401 UNAUTHORIZED' error to be logged on your webserver. Specify this option if you access webpage over hidden basic authentication or you'll get a '404 NOT FOUND' error. (Use with --credentials) =item B<--ntlmv2> Specify this option if you access webpage over ntlmv2 authentication (Use with --credentials and --port options) =item B<--timeout> Threshold for HTTP timeout (Default: 10) =item B<--cert-file> Specify certificate to send to the webserver =item B<--key-file> Specify key to send to the webserver =item B<--cacert-file> Specify root certificate to send to the webserver =item B<--cert-pwd> Specify certificate's password =item B<--cert-pkcs12> Specify type of certificate (PKCS12) =item B<--get-param> Set GET params (Multiple option. Example: --get-param='key=value') =item B<--header> Set HTTP headers (Multiple option. Example: --header='Content-Type: xxxxx') =item B<--unknown-status> Threshold warning for http response code (Default: '%{http_code} < 200 or %{http_code} >= 300') =item B<--warning-status> Threshold warning for http response code =item B<--critical-status> Threshold critical for http response code =back =cut centreon-plugins-20220113/apps/protocols/http/mode/response.pm000066400000000000000000000234541417000230700243320ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::http::mode::response; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use Time::HiRes qw(gettimeofday tv_interval); use centreon::plugins::http; sub custom_status_output { my ($self, %options) = @_; return $self->{result_values}->{http_code} . ' ' . $self->{result_values}->{message}; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'status', type => 2, critical_default => '%{http_code} < 200 or %{http_code} >= 300', display_ok => 0, set => { key_values => [ { name => 'http_code' }, { name => 'message' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'time', nlabel => 'http.response.time.seconds', set => { key_values => [ { name => 'time' } ], output_template => 'response time %.3fs', perfdatas => [ { label => 'time', template => '%.3f', min => 0, unit => 's' } ] } }, { label => 'size', nlabel => 'http.response.size.count', display_ok => 0, set => { key_values => [ { name => 'size' } ], output_template => 'content size: %s', perfdatas => [ { label => 'size', template => '%s', min => 0, unit => 'B' } ] } }, { label => 'resolve', nlabel => 'http.response.resolve.time.milliseconds', display_ok => 0, set => { key_values => [ { name => 'resolve' } ], output_template => 'resolve: %.3f ms', perfdatas => [ { label => 'resolve', template => '%.3f', min => 0, unit => 'ms' } ] } }, { label => 'connect', nlabel => 'http.response.connect.time.milliseconds', display_ok => 0, set => { key_values => [ { name => 'resolve' } ], output_template => 'connect: %.3f ms', perfdatas => [ { label => 'connect', template => '%.3f', min => 0, unit => 'ms' } ] } }, { label => 'tls', nlabel => 'http.response.tls.time.milliseconds', display_ok => 0, set => { key_values => [ { name => 'tls' } ], output_template => 'tls: %.3f ms', perfdatas => [ { label => 'tls', template => '%.3f', min => 0, unit => 'ms' } ] } }, { label => 'processing', nlabel => 'http.response.processing.time.milliseconds', display_ok => 0, set => { key_values => [ { name => 'processing' } ], output_template => 'processing: %.3f ms', perfdatas => [ { label => 'processing', template => '%.3f', min => 0, unit => 'ms' } ] } }, { label => 'transfer', nlabel => 'http.response.transfer.time.milliseconds', display_ok => 0, set => { key_values => [ { name => 'resolve' } ], output_template => 'transfer: %.3f ms', perfdatas => [ { label => 'transfer', template => '%.3f', min => 0, unit => 'ms' } ] } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port', }, 'method:s' => { name => 'method' }, 'proto:s' => { name => 'proto' }, 'urlpath:s' => { name => 'url_path' }, 'credentials' => { name => 'credentials' }, 'basic' => { name => 'basic' }, 'ntlmv2' => { name => 'ntlmv2' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'timeout:s' => { name => 'timeout' }, 'no-follow' => { name => 'no_follow', }, 'cert-file:s' => { name => 'cert_file' }, 'key-file:s' => { name => 'key_file' }, 'cacert-file:s' => { name => 'cacert_file' }, 'cert-pwd:s' => { name => 'cert_pwd' }, 'cert-pkcs12' => { name => 'cert_pkcs12' }, 'header:s@' => { name => 'header' }, 'get-param:s@' => { name => 'get_param' }, 'post-param:s@' => { name => 'post_param' }, 'cookies-file:s' => { name => 'cookies_file' }, 'warning:s' => { name => 'warning' }, 'critical:s' => { name => 'critical' }, 'extra-stats' => { name => 'extra_stats' } }); $self->{http} = centreon::plugins::http->new(%options); return $self; } sub check_options { my ($self, %options) = @_; # Compat if (defined($options{option_results}->{warning})) { $options{option_results}->{'warning-time'} = $options{option_results}->{warning}; $options{option_results}->{'warning-http-response-time-seconds'} = $options{option_results}->{warning}; } if (defined($options{option_results}->{critical})) { $options{option_results}->{'critical-time'} = $options{option_results}->{critical}; $options{option_results}->{'critical-http-response-time-seconds'} = $options{option_results}->{critical}; } $self->SUPER::check_options(%options); $self->{http}->set_options(%{$self->{option_results}}); } sub manage_selection { my ($self, %options) = @_; $self->{global} = {}; my $timing0 = [gettimeofday]; my $webcontent = $self->{http}->request( unknown_status => '', warning_status => '', critical_status => '' ); $self->{global}->{time} = tv_interval($timing0, [gettimeofday]); $self->{global}->{http_code} = $self->{http}->get_code(); $self->{global}->{message} = $self->{http}->get_message(); { require bytes; $self->{global}->{size} = bytes::length($webcontent); } if (defined($self->{option_results}->{extra_stats})) { my $times = $self->{http}->get_times(); if (!defined($times)) { $self->{output}->add_option_msg(short_msg => 'Unsupported --extra-stats option for current http backend. Please try with curl backend.'); $self->{output}->option_exit(); } $self->{global} = { %$times, %{$self->{global}} }; } } 1; __END__ =head1 MODE Check Webpage response and size. =over 8 =item B<--hostname> IP Addr/FQDN of the webserver host =item B<--port> Port used by Webserver =item B<--method> Specify http method used (Default: 'GET') =item B<--proto> Specify https if needed (Default: 'http') =item B<--urlpath> Set path to get webpage (Default: '/') =item B<--credentials> Specify this option if you access webpage with authentication =item B<--username> Specify username for authentication (Mandatory if --credentials is specified) =item B<--password> Specify password for authentication (Mandatory if --credentials is specified) =item B<--basic> Specify this option if you access webpage over basic authentication and don't want a '401 UNAUTHORIZED' error to be logged on your webserver. Specify this option if you access webpage over hidden basic authentication or you'll get a '404 NOT FOUND' error. (Use with --credentials) =item B<--ntlmv2> Specify this option if you access webpage over ntlmv2 authentication (Use with --credentials and --port options) =item B<--timeout> Threshold for HTTP timeout (Default: 5) =item B<--no-follow> Do not follow http redirect =item B<--cert-file> Specify certificate to send to the webserver =item B<--key-file> Specify key to send to the webserver =item B<--cacert-file> Specify root certificate to send to the webserver =item B<--cert-pwd> Specify certificate's password =item B<--cert-pkcs12> Specify type of certificate (PKCS12) =item B<--header> Set HTTP headers (Multiple option) =item B<--get-param> Set GET params (Multiple option. Example: --get-param='key=value') =item B<--post-param> Set POST params (Multiple option. Example: --post-param='key=value') =item B<--cookies-file> Save cookies in a file (Example: '/tmp/lwp_cookies.dat') =item B<--unknown-status> Threshold warning for http response code =item B<--warning-status> Threshold warning for http response code =item B<--critical-status> Threshold critical for http response code (Default: '%{http_code} < 200 or %{http_code} >= 300') =item B<--extra-stats> Add detailed time statistics (only with curl backend). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'time', 'size', 'resolve', 'connect', 'tls', 'processing', 'transfer'. =back =cut centreon-plugins-20220113/apps/protocols/http/mode/soapcontent.pm000066400000000000000000000414221417000230700250240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::http::mode::soapcontent; use base qw(centreon::plugins::mode); use strict; use warnings; use Time::HiRes qw(gettimeofday tv_interval); use centreon::plugins::http; use XML::XPath; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'service-soap:s' => { name => 'service_soap' }, 'data:s' => { name => 'data' }, 'lookup:s@' => { name => 'lookup' }, 'hostname:s' => { name => 'hostname' }, 'vhost:s' => { name => 'vhost' }, 'port:s' => { name => 'port', }, 'proto:s' => { name => 'proto' }, 'urlpath:s' => { name => 'url_path' }, 'credentials' => { name => 'credentials' }, 'basic' => { name => 'basic' }, 'ntlmv2' => { name => 'ntlmv2' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'header:s@' => { name => 'header' }, 'timeout:s' => { name => 'timeout', default => 10 }, 'cert-file:s' => { name => 'cert_file' }, 'key-file:s' => { name => 'key_file' }, 'cacert-file:s' => { name => 'cacert_file' }, 'cert-pwd:s' => { name => 'cert_pwd' }, 'cert-pkcs12' => { name => 'cert_pkcs12' }, 'unknown-status:s' => { name => 'unknown_status' }, 'warning-status:s' => { name => 'warning_status' }, 'critical-status:s' => { name => 'critical_status' }, 'warning-numeric:s' => { name => 'warning_numeric' }, 'critical-numeric:s' => { name => 'critical_numeric' }, 'warning-string:s' => { name => 'warning_string' }, 'critical-string:s' => { name => 'critical_string' }, 'warning-time:s' => { name => 'warning_time' }, 'critical-time:s' => { name => 'critical_time' }, 'threshold-value:s' => { name => 'threshold_value', default => 'count' }, 'format-ok:s' => { name => 'format_ok', default => '%{count} element(s) found' }, 'format-warning:s' => { name => 'format_warning', default => '%{count} element(s) found' }, 'format-critical:s' => { name => 'format_critical', default => '%{count} element(s) found' }, 'values-separator:s' => { name => 'values_separator', default => ', ' } }); $self->{count} = 0; $self->{count_ok} = 0; $self->{count_warning} = 0; $self->{count_critical} = 0; $self->{values_ok} = []; $self->{values_warning} = []; $self->{values_critical} = []; $self->{values_string_ok} = []; $self->{values_string_warning} = []; $self->{values_string_critical} = []; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{threshold_value}) || $self->{option_results}->{threshold_value} !~ /^(count|values)$/) { $self->{option_results}->{threshold_value} = 'count'; } if (($self->{perfdata}->threshold_validate(label => 'warning-numeric', value => $self->{option_results}->{warning_numeric})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning-numeric threshold '" . $self->{option_results}->{warning_numeric} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'critical-numeric', value => $self->{option_results}->{critical_numeric})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical-numeric threshold '" . $self->{option_results}->{critical_numeric} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'warning-time', value => $self->{option_results}->{warning_time})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning-time threshold '" . $self->{option_results}->{warning_time} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'critical-time', value => $self->{option_results}->{critical_time})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical-time threshold '" . $self->{option_results}->{critical_time} . "'."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{service_soap})) { $self->{output}->add_option_msg(short_msg => "You need to specify service-soap."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{data})) { $self->{output}->add_option_msg(short_msg => "You need to specify data."); $self->{output}->option_exit(); } $self->{http}->set_options(%{$self->{option_results}}); $self->{http}->add_header(key => 'SOAPAction', value => $self->{option_results}->{service_soap}); } sub load_request { my ($self, %options) = @_; local $/ = undef; if (!open(FILE, "<", $self->{option_results}->{data})) { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => sprintf("Could not read file '%s': %s", $self->{option_results}->{data}, $!)); $self->{output}->display(); $self->{output}->exit(); } $self->{soap_request} = ; close FILE; } sub display_output { my ($self, %options) = @_; foreach my $severity (('ok', 'warning', 'critical')) { next if (scalar(@{$self->{'values_' . $severity}}) == 0 && scalar(@{$self->{'values_string_' . $severity}}) == 0); my $format = $self->{option_results}->{'format_' . $severity}; while ($format =~ /%\{(.*?)\}/g) { my $replace = ''; if (ref($self->{$1}) eq 'ARRAY') { $replace = join($self->{option_results}->{values_separator}, @{$self->{$1}}); } else { $replace = defined($self->{$1}) ? $self->{$1} : ''; } $format =~ s/%\{$1\}/$replace/g; } $self->{output}->output_add( severity => $severity, short_msg => $format ); } } sub check_encoding { my ($self, %options) = @_; my $charset; my ($content_type) = $self->{http}->get_header(name => 'Content-Type'); if (defined($content_type) && $content_type =~ /charset\s*=\s*(\S+)/i) { $charset = $1; } if ($self->{soap_response} =~ /<\?xml(.*?)\?>/ms) { if ($1 !~ /encoding=/ && defined($charset)) { $self->{soap_response} =~ s/<\?xml(.*?)\?>/<\?xml$1 encoding="$charset"\?>/ms } } elsif (defined($charset)) { $self->{soap_response} = '' . "\n" . $self->{soap_response}; } } sub lookup { my ($self, %options) = @_; my ($xpath, $nodeset); $self->check_encoding(); eval { $xpath = XML::XPath->new(xml => $self->{soap_response}); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot load SOAP response"); $self->{output}->option_exit(); } foreach my $xpath_find (@{$self->{option_results}->{lookup}}) { eval { $nodeset = $xpath->find($xpath_find); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot lookup: $@"); $self->{output}->option_exit(); } $self->{output}->output_add(long_msg => "Lookup XPath $xpath_find:"); foreach my $node ($nodeset->get_nodelist()) { $self->{count}++; my $node_type = ref($node); $self->{output}->output_add(long_msg => " Node type: $node_type"); if ($node_type eq 'XML::XPath::Node::Text') { $self->{output}->output_add(long_msg => ' Node value: ' . $node->string_value); push @{$self->{values}}, $node->string_value; } if ($node_type eq 'XML::XPath::Node::Attribute') { $self->{output}->output_add(long_msg => ' Node value: ' . $node->toString); push @{$self->{values}}, $node->getNodeValue; } } } if ($self->{option_results}->{threshold_value} eq 'count') { my $exit = lc($self->{perfdata}->threshold_check( value => $self->{count}, threshold => [ { label => 'critical-numeric', exit_litteral => 'critical' }, { label => 'warning-numeric', exit_litteral => 'warning' } ]) ); push @{$self->{'values_' . $exit}}, $self->{count}; $self->{'count_' . $exit}++; } $self->{output}->perfdata_add( label => 'count', nlabel => 'xml.match.total.count', value => $self->{count}, warning => $self->{option_results}->{threshold_value} eq 'count' ? $self->{perfdata}->get_perfdata_for_output(label => 'warning-numeric') : undef, critical => $self->{option_results}->{threshold_value} eq 'count' ? $self->{perfdata}->get_perfdata_for_output(label => 'critical-numeric') : undef, min => 0 ); my $count = 0; foreach my $value (@{$self->{values}}) { $count++; if ($value =~ /^[0-9.]+$/) { if ($self->{option_results}->{threshold_value} eq 'values') { my $exit = lc($self->{perfdata}->threshold_check( value => $value, threshold => [ { label => 'critical-numeric', exit_litteral => 'critical' }, { label => 'warning-numeric', exit_litteral => 'warning' } ]) ); push @{$self->{'values_' . $exit}}, $value; $self->{'count_' . $exit}++ } $self->{output}->perfdata_add( label => 'element_' . $count, nlabel => 'xml.match.element.' . $count . '.count', value => $value, warning => $self->{option_results}->{threshold_value} eq 'values' ? $self->{perfdata}->get_perfdata_for_output(label => 'warning-numeric') : undef, critical => $self->{option_results}->{threshold_value} eq 'values' ? $self->{perfdata}->get_perfdata_for_output(label => 'critical-numeric') : undef ); } else { if (defined($self->{option_results}->{critical_string}) && $self->{option_results}->{critical_string} ne '' && $value =~ /$self->{option_results}->{critical_string}/) { push @{$self->{values_string_critical}}, $value; } elsif (defined($self->{option_results}->{warning_string}) && $self->{option_results}->{warning_string} ne '' && $value =~ /$self->{option_results}->{warning_string}/) { push @{$self->{values_string_warning}}, $value; } else { push @{$self->{values_string_ok}}, $value; } } } $self->display_output(); } sub run { my ($self, %options) = @_; $self->load_request(); my $timing0 = [gettimeofday]; $self->{soap_response} = $self->{http}->request(method => 'POST', query_form_post => $self->{soap_request}); my $timeelapsed = tv_interval ($timing0, [gettimeofday]); $self->{output}->output_add(long_msg => $self->{soap_response}, debug => 1); if (!defined($self->{option_results}->{lookup}) || scalar(@{$self->{option_results}->{lookup}}) == 0 || $self->{option_results}->{lookup}->[0] eq '' ) { $self->{output}->output_add( severity => 'OK', short_msg => 'SOAP request success' ); } else { $self->lookup(); } my $exit = $self->{perfdata}->threshold_check( value => $timeelapsed, threshold => [ { label => 'critical-time', exit_litteral => 'critical' }, { label => 'warning-time', exit_litteral => 'warning' } ] ); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Response time %.3fs", $timeelapsed) ); } else { $self->{output}->output_add(long_msg => sprintf('Response time %.3fs', $timeelapsed)); } $self->{output}->perfdata_add( label => 'time', nlabel => 'http.response.time.seconds', unit => 's', value => sprintf('%.3f', $timeelapsed), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-time'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-time'), min => 0 ); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check SOAP content. Send the soap request with option '--data'. Example: centreon_plugins.pl --plugin=apps::protocols::http::plugin --mode=soap-content --service-soap='http://www.mysite.com/mysoapaction' --header='Content-Type: text/xml;charset=UTF-8' --data='/home/user/soap_request.xml' --hostname='myws.site.com' --urlpath='/get/payment' --lookup='//numeric/text()' SOAP OPTIONS: =over 8 =item B<--service-soap> Service Soap Action (Required) =item B<--data> Set file with SOAP request (Required) =item B<--lookup> What to lookup in XML response (XPath string) (can be multiple) =back FORMAT OPTIONS: =over 8 =item B<--format-ok> Output format (Default: '%{count} element(s) found') Can used: '%{values}' = display all values (also text string) '%{values_ok}' = values from attributes and text node only (seperated by option values-separator) '%{values_warning}' and '%{values_critical}' =item B<--format-warning> Output warning format (Default: %{count} element(s) found') =item B<--format-critical> Output critical format (Default: %{count} element(s) found') =item B<--values-separator> Separator used for values in format option (Default: ', ') =back THRESHOLD OPTIONS: =over 8 =item B<--warning-numeric> Threshold warning (Default: on total matching elements) =item B<--critical-numeric> Threshold critical (Default: on total matching elements) =item B<--threshold-value> Which value to use (Default: 'count') Can be: 'values' (only check numeric values) =item B<--warning-string> Threshold warning if the string match =item B<--critical-string> Threshold critical if the string match =item B<--warning-time> Threshold warning in seconds of webservice response time =item B<--critical-time> Threshold critical in seconds of webservice response time =back HTTP OPTIONS: =over 8 =item B<--hostname> IP Addr/FQDN of the Webserver host =item B<--port> Port used by Webserver =item B<--proto> Specify https if needed =item B<--urlpath> Set path to get Webpage (Default: '/') =item B<--credentials> Specify this option if you access webpage with authentication =item B<--username> Specify username for authentication (Mandatory if --credentials is specified) =item B<--password> Specify password for authentication (Mandatory if --credentials is specified) =item B<--basic> Specify this option if you access webpage over basic authentication and don't want a '401 UNAUTHORIZED' error to be logged on your webserver. Specify this option if you access webpage over hidden basic authentication or you'll get a '404 NOT FOUND' error. (Use with --credentials) =item B<--ntlmv2> Specify this option if you access webpage over ntlmv2 authentication (Use with --credentials and --port options) =item B<--timeout> Threshold for HTTP timeout (Default: 10) =item B<--cert-file> Specify certificate to send to the webserver =item B<--key-file> Specify key to send to the webserver =item B<--cacert-file> Specify root certificate to send to the webserver =item B<--cert-pwd> Specify certificate's password =item B<--cert-pkcs12> Specify type of certificate (PKCS1 =item B<--header> Set HTTP headers (Multiple option) =item B<--unknown-status> Threshold unknown for http response code (Default: '%{http_code} < 200 or %{http_code} >= 300') =item B<--warning-status> Threshold warning for http response code =item B<--critical-status> Threshold critical for http response code =back =cut centreon-plugins-20220113/apps/protocols/http/plugin.pm000066400000000000000000000026701417000230700230430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::http::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} = '0.1'; $self->{modes} = { 'expected-content' => 'apps::protocols::http::mode::expectedcontent', 'json-content' => 'apps::protocols::http::mode::jsoncontent', 'response' => 'apps::protocols::http::mode::response', 'soap-content' => 'apps::protocols::http::mode::soapcontent' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check HTTP or HTTPS webpage. =cut centreon-plugins-20220113/apps/protocols/imap/000077500000000000000000000000001417000230700211515ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/imap/lib/000077500000000000000000000000001417000230700217175ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/imap/lib/imap.pm000066400000000000000000000067161417000230700232150ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::imap::lib::imap; use strict; use warnings; use Net::IMAP::Simple; use IO::Socket::SSL; my $imap_handle; sub quit { $imap_handle->quit; } sub search { my ($self, %options) = @_; if (!defined($imap_handle->select($self->{option_results}->{folder}))) { my $output = $imap_handle->errstr; $output =~ s/\r//g; $self->{output}->output_add( severity => 'UNKNOWN', short_msg => 'Folder Select Error: ' . $output ); quit(); $self->{output}->display(); $self->{output}->exit(); } my @ids = $imap_handle->search($self->{option_results}->{search}); if (defined($self->{option_results}->{delete})) { foreach my $msg_num (@ids) { $imap_handle->delete($msg_num); } $imap_handle->expunge_mailbox(); } return scalar(@ids); } sub connect { my ($self, %options) = @_; my %imap_options = (); my $connection_exit = defined($options{connection_exit}) ? $options{connection_exit} : 'unknown'; $imap_options{port} = $self->{option_results}->{port} if (defined($self->{option_results}->{port})); $imap_options{use_ssl} = 1 if (defined($self->{option_results}->{use_ssl})); $imap_options{timeout} = $self->{option_results}->{timeout} if (defined($self->{option_results}->{timeout})); if ($self->{ssl_options} ne '') { $imap_options{ssl_options} = [ eval $self->{ssl_options} ]; } if (defined($self->{option_results}->{username}) && $self->{option_results}->{username} ne '' && !defined($self->{option_results}->{password})) { $self->{output}->add_option_msg(short_msg => 'Please set --password option.'); $self->{output}->option_exit(); } $imap_handle = Net::IMAP::Simple->new( $self->{option_results}->{hostname}, %imap_options ); if (!defined($imap_handle)) { $self->{output}->output_add( severity => $connection_exit, short_msg => 'Unable to connect to IMAP: ' . $Net::IMAP::Simple::errstr ); $self->{output}->display(); $self->{output}->exit(); } if (defined($self->{option_results}->{username}) && $self->{option_results}->{username} ne '') { if (!$imap_handle->login($self->{option_results}->{username}, $self->{option_results}->{password})) { # Exchange put '\r'... my $output = $imap_handle->errstr; $output =~ s/\r//g; $self->{output}->output_add( severity => $connection_exit, short_msg => 'Login failed: ' . $output ); quit(); $self->{output}->display(); $self->{output}->exit(); } } } 1; centreon-plugins-20220113/apps/protocols/imap/mode/000077500000000000000000000000001417000230700220755ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/imap/mode/login.pm000066400000000000000000000103171417000230700235450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::imap::mode::login; use base qw(centreon::plugins::mode); use strict; use warnings; use Time::HiRes qw(gettimeofday tv_interval); use apps::protocols::imap::lib::imap; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port', }, 'ssl' => { name => 'use_ssl' }, 'ssl-opt:s@' => { name => 'ssl_opt' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'warning:s' => { name => 'warning' }, 'critical:s' => { name => 'critical' }, 'timeout:s' => { name => 'timeout', default => '30' } }); 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}->{hostname})) { $self->{output}->add_option_msg(short_msg => "Please set the hostname option"); $self->{output}->option_exit(); } my $append = ''; $self->{ssl_options} = ''; foreach (@{$self->{option_results}->{ssl_opt}}) { if ($_ ne '') { $self->{ssl_options} .= $append . $_; $append = ', '; } } } sub run { my ($self, %options) = @_; my $timing0 = [gettimeofday]; apps::protocols::imap::lib::imap::connect($self, connection_exit => 'critical'); apps::protocols::imap::lib::imap::quit(); my $timeelapsed = tv_interval($timing0, [gettimeofday]); my $exit = $self->{perfdata}->threshold_check( value => $timeelapsed, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ] ); $self->{output}->output_add( severity => $exit, short_msg => sprintf("Response time %.3f ", $timeelapsed) ); $self->{output}->perfdata_add( label => 'time', value => sprintf('%.3f', $timeelapsed), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical') ); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check Connection (also login) to an IMAP Server. =over 8 =item B<--hostname> IP Addr/FQDN of the imap host =item B<--port> Port used =item B<--ssl> Use SSL connection. =item B<--ssl-opt> Set SSL options: --ssl-opt="SSL_verify_mode => SSL_VERIFY_NONE" --ssl-opt="SSL_version => 'TLSv1'" =item B<--username> Specify username for authentification =item B<--password> Specify password for authentification =item B<--timeout> Connection timeout in seconds (Default: 30) =item B<--warning> Threshold warning in seconds =item B<--critical> Threshold critical in seconds =back =cut centreon-plugins-20220113/apps/protocols/imap/mode/searchmessage.pm000066400000000000000000000111441417000230700252460ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::imap::mode::searchmessage; use base qw(centreon::plugins::mode); use strict; use warnings; use apps::protocols::imap::lib::imap; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port', }, 'ssl' => { name => 'use_ssl' }, 'ssl-opt:s@' => { name => 'ssl_opt' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'warning:s' => { name => 'warning' }, 'critical:s' => { name => 'critical' }, 'timeout:s' => { name => 'timeout', default => '30' }, 'search:s' => { name => 'search' }, 'delete' => { name => 'delete' }, 'folder:s' => { name => 'folder', default => 'INBOX' } }); 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}->{hostname})) { $self->{output}->add_option_msg(short_msg => 'Please set the --hostname option'); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{search})) { $self->{output}->add_option_msg(short_msg => 'Please set the --search option'); $self->{output}->option_exit(); } my $append = ''; $self->{ssl_options} = ''; foreach (@{$self->{option_results}->{ssl_opt}}) { if ($_ ne '') { $self->{ssl_options} .= $append . $_; $append = ', '; } } } sub run { my ($self, %options) = @_; apps::protocols::imap::lib::imap::connect($self); my ($num) = apps::protocols::imap::lib::imap::search($self); apps::protocols::imap::lib::imap::quit(); my $exit = $self->{perfdata}->threshold_check( value => $num, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ] ); $self->{output}->output_add( severity => $exit, short_msg => sprintf('%d message(s) found', $num) ); $self->{output}->perfdata_add( label => 'numbers', value => $num, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0 ); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check messages in a mailbox with IMAP filter. =over 8 =item B<--hostname> IP Addr/FQDN of the imap host =item B<--port> Port used =item B<--ssl> Use SSL connection. =item B<--ssl-opt> Set SSL options: --ssl-opt="SSL_verify_mode => SSL_VERIFY_NONE" --ssl-opt="SSL_version => 'TLSv1'" =item B<--username> Specify username for authentification =item B<--password> Specify password for authentification =item B<--timeout> Connection timeout in seconds (Default: 30) =item B<--search> Set the search string (Required) =item B<--delete> Delete messages found =item B<--folder> Set IMAP folder (Default: 'INBOX') =item B<--warning> Threshold warning of number messages found =item B<--critical> Threshold critical of number message found =back =cut centreon-plugins-20220113/apps/protocols/imap/plugin.pm000066400000000000000000000024341417000230700230100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::imap::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} = '0.1'; %{$self->{modes}} = ( 'login' => 'apps::protocols::imap::mode::login', 'search-message' => 'apps::protocols::imap::mode::searchmessage', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check an IMAP server. =cut centreon-plugins-20220113/apps/protocols/jmx/000077500000000000000000000000001417000230700210215ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/jmx/mode/000077500000000000000000000000001417000230700217455ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/jmx/mode/listattributes.pm000066400000000000000000000045311417000230700253700ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::jmx::mode::listattributes; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "max-depth:s" => { name => 'max_depth', default => 6 }, "max-objects:s" => { name => 'max_objects', default => 10000 }, "max-collection-size:s" => { name => 'max_collection_size', default => 150 }, "mbean-pattern:s" => { name => 'mbean_pattern', default => '*:*' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; $self->{connector} = $options{custom}; $self->{connector}->list_attributes(%{$self->{option_results}}); $self->{output}->exit(); } 1; __END__ =head1 MODE List JMX attributes. =over 8 =item B<--max-depth> Maximum nesting level of the returned JSON structure for a certain MBean (Default: 6) =item B<--max-collection-size> Maximum size of a collection after which it gets truncated (default: 150) =item B<--max-objects> Maximum overall objects to fetch for a mbean (default: 10000) =item B<--mbean-pattern> Pattern matching (Default: '*:*'). For details: http://docs.oracle.com/javase/1.5.0/docs/api/javax/management/ObjectName.html =back =cut centreon-plugins-20220113/apps/protocols/jmx/mode/numericvalue.pm000066400000000000000000000345461417000230700250160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::jmx::mode::numericvalue; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::statefile; use Digest::MD5 qw(md5_hex); use centreon::plugins::misc; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "mbean-pattern:s" => { name => 'mbean_pattern' }, "attribute:s@" => { name => 'attribute' }, "lookup-path:s" => { name => 'lookup_path' }, "lookup-jpath:s" => { name => 'lookup_jpath' }, "type:s@" => { name => 'type' }, "counter-per-seconds:s@" => { name => 'counter_per_seconds' }, "warning:s@" => { name => 'warning' }, "critical:s@" => { name => 'critical' }, "format:s@" => { name => 'format' }, "format-scale:s@" => { name => 'format_scale' }, "format-scale-type:s@" => { name => 'format_scale_type' }, "perfdata-unit:s@" => { name => 'perfdata_unit' }, "perfdata-name:s@" => { name => 'perfdata_name' }, "perfdata-min:s@" => { name => 'perfdata_min' }, "perfdata-max:s@" => { name => 'perfdata_max' }, }); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); $self->{jpath} = undef; return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{mbean_pattern}) || $self->{option_results}->{mbean_pattern} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify mbean-pattern option."); $self->{output}->option_exit(); } $self->{request} = [ { mbean => $self->{option_results}->{mbean_pattern} } ]; if (!defined($self->{option_results}->{attribute}) || scalar($self->{option_results}->{attribute}) == 0) { $self->{option_results}->{attribute} = undef; } else { $self->{request}->[0]->{attributes} = []; foreach (@{$self->{option_results}->{attribute}}) { push @{$self->{request}->[0]->{attributes}}, { name => $_, path => $self->{option_results}->{lookup_path}}; } } if (defined($self->{option_results}->{type})) { foreach (@{$self->{option_results}->{type}}) { if ($_ =~ /^counter$/) { $self->{statefile_cache}->check_options(%options); last; } } } if ((!defined($self->{option_results}->{lookup_jpath}) || $self->{option_results}->{lookup_jpath} eq '') && (!defined($self->{option_results}->{lookup_path}) || $self->{option_results}->{lookup_path} eq '')) { $self->{output}->add_option_msg(short_msg => "Need to specify --lookup-path or --lookup-jpath option."); $self->{output}->option_exit(); } if (defined($self->{option_results}->{lookup_jpath}) && $self->{option_results}->{lookup_jpath} ne '') { centreon::plugins::misc::mymodule_load(output => $self->{output}, module => 'JSON::Path', error_msg => "Cannot load module 'JSON::Path'."); $self->{jpath} = JSON::Path->new($self->{option_results}->{lookup_jpath}); } } sub set_attributes { my ($self, %options) = @_; $self->{attributes} = {}; $self->{attributes}->{type} = (defined($self->{option_results}->{type}) && scalar(@{$self->{option_results}->{type}}) > 0) ? shift(@{$self->{option_results}->{type}}) : 'gauge'; $self->{attributes}->{counter_per_seconds} = (defined($self->{option_results}->{counter_per_seconds}) && scalar(@{$self->{option_results}->{counter_per_seconds}}) > 0) ? shift(@{$self->{option_results}->{counter_per_seconds}}) : undef; $self->{attributes}->{warning} = (defined($self->{option_results}->{warning}) && scalar(@{$self->{option_results}->{warning}}) > 0) ? shift(@{$self->{option_results}->{warning}}) : undef; $self->{attributes}->{critical} = (defined($self->{option_results}->{critical}) && scalar(@{$self->{option_results}->{critical}}) > 0) ? shift(@{$self->{option_results}->{critical}}) : undef; $self->{attributes}->{format} = (defined($self->{option_results}->{format}) && scalar(@{$self->{option_results}->{format}}) > 0) ? shift(@{$self->{option_results}->{format}}) : 'current value' . $options{number} . ' is %s'; $self->{attributes}->{format_scale} = (defined($self->{option_results}->{format_scale}) && scalar(@{$self->{option_results}->{format_scale}}) > 0) ? shift(@{$self->{option_results}->{format_scale}}) : undef; $self->{attributes}->{format_scale_type} = (defined($self->{option_results}->{format_scale_type}) && scalar(@{$self->{option_results}->{format_scale_type}}) > 0) ? shift(@{$self->{option_results}->{format_scale_type}}) : 'other'; $self->{attributes}->{perfdata_unit} = (defined($self->{option_results}->{perfdata_unit}) && scalar(@{$self->{option_results}->{perfdata_unit}}) > 0) ? shift(@{$self->{option_results}->{perfdata_unit}}) : ''; $self->{attributes}->{perfdata_name} = (defined($self->{option_results}->{perfdata_name}) && scalar(@{$self->{option_results}->{perfdata_name}}) > 0) ? shift(@{$self->{option_results}->{perfdata_name}}) : 'value' . $options{number}; $self->{attributes}->{perfdata_min} = (defined($self->{option_results}->{perfdata_min}) && scalar(@{$self->{option_results}->{perfdata_min}}) > 0) ? shift(@{$self->{option_results}->{perfdata_min}}) : ''; $self->{attributes}->{perfdata_max} = (defined($self->{option_results}->{perfdata_max}) && scalar(@{$self->{option_results}->{perfdata_max}}) > 0) ? shift(@{$self->{option_results}->{perfdata_max}}) : ''; if ($self->{attributes}->{type} !~ /^gauge|counter$/i) { $self->{output}->add_option_msg(short_msg => "Wrong --type argument '" . $self->{attributes}->{type} . "' ('gauge' or 'counter')."); $self->{output}->option_exit(); } if ($self->{attributes}->{format_scale_type} !~ /^other|network$/i) { $self->{output}->add_option_msg(short_msg => "Wrong --format-scale-unit argument '" . $self->{attributes}->{format_scale_type} . "' ('other' or 'network')."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'warning-' . $options{number}, value => $self->{attributes}->{warning})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning threshold '" . $self->{attributes}->{warning} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'critical-' . $options{number}, value => $self->{attributes}->{critical})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical threshold '" . $self->{attributes}->{critical} . "'."); $self->{output}->option_exit(); } } sub check_value { my ($self, %options) = @_; my $value = $options{value}; if ($self->{attributes}->{type} =~ /^counter$/i) { if (!defined($self->{datas})) { $self->{datas} = {}; $self->{statefile_cache}->read(statefile => "jmxstandard_" . $self->{mode} . '_' . md5_hex($self->{connector}->get_connection_info() . ' ' . $self->{option_results}->{mbean_pattern})); } my $old_timestamp = $self->{statefile_cache}->get(name => 'timestamp'); my $old_value = $self->{statefile_cache}->get(name => 'value' . $options{number}); $self->{datas}->{timestamp} = time(); $self->{datas}->{'value' . $options{number}} = $value; if (!defined($old_timestamp)) { $self->{output}->output_add(severity => 'OK', short_msg => "Value " . $options{number} . ": buffer creation..."); return ; } # Reboot or counter goes back if ($old_value > $value) { $old_value = 0; } $value = $value - $old_value; if (defined($self->{attributes}->{counter_per_seconds})) { my $delta_time = $self->{datas}->{timestamp} - $old_timestamp; $delta_time = 1 if ($delta_time == 0); # at least 1 sec $value = $value / $delta_time; } } my $exit = $self->{perfdata}->threshold_check(value => $value, threshold => [ { label => 'critical-' . $options{number}, exit_litteral => 'critical' }, { label => 'warning-' . $options{number}, exit_litteral => 'warning' } ]); if (defined($self->{attributes}->{format_scale})) { my ($value_mod, $value_unit) = $self->{perfdata}->change_bytes(value => $value); if ($self->{attributes}->{format_scale_type} =~ /^network$/i) { ($value_mod, $value_unit) = $self->{perfdata}->change_bytes(value => $value, network => 1); } $self->{output}->output_add(severity => $exit, short_msg => sprintf($self->{attributes}->{format}, $value_mod . $value_unit)); } else { $self->{output}->output_add(severity => $exit, short_msg => sprintf($self->{attributes}->{format}, $value)); } $self->{output}->perfdata_add(label => $self->{attributes}->{perfdata_name}, unit => $self->{attributes}->{perfdata_unit}, value => $value, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $options{number}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $options{number}), min => $self->{attributes}->{perfdata_min}, max => $self->{attributes}->{perfdata_max}); } sub find_values { my ($self, %options) = @_; $self->{values} = []; if (defined($options{result})) { if (defined($self->{option_results}->{attribute})) { foreach (@{$self->{option_results}->{attribute}}) { if (defined($options{result}->{$self->{option_results}->{mbean_pattern}}->{$_}) && !ref($options{result}->{$self->{option_results}->{mbean_pattern}}->{$_})) { push @{$self->{values}}, $options{result}->{$self->{option_results}->{mbean_pattern}}->{$_} if ($options{result}->{$self->{option_results}->{mbean_pattern}}->{$_} =~ /^[0-9\.,]+$/); } } } if (defined($self->{jpath})) { my @values = (); eval { @values = $self->{jpath}->values($options{result}); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot lookup: $@"); $self->{output}->option_exit(); } foreach my $value (@values) { push @{$self->{values}}, $value if (!ref($value) && $value =~ /^[0-9\.,]+$/); } } } if (scalar(@{$self->{values}}) == 0) { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => 'Cannot find numeric values'); $self->{output}->display(); $self->{output}->exit(); } } sub run { my ($self, %options) = @_; $self->{connector} = $options{custom}; my $result = $self->{connector}->get_attributes(request => $self->{request}, nothing_quit => 1); $self->find_values(result => $result); for (my $i = 1; $i <= scalar(@{$self->{values}}); $i++) { $self->set_attributes(number => $i); $self->check_value(value => $self->{values}->[$i - 1], number => $i); } if (defined($self->{datas})) { $self->{statefile_cache}->write(data => $self->{datas}); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check an JMX numeric value. Example: perl centreon_plugins.pl --plugin=apps::protocols::jmx::plugin --custommode=jolokia --url=http://127.0.0.1/jolokia --mode=numeric-value --mbean-pattern='java.lang:type=Memory' --attribute='HeapMemoryUsage' --lookup-path='used' --format-scale --format='HeapMemory Usage used: %s' --perfdata-unit='B' --perfdata-name='used' =over 8 =item B<--lookup-path> What to lookup (from internal Jmx4Perl). Use --lookup-jpath for complex matching. =item B<--lookup-jpath> What to lookup in JSON response (JSON XPath string) See: http://goessner.net/articles/JsonPath/ =item B<--warning> Threshold warning. =item B<--critical> Threshold critical. =item B<--type> Type (Default: 'gauge'). Can be 'counter' also. 'counter' will use a retention file. =item B<--counter-per-seconds> Convert counter value on a value per seconds (only with type 'counter'. =item B<--format> Output format (Default: 'current valueX is %s') =item B<--format-scale> Scale bytes value. We'll display value in output. =item B<--format-scale-type> Could be 'network' (value divide by 1000) or 'other' (divide by 1024) (Default: 'other') =item B<--perfdata-unit> Perfdata unit in perfdata output (Default: '') =item B<--perfdata-name> Perfdata name in perfdata output (Default: 'valueX') =item B<--perfdata-min> Minimum value to add in perfdata output (Default: '') =item B<--perfdata-max> Maximum value to add in perfdata output (Default: '') =back =cut centreon-plugins-20220113/apps/protocols/jmx/plugin.pm000066400000000000000000000026151417000230700226610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::jmx::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}} = ( 'list-attributes' => 'apps::protocols::jmx::mode::listattributes', 'numeric-value' => 'apps::protocols::jmx::mode::numericvalue', ); $self->{custom_modes}{jolokia} = 'centreon::common::protocols::jmx::custom::jolokia'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Generic JMX plugin. Need Jolokia agent. =cut centreon-plugins-20220113/apps/protocols/ldap/000077500000000000000000000000001417000230700211435ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/ldap/mode/000077500000000000000000000000001417000230700220675ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/ldap/mode/login.pm000066400000000000000000000133001417000230700235320ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::ldap::mode::login; use base qw(centreon::plugins::mode); use strict; use warnings; use Time::HiRes qw(gettimeofday tv_interval); use centreon::common::protocols::ldap::lib::ldap; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'hostname:s' => { name => 'hostname' }, 'ldap-connect-options:s@' => { name => 'ldap_connect_options' }, 'ldap-starttls-options:s@' => { name => 'ldap_starttls_options' }, 'ldap-bind-options:s@' => { name => 'ldap_bind_options' }, 'tls' => { name => 'use_tls' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'warning:s' => { name => 'warning' }, 'critical:s' => { name => 'critical' }, 'timeout:s' => { name => 'timeout', default => '30' }, }); 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}->{hostname})) { $self->{output}->add_option_msg(short_msg => 'Please set the hostname option'); $self->{output}->option_exit(); } if (defined($self->{option_results}->{username}) && $self->{option_results}->{username} ne '' && !defined($self->{option_results}->{password})) { $self->{output}->add_option_msg(short_msg => "Please set --password option."); $self->{output}->option_exit(); } } sub run { my ($self, %options) = @_; my $timing0 = [gettimeofday]; my ($ldap_handle, $code, $err_msg) = centreon::common::protocols::ldap::lib::ldap::connect( hostname => $self->{option_results}->{hostname}, username => $self->{option_results}->{username}, password => $self->{option_results}->{password}, timeout => $self->{option_results}->{timeout}, ldap_connect_options => $self->{option_results}->{ldap_connect_options}, use_tls => $self->{option_results}->{use_tls}, ldap_starttls_options => $self->{option_results}->{ldap_starttls_options}, ldap_bind_options => $self->{option_results}->{ldap_bind_options}, ); if ($code == 1) { $self->{output}->output_add(severity => 'critical', short_msg => $err_msg); $self->{output}->display(); $self->{output}->exit(); } centreon::common::protocols::ldap::lib::ldap::quit(ldap_handle => $ldap_handle); my $timeelapsed = tv_interval ($timing0, [gettimeofday]); my $exit = $self->{perfdata}->threshold_check(value => $timeelapsed, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit, short_msg => sprintf('Response time %.3f second(s)', $timeelapsed)); $self->{output}->perfdata_add(label => 'time', unit => 's', value => sprintf('%.3f', $timeelapsed), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical')); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check Connection (also login) to an LDAP Server. LDAP Control are not still managed. =over 8 =item B<--hostname> IP Addr/FQDN of the ldap host =item B<--ldap-connect-options> Add custom ldap connect options: =over 16 =item B --ldap-connect-options='scheme=ldaps' =item B --ldap-connect-options='version=2' =back =item B<--ldap-starttls-options> Add custom start tls options (need --tls option): =over 16 =item B --ldap-starttls-options='verify=none' =back =item B<--ldap-bind-options> Add custom bind options (can force noauth) (not really useful now). =item B<--username> Specify username for authentification (can be a DN) =item B<--password> Specify password for authentification =item B<--timeout> Connection timeout in seconds (Default: 30) =item B<--warning> Threshold warning in seconds =item B<--critical> Threshold critical in seconds =back =cut centreon-plugins-20220113/apps/protocols/ldap/mode/search.pm000066400000000000000000000205551417000230700237010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::ldap::mode::search; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Time::HiRes qw(gettimeofday tv_interval); use centreon::common::protocols::ldap::lib::ldap; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ { label => 'entries', nlabel => 'ldap.request.entries.count', set => { key_values => [ { name => 'entries' } ], output_template => 'Number of results returned: %s', perfdatas => [ { value => 'entries', template => '%s', min => 0 }, ], } }, { label => 'time', display_ok => 0, nlabel => 'ldap.request.time.second', set => { key_values => [ { name => 'time' } ], output_template => 'Response time : %.3fs', perfdatas => [ { label => 'time', value => 'time', template => '%.3f', min => 0, unit => 's' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'hostname:s' => { name => 'hostname' }, 'search-base:s' => { name => 'search_base' }, 'search-filter:s' => { name => 'search_filter' }, 'ldap-connect-options:s@' => { name => 'ldap_connect_options' }, 'ldap-starttls-options:s@' => { name => 'ldap_starttls_options' }, 'ldap-bind-options:s@' => { name => 'ldap_bind_options' }, 'ldap-search-options:s@' => { name => 'ldap_search_options' }, 'tls' => { name => 'use_tls' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'timeout:s' => { name => 'timeout', default => '30' }, 'display-entry:s' => { name => 'display_entry' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{hostname})) { $self->{output}->add_option_msg(short_msg => 'Please set the hostname option'); $self->{output}->option_exit(); } if (defined($self->{option_results}->{username}) && $self->{option_results}->{username} ne '' && !defined($self->{option_results}->{password})) { $self->{output}->add_option_msg(short_msg => "Please set --password option."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{search_base})) { $self->{output}->add_option_msg(short_msg => 'Please set the search-base option'); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{search_filter})) { $self->{output}->add_option_msg(short_msg => 'Please set the search-filter option'); $self->{output}->option_exit(); } $self->{option_results}->{ldap_search_options} = [] if (!defined($self->{option_results}->{ldap_search_options})); if (defined($self->{option_results}->{display_entry}) && $self->{option_results}->{display_entry} ne '') { while ($self->{option_results}->{display_entry} =~ /%\{(.*?)\}/g) { push @{$self->{option_results}->{ldap_search_options}}, 'attrs=' . $1; } } } sub ldap_error { my ($self, %options) = @_; if ($options{code} == 1) { $self->{output}->output_add( severity => 'unknown', short_msg => $options{err_msg} ); $self->{output}->display(); $self->{output}->exit(); } } sub display_entries { my ($self, %options) = @_; return if (!defined($self->{option_results}->{display_entry}) || $self->{option_results}->{display_entry} eq ''); foreach my $entry ($options{result}->entries()) { my $display = $self->{option_results}->{display_entry}; while ($display =~ /%\{(.*?)\}/g) { my $attr = $1; my $value = $entry->get_value($attr); $value = '' if (!defined($value)); $display =~ s/%\{$attr\}/$value/g; } $self->{output}->output_add(long_msg => $display); } } sub manage_selection { my ($self, %options) = @_; my $timing0 = [gettimeofday]; my ($ldap_handle, $code, $err_msg) = centreon::common::protocols::ldap::lib::ldap::connect( hostname => $self->{option_results}->{hostname}, username => $self->{option_results}->{username}, password => $self->{option_results}->{password}, timeout => $self->{option_results}->{timeout}, ldap_connect_options => $self->{option_results}->{ldap_connect_options}, use_tls => $self->{option_results}->{use_tls}, ldap_starttls_options => $self->{option_results}->{ldap_starttls_options}, ldap_bind_options => $self->{option_results}->{ldap_bind_options}, ); $self->ldap_error(code => $code, err_msg => $err_msg); (my $search_result, $code, $err_msg) = centreon::common::protocols::ldap::lib::ldap::search( ldap_handle => $ldap_handle, search_base => $self->{option_results}->{search_base}, search_filter => $self->{option_results}->{search_filter}, ldap_search_options => $self->{option_results}->{ldap_search_options}, ); $self->ldap_error(code => $code, err_msg => $err_msg); centreon::common::protocols::ldap::lib::ldap::quit(ldap_handle => $ldap_handle); $self->{global} = { time => tv_interval($timing0, [gettimeofday]), entries => scalar($search_result->entries) }; $self->display_entries(result => $search_result); } 1; __END__ =head1 MODE Check search results (by default it uses the scope 'sub'). LDAP Control are not still managed. Example: centreon_plugins.pl --plugin=apps::protocols::ldap::plugin --mode=search --hostname='xxx.xxx.xxx.xxx' --username='cn=Manager,dc=merethis,dc=com' --password='secret' --search-base='dc=merethis,dc=com' --search-filter='(objectclass=organizationalunit)' =over 8 =item B<--hostname> IP Addr/FQDN of the ldap host (required). =item B<--search-base> Set the DN that is the base object entry relative to which the search is to be performed (required). =item B<--search-filter> Set filter that defines the conditions an entry in the directory must meet in order for it to be returned by the search (required). =item B<--ldap-connect-options> Add custom ldap connect options: =over 16 =item B --ldap-connect-options='scheme=ldaps' =item B --ldap-connect-options='version=2' =back =item B<--ldap-starttls-options> Add custom start tls options (need --tls option): =over 16 =item B --ldap-starttls-options='verify=none' =back =item B<--ldap-bind-options> Add custom bind options (can force noauth) (not really useful now). =item B<--ldap-search-options> Add custom search options (can change the scope for example). =item B<--display-entry> Display ldap entries (with --verbose option) (Example: '%{cn} account locked') =item B<--username> Specify username for authentification (can be a DN) =item B<--password> Specify password for authentification =item B<--timeout> Connection timeout in seconds (Default: 30) =item B<--warning-time> Threshold warning in seconds =item B<--critical-time> Threshold critical in seconds =item B<--warning-entries> Threshold warning (number of results) =item B<--critical-entries> Threshold critical (number of results) =back =cut centreon-plugins-20220113/apps/protocols/ldap/plugin.pm000066400000000000000000000024241417000230700230010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::ldap::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} = '0.1'; %{$self->{modes}} = ( 'login' => 'apps::protocols::ldap::mode::login', 'search' => 'apps::protocols::ldap::mode::search', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check a LDAP server. =cut centreon-plugins-20220113/apps/protocols/modbus/000077500000000000000000000000001417000230700215145ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/modbus/mode/000077500000000000000000000000001417000230700224405ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/modbus/mode/numericvalue.pm000066400000000000000000000450411417000230700255010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package 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 get_printf_vars { my ($self, %options) = @_; # compat if (ref($options{printf_var}) ne 'ARRAY') { $options{printf_var} = [split /,/, $options{printf_var}]; } my $message; my $vars = []; eval { local $SIG{__WARN__} = sub { $message = $_[0]; }; local $SIG{__DIE__} = sub { $message = $_[0]; }; foreach my $var (@{$options{printf_var}}) { $var =~ s/\$self->\{result_values\}/\$values/; push @$vars, $self->{output}->assign_eval(eval => $var, values => $options{values}); } }; if (defined($message)) { $self->{output}->output_add(long_msg => 'eval printf_var problem: ' . $message); $self->{output}->option_exit(); } return $vars; } sub custom_metric_output { my ($self, %options) = @_; my $output; 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})) { my $vars = $self->{instance_mode}->get_printf_vars( printf_var => $config_data->{selection}->{ $self->{result_values}->{instance} }->{formatting}->{printf_var}, values => $self->{result_values} ); $output = sprintf( $config_data->{selection}->{ $self->{result_values}->{instance} }->{formatting}->{printf_msg}, @$vars ); } elsif (defined($config_data->{formatting}->{printf_var}) && defined($config_data->{formatting}->{printf_msg})) { my $vars = $self->{instance_mode}->get_printf_vars( printf_var => $config_data->{formatting}->{printf_var}, values => $self->{result_values} ); $output = sprintf( $config_data->{formatting}->{printf_msg}, @$vars ); } else { $output = 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})) { my $vars = $self->{instance_mode}->get_printf_vars( printf_var => $config_data->{virtualcurve}->{ $self->{result_values}->{instance} }->{formatting}->{printf_var}, values => $self->{result_values} ); $output = sprintf( $config_data->{virtualcurve}->{ $self->{result_values}->{instance} }->{formatting}->{printf_msg}, @$vars ); } elsif (defined($config_data->{formatting}->{printf_var}) && defined($config_data->{formatting}->{printf_msg})) { my $vars = $self->{instance_mode}->get_printf_vars( printf_var => $config_data->{formatting}->{printf_var}, values => $self->{result_values} ); $output = sprintf( $config_data->{formatting}->{printf_msg}, @$vars ); } else { $output = sprintf("Metric '%s' value is '%s'", $self->{result_values}->{instance}, $self->{result_values}->{value}); } } return $output; } 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; $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 centreon-plugins-20220113/apps/protocols/modbus/plugin.pm000066400000000000000000000024561417000230700233570ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package 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 centreon-plugins-20220113/apps/protocols/nrpe/000077500000000000000000000000001417000230700211675ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/nrpe/custom/000077500000000000000000000000001417000230700225015ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/nrpe/custom/nrpe.pm000066400000000000000000000061031417000230700240030ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::nrpe::custom::nrpe; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::nrpe; my %errors_num = (0 => 'OK', 1 => 'WARNING', 2 => 'CRITICAL', 3 => 'UNKNOWN'); 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 => { 'hostname:s' => { name => 'hostname' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'CUSTOM MODE OPTIONS', once => 1); $self->{output} = $options{output}; $self->{nrpe} = centreon::plugins::nrpe->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; if (!defined($self->{hostname}) || $self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } $self->{nrpe}->check_options(option_results => $self->{option_results}); return 0; } sub format_result { my ($self, %options) = @_; my %result = ( code => ($options{content}->{result_code} =~ /^[0-3]$/) ? $errors_num{$options{content}->{result_code}} : $options{content}->{result_code}, message => $options{content}->{buffer}, perf => [] ); return \%result; } sub request { my ($self, %options) = @_; my ($content) = $self->{nrpe}->request(check => $options{command}, arg => $options{arg}); my $result = $self->format_result(content => $content); return $result; } 1; __END__ =head1 NAME NRPE protocol =head1 CUSTOM MODE OPTIONS NRPE protocol =over 8 =item B<--hostname> Remote hostname or IP address. =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/protocols/nrpe/custom/nsclient.pm000066400000000000000000000254271417000230700246700ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::nrpe::custom::nsclient; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::http; use URI::Encode; use JSON::XS; my %errors_num = (0 => 'OK', 1 => 'WARNING', 2 => 'CRITICAL', 3 => 'UNKNOWN'); 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'credentials' => { name => 'credentials' }, 'basic' => { name => 'basic' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'legacy-password:s' => { name => 'legacy_password' }, 'new-api' => { name => 'new_api' }, 'timeout:s' => { name => 'timeout' }, 'unknown-http-status:s' => { name => 'unknown_http_status' }, 'warning-http-status:s' => { name => 'warning_http_status' }, 'critical-http-status:s' => { name => 'critical_http_status' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'CUSTOM MODE OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 8443; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{username} = (defined($self->{option_results}->{username})) ? $self->{option_results}->{username} : undef; $self->{password} = (defined($self->{option_results}->{password})) ? $self->{option_results}->{password} : undef; $self->{legacy_password} = (defined($self->{option_results}->{legacy_password})) ? $self->{option_results}->{legacy_password} : undef; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300' ; $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --hostname option.'); $self->{output}->option_exit(); } return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; if (defined($self->{username})) { $self->{option_results}->{username} = $self->{username}; $self->{option_results}->{password} = $self->{password}; $self->{option_results}->{credentials} = 1; $self->{option_results}->{basic} = 1; } } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); if (defined($self->{legacy_password}) && $self->{legacy_password} ne '') { $self->{http}->add_header(key => 'password', value => $self->{legacy_password}); } $self->{http}->set_options(%{$self->{option_results}}); } sub output_perf { my ($self, %options) = @_; my $result = 'UNKNOWN'; $result = $errors_num{$options{result}} if ($options{result} =~ /[0-3]/); $result = $options{result} if ($options{result} =~ /[A-Z]+/); my %result = ( code => $result, message => $options{data}->{message} ); if (defined($self->{option_results}->{new_api})) { foreach (keys %{$options{data}->{perf}}) { my $printf_format = '%d'; ($options{data}->{perf}->{$_}->{value} =~ /\.(\d\d\d)/); $printf_format = '%.3f' if ($options{data}->{perf}->{$_}->{value} =~ /\.(\d\d\d)/ && $1 !~ /000/); push @{$result{perf}}, { label => $_, unit => $options{data}->{perf}->{$_}->{unit}, value => sprintf($printf_format, $options{data}->{perf}->{$_}->{value}), warning => defined($options{data}->{perf}->{$_}->{warning}) ? sprintf($printf_format, $options{data}->{perf}->{$_}->{warning}) : undef, critical => defined($options{data}->{perf}->{$_}->{critical}) ? sprintf($printf_format, $options{data}->{perf}->{$_}->{critical}) : undef, min => defined($options{data}->{perf}->{$_}->{minimum}) ? sprintf($printf_format, $options{data}->{perf}->{$_}->{minimum}) : undef, max => defined($options{data}->{perf}->{$_}->{maximum}) ? sprintf($printf_format, $options{data}->{perf}->{$_}->{maximum}) : undef, }; } } else { foreach (@{$options{data}->{perf}}) { my $perf = defined($_->{float_value}) ? $_->{float_value} : $_->{int_value}; my $printf_format = '%d'; $printf_format = '%.3f' if (defined($_->{float_value})); push @{$result{perf}}, { label => $_->{alias}, unit => $perf->{unit}, value => sprintf($printf_format, $perf->{value}), warning => defined($perf->{warning}) ? sprintf($printf_format, $perf->{warning}) : undef, critical => defined($perf->{critical}) ? sprintf($printf_format, $perf->{critical}) : undef, min => defined($perf->{minimum}) ? sprintf($printf_format, $perf->{minimum}) : undef, max => defined($perf->{maximum}) ? sprintf($printf_format, $perf->{maximum}) : undef, }; } } return \%result; } sub output_noperf { my ($self, %options) = @_; my %result = ( code => $options{result}, message => $options{data}->{message}, perf => [] ); return \%result; } sub format_result { my ($self, %options) = @_; my $decoded; eval { $decoded = JSON::XS->new->decode($options{content}); }; if ($@) { $self->{output}->output_add(long_msg => $options{content}, debug => 1); $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } my $entry; if (defined($self->{option_results}->{new_api})) { $entry = $decoded; } else { $entry = $decoded->{payload}->[0]; } $entry->{lines}->[0]->{message} =~ s/\r//msg; if (defined($entry->{lines}->[0]->{perf})) { return $self->output_perf(result => $entry->{result}, data => $entry->{lines}->[0]); } else { return $self->output_noperf(result => $entry->{result}, data => $entry->{lines}->[0]); } } sub request { my ($self, %options) = @_; $self->settings(); my $url = ''; my $uri = URI::Encode->new({encode_reserved => 1}); my ($encoded_args, $append) = ('', ''); if (defined($options{arg})) { foreach (@{$options{arg}}) { $encoded_args .= $append . $uri->encode($_); $append = '&'; } } if (defined($self->{option_results}->{new_api})) { $url = '/api/v1/queries/' . $options{command} . '/commands/execute?' . $encoded_args } else { $url = '/query/' . $options{command} . '?' . $encoded_args } my ($content) = $self->{http}->request( url_path => $url, unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status} ); if (!defined($content) || $content eq '') { $self->{output}->add_option_msg(short_msg => "API returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } $self->{output}->output_add(long_msg => "nsclient return = " . $content, debug => 1); my $result = $self->format_result(content => $content); return $result; } 1; __END__ =head1 NAME NSClient++ Rest API (New v1 & Legacy) =head1 CUSTOM MODE OPTIONS NSClient++ Rest API =over 8 =item B<--hostname> Remote hostname or IP address. =item B<--port> Port used (Default: 8443) =item B<--proto> Specify https if needed (Default: 'https') =item B<--username> Specify username for authentication (If basic authentication) =item B<--password> Specify password for authentication (If basic authentication) =item B<--legacy-password> Specify password for old authentication system. =item B<--new-api> Use new RestAPI (> 5.2.33). =item B<--timeout> Set timeout in seconds (Default: 10). =item B<--unknown-status> Threshold warning for http response code. (Default: '%{http_code} < 200 or %{http_code} >= 300') =item B<--warning-status> Threshold warning for http response code. =item B<--critical-status> Threshold critical for http response code. =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/protocols/nrpe/mode/000077500000000000000000000000001417000230700221135ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/nrpe/mode/query.pm000066400000000000000000000061421417000230700236210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::nrpe::mode::query; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'command:s' => { name => 'command' }, 'arg:s@' => { name => 'arg' }, 'sanitize-message:s' => { name => 'sanitize_message' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{command}) || $self->{option_results}->{command} eq '') { $self->{output}->add_option_msg(short_msg => 'Please set --command option'); $self->{output}->option_exit(); } } sub sanitize_message { my ($self, %options) = @_; $self->{display_options}->{nolabel} = 1; return $options{message} unless (defined($self->{option_results}->{sanitize_message})); my $message = $options{message}; foreach my $code (('OK', 'WARNING', 'CRITICAL', 'UNKNOWN')) { foreach my $separator (('-', ':')) { if ($message =~ /^\w+\s*$code\s*$separator\s*(.*)$/) { delete $self->{display_options}->{nolabel}; return $1; } } } return $message; } sub run { my ($self, %options) = @_; my $result = $options{custom}->request( command => $self->{option_results}->{command}, arg => $self->{option_results}->{arg} ); $self->{output}->output_add( severity => $result->{code}, short_msg => $self->sanitize_message(message => $result->{message}) ); foreach (@{$result->{perf}}) { $self->{output}->perfdata_add(%{$_}); } $self->{display_options}->{force_ignore_perfdata} = 1 if (scalar(@{$result->{perf}}) == 0); $self->{output}->display(%{$self->{display_options}}); $self->{output}->exit(); } 1; __END__ =head1 MODE Trigger commands against NRPE/NSClient agent. =item B<--command> Set command. In nrpe use following command to get server version: --command='_NRPE_CHECK' =item B<--arg> Set arguments (Multiple option. Example: --arg='arg1' --arg='arg2'). =item B<--sanitize-message> Sanitize message by removing heading code and separator from returned message (ie "OK - "). =back =cut centreon-plugins-20220113/apps/protocols/nrpe/plugin.pm000066400000000000000000000025731417000230700230320ustar00rootroot00000000000000 # # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::nrpe::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} = { 'query' => 'apps::protocols::nrpe::mode::query' }; $self->{custom_modes}->{nrpe} = 'apps::protocols::nrpe::custom::nrpe'; $self->{custom_modes}->{nsclient} = 'apps::protocols::nrpe::custom::nsclient'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Trigger commands against NRPE/NSClient agent. =cut centreon-plugins-20220113/apps/protocols/ntp/000077500000000000000000000000001417000230700210245ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/ntp/mode/000077500000000000000000000000001417000230700217505ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/ntp/mode/offset.pm000066400000000000000000000102501417000230700235720ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::ntp::mode::offset; use base qw(centreon::plugins::mode); use strict; use warnings; use Net::NTP; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "ntp-host:s" => { name => 'ntp_host' }, "port:s" => { name => 'port', default => 123 }, "warning:s" => { name => 'warning' }, "critical:s" => { name => 'critical' }, "timeout:s" => { name => 'timeout', default => 30 }, }); 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}->{ntp_host})) { $self->{output}->add_option_msg(short_msg => "Please set the ntp-host option"); $self->{output}->option_exit(); } } sub run { my ($self, %options) = @_; my %ntp; eval { $Net::NTP::TIMEOUT = $self->{option_results}->{timeout}; %ntp = get_ntp_response($self->{option_results}->{ntp_host}, $self->{option_results}->{port}); }; if ($@) { $self->{output}->output_add(severity => 'CRITICAL', short_msg => "Couldn't connect to ntp server: " . $@); $self->{output}->display(); $self->{output}->exit(); } my $localtime = time(); my $offset = (($ntp{'Receive Timestamp'} - $ntp{'Originate Timestamp'}) + ($ntp{'Transmit Timestamp'} - $localtime)) / 2; my $exit = $self->{perfdata}->threshold_check(value => $offset, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit, short_msg => sprintf("Offset: %.3fs", $offset)); $self->{output}->output_add(long_msg => sprintf("Host has an offset of %.5fs with its time server reference %s", $offset, $self->{option_results}->{ntp_host})); $self->{output}->perfdata_add(label => "time", unit => 's', value => sprintf('%.3f', $offset), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical')); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check Ntp server response. =over 8 =item B<--ntp-host> Ntp server address or FQDN =item B<--port> Port used (Default: 123) =item B<--timeout> Threshold for NTP timeout =item B<--warning> Threshold warning in seconds =item B<--critical> Threshold critical in seconds (e.g @10:10 means CRITICAL if offset is not between -10 and +10 seconds) =back =cut centreon-plugins-20220113/apps/protocols/ntp/mode/responsetime.pm000066400000000000000000000076731417000230700250400ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::ntp::mode::responsetime; use base qw(centreon::plugins::mode); use strict; use warnings; use Time::HiRes qw(gettimeofday tv_interval); use Net::NTP; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "hostname:s" => { name => 'hostname' }, "port:s" => { name => 'port', default => 123 }, "warning:s" => { name => 'warning' }, "critical:s" => { name => 'critical' }, "timeout:s" => { name => 'timeout', default => 30 }, }); 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}->{hostname})) { $self->{output}->add_option_msg(short_msg => "Please set the hostname option"); $self->{output}->option_exit(); } } sub run { my ($self, %options) = @_; my $timing0 = [gettimeofday]; my %ntp; eval { $Net::NTP::TIMEOUT = $self->{option_results}->{timeout}; %ntp = get_ntp_response($self->{option_results}->{hostname}, $self->{option_results}->{port}); }; if ($@) { $self->{output}->output_add(severity => 'CRITICAL', short_msg => "Couldn't connect to ntp server: " . $@); $self->{output}->display(); $self->{output}->exit(); } my $timeelapsed = tv_interval ($timing0, [gettimeofday]); my $exit = $self->{perfdata}->threshold_check(value => $timeelapsed, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit, short_msg => sprintf("Response time %.3fs", $timeelapsed)); $self->{output}->perfdata_add(label => "time", value => sprintf('%.3f', $timeelapsed), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical')); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check Ntp server response. =over 8 =item B<--hostname> Ntp server hostname =item B<--port> Port used (Default: 123) =item B<--timeout> Threshold for NTP timeout =item B<--warning> Threshold warning in seconds =item B<--critical> Threshold critical in seconds =back =cut centreon-plugins-20220113/apps/protocols/ntp/plugin.pm000066400000000000000000000024231417000230700226610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::ntp::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} = '0.1'; %{$self->{modes}} = ( 'offset' => 'apps::protocols::ntp::mode::offset', 'response-time' => 'apps::protocols::ntp::mode::responsetime', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check NTP server. =cut centreon-plugins-20220113/apps/protocols/ospf/000077500000000000000000000000001417000230700211725ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/ospf/snmp/000077500000000000000000000000001417000230700221475ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/ospf/snmp/mode/000077500000000000000000000000001417000230700230735ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/ospf/snmp/mode/neighbor.pm000066400000000000000000000140531417000230700252310ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::ospf::snmp::mode::neighbor; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return 'state: ' . $self->{result_values}->{NbrState}; } sub custom_change_output { my ($self, %options) = @_; return 'Neighbors current: ' . $self->{result_values}->{Total} . ' (last: ' . $self->{result_values}->{TotalLast} . ')'; } sub custom_change_calc { my ($self, %options) = @_; $self->{result_values}->{TotalLast} = $options{old_datas}->{$self->{instance} . '_total'}; $self->{result_values}->{Total} = $options{new_datas}->{$self->{instance} . '_total'}; return 0; } sub prefix_nb_output { my ($self, %options) = @_; return "Neighbor '" . $options{instance_value}->{NbrIpAddr} . "/" . $options{instance_value}->{NbrRtrId} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, message_separator => ' - ' }, { name => 'nb', type => 1, cb_prefix_output => 'prefix_nb_output', message_multiple => 'All neighbor relations are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'total', nlabel => 'neighbors.total.count',set => { key_values => [ { name => 'total' } ], output_template => 'Total neighbors: %s', perfdatas => [ { label => 'total', template => '%s', min => 0 } ] } }, { label => 'total-change', type => 2, set => { key_values => [ { name => 'total', diff => 1 } ], closure_custom_calc => $self->can('custom_change_calc'), closure_custom_output => $self->can('custom_change_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{nb} = [ { label => 'status', type => 2, critical_default => '%{NbrState} =~ /down/i', set => { key_values => [ { name => 'NbrIpAddr' }, { name => 'NbrRtrId' }, { name => 'NbrState' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my %map_state = ( 1 => 'down', 2 => 'attempt', 3 => 'init', 4 => 'twoWay', 5 => 'exchangeStart', 6 => 'exchange', 7 => 'loading', 8 => 'full' ); my $mapping = { NbrIpAddr => { oid => '.1.3.6.1.2.1.14.10.1.1' }, NbrRtrId => { oid => '.1.3.6.1.2.1.14.10.1.3' }, NbrState => { oid => '.1.3.6.1.2.1.14.10.1.6', map => \%map_state } }; my $oid_ospfNbrEntry = '.1.3.6.1.2.1.14.10.1'; sub manage_selection { my ($self, %options) = @_; $self->{global} = { total => 0 }; my $snmp_result = $options{snmp}->get_table( oid => $oid_ospfNbrEntry, nothing_quit => 1 ); $self->{nb} = {}; foreach my $oid (keys %{$snmp_result}) { next if ($oid !~ /^$mapping->{NbrState}->{oid}\.(.*)$/); my $instance = $1; $self->{nb}->{$instance} = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); if (!defined($self->{nb}->{$instance}->{NbrIpAddr})) { $instance =~ /^(.*)\.(\d+)$/; $self->{nb}->{$instance}->{NbrIpAddr} = $1; } $self->{global}->{total}++; } if (scalar(keys %{$self->{nb}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No neighbors found.'); $self->{output}->option_exit(); } $self->{cache_name} = 'ospf_' . $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')); } 1; __END__ =head1 MODE Check neighbor relations. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^status$' =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{NbrState}, %{NbrRtrId}, %{NbrIpAddr} =item B<--critical-status> Set critical threshold for status (Default: '%{NbrState} =~ /down/i'). Can used special variables like: %{NbrState}, %{NbrRtrId}, %{NbrIpAddr} =item B<--warning-total-change> Set warning threshold. Should be used if there is a difference of total neighbors between two checks. Example: %{TotalLast} != %{Total} =item B<--critical-total-change> Set critical threshold. Should be used if there is a difference of total neighbors between two checks. Example: %{TotalLast} != %{Total} =item B<--warning-*> Threshold warning. Can be: 'total'. =item B<--critical-*> Threshold critical. Can be: 'total'. =back =cut centreon-plugins-20220113/apps/protocols/ospf/snmp/plugin.pm000066400000000000000000000023301417000230700240010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::ospf::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} = { 'neighbor' => 'apps::protocols::ospf::snmp::mode::neighbor' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check OSPF protocol in SNMP. =cut centreon-plugins-20220113/apps/protocols/radius/000077500000000000000000000000001417000230700215125ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/radius/mode/000077500000000000000000000000001417000230700224365ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/radius/mode/login.pm000066400000000000000000000223411417000230700241060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::radius::mode::login; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Time::HiRes qw(gettimeofday tv_interval); use Authen::Radius; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; my $msg = 'Radius Access Request Status: ' . $self->{result_values}->{status} . ' [error msg: ' . $self->{result_values}->{error_msg} . ']'; return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; $self->{result_values}->{error_msg} = $options{new_datas}->{$self->{instance} . '_error_msg'}; $self->{result_values}->{attributes} = $self->{instance_mode}->{radius_result_attributes}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'radius', type => 0, message_separator => ' - ' } ]; $self->{maps_counters}->{radius} = [ { label => 'status', type => 2, critical_default => '%{status} ne "accepted"', set => { key_values => [ { name => 'status' }, { name => 'error_msg' } ], 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 => \&catalog_status_threshold_ng } }, { label => 'time', nlabel => 'radius.response.time.seconds', set => { key_values => [ { name => 'elapsed' } ], output_template => 'Response time : %.3f second(s)', perfdatas => [ { label => 'time', template => '%.3f', min => 0, unit => 's' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port', default => 1812 }, 'secret:s' => { name => 'secret' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'warning:s' => { name => 'warning' }, 'critical:s' => { name => 'critical' }, 'timeout:s' => { name => 'timeout', default => 5 }, 'retry:s' => { name => 'retry', default => 0 }, 'radius-attribute:s%' => { name => 'radius_attribute' }, 'radius-dictionary:s@' => { name => 'radius_dictionary' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); my @mandatory = ('hostname', 'secret'); push @mandatory, 'username', 'password' if (!defined($self->{option_results}->{radius_attribute})); foreach (@mandatory) { if (!defined($self->{option_results}->{$_})) { $self->{output}->add_option_msg(short_msg => "Please set the " . $_ . " option"); $self->{output}->option_exit(); } } $self->{radius_dictionary} = []; if (defined($self->{option_results}->{radius_attribute})) { $self->{radius_dictionary} = $self->{option_results}->{radius_attribute}; } $self->{option_results}->{retry} = 0 if (!defined($self->{option_results}->{retry}) || $self->{option_results}->{retry} !~ /^\d+$/); if (defined($self->{option_results}->{port}) && $self->{option_results}->{port} =~ /^\d+$/) { $self->{option_results}->{hostname} .= ':' . $self->{option_results}->{port}; } } sub radius_simple_connection { my ($self, %options) = @_; $self->{timing0} = [gettimeofday]; my $retry = 0; while ($retry <= $self->{option_results}->{retry}) { if ($self->{radius_session}->check_pwd($self->{option_results}->{username}, $self->{option_results}->{password})) { $self->{radius}->{status} = 'accepted'; last; } if ($retry + 1 > $self->{option_results}->{retry}) { $self->{radius}->{status} = 'rejected'; $self->{radius}->{error_msg} = $self->{radius_session}->strerror(); } $retry++; } } sub radius_attr_connection { my ($self, %options) = @_; my $message; eval { local $SIG{__WARN__} = sub { $message = join(' - ', @_); }; local $SIG{__DIE__} = sub { $message = join(' - ', @_); }; foreach my $dic (@{$self->{radius_dictionary}}) { next if ($dic eq ''); Authen::Radius->load_dictionary($dic); } foreach (keys %{$self->{option_results}->{radius_attribute}}) { $self->{radius_session}->add_attributes({ Name => $_, Value => $self->{option_results}->{radius_attribute}->{$_} }); } }; if (defined($message)) { $self->{output}->output_add(long_msg => $message, debug => 1); $self->{output}->add_option_msg(short_msg => "Issue with dictionary and attributes"); $self->{output}->option_exit(); } $self->{timing0} = [gettimeofday]; my $retry = 0; while ($retry <= $self->{option_results}->{retry}) { my $type; if ($self->{radius_session}->send_packet(ACCESS_REQUEST) && ($type = $self->{radius_session}->recv_packet()) == ACCESS_ACCEPT) { $self->{radius}->{status} = 'accepted'; last; } if ($retry + 1 > $self->{option_results}->{retry}) { $self->{radius}->{status} = 'unknown'; $self->{radius}->{error_msg} = $self->{radius_session}->strerror(); if (defined($type) && $type == ACCESS_REJECT) { $self->{radius}->{status} = 'rejected'; } } $retry++; } } sub manage_selection { my ($self, %options) = @_; $self->{radius} = { status => 'unknown', error_msg => 'none' }; $self->{radius_session} = Authen::Radius->new( Host => $self->{option_results}->{hostname}, Secret => $self->{option_results}->{secret}, TimeOut => $self->{option_results}->{timeout}, ); if (!defined($self->{radius_session})) { $self->{output}->add_option_msg(short_msg => 'failure: ' . Authen::Radius::strerror()); $self->{output}->option_exit(); } if (defined($self->{option_results}->{radius_attribute})) { $self->radius_attr_connection(); } else { $self->radius_simple_connection(); } $self->{radius}->{elapsed} = tv_interval($self->{timing0}, [gettimeofday]); $self->{radius_result_attributes} = {}; foreach my $attr ($self->{radius_session}->get_attributes()) { $self->{radius_result_attributes}->{$attr->{Name}} = defined($attr->{Value}) ? $attr->{Value} : ''; $self->{output}->output_add(long_msg => 'Attribute Name = ' . $attr->{Name} . ', Value = ' . (defined($attr->{Value}) ? $attr->{Value} : ''), debug => 1); } } 1; __END__ =head1 MODE Check login to a Radius Server. Example with attributes: centreon_plugins.pl --plugin=apps/protocols/radius/plugin.pm --mode=login --hostname=192.168.1.2 --secret=centreon --radius-attribute='User-Password=test' --radius-attribute='User-Name=user@test.com' --radius-dictionary=dictionary.txt =over 8 =item B<--hostname> IP Addr/FQDN of the radius host =item B<--port> Radius port (Default: 1812) =item B<--secret> Secret of the radius host =item B<--username> Specify username for authentication =item B<--password> Specify password for authentication =item B<--timeout> Connection timeout in seconds (Default: 5) =item B<--retry> Number of retry connection (Default: 0) =item B<--radius-attribute> If you need to add option, please following attributes. Option username and password should be set with that option. Example: --radius-attribute="User-Password=test" =item B<--radius-dictionary> Set radius-dictionary file (mandatory with --radius-attribute) (multiple option). =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{error_msg}, %{attributes}. =item B<--critical-status> Set critical threshold for status (Default: '%{status} ne "accepted"'). Can used special variables like: %{status}, %{error_msg}, %{attributes}. =item B<--warning-time> Threshold warning in seconds =item B<--critical-time> Threshold critical in seconds =back =cut centreon-plugins-20220113/apps/protocols/radius/plugin.pm000066400000000000000000000023061417000230700233470ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::radius::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} = '0.1'; $self->{modes} = { 'login' => 'apps::protocols::radius::mode::login' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check a Radius server. =cut centreon-plugins-20220113/apps/protocols/smtp/000077500000000000000000000000001417000230700212065ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/smtp/lib/000077500000000000000000000000001417000230700217545ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/smtp/lib/smtp.pm000066400000000000000000000103731417000230700233010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::smtp::lib::smtp; use strict; use warnings; use Email::Send::SMTP::Gmail; my $smtp_handle; my $connected = 0; sub quit { if ($connected == 1) { $smtp_handle->bye; } } sub message { my ($self, %options) = @_; my %smtp_options = (); foreach my $option (@{$self->{option_results}->{smtp_send_options}}) { next if ($option !~ /^(.+?)=(.+)$/); $smtp_options{-$1} = $2; } my $result; eval { local $SIG{ALRM} = sub { die 'timeout' }; alarm($self->{option_results}->{timeout}); $result = $smtp_handle->send( -to => $self->{option_results}->{smtp_to}, -from => $self->{option_results}->{smtp_from}, %smtp_options ); alarm(0); }; if ($@) { $self->{output}->output_add( severity => 'unknown', short_msg => 'Unable to send message: ' . $@ ); $self->{output}->display(); $self->{output}->exit(); } if ($result == -1) { $self->{output}->output_add( severity => 'critical', short_msg => 'Unable to send message.' ); $self->{output}->display(); $self->{output}->exit(); } $self->{output}->output_add( severity => 'ok', short_msg => 'Message sent' ); } sub connect { my ($self, %options) = @_; my %smtp_options = (); if (defined($self->{option_results}->{username}) && $self->{option_results}->{username} ne '' && !defined($self->{option_results}->{password})) { $self->{output}->add_option_msg(short_msg => "Please set --password option."); $self->{output}->option_exit(); } $smtp_options{-auth} = 'none'; if (defined($self->{option_results}->{username}) && $self->{option_results}->{username} ne '') { $smtp_options{-login} = $self->{option_results}->{username}; delete $smtp_options{-auth}; } if (defined($self->{option_results}->{username}) && defined($self->{option_results}->{password})) { $smtp_options{-pass} = $self->{option_results}->{password}; } my $connection_exit = defined($options{connection_exit}) ? $options{connection_exit} : 'unknown'; $smtp_options{-port} = $self->{option_results}->{port} if (defined($self->{option_results}->{port})); foreach my $option (@{$self->{option_results}->{smtp_options}}) { next if ($option !~ /^(.+?)=(.+)$/); $smtp_options{-$1} = $2; } my ($stdout, $error_msg); { eval { local $SIG{ALRM} = sub { die "timeout\n" }; local *STDOUT; open STDOUT, '>', \$stdout; alarm($self->{option_results}->{timeout}); ($smtp_handle, $error_msg) = Email::Send::SMTP::Gmail->new( -smtp=> $self->{option_results}->{hostname}, %smtp_options ); alarm(0); }; } if ($@) { chomp $@; $self->{output}->output_add( severity => $connection_exit, short_msg => 'Unable to connect to SMTP: ' . $@ ); $self->{output}->display(); $self->{output}->exit(); } if ($smtp_handle == -1) { chomp $stdout; $self->{output}->output_add( severity => $connection_exit, short_msg => 'Unable to connect to SMTP: ' . (defined($stdout) ? $stdout : $error_msg) ); $self->{output}->display(); $self->{output}->exit(); } $connected = 1; } 1; centreon-plugins-20220113/apps/protocols/smtp/mode/000077500000000000000000000000001417000230700221325ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/smtp/mode/login.pm000066400000000000000000000101261417000230700236000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::smtp::mode::login; use base qw(centreon::plugins::mode); use strict; use warnings; use Time::HiRes qw(gettimeofday tv_interval); use apps::protocols::smtp::lib::smtp; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "hostname:s" => { name => 'hostname' }, "port:s" => { name => 'port', }, "smtp-options:s@" => { name => 'smtp_options' }, "username:s" => { name => 'username' }, "password:s" => { name => 'password' }, "warning:s" => { name => 'warning' }, "critical:s" => { name => 'critical' }, "timeout:s" => { name => 'timeout', default => '30' }, }); 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}->{hostname})) { $self->{output}->add_option_msg(short_msg => "Please set the hostname option"); $self->{output}->option_exit(); } } sub run { my ($self, %options) = @_; my $timing0 = [gettimeofday]; apps::protocols::smtp::lib::smtp::connect($self, connection_exit => 'critical'); apps::protocols::smtp::lib::smtp::quit(); my $timeelapsed = tv_interval ($timing0, [gettimeofday]); my $exit = $self->{perfdata}->threshold_check(value => $timeelapsed, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit, short_msg => sprintf("Response time %.3f second(s)", $timeelapsed)); $self->{output}->perfdata_add(label => "time", unit => 's', value => sprintf('%.3f', $timeelapsed), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical')); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check Connection (also login) to an SMTP Server. =over 8 =item B<--hostname> IP Addr/FQDN of the smtp host =item B<--port> Port used =item B<--smtp-options> Add custom smtp options. Example: --smtp-options='debug=1" --smtp-options='layer=none" =item B<--username> Specify username for authentification =item B<--password> Specify password for authentification =item B<--timeout> Connection timeout in seconds (Default: 30) =item B<--warning> Threshold warning in seconds =item B<--critical> Threshold critical in seconds =back =cut centreon-plugins-20220113/apps/protocols/smtp/mode/message.pm000066400000000000000000000116341417000230700241210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::smtp::mode::message; use base qw(centreon::plugins::mode); use strict; use warnings; use Time::HiRes qw(gettimeofday tv_interval); use apps::protocols::smtp::lib::smtp; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "hostname:s" => { name => 'hostname' }, "port:s" => { name => 'port', }, "smtp-from:s" => { name => 'smtp_from' }, "smtp-to:s" => { name => 'smtp_to' }, "smtp-options:s@" => { name => 'smtp_options' }, "smtp-send-options:s@" => { name => 'smtp_send_options' }, "username:s" => { name => 'username' }, "password:s" => { name => 'password' }, "warning:s" => { name => 'warning' }, "critical:s" => { name => 'critical' }, "timeout:s" => { name => 'timeout', default => '30' }, }); 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}->{hostname})) { $self->{output}->add_option_msg(short_msg => "Please set the hostname option"); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{smtp_from})) { $self->{output}->add_option_msg(short_msg => "Please set smtp-from option"); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{smtp_to})) { $self->{output}->add_option_msg(short_msg => "Please set smtp-to option"); $self->{output}->option_exit(); } } sub run { my ($self, %options) = @_; my $timing0 = [gettimeofday]; apps::protocols::smtp::lib::smtp::connect($self); apps::protocols::smtp::lib::smtp::message($self); apps::protocols::smtp::lib::smtp::quit(); my $timeelapsed = tv_interval ($timing0, [gettimeofday]); my $exit = $self->{perfdata}->threshold_check(value => $timeelapsed, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit, short_msg => sprintf("Response time %.3f second(s)", $timeelapsed)); $self->{output}->perfdata_add(label => "time", unit => 's', value => sprintf('%.3f', $timeelapsed), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical')); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check send a message to a SMTP Server. =over 8 =item B<--hostname> IP Addr/FQDN of the smtp host =item B<--port> Port used =item B<--smtp-from> Set 'from' email (required). =item B<--smtp-to> Set 'to' email (required). =item B<--smtp-options> Add custom smtp options. Example: --smtp-options='debug=1" --smtp-options='layer=none" =item B<--smtp-send-options> Add custom smtp send options. Example: --smtp-send-options='contenttype=text/html" --smtp-send-options='subject=My subject" =item B<--username> Specify username for authentification =item B<--password> Specify password for authentification =item B<--timeout> Connection timeout in seconds (Default: 30) =item B<--warning> Threshold warning in seconds =item B<--critical> Threshold critical in seconds =back =cut centreon-plugins-20220113/apps/protocols/smtp/plugin.pm000066400000000000000000000024031417000230700230410ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::smtp::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} = '0.1'; %{$self->{modes}} = ( 'login' => 'apps::protocols::smtp::mode::login', 'message' => 'apps::protocols::smtp::mode::message', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check a SMTP server. =cut centreon-plugins-20220113/apps/protocols/snmp/000077500000000000000000000000001417000230700212005ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/snmp/mode/000077500000000000000000000000001417000230700221245ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/snmp/mode/collection.pm000066400000000000000000001614071417000230700246260ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::snmp::mode::collection; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use JSON::XS; use Safe; use centreon::plugins::statefile; use Digest::MD5 qw(md5_hex); sub custom_select_threshold { my ($self, %options) = @_; my $status = 'ok'; our $expand = $self->{result_values}->{expand}; if (defined($self->{result_values}->{config}->{critical}) && $self->{result_values}->{config}->{critical} && $self->{instance_mode}->{safe}->reval($self->{result_values}->{config}->{critical})) { $status = 'critical'; } elsif (defined($self->{result_values}->{config}->{warning}) && $self->{result_values}->{config}->{warning} ne '' && $self->{instance_mode}->{safe}->reval($self->{result_values}->{config}->{warning})) { $status = 'warning'; } elsif (defined($self->{result_values}->{config}->{unknown}) && $self->{result_values}->{config}->{unknown} && $self->{instance_mode}->reval($self->{result_values}->{config}->{unknown})) { $status = 'unknown'; } if ($@) { $self->{output}->add_option_msg(short_msg => 'Unsafe code evaluation: ' . $@); $self->{output}->option_exit(); } $self->{result_values}->{last_status} = $status; return $status; } sub custom_select_perfdata { my ($self, %options) = @_; return if (!defined($self->{result_values}->{config}->{perfdatas})); foreach (@{$self->{result_values}->{config}->{perfdatas}}) { next if (!defined($_->{value}) || $_->{value} !~ /^\d+(?:\.\d+)?$/); $self->{output}->perfdata_add(%$_); } } sub custom_select_output { my ($self, %options) = @_; return '' if ( $self->{result_values}->{last_status} eq 'ok' && defined($self->{result_values}->{config}->{formatting}) && defined($self->{result_values}->{config}->{formatting}->{display_ok}) && $self->{result_values}->{config}->{formatting}->{display_ok} =~ /^false|0$/ ); my $format; if (defined($self->{result_values}->{config}->{ 'formatting_' . $self->{result_values}->{last_status} })) { $format = $self->{result_values}->{config}->{ 'formatting_' . $self->{result_values}->{last_status} }; } elsif (defined($self->{result_values}->{config}->{formatting})) { $format = $self->{result_values}->{config}->{formatting}; } if (defined($format)) { return sprintf( $format->{printf_msg}, @{$format->{printf_var}} ); } # without formatting: [name: xxxxxx][test: xxxx][test2: xxx][mytable.plcRead: xxx][mytable.plcWrite: xxx] my $output = ''; foreach (sort keys %{$self->{result_values}->{expand}}) { next if (/^(?:constants|builtin)\./); $output .= '[' . $_ . ': ' . $self->{result_values}->{expand}->{$_} . ']'; } return $output; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'selections', type => 1, message_multiple => 'All selections are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{selections} = [ { label => 'select', threshold => 0, set => { key_values => [ { name => 'expand' }, { name => 'config' } ], closure_custom_output => $self->can('custom_select_output'), closure_custom_perfdata => $self->can('custom_select_perfdata'), closure_custom_threshold_check => $self->can('custom_select_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 => { 'config:s' => { name => 'config' }, 'filter-selection:s%' => { name => 'filter_selection' }, 'constant:s%' => { name => 'constant' } }); $self->{safe} = Safe->new(); $self->{safe}->share('$expand'); $self->{safe_func} = Safe->new(); $self->{safe_func}->share('$assign_var'); $self->{builtin} = {}; $self->{snmp_cache} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{config})) { $self->{output}->add_option_msg(short_msg => 'Please set config option'); $self->{output}->option_exit(); } $self->{snmp_cache}->check_options(option_results => $self->{option_results}); } sub read_config { my ($self, %options) = @_; my $content; if ($self->{option_results}->{config} =~ /\n/m || ! -f "$self->{option_results}->{config}") { $content = $self->{option_results}->{config}; } else { $content = do { local $/ = undef; if (!open my $fh, '<', $self->{option_results}->{config}) { $self->{output}->add_option_msg(short_msg => "Could not open file $self->{option_results}->{config} : $!"); $self->{output}->option_exit(); } <$fh>; }; } eval { $self->{config} = JSON::XS->new->decode($content); }; if ($@) { $self->{output}->output_add(long_msg => "json config error: $@", debug => 1); $self->{output}->add_option_msg(short_msg => 'Cannot decode json config'); $self->{output}->option_exit(); } } sub get_map_value { my ($self, %options) = @_; return undef if ( !defined($self->{config}->{mapping}) || !defined($self->{config}->{mapping}->{ $options{map} }) ); return '' if (!defined($self->{config}->{mapping}->{ $options{map} }->{ $options{value} })); return $self->{config}->{mapping}->{ $options{map} }->{ $options{value} }; } 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}->option_exit(); } if ($options{name} !~ /^[a-zA-Z0-9]+$/) { $self->{output}->add_option_msg(short_msg => 'incorrect name attribute: ' . $options{name}); $self->{output}->option_exit(); } } sub collect_snmp_tables { my ($self, %options) = @_; return if (!defined($self->{config}->{snmp}->{tables})); foreach my $table (@{$self->{config}->{snmp}->{tables}}) { $self->validate_name(name => $table->{name}, section => "[snmp > tables]"); if (!defined($table->{oid}) || $table->{oid} eq '') { $self->{output}->add_option_msg(short_msg => "oid attribute is missing [snmp > tables > $table->{name}]"); $self->{output}->option_exit(); } if (!defined($table->{entries})) { $self->{output}->add_option_msg(short_msg => "entries section is missing [snmp > tables > $table->{name}]"); $self->{output}->option_exit(); } my $mapping = {}; my $sampling = {}; foreach (@{$table->{entries}}) { $self->validate_name(name => $_->{name}, section => "[snmp > tables > $table->{name}]"); if (!defined($_->{oid}) || $_->{oid} eq '') { $self->{output}->add_option_msg(short_msg => "oid attribute is missing [snmp > tables > $table->{name} > $_->{name}]"); $self->{output}->option_exit(); } $mapping->{ $_->{name} } = { oid => $_->{oid} }; $sampling->{ $_->{name} } = 1 if (defined($_->{sampling}) && $_->{sampling} == 1); if (defined($_->{map}) && $_->{map} ne '') { if (!defined($self->{config}->{mapping}) || !defined($self->{config}->{mapping}->{ $_->{map} })) { $self->{output}->add_option_msg(short_msg => "unknown map attribute [snmp > tables > $table->{name} > $_->{name}]: $_->{map}"); $self->{output}->option_exit(); } $mapping->{ $_->{name} }->{map} = $self->{config}->{mapping}->{ $_->{map} }; } } if (scalar(keys %$mapping) <= 0) { $self->{output}->add_option_msg(short_msg => "entries section is empty [snmp > tables > $table->{name}]"); $self->{output}->option_exit(); } $self->{snmp_collected}->{tables}->{ $table->{name} } = {}; my $used_instance = defined($table->{used_instance}) && $table->{used_instance} ne '' ? $table->{used_instance} : '\.(\d+)$'; my $snmp_result = $options{snmp}->get_table(oid => $table->{oid}); foreach (keys %$snmp_result) { /$used_instance/; next if (defined($self->{snmp_collected}->{tables}->{ $table->{name} }->{$1})); $self->{snmp_collected}->{tables}->{ $table->{name} }->{$1} = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $1); foreach my $sample_name (keys %$sampling) { $self->{snmp_collected_sampling}->{tables}->{ $table->{name} } = {} if (!defined($self->{snmp_collected_sampling}->{tables}->{ $table->{name} })); $self->{snmp_collected_sampling}->{tables}->{ $table->{name} }->{$1}->{$sample_name} = $self->{snmp_collected}->{tables}->{ $table->{name} }->{$1}->{$sample_name}; } } } } sub collect_snmp_leefs { my ($self, %options) = @_; return if (!defined($self->{config}->{snmp}->{leefs})); my $oids = [ map($_->{oid}, @{$self->{config}->{snmp}->{leefs}}) ]; return if (scalar(@$oids) <= 0); my $snmp_result = $options{snmp}->get_leef(oids => $oids); foreach (@{$self->{config}->{snmp}->{leefs}}) { $self->validate_name(name => $_->{name}, section => "[snmp > leefs]"); $self->{snmp_collected}->{leefs}->{ $_->{name} } = defined($_->{default}) ? $_->{default} : ''; next if (!defined($_->{oid}) || !defined($snmp_result->{ $_->{oid } })); $self->{snmp_collected}->{leefs}->{ $_->{name} } = $snmp_result->{ $_->{oid } }; if (defined($_->{sampling}) && $_->{sampling} == 1) { $self->{snmp_collected_sampling}->{leefs}->{ $_->{name} } = $snmp_result->{ $_->{oid } }; } if (defined($_->{map}) && $_->{map} ne '') { my $value = $self->get_map_value(value => $snmp_result->{ $_->{oid } }, map => $_->{map}); if (!defined($value)) { $self->{output}->add_option_msg(short_msg => "unknown map attribute [snmp > leefs > $_->{name}]: $_->{map}"); $self->{output}->option_exit(); } $self->{snmp_collected}->{leefs}->{ $_->{name} } = $value; } } } sub is_snmp_cache_enabled { my ($self, %options) = @_; return 0 if ( !defined($self->{config}->{snmp}->{cache}) || !defined($self->{config}->{snmp}->{cache}->{enable}) || $self->{config}->{snmp}->{cache}->{enable} !~ /^true|1$/i ); return 1; } sub use_snmp_cache { my ($self, %options) = @_; return 0 if ($self->is_snmp_cache_enabled() == 0); my $has_cache_file = $self->{snmp_cache}->read( statefile => 'cache_snmp_collection_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . md5_hex($self->{option_results}->{config}) ); $self->{snmp_collected} = $self->{snmp_cache}->get(name => 'snmp_collected'); my $reload = defined($self->{config}->{snmp}->{cache}->{reload}) && $self->{config}->{snmp}->{cache}->{reload} =~ /(\d+)/ ? $self->{config}->{snmp}->{cache}->{reload} : 30; return 0 if ( $has_cache_file == 0 || !defined($self->{snmp_collected}) || ((time() - $self->{snmp_collected}->{epoch}) > ($reload * 60)) ); return 1; } sub save_snmp_cache { my ($self, %options) = @_; return 0 if ($self->is_snmp_cache_enabled() == 0); $self->{snmp_cache}->write(data => { snmp_collected => $self->{snmp_collected} }); } sub collect_snmp_sampling { my ($self, %options) = @_; return if ($self->{snmp_collected}->{sampling} == 0); my $has_cache_file = $self->{snmp_cache}->read( statefile => 'cache_snmp_collection_sampling_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . md5_hex($self->{option_results}->{config}) ); my $snmp_collected_sampling_old = $self->{snmp_cache}->get(name => 'snmp_collected_sampling'); # with cache, we need to load the sampling cache maybe. please a statefile-suffix to get uniq files. # sampling with a global cache can be a nonsense if (!defined($self->{snmp_collected_sampling})) { $self->{snmp_collected_sampling} = $snmp_collected_sampling_old; } my $delta_time; if (defined($snmp_collected_sampling_old->{epoch})) { $delta_time = $self->{snmp_collected_sampling}->{epoch} - $snmp_collected_sampling_old->{epoch}; $delta_time = 1 if ($delta_time <= 0); } foreach (keys %{$self->{snmp_collected_sampling}->{leefs}}) { next if (!defined($snmp_collected_sampling_old->{leefs}->{$_}) || $snmp_collected_sampling_old->{leefs}->{$_} !~ /\d/); my $old = $snmp_collected_sampling_old->{leefs}->{$_}; my $diff = $self->{snmp_collected_sampling}->{leefs}->{$_} - $old; my $diff_counter = $diff; $diff_counter = $self->{snmp_collected_sampling}->{leefs}->{$_} if ($diff_counter < 0); $self->{snmp_collected}->{leefs}->{ $_ . 'Diff' } = $diff; $self->{snmp_collected}->{leefs}->{ $_ . 'DiffCounter' } = $diff_counter; if (defined($delta_time)) { $self->{snmp_collected}->{leefs}->{ $_ . 'PerSeconds' } = $diff_counter / $delta_time; $self->{snmp_collected}->{leefs}->{ $_ . 'PerMinutes' } = $diff_counter / $delta_time / 60; } } foreach my $tbl_name (keys %{$self->{snmp_collected_sampling}->{tables}}) { foreach my $instance (keys %{$self->{snmp_collected_sampling}->{tables}->{$tbl_name}}) { foreach my $attr (keys %{$self->{snmp_collected_sampling}->{tables}->{$tbl_name}->{$instance}}) { next if ( !defined($snmp_collected_sampling_old->{tables}->{$tbl_name}) || !defined($snmp_collected_sampling_old->{tables}->{$tbl_name}->{$instance}) || !defined($snmp_collected_sampling_old->{tables}->{$tbl_name}->{$instance}->{$attr}) || $snmp_collected_sampling_old->{tables}->{$tbl_name}->{$instance}->{$attr} !~ /\d/ ); my $old = $snmp_collected_sampling_old->{tables}->{$tbl_name}->{$instance}->{$attr}; my $diff = $self->{snmp_collected_sampling}->{tables}->{$tbl_name}->{$instance}->{$attr} - $old; my $diff_counter = $diff; $diff_counter = $self->{snmp_collected_sampling}->{tables}->{$tbl_name}->{$instance}->{$attr} if ($diff_counter < 0); $self->{snmp_collected}->{tables}->{$tbl_name}->{$instance}->{ $attr . 'Diff' } = $diff; $self->{snmp_collected}->{tables}->{$tbl_name}->{$instance}->{ $attr . 'DiffCounter' } = $diff_counter; if (defined($delta_time)) { $self->{snmp_collected}->{tables}->{$tbl_name}->{$instance}->{ $attr . 'PerSeconds' } = $diff_counter / $delta_time; $self->{snmp_collected}->{tables}->{$tbl_name}->{$instance}->{ $attr . 'PerMinutes' } = $diff_counter / $delta_time / 60; } } } } $self->{snmp_cache}->write(data => { snmp_collected_sampling => $self->{snmp_collected_sampling} }); } sub collect_snmp { my ($self, %options) = @_; if (!defined($self->{config}->{snmp})) { $self->{output}->add_option_msg(short_msg => 'please set snmp config'); $self->{output}->option_exit(); } $self->add_builtin(name => 'currentTime', value => time()); if ($self->use_snmp_cache(snmp => $options{snmp}) == 0) { $self->{snmp_collected_sampling} = { tables => {}, leefs => {}, epoch => time() }; $self->{snmp_collected} = { tables => {}, leefs => {}, epoch => time(), sampling => 0 }; $self->collect_snmp_tables(snmp => $options{snmp}); $self->collect_snmp_leefs(snmp => $options{snmp}); $self->{snmp_collected}->{sampling} = 1 if ( scalar(keys(%{$self->{snmp_collected_sampling}->{tables}})) > 0 || scalar(keys(%{$self->{snmp_collected_sampling}->{leefs}})) > 0 ); $self->save_snmp_cache(); } $self->collect_snmp_sampling(snmp => $options{snmp}); } sub exist_table_name { my ($self, %options) = @_; return 1 if (defined($self->{snmp_collected}->{tables}->{ $options{name} })); return 0; } sub get_local_variable { my ($self, %options) = @_; return $self->{expand}->{ $options{name} }; } sub set_local_variable { my ($self, %options) = @_; $self->{expand}->{ $options{name} } = $options{value}; } sub get_leef_variable { my ($self, %options) = @_; return $self->{snmp_collected}->{leefs}->{ $options{name} }; } sub set_leef_variable { my ($self, %options) = @_; $self->{snmp_collected}->{leefs}->{ $options{name} } = $options{value}; } sub get_table { my ($self, %options) = @_; return undef if ( !defined($self->{snmp_collected}->{tables}->{ $options{table} }) ); return $self->{snmp_collected}->{tables}->{ $options{table} }; } sub get_table_instance { my ($self, %options) = @_; return undef if ( !defined($self->{snmp_collected}->{tables}->{ $options{table} }) || !defined($self->{snmp_collected}->{tables}->{ $options{table} }->{ $options{instance} }) ); return $self->{snmp_collected}->{tables}->{ $options{table} }->{ $options{instance} }; } sub get_table_attribute_value { my ($self, %options) = @_; return undef if ( !defined($self->{snmp_collected}->{tables}->{ $options{table} }) || !defined($self->{snmp_collected}->{tables}->{ $options{table} }->{ $options{instance} }) || !defined($self->{snmp_collected}->{tables}->{ $options{table} }->{ $options{instance} }->{ $options{attribute} }) ); return $self->{snmp_collected}->{tables}->{ $options{table} }->{ $options{instance} }->{ $options{attribute} }; } sub set_table_attribute_value { my ($self, %options) = @_; $self->{snmp_collected}->{tables}->{ $options{table} } = {} if (!defined($self->{snmp_collected}->{tables}->{ $options{table} })); $self->{snmp_collected}->{tables}->{ $options{table} } = {} if (!defined($self->{snmp_collected}->{tables}->{ $options{table} }->{ $options{instance} })); $self->{snmp_collected}->{tables}->{ $options{table} }->{ $options{instance} }->{ $options{attribute} } = $options{value}; } sub get_special_variable_value { my ($self, %options) = @_; my $data; if ($options{type} == 0) { $data = $self->get_local_variable(name => $options{label}); } elsif ($options{type} == 1) { $data = $self->get_leef_variable(name => $options{label}); } elsif ($options{type} == 2) { $data = $self->get_table(table => $options{table}); } elsif ($options{type} == 4) { $data = $self->get_table_attribute_value( table => $options{table}, instance => $options{instance}, attribute => $options{label} ); } return $data; } sub set_special_variable_value { my ($self, %options) = @_; my $data; if ($options{type} == 0) { $data = $self->set_local_variable(name => $options{label}, value => $options{value}); } elsif ($options{type} == 1) { $data = $self->set_leef_variable(name => $options{label}, value => $options{value}); } elsif ($options{type} == 4) { $data = $self->set_table_attribute_value( table => $options{table}, instance => $options{instance}, attribute => $options{label}, value => $options{value} ); } return $data; } sub strcmp { my ($self, %options) = @_; my @cmp = split //, $options{test}; for (my $i = 0; $i < scalar(@cmp); $i++) { return 0 if ( !defined($options{chars}->[ $options{start} + $i ]) || $options{chars}->[ $options{start} + $i ] ne $cmp[$i] ); } return 1; } sub parse_forward { my ($self, %options) = @_; my ($string, $i) = ('', 0); while (1) { return (1, 'cannot find ' . $options{stop} . ' character') if (!defined($options{chars}->[ $options{start} + $i ])); last if ($options{chars}->[ $options{start} + $i ] =~ /$options{stop}/); return (1, "character '" . $options{chars}->[ $options{start} + $i ] . "' forbidden") if ($options{chars}->[ $options{start} + $i ] !~ /$options{allowed}/); $string .= $options{chars}->[ $options{start} + $i ]; $i++; } return (0, undef, $options{start} + $i, $string); } =pod managed variables: %(snmp.tables.plcData) %(snmp.tables.plcData.[1]) %(snmp.tables.plcOther.[1].plop) %(snmp.tables.plcOther.[%(mytable.instance)] %(snmp.tables.plcOther.[%(snmp.tables.plcOther.[%(mytable.instance)].test)] %(test2) %(mytable.test) result: - type: 0=%(test) (label) 1=%(snmp.leefs.variable) 2=%(snmp.tables.test) 3=%(snmp.tables.test.[2]) 4=%(snmp.tables.test.[2].attrname) =cut sub parse_snmp_tables { my ($self, %options) = @_; my ($code, $msg_error, $end, $table_label, $instance_label, $label); ($code, $msg_error, $end, $table_label) = $self->parse_forward( chars => $options{chars}, start => $options{start}, allowed => '[a-zA-Z0-9]', stop => '[).]' ); if ($code) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " $msg_error"); $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'"); $self->{output}->option_exit(); } if ($options{chars}->[$end] eq ')') { return { type => 2, end => $end, table => $table_label }; } # instance part managenent if (!defined($options{chars}->[$end + 1]) || $options{chars}->[$end + 1] ne '[') { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable snmp.tables character '[' mandatory"); $self->{output}->option_exit(); } if ($self->strcmp(chars => $options{chars}, start => $end + 2, test => '%(')) { my $result = $self->parse_special_variable(chars => $options{chars}, start => $end + 2); # type allowed: 0,1,4 if ($result->{type} !~ /^(?:0|1|4)$/) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . ' special variable type not allowed'); $self->{output}->option_exit(); } $end = $result->{end} + 1; if ($result->{type} == 0) { $instance_label = $self->get_local_variable(name => $result->{label}); } elsif ($result->{type} == 1) { $instance_label = $self->get_leef_variable(name => $result->{label}); } elsif ($result->{type} == 4) { $instance_label = $self->get_table_attribute_value( table => $result->{table}, instance => $result->{instance}, attribute => $result->{label} ); } $instance_label = defined($instance_label) ? $instance_label : ''; } else { ($code, $msg_error, $end, $instance_label) = $self->parse_forward( chars => $options{chars}, start => $end + 2, allowed => '[0-9\.]', stop => '[\]]' ); if ($code) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " $msg_error"); $self->{output}->option_exit(); } } if (!defined($options{chars}->[$end + 1]) || $options{chars}->[$end + 1] !~ /[.)]/) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . ' special variable snmp.tables character [.)] missing'); $self->{output}->option_exit(); } if ($options{chars}->[$end + 1] eq ')') { return { type => 3, end => $end + 1, table => $table_label, instance => $instance_label }; } ($code, $msg_error, $end, $label) = $self->parse_forward( chars => $options{chars}, start => $end + 2, allowed => '[a-zA-Z0-9]', stop => '[)]' ); if ($code) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " $msg_error"); $self->{output}->option_exit(); } return { type => 4, end => $end, table => $table_label, instance => $instance_label, label => $label }; } sub parse_snmp_type { my ($self, %options) = @_; if ($self->strcmp(chars => $options{chars}, start => $options{start}, test => 'leefs.')) { my ($code, $msg_error, $end, $label) = $self->parse_forward( chars => $options{chars}, start => $options{start} + 6, allowed => '[a-zA-Z0-9]', stop => '[)]' ); if ($code) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " $msg_error"); $self->{output}->option_exit(); } return { type => 1, end => $end, label => $label }; } elsif ($self->strcmp(chars => $options{chars}, start => $options{start}, test => 'tables.')) { return $self->parse_snmp_tables(chars => $options{chars}, start => $options{start} + 7); } else { $self->{output}->add_option_msg(short_msg => $self->{current_section} . ' special variable snmp not followed by leefs/tables'); $self->{output}->option_exit(); } } sub parse_special_variable { my ($self, %options) = @_; my $start = $options{start}; if ($options{chars}->[$start] ne '%' || $options{chars}->[$start + 1] ne '(') { $self->{output}->add_option_msg(short_msg => $self->{current_section} . ' special variable not starting by %('); $self->{output}->option_exit(); } my $result = { start => $options{start} }; if ($self->strcmp(chars => $options{chars}, start => $start + 2, test => 'snmp.')) { my $parse = $self->parse_snmp_type(chars => $options{chars}, start => $start + 2 + 5); $result = { %$parse, %$result }; } else { my ($code, $msg_error, $end, $label) = $self->parse_forward( chars => $options{chars}, start => $start + 2, allowed => '[a-zA-Z0-9.]', stop => '[)]' ); if ($code) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " $msg_error"); $self->{output}->option_exit(); } $result->{end} = $end; $result->{type} = 0; $result->{label} = $label; } return $result; } sub substitute_string { my ($self, %options) = @_; my $arr = [split //, $options{value}]; my $results = {}; my $last_end = -1; while ($options{value} =~ /\Q%(\E/g) { next if ($-[0] < $last_end); my $result = $self->parse_special_variable(chars => $arr, start => $-[0]); if ($result->{type} !~ /^(?:0|1|4)$/) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed"); $self->{output}->option_exit(); } $last_end = $result->{end}; $results->{ $result->{start} } = $result; } my $end = -1; my $str = ''; for (my $i = 0; $i < scalar(@$arr); $i++) { next if ($i <= $end); if (defined($results->{$i})) { my $data = $self->get_special_variable_value(%{$results->{$i}}); $end = $results->{$i}->{end}; $str .= defined($data) ? $data : ''; } else { $str .= $arr->[$i]; } } return $str; } sub add_builtin { my ($self, %options) = @_; $self->{builtin}->{ $options{name} } = $options{value}; } sub set_builtin { my ($self, %options) = @_; foreach (keys %{$self->{builtin}}) { $self->{expand}->{ 'builtin.' . $_ } = $self->{builtin}->{$_}; } } sub set_constants { my ($self, %options) = @_; my $constants = {}; if (defined($self->{config}->{constants})) { foreach (keys %{$self->{config}->{constants}}) { $constants->{'constants.' . $_} = $self->{config}->{constants}->{$_}; } } foreach (keys %{$self->{option_results}->{constant}}) { $constants->{'constants.' . $_} = $self->{option_results}->{constant}->{$_}; } return $constants; } sub set_expand_table { my ($self, %options) = @_; return if (!defined($options{expand})); foreach my $name (keys %{$options{expand}}) { $self->{current_section} = '[' . $options{section} . ' > ' . $name . ']'; my $result = $self->parse_special_variable(chars => [split //, $options{expand}->{$name}], start => 0); if ($result->{type} != 3) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed"); $self->{output}->option_exit(); } my $table = $self->get_table_instance(table => $result->{table}, instance => $result->{instance}); next if (!defined($table)); $self->{expand}->{ $name . '.instance' } = $result->{instance}; foreach (keys %$table) { $self->{expand}->{ $name . '.' . $_ } = $table->{$_}; } } } sub set_expand { my ($self, %options) = @_; return if (!defined($options{expand})); foreach my $name (keys %{$options{expand}}) { $self->{current_section} = '[' . $options{section} . ' > ' . $name . ']'; $self->{expand}->{$name} = $self->substitute_string(value => $options{expand}->{$name}); } } sub exec_func_map { my ($self, %options) = @_; if (!defined($options{map_name}) || $options{map_name} eq '') { $self->{output}->add_option_msg(short_msg => "$self->{current_section} please set map_name attribute"); $self->{output}->option_exit(); } if (!defined($options{src}) || $options{src} eq '') { $self->{output}->add_option_msg(short_msg => "$self->{current_section} please set src attribute"); $self->{output}->option_exit(); } my $result = $self->parse_special_variable(chars => [split //, $options{src}], start => 0); if ($result->{type} !~ /^(?:0|1|4)$/) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed in src attribute"); $self->{output}->option_exit(); } my $data = $self->get_special_variable_value(%$result); my $value = $self->get_map_value(value => $data, map => $options{map_name}); if (!defined($value)) { $self->{output}->add_option_msg(short_msg => "$self->{current_section} unknown map attribute: $options{map_name}"); $self->{output}->option_exit(); } my $save = $result; if (defined($options{save}) && $options{save} ne '') { $save = $self->parse_special_variable(chars => [split //, $options{save}], start => 0); if ($save->{type} !~ /^(?:0|1|4)$/) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed in save attribute"); $self->{output}->option_exit(); } } elsif (defined($options{dst}) && $options{dst} ne '') { $save = $self->parse_special_variable(chars => [split //, $options{dst}], start => 0); if ($save->{type} !~ /^(?:0|1|4)$/) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed in dst attribute"); $self->{output}->option_exit(); } } $self->set_special_variable_value(value => $value, %$save); } sub scale { my ($self, %options) = @_; my ($src_quantity, $src_unit) = (undef, 'B'); if ($options{src_unit} =~ /([kmgtpe])?(b)/i) { $src_quantity = $1; $src_unit = $2; } my ($dst_quantity, $dst_unit) = ('auto', $src_unit); if ($options{dst_unit} =~ /([kmgtpe])?(b)/i) { $dst_quantity = $1; $dst_unit = $2; } my $base = 1024; $options{value} *= 8 if ($dst_unit eq 'b' && $src_unit eq 'B'); $options{value} /= 8 if ($dst_unit eq 'B' && $src_unit eq 'b'); $base = 1000 if ($dst_unit eq 'b'); my %expo = (k => 1, m => 2, g => 3, t => 4, p => 5, e => 6); my $src_expo = 0; $src_expo = $expo{ lc($src_quantity) } if (defined($src_quantity)); if (defined($dst_quantity) && $dst_quantity eq 'auto') { my @auto = ('', 'k', 'm', 'g', 't', 'p', 'e'); for (; $src_expo < scalar(@auto); $src_expo++) { last if ($options{value} < $base); $options{value} = $options{value} / $base; } return ($options{value}, uc($auto[$src_expo]) . $dst_unit); } my $dst_expo = 0; $dst_expo = $expo{ lc($dst_quantity) } if (defined($dst_quantity)); if ($dst_expo - $src_expo > 0) { $options{value} = $options{value} / ($base ** ($dst_expo - $src_expo)); } elsif ($dst_expo - $src_expo < 0) { $options{value} = $options{value} * ($base ** (($dst_expo - $src_expo) * -1)); } return ($options{value}, $options{dst_unit}); } sub exec_func_scale { my ($self, %options) = @_; #{ # "type": "scale", # "src": "%(memoryUsed)", # "src_unit": "KB", (default: 'B') # "dst_unit": "auto", (default: 'auto') # "save_value": "%(memoryUsedScaled)", # "save_unit": "%(memoryUsedUnit)" #} if (!defined($options{src}) || $options{src} eq '') { $self->{output}->add_option_msg(short_msg => "$self->{current_section} please set src attribute"); $self->{output}->option_exit(); } my $result = $self->parse_special_variable(chars => [split //, $options{src}], start => 0); if ($result->{type} !~ /^(?:0|1|4)$/) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed in src attribute"); $self->{output}->option_exit(); } my $data = $self->get_special_variable_value(%$result); my ($save_value, $save_unit) = $self->scale( value => $data, src_unit => $options{src_unit}, dst_unit => $options{dst_unit} ); if (defined($options{save_value}) && $options{save_value} ne '') { my $var_save_value = $self->parse_special_variable(chars => [split //, $options{save_value}], start => 0); if ($var_save_value->{type} !~ /^(?:0|1|4)$/) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed in save_value attribute"); $self->{output}->option_exit(); } $self->set_special_variable_value(value => $save_value, %$var_save_value); } if (defined($options{save_unit}) && $options{save_unit} ne '') { my $var_save_unit = $self->parse_special_variable(chars => [split //, $options{save_unit}], start => 0); if ($var_save_unit->{type} !~ /^(?:0|1|4)$/) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed in save_value attribute"); $self->{output}->option_exit(); } $self->set_special_variable_value(value => $save_unit, %$var_save_unit); } } sub exec_func_date2epoch { my ($self, %options) = @_; if (!defined($self->{module_datetime_loaded})) { centreon::plugins::misc::mymodule_load( module => 'DateTime', error_msg => "Cannot load module 'DateTime'." ); $self->{module_datetime_loaded} = 1; } #{ # "type": "date2epoch", # "src": "%(dateTest)", # "format": "DateAndTime", # "timezone": "Europe/Paris", # "save_epoch": "%(plopDateEpoch)", # "save_diff1": "%(plopDateDiff1)", # "save_diff2": "%(plopDateDiff2)" #}, #{ # "type": "date2epoch", # "src": "%(dateTest2)", # "format_custom": "(\\d+)-(\\d+)-(\\d+)", # "year": 1, # "month": 2, # "day": 3, # "timezone": "Europe/Paris" #} if (!defined($options{src}) || $options{src} eq '') { $self->{output}->add_option_msg(short_msg => "$self->{current_section} please set src attribute"); $self->{output}->option_exit(); } my $result = $self->parse_special_variable(chars => [split //, $options{src}], start => 0); if ($result->{type} !~ /^(?:0|1|4)$/) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed in src attribute"); $self->{output}->option_exit(); } my $data = $self->get_special_variable_value(%$result); my $tz = {}; $tz->{time_zone} = $options{timezone} if (defined($options{timezone}) && $options{timezone} ne ''); my $dt; if (defined($options{format}) && lc($options{format}) eq 'dateandtime') { my @date = unpack('n C6 a C2', $data); my $timezone; if (defined($date[7]) && !defined($tz->{time_zone})) { $tz->{time_zone} = sprintf('%s%02d%02d', $date[7], $date[8], $date[9]); } $dt = DateTime->new( year => $date[0], month => $date[1], day => $date[2], hour => $date[3], minute => $date[4], second => $date[5], %$tz ); } elsif (defined($options{format_custom}) && $options{format_custom} ne '') { my @matches = ($data =~ /$options{format_custom}/); my $date = {}; foreach (('year', 'month', 'day', 'hour', 'minute', 'second')) { $date->{$_} = $matches[ $options{$_} -1 ] if (defined($options{$_}) && $options{$_} =~ /^\d+$/ && defined($matches[ $options{$_} -1 ])); } foreach (('year', 'month', 'day')) { if (!defined($date->{$_})) { $self->{output}->add_option_msg(short_msg => "$self->{current_section} cannot find $_ attribute"); $self->{output}->option_exit(); } } $dt = DateTime->new(%$date, %$tz); } else { $self->{output}->add_option_msg(short_msg => "$self->{current_section} please set format or format_custom attribute"); $self->{output}->option_exit(); } my $results = { epoch => $dt->epoch(), diff1 => time() - $dt->epoch(), diff2 => $dt->epoch() - time() }; foreach (keys %$results) { my $attr = '%(' . $result->{label} . ucfirst($_) . ')'; $attr = $options{'save_' . $_} if (defined($options{'save_' . $_}) && $options{'save_' . $_} ne ''); my $var_save_value = $self->parse_special_variable(chars => [split //, $attr], start => 0); if ($var_save_value->{type} !~ /^(?:0|1|4)$/) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed in save_$_ attribute"); $self->{output}->option_exit(); } $self->set_special_variable_value(value => $results->{$_}, %$var_save_value); } } sub exec_func_epoch2date { my ($self, %options) = @_; if (!defined($self->{module_datetime_loaded})) { centreon::plugins::misc::mymodule_load( module => 'DateTime', error_msg => "Cannot load module 'DateTime'." ); $self->{module_datetime_loaded} = 1; } #{ # "type": "epoch2date", # "src": "%(dateTestEpoch)", # "format": "%a %b %e %H:%M:%S %Y", # "timezone": "Asia/Tokyo", # "locale": "fr", # "save": "%(dateTestReformat)" #} if (!defined($options{src}) || $options{src} eq '') { $self->{output}->add_option_msg(short_msg => "$self->{current_section} please set src attribute"); $self->{output}->option_exit(); } my $result = $self->parse_special_variable(chars => [split //, $options{src}], start => 0); if ($result->{type} !~ /^(?:0|1|4)$/) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed in src attribute"); $self->{output}->option_exit(); } my $data = $self->get_special_variable_value(%$result); my $extras = {}; $extras->{time_zone} = $options{timezone} if (defined($options{timezone}) && $options{timezone} ne ''); $extras->{locale} = $options{locale} if (defined($options{locale}) && $options{locale} ne ''); my $dt = DateTime->from_epoch( epoch => $data, %$extras ); my $time_value = $dt->strftime($options{format}); if (defined($options{save}) && $options{save} ne '') { my $var_save_value = $self->parse_special_variable(chars => [split //, $options{save}], start => 0); if ($var_save_value->{type} !~ /^(?:0|1|4)$/) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed in save attribute"); $self->{output}->option_exit(); } $self->set_special_variable_value(value => $time_value, %$var_save_value); } } sub exec_func_count { my ($self, %options) = @_; #{ # "type": "count", # "src": "%(snmp.tables.test)", # "save": "%(testCount)" #} if (!defined($options{src}) || $options{src} eq '') { $self->{output}->add_option_msg(short_msg => "$self->{current_section} please set src attribute"); $self->{output}->option_exit(); } my $result = $self->parse_special_variable(chars => [split //, $options{src}], start => 0); if ($result->{type} !~ /^2$/) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed in src attribute"); $self->{output}->option_exit(); } my $data = $self->get_special_variable_value(%$result); my $value = 0; if (defined($data)) { if (defined($options{filter}) && $options{filter} ne '') { my $count = 0; foreach my $instance (keys %$data) { my $values = $self->{expand}; foreach my $label (keys %{$data->{$instance}}) { $values->{'src.' . $label} = $data->{$instance}->{$label}; } $count++ unless ($self->check_filter(filter => $options{filter}, values => $values)); } $value = $count; } else { $value = scalar(keys %$data); } } if (defined($options{save}) && $options{save} ne '') { my $save = $self->parse_special_variable(chars => [split //, $options{save}], start => 0); if ($save->{type} !~ /^(?:0|1|4)$/) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed in save attribute"); $self->{output}->option_exit(); } $self->set_special_variable_value(value => $value, %$save); } } sub exec_func_replace { my ($self, %options) = @_; #{ # "type": "replace", # "src": "%(sql.tables.test)", # "expression": "s/name/name is/" #} if (!defined($options{src}) || $options{src} eq '') { $self->{output}->add_option_msg(short_msg => "$self->{current_section} please set src attribute"); $self->{output}->option_exit(); } if (!defined($options{expression}) || $options{expression} eq '') { $self->{output}->add_option_msg(short_msg => "$self->{current_section} please set expression attribute"); $self->{output}->option_exit(); } my $result = $self->parse_special_variable(chars => [split //, $options{src}], start => 0); if ($result->{type} !~ /^(?:0|4)$/) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed in src attribute"); $self->{output}->option_exit(); } my $data = $self->get_special_variable_value(%$result); if (defined($data)) { my $expression = $self->substitute_string(value => $options{expression}); our $assign_var = $data; $self->{safe_func}->reval("\$assign_var =~ $expression", 1); if ($@) { die 'Unsafe code evaluation: ' . $@; } $self->set_special_variable_value(value => $assign_var, %$result); } } sub exec_func_assign { my ($self, %options) = @_; #{ # "type": "assign", # "save": "%(sql.tables.test)", # "expression": "'%(sql.tables.test)' . 'toto'" #} if (!defined($options{save}) || $options{save} eq '') { $self->{output}->add_option_msg(short_msg => "$self->{current_section} please set save attribute"); $self->{output}->option_exit(); } if (!defined($options{expression}) || $options{expression} eq '') { $self->{output}->add_option_msg(short_msg => "$self->{current_section} please set expression attribute"); $self->{output}->option_exit(); } my $result = $self->parse_special_variable(chars => [split //, $options{save}], start => 0); if ($result->{type} !~ /^(?:0|4)$/) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed in src attribute"); $self->{output}->option_exit(); } my $expression = $self->substitute_string(value => $options{expression}); our $assign_var; $self->{safe_func}->reval("\$assign_var = $expression", 1); if ($@) { die 'Unsafe code evaluation: ' . $@; } $self->set_special_variable_value(value => $assign_var, %$result); } sub set_functions { my ($self, %options) = @_; return if (!defined($options{functions})); my $i = -1; foreach (@{$options{functions}}) { $i++; $self->{current_section} = '[' . $options{section} . ' > ' . $i . ']'; next if (defined($_->{position}) && $options{position} ne $_->{position}); next if (!defined($_->{position}) && !(defined($options{default}) && $options{default} == 1)); next if (!defined($_->{type})); if ($_->{type} eq 'map') { $self->exec_func_map(%$_); } elsif ($_->{type} eq 'scale') { $self->exec_func_scale(%$_); } elsif (lc($_->{type}) eq 'date2epoch') { $self->exec_func_date2epoch(%$_); } elsif (lc($_->{type}) eq 'epoch2date') { $self->exec_func_epoch2date(%$_); } elsif (lc($_->{type}) eq 'count') { $self->exec_func_count(%$_); } elsif (lc($_->{type}) eq 'replace') { $self->exec_func_replace(%$_); } elsif (lc($_->{type}) eq 'assign') { $self->exec_func_assign(%$_); } } } sub prepare_variables { my ($self, %options) = @_; return undef if (!defined($options{value})); $options{value} =~ s/%\(([a-zA-Z0-9\.]+?)\)/\$expand->{'$1'}/g; return $options{value}; } sub check_filter { my ($self, %options) = @_; return 0 if (!defined($options{filter}) || $options{filter} eq ''); our $expand = $options{values}; $options{filter} =~ s/%\(([a-zA-Z0-9\.]+?)\)/\$expand->{'$1'}/g; my $result = $self->{safe}->reval("$options{filter}"); if ($@) { $self->{output}->add_option_msg(short_msg => 'Unsafe code evaluation: ' . $@); $self->{output}->option_exit(); } return 0 if ($result); return 1; } sub check_filter_option { my ($self, %options) = @_; foreach (keys %{$self->{option_results}->{filter_selection}}) { return 1 if ( defined($self->{expand}->{$_}) && $self->{option_results}->{filter_selection}->{$_} ne '' && $self->{expand}->{$_} !~ /$self->{option_results}->{filter_selection}->{$_}/ ); } return 0; } sub prepare_perfdatas { my ($self, %options) = @_; return undef if (!defined($options{perfdatas})); my $perfdatas = []; foreach (@{$options{perfdatas}}) { next if (!defined($_->{nlabel}) || $_->{nlabel} eq ''); next if (!defined($_->{value}) || $_->{value} eq ''); my $perf = {}; $perf->{nlabel} = $self->substitute_string(value => $_->{nlabel}); $perf->{value} = $self->substitute_string(value => $_->{value}); foreach my $label (('warning', 'critical', 'min', 'max', 'unit')) { next if (!defined($_->{$label})); $perf->{$label} = $self->substitute_string(value => $_->{$label}); } if (defined($_->{instances})) { $perf->{instances} = []; foreach my $instance (@{$_->{instances}}) { push @{$perf->{instances}}, $self->substitute_string(value => $instance); } } push @$perfdatas, $perf; } return $perfdatas; } sub prepare_formatting { my ($self, %options) = @_; return undef if (!defined($options{formatting})); my $format = {}; $format->{printf_msg} = $options{formatting}->{printf_msg}; $format->{display_ok} = $options{formatting}->{display_ok}; if (defined($options{formatting}->{printf_var})) { $format->{printf_var} = []; foreach my $var (@{$options{formatting}->{printf_var}}) { push @{$format->{printf_var}}, $self->substitute_string(value => $var); } } return $format } sub add_selection { my ($self, %options) = @_; return if (!defined($self->{config}->{selection})); my $i = -1; foreach (@{$self->{config}->{selection}}) { $i++; my $config = {}; $self->{expand} = $self->set_constants(); $self->set_builtin(); $self->{expand}->{name} = $_->{name} if (defined($_->{name})); $self->set_functions(section => "selection > $i > functions", functions => $_->{functions}, position => 'before_expand'); $self->set_expand_table(section => "selection > $i > expand_table", expand => $_->{expand_table}); $self->set_expand(section => "selection > $i > expand", expand => $_->{expand}); $self->set_functions(section => "selection > $i > functions", functions => $_->{functions}, position => 'after_expand', default => 1); next if ($self->check_filter(filter => $_->{filter}, values => $self->{expand})); next if ($self->check_filter_option()); $config->{unknown} = $self->prepare_variables(section => "selection > $i > unknown", value => $_->{unknown}); $config->{warning} = $self->prepare_variables(section => "selection > $i > warning", value => $_->{warning}); $config->{critical} = $self->prepare_variables(section => "selection > $i > critical", value => $_->{critical}); $config->{perfdatas} = $self->prepare_perfdatas(section => "selection > $i > perfdatas", perfdatas => $_->{perfdatas}); $config->{formatting} = $self->prepare_formatting(section => "selection > $i > formatting", formatting => $_->{formatting}); $config->{formatting_unknown} = $self->prepare_formatting(section => "selection > $i > formatting_unknown", formatting => $_->{formatting_unknown}); $config->{formatting_warning} = $self->prepare_formatting(section => "selection > $i > formatting_warning", formatting => $_->{formatting_warning}); $config->{formatting_critical} = $self->prepare_formatting(section => "selection > $i > formatting_critical", formatting => $_->{formatting_critical}); $self->{selections}->{'s' . $i} = { expand => $self->{expand}, config => $config }; } } sub add_selection_loop { my ($self, %options) = @_; return if (!defined($self->{config}->{selection_loop})); my $i = -1; foreach (@{$self->{config}->{selection_loop}}) { $i++; next if (!defined($_->{source}) || $_->{source} eq ''); $self->{current_section} = '[selection_loop > ' . $i . ' > source]'; my $result = $self->parse_special_variable(chars => [split //, $_->{source}], start => 0); if ($result->{type} != 2) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed"); $self->{output}->option_exit(); } next if (!defined($self->{snmp_collected}->{tables}->{ $result->{table} })); foreach my $instance (keys %{$self->{snmp_collected}->{tables}->{ $result->{table} }}) { $self->{expand} = $self->set_constants(); $self->set_builtin(); $self->{expand}->{ $result->{table} . '.instance' } = $instance; foreach my $label (keys %{$self->{snmp_collected}->{tables}->{ $result->{table} }->{$instance}}) { $self->{expand}->{ $result->{table} . '.' . $label } = $self->{snmp_collected}->{tables}->{ $result->{table} }->{$instance}->{$label}; } my $config = {}; $self->{expand}->{name} = $_->{name} if (defined($_->{name})); $self->set_functions(section => "selection_loop > $i > functions", functions => $_->{functions}, position => 'before_expand'); $self->set_expand_table(section => "selection_loop > $i > expand_table", expand => $_->{expand_table}); $self->set_expand(section => "selection_loop > $i > expand", expand => $_->{expand}); $self->set_functions(section => "selection_loop > $i > functions", functions => $_->{functions}, position => 'after_expand', default => 1); next if ($self->check_filter(filter => $_->{filter}, values => $self->{expand})); next if ($self->check_filter_option()); $config->{unknown} = $self->prepare_variables(section => "selection_loop > $i > unknown", value => $_->{unknown}); $config->{warning} = $self->prepare_variables(section => "selection_loop > $i > warning", value => $_->{warning}); $config->{critical} = $self->prepare_variables(section => "selection_loop > $i > critical", value => $_->{critical}); $config->{perfdatas} = $self->prepare_perfdatas(section => "selection_loop > $i > perfdatas", perfdatas => $_->{perfdatas}); $config->{formatting} = $self->prepare_formatting(section => "selection_loop > $i > formatting", formatting => $_->{formatting}); $config->{formatting_unknown} = $self->prepare_formatting(section => "selection_loop > $i > formatting_unknown", formatting => $_->{formatting_unknown}); $config->{formatting_warning} = $self->prepare_formatting(section => "selection_loop > $i > formatting_warning", formatting => $_->{formatting_warning}); $config->{formatting_critical} = $self->prepare_formatting(section => "selection_loop > $i > formatting_critical", formatting => $_->{formatting_critical}); $self->{selections}->{'s' . $i . '-' . $instance} = { expand => $self->{expand}, config => $config }; } } } sub set_formatting { my ($self, %options) = @_; return if (!defined($self->{config}->{formatting})); if (defined($self->{config}->{formatting}->{custom_message_global})) { $self->{maps_counters_type}->[0]->{message_multiple} = $self->{config}->{formatting}->{custom_message_global}; } if (defined($self->{config}->{formatting}->{separator})) { $self->{maps_counters_type}->[0]->{message_separator} = $self->{config}->{formatting}->{separator}; } } sub disco_format { my ($self, %options) = @_; $self->{output}->add_disco_format(elements => ['name']); } sub disco_show { my ($self, %options) = @_; $self->read_config(); $self->collect_snmp(snmp => $options{snmp}); $self->{selections} = {}; $self->add_selection(); $self->add_selection_loop(); foreach (values %{$self->{selections}}) { my $entry = {}; foreach my $label (keys %{$_->{expand}}) { next if ($label =~ /^(?:constants|builtin)\./); my $name = $label; $name =~ s/\./_/g; $entry->{$name} = defined($_->{expand}->{$label}) ? $_->{expand}->{$label} : ''; } $self->{output}->add_disco_entry(%$entry); } } sub manage_selection { my ($self, %options) = @_; # TODO: # add some functions types: # decode snmp type: ipAddress # can cache only some parts of snmp requests: # use an array for "snmp" ? $self->read_config(); $self->collect_snmp(snmp => $options{snmp}); $self->{selections} = {}; $self->add_selection(); $self->add_selection_loop(); $self->set_formatting(); } 1; __END__ =head1 MODE Collect and compute SNMP datas. =over 8 =item B<--config> config used (Required). Can be a file or json content. =item B<--filter-selection> Filter selections. Eg: --filter-selection='name=test' =item B<--constant> Add a constant. Eg: --constant='warning=30' --constant='critical=45' =back =cut centreon-plugins-20220113/apps/protocols/snmp/mode/responsetime.pm000066400000000000000000000122371417000230700252040ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::snmp::mode::responsetime; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Time::HiRes qw(gettimeofday tv_interval); sub prefix_output { my ($self, %options) = @_; return 'SNMP Agent '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_output' } ]; $self->{maps_counters}->{global} = [ { label => 'rta', nlabel => 'roundtrip.time.average.milliseconds', set => { key_values => [ { name => 'rta' } ], output_template => 'rta %.3fms', perfdatas => [ { label => 'rta', template => '%.3f', min => 0, unit => 'ms' } ] } }, { label => 'rtmax', nlabel => 'roundtrip.time.maximum.milliseconds', display_ok => 0, set => { key_values => [ { name => 'rtmax' } ], perfdatas => [ { label => 'rtmax', template => '%.3f', min => 0, unit => 'ms' } ] } }, { label => 'rtmin', nlabel => 'roundtrip.time.minimum.milliseconds', display_ok => 0, set => { key_values => [ { name => 'rtmin' } ], perfdatas => [ { label => 'rtmin', template => '%.3f', min => 0, unit => 'ms' } ] } }, { label => 'pl', nlabel => 'packets.loss.percentage', set => { key_values => [ { name => 'pl' } ], output_template => 'lost %s%%', perfdatas => [ { label => 'pl', template => '%s', min => 0, max => 100, unit => '%' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'timeout:s' => { name => 'timeout' }, 'packets:s' => { name => 'packets' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{option_timeout} = 5; $self->{option_packets} = 5; if (defined($self->{option_results}->{timeout}) && $self->{option_results}->{timeout} =~ /(\d+)/) { $self->{option_timeout} = $1; } if (defined($self->{option_results}->{packets}) && $self->{option_results}->{packets} =~ /(\d+)/) { $self->{option_packets} = $1; } $options{snmp}->set_snmp_connect_params(Timeout => $self->{option_timeout} * (10**6)); $options{snmp}->set_snmp_connect_params(Retries => 0); $options{snmp}->set_snmp_params(subsetleef => 1); } sub manage_selection { my ($self, %options) = @_; my $sysDescr = '.1.3.6.1.2.1.1.1.0'; my $total_time_elapsed = 0; my $max_time_elapsed = 0; my $min_time_elapsed = 0; my $total_packet_lost = 0; for (my $i = 0; $i < $self->{option_packets}; $i++) { my $timing0 = [gettimeofday]; my $return = $options{snmp}->get_leef(oids => [$sysDescr], nothing_quit => 0, dont_quit => 1); my $timeelapsed = tv_interval($timing0, [gettimeofday]); if (!defined($return)) { $total_packet_lost++; } else { $total_time_elapsed += $timeelapsed; $max_time_elapsed = $timeelapsed if ($timeelapsed > $max_time_elapsed); $min_time_elapsed = $timeelapsed if ($timeelapsed < $min_time_elapsed || $min_time_elapsed == 0); } } $self->{global} = { rta => ($self->{option_packets} > $total_packet_lost) ? $total_time_elapsed * 1000 / ($self->{option_packets} - $total_packet_lost) : 0, rtmax => $max_time_elapsed * 1000, rtmin => $min_time_elapsed * 1000, pl => int($total_packet_lost * 100 / $self->{option_packets}) }; } 1; __END__ =head1 MODE Check SNMP agent response time. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example : --filter-counters='rta' =item B<--timeout> Set timeout in seconds (Default: 5). =item B<--packets> Number of packets to send (Default: 5). =item B<--warning-rta> Response time threshold warning in milliseconds =item B<--critical-rta> Response time threshold critical in milliseconds =item B<--warning-pl> Packets lost threshold warning in % =item B<--critical-pl> Packets lost threshold critical in % =back =cut centreon-plugins-20220113/apps/protocols/snmp/plugin.pm000066400000000000000000000030761417000230700230420ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::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} = { 'collection' => 'apps::protocols::snmp::mode::collection', 'dynamic-command' => 'snmp_standard::mode::dynamiccommand', 'numeric-value' => 'snmp_standard::mode::numericvalue', 'response-time' => 'apps::protocols::snmp::mode::responsetime', 'string-value' => 'snmp_standard::mode::stringvalue', 'uptime' => 'snmp_standard::mode::uptime' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check SNMP values (string, numeric or execute commands). =cut centreon-plugins-20220113/apps/protocols/ssh/000077500000000000000000000000001417000230700210205ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/ssh/mode/000077500000000000000000000000001417000230700217445ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/ssh/mode/login.pm000066400000000000000000000061101417000230700234100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::ssh::mode::login; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Time::HiRes qw(gettimeofday tv_interval); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf('%s', $self->{result_values}->{message}); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, message_separator => ' - ' }, ]; $self->{maps_counters}->{global} = [ { label => 'status', type => 2, critical_default => '%{message} !~ /authentification succeeded/i', set => { key_values => [ { name => 'status' }, { name => 'message' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'time', nlabel => 'response.time.seconds' , set => { key_values => [ { name => 'time_elapsed' } ], output_template => 'Response time %.3fs', perfdatas => [ { label => 'time', template => '%.3f', unit => 's', min => 0 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $timing0 = [gettimeofday]; my $result = $options{custom}->login(); my $timeelapsed = tv_interval($timing0, [gettimeofday]); $self->{global} = { %$result, time_elapsed => $timeelapsed }; } 1; __END__ =head1 MODE Check SSH connection. =over 8 =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{status}, %{message} =item B<--critical-status> Set critical threshold for status (Default: '%{message} !~ /authentification succeeded/i' Can used special variables like: %{status}, %{message} =item B<--warning-time> Threshold warning in seconds. =item B<--critical-time> Threshold critical in seconds. =back =cut centreon-plugins-20220113/apps/protocols/ssh/plugin.pm000066400000000000000000000025231417000230700226560ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::ssh::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} = { 'login' => 'apps::protocols::ssh::mode::login' }; $self->{custom_modes}->{api} = 'centreon::common::protocols::ssh::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check a SSH server. Need Libssh perl: https://github.com/garnier-quentin/perl-libssh =cut centreon-plugins-20220113/apps/protocols/tcp/000077500000000000000000000000001417000230700210115ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/tcp/mode/000077500000000000000000000000001417000230700217355ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/tcp/mode/responsetime.pm000066400000000000000000000133771417000230700250230ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::tcp::mode::responsetime; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Time::HiRes qw(gettimeofday tv_interval); use IO::Socket::SSL; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf( 'Connection status on port %s is %s', $self->{result_values}->{port}, $self->{result_values}->{status} ); if ($self->{result_values}->{status} ne 'ok') { $msg .= ': ' . $self->{result_values}->{error_message}; } return $msg; } sub custom_time_output { my ($self, %options) = @_; return sprintf( "Response time on port %s is %.3fs", $self->{result_values}->{port}, $self->{result_values}->{response_time} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 } ]; $self->{maps_counters}->{global} = [ { label => 'status', type => 2, critical_default => '%{status} eq "failed"', display_ok => 0, set => { key_values => [ { name => 'status' }, { name => 'port' }, { name => 'error_message' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'time', nlabel => 'tcp.response.time.seconds', set => { key_values => [ { name => 'response_time' }, { name => 'port' } ], closure_custom_output => $self->can('custom_time_output'), perfdatas => [ { template => '%s', min => 0, unit => 's' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port', }, 'warning:s' => { name => 'warning', redirect => 'warning-tcp-response-time-seconds' }, 'critical:s' => { name => 'critical', redirect => 'critical-tcp-response-time-seconds' }, 'timeout:s' => { name => 'timeout', default => 3 }, 'ssl' => { name => 'ssl' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{hostname})) { $self->{output}->add_option_msg(short_msg => 'Please set the hostname option'); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{port})) { $self->{output}->add_option_msg(short_msg => 'Please set the port option'); $self->{output}->option_exit(); } } sub manage_selection { my ($self, %options) = @_; my $connection; my $timing0 = [gettimeofday]; if (defined($self->{option_results}->{ssl})) { $connection = IO::Socket::SSL->new( PeerAddr => $self->{option_results}->{hostname}, PeerPort => $self->{option_results}->{port}, Timeout => $self->{option_results}->{timeout}, ); } else { $connection = IO::Socket::INET->new( PeerAddr => $self->{option_results}->{hostname}, PeerPort => $self->{option_results}->{port}, Timeout => $self->{option_results}->{timeout}, ); } my $timeelapsed = tv_interval($timing0, [gettimeofday]); $self->{global} = { port => $self->{option_results}->{port}, status => 'ok', response_time => $timeelapsed, error_message => '' }; if (!defined($connection)) { $self->{global}->{status} = 'failed'; my $append = ''; if (defined($!) && $! ne '') { $self->{global}->{error_message} = "error=$!"; $append = ', '; } $self->{global}->{error_message} .= "${append}ssl_error=$SSL_ERROR" if (defined($SSL_ERROR)); } close($connection) if (defined($connection)); } 1; __END__ =head1 MODE Check TCP connection time =over 8 =item B<--hostname> IP Addr/FQDN of the host =item B<--port> Port used =item B<--ssl> Use SSL connection. (no attempt is made to check the certificate validity by default). =item B<--timeout> Connection timeout in seconds (Default: 3) =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{status}, %{port}, %{error_message} =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{status}, %{port}, %{error_message} =item B<--critical-status> Set critical threshold for status (Default: '%{status} eq "failed"'). Can used special variables like: %{status}, %{port}, %{error_message} =item B<--warning-time> Threshold warning in seconds =item B<--critical-time> Threshold critical in seconds =back =cut centreon-plugins-20220113/apps/protocols/tcp/plugin.pm000066400000000000000000000023201417000230700226420ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::tcp::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} = '0.1'; %{$self->{modes}} = ( 'response-time' => 'apps::protocols::tcp::mode::responsetime', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check TCP port. =cut centreon-plugins-20220113/apps/protocols/telnet/000077500000000000000000000000001417000230700215165ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/telnet/mode/000077500000000000000000000000001417000230700224425ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/telnet/mode/scenario.pm000066400000000000000000000155101417000230700246050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::telnet::mode::scenario; use base qw(centreon::plugins::mode); use strict; use warnings; use Time::HiRes qw(gettimeofday tv_interval); use JSON; use Net::Telnet; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "scenario:s" => { name => 'scenario' }, "warning:s" => { name => 'warning' }, "critical:s" => { name => 'critical' }, "hostname:s" => { name => 'hostname' }, "port:s" => { name => 'port', default => 23 }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); # Example of a scenario file: # [ # {"cmd": "open", "options": { "Host": "10.0.0.1", "Port": "23", "Timeout": "30" } }, # {"cmd": "login", "options": { "Name": "admin", "Password": "pass", "Timeout": "5" } }, # {"cmd": "waitfor", "options": { "Match": "/string/", "Timeout": "5" } }, # {"cmd": "put", "options": { "String": "mystring", "Timeout": "5" } }, # {"cmd": "close" } #] if (!defined($self->{option_results}->{scenario})) { $self->{output}->add_option_msg(short_msg => "Please specify a scenario file."); $self->{output}->option_exit(); } 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 read_scenario { my ($self, %options) = @_; my $content_scenario; if (-f $self->{option_results}->{scenario}) { $content_scenario = do { local $/ = undef; if (!open my $fh, "<", $self->{option_results}->{scenario}) { $self->{output}->add_option_msg(short_msg => "Could not open file $self->{option_results}->{scenario} : $!"); $self->{output}->option_exit(); } <$fh>; }; } else { $content_scenario = $self->{option_results}->{scenario}; } eval { $self->{json_scenario} = decode_json($content_scenario); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json scenario"); $self->{output}->option_exit(); } } sub execute_scenario { my ($self, %options) = @_; my $timing0 = [gettimeofday]; my $session = new Net::Telnet(); $session->errmode('return'); if (defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '') { if (!$session->open(Host => $self->{option_results}->{hostname}, Port => $self->{option_results}->{port}, Timeout => 30)) { $self->{output}->output_add(severity => 'critical', short_msg => sprintf("cannot open session: %s", $session->errmsg())); return ; } } my ($step_ok, $exit1) = (0, 'OK'); my $step_total = scalar(@{$self->{json_scenario}}); foreach my $cmd (@{$self->{json_scenario}}) { next if (!defined($cmd->{cmd})); if ($cmd->{cmd} !~ /^(open|login|waitfor|put|close)$/i) { $self->{output}->add_option_msg(short_msg => "command '$cmd->{cmd}' is not managed"); $self->{output}->option_exit(); } my $cmd_name = lc($cmd->{cmd}); my $method = $session->can($cmd_name); if ($method) { my $ret = $method->($session, defined($cmd->{options}) ? %{$cmd->{options}} : undef); if (!defined($ret)) { $self->{output}->output_add(long_msg => sprintf("errmsg: %s", $session->errmsg())); $exit1 = 'CRITICAL'; last; } } $step_ok++; } my $timeelapsed = tv_interval($timing0, [gettimeofday]); 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 ]); $self->{output}->output_add(severity => $exit, short_msg => sprintf("%d/%d steps (%.3fs)", $step_ok, $step_total, $timeelapsed)); $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 => $step_ok, min => 0, max => $step_total); } sub run { my ($self, %options) = @_; $self->read_scenario(); $self->execute_scenario(); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check telnet scenario execution =over 8 =item B<--scenario> Scenario used (Required). Can be a file or json content. =item B<--timeout> Set global execution timeout (Default: 50) =item B<--hostname> Set telnet hostname. Could be used if you want to use the same scenario for X hosts. =item B<--port> Set telnet port. Could be used if you want to use the same scenario for X hosts. =item B<--warning> Threshold warning in seconds (Scenario execution time) =item B<--critical> Threshold critical in seconds (Scenario execution time) =back =cut centreon-plugins-20220113/apps/protocols/telnet/plugin.pm000066400000000000000000000023231417000230700233520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::telnet::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} = '0.1'; %{$self->{modes}} = ( 'scenario' => 'apps::protocols::telnet::mode::scenario', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check telnet server. =cut centreon-plugins-20220113/apps/protocols/tftp/000077500000000000000000000000001417000230700212005ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/tftp/mode/000077500000000000000000000000001417000230700221245ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/tftp/mode/commands.pm000066400000000000000000000170231417000230700242660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::tftp::mode::commands; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); use Net::TFTP; use Time::HiRes qw(gettimeofday tv_interval); 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} . '_status'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'command', type => 1, cb_prefix_output => 'prefix_command_output', message_multiple => 'All commands are ok' } ]; $self->{maps_counters}->{command} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { 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 => \&catalog_status_threshold } }, { label => 'time', display_ok => 0, set => { key_values => [ { name => 'timeelapsed' }, { name => 'display' } ], output_template => 'response time %.3fs', perfdatas => [ { label => 'time', value => 'timeelapsed', template => '%.3f', min => 0, unit => 's', label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "hostname:s" => { name => 'hostname' }, "port:s" => { name => 'port', default => 69 }, "timeout:s" => { name => 'timeout', default => 5 }, "retries:s" => { name => 'retries', default => 5 }, "block-size:s" => { name => 'block_size', default => 512 }, "warning-status:s" => { name => 'warning_status', default => '' }, "critical-status:s" => { name => 'critical_status', default => '%{status} ne "ok"' }, "command:s@" => { name => 'command' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); if (!defined($self->{option_results}->{hostname}) || $self->{option_results}->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Please set the --hostname option"); $self->{output}->option_exit(); } $self->{option_results}->{command} = [] if (!defined($self->{option_results}->{command})); } sub prefix_command_output { my ($self, %options) = @_; return "Command '" . $options{instance_value}->{display} . "' "; } sub put_command { my ($self, %options) = @_; my $status = 'ok'; if (!$options{tftp}->put($options{localfile}, $options{remotefile})) { $status = $options{tftp}->error; } return $status; } sub get_command { my ($self, %options) = @_; my ($status, $stdout); { local *STDOUT; open STDOUT, '>', \$stdout; if (!$options{tftp}->get($options{remotefile}, \*STDOUT)) { $status = $options{tftp}->error; } else { $status = 'ok'; } } return $status; } sub manage_selection { my ($self, %options) = @_; my $tftp = Net::TFTP->new( $self->{option_results}->{hostname}, Timeout => $self->{option_results}->{timeout}, Retries => $self->{option_results}->{retries}, Port => $self->{option_results}->{port}, BlockSize => $self->{option_results}->{block_size}, ); $self->{command} = {}; my $i = 0; foreach (@{$self->{option_results}->{command}}) { my ($label, $command, $arg1, $arg2) = split /,/; if (!defined($command) || $command !~ /(put|get)/) { $self->{output}->add_option_msg(short_msg => "Unknown command. Please use 'get' or 'put' command name"); $self->{output}->option_exit(); } $i++; $command = $1; $label = $i if (!defined($label) || $label eq ''); if (!defined($arg1) || $arg1 eq '') { $self->{output}->add_option_msg(short_msg => "Unknown first argument. first argument is required."); $self->{output}->option_exit(); } if ($command eq 'put' && (!defined($arg2) || $arg2 eq '')) { $self->{output}->add_option_msg(short_msg => "Unknown second argument. second argument is required for 'put' command."); $self->{output}->option_exit(); } my $status; my $timing0 = [gettimeofday]; if ($command eq 'put') { $status = $self->put_command(tftp => $tftp, localfile => $arg1, remotefile => $arg2); } else { $status = $self->get_command(tftp => $tftp, remotefile => $arg1); } my $timeelapsed = tv_interval($timing0, [gettimeofday]); $self->{command}->{$i} = { display => $label, status => $status, timeelapsed => $timeelapsed, }; } if (scalar(keys %{$self->{command}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No command found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check tftp commands. =over 8 =item B<--hostname> TFTP server name (required). =item B<--port> TFTP port (Default: 69). =item B<--timeout> TFTP timeout in seconds (Default: 5). =item B<--retries> TFTP number of retries (Default: 5). =item B<--block-size> TFTP size of blocks to use in the transfer (Default: 512). =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^status$' =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{display} =item B<--critical-status> Set critical threshold for status (Default: '%{status} ne "ok"'). Can used special variables like: %{status}, %{display} =item B<--warning-time> Threshold warning. =item B<--critical-time> Threshold critical. =item B<--command> TFP command. Example: --command='labeldisplay,get,remotefile' --command='labeldisplay2,put,localfile,remotefile" =back =cut centreon-plugins-20220113/apps/protocols/tftp/plugin.pm000066400000000000000000000023201417000230700230310ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::tftp::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} = '0.1'; %{$self->{modes}} = ( 'commands' => 'apps::protocols::tftp::mode::commands', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check an TFTP server. =cut centreon-plugins-20220113/apps/protocols/udp/000077500000000000000000000000001417000230700210135ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/udp/mode/000077500000000000000000000000001417000230700217375ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/udp/mode/connection.pm000066400000000000000000000102741417000230700244400ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::udp::mode::connection; use base qw(centreon::plugins::mode); use strict; use warnings; use IO::Socket::INET; use IO::Select; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'timeout:s' => { name => 'timeout', default => '3' } }); 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}->{hostname})) { $self->{output}->add_option_msg(short_msg => "Need to specify '--hostname' option"); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{port}) || $self->{option_results}->{port} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify '--port' option"); $self->{output}->option_exit(); } $self->{option_results}->{port} = $self->{option_results}->{port} =~ /(\d+)/ ? $1 : -1; if ($self->{option_results}->{port} < 0 || $self->{option_results}->{port} > 65535) { $self->{output}->add_option_msg(short_msg => 'Illegal port number (allowed range: 1-65535)'); $self->{output}->option_exit(); } } sub run { my ($self, %options) = @_; my $icmp_sock = new IO::Socket::INET(Proto => "icmp"); if (!defined($icmp_sock)) { $self->{output}->add_option_msg(short_msg => "Cannot create socket: $!"); $self->{output}->option_exit(); } my $read_set = new IO::Select(); $read_set->add($icmp_sock); my $sock = IO::Socket::INET->new( PeerAddr => $self->{option_results}->{hostname}, PeerPort => $self->{option_results}->{port}, Proto => 'udp', ); $sock->send("Hello"); close($sock); my ($new_readable) = IO::Select->select($read_set, undef, undef, $self->{option_results}->{timeout}); my $icmp_arrived = 0; foreach $sock (@$new_readable) { if ($sock == $icmp_sock) { $icmp_arrived = 1; $icmp_sock->recv(my $buffer,50,0); } } close($icmp_sock); if ($icmp_arrived == 1) { $self->{output}->output_add( severity => 'CRITICAL', short_msg => sprintf("Connection failed on port %s", $self->{option_results}->{port}) ); } else { $self->{output}->output_add( severity => 'OK', short_msg => sprintf("Connection success on port %s", $self->{option_results}->{port}) ); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check UDP connection =over 8 =item B<--hostname> IP Addr/FQDN of the host =item B<--port> Port used =item B<--timeout> Connection timeout in seconds (Default: 3) =back =cut centreon-plugins-20220113/apps/protocols/udp/plugin.pm000066400000000000000000000023031417000230700226450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::udp::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} = '0.1'; $self->{modes} = { 'connection' => 'apps::protocols::udp::mode::connection' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check UDP port. =cut centreon-plugins-20220113/apps/protocols/x509/000077500000000000000000000000001417000230700207305ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/x509/custom/000077500000000000000000000000001417000230700222425ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/x509/custom/file.pm000066400000000000000000000121241417000230700235170ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::x509::custom::file; use strict; use warnings; use centreon::plugins::http; use Socket; use Net::SSLeay 1.42; use DateTime; 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 => { 'certificate:s' => { name => 'certificate' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'CUSTOM FILE OPTIONS', once => 1); $self->{output} = $options{output}; return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{option_results}->{certificate} = (defined($self->{option_results}->{certificate})) ? $self->{option_results}->{certificate} : ''; if ($self->{option_results}->{certificate} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify certificate option."); $self->{output}->option_exit(); } return 0; } sub read_pem { my ($self, %options) = @_; my $bio_cert = Net::SSLeay::BIO_new_file($self->{option_results}->{certificate}, 'rb'); if (!$bio_cert) { return (undef, 'Cannot read file'); } my $x509 = Net::SSLeay::PEM_read_bio_X509($bio_cert); if (!$x509) { return (undef, 'Cannot read certificate'); } Net::SSLeay::BIO_free($bio_cert); return $x509; } sub read_der { my ($self, %options) = @_; my $bio_cert = Net::SSLeay::BIO_new_file($self->{option_results}->{certificate}, 'rb'); if (!$bio_cert) { return (undef, 'Cannot read file'); } my $x509 = Net::SSLeay::d2i_X509_bio($bio_cert); if (!$x509) { return (undef, 'Cannot read certificate'); } Net::SSLeay::BIO_free($bio_cert); return $x509; } sub read_certificate { my ($self, %options) = @_; my ($x509, $message) = $self->read_pem(); if (!defined($x509)) { ($x509, $message) = $self->read_der(); } if (!defined($x509)) { $self->{output}->output_add(long_msg => Net::SSLeay::print_errs(), debug => 1); $self->{output}->add_option_msg(short_msg => $message); $self->{output}->option_exit(); } my $cert_infos = {}; $cert_infos->{issuer} = Net::SSLeay::X509_NAME_oneline(Net::SSLeay::X509_get_issuer_name($x509)); $cert_infos->{expiration_date} = Net::SSLeay::P_ASN1_TIME_get_isotime(Net::SSLeay::X509_get_notAfter($x509)); my $subject = Net::SSLeay::X509_NAME_oneline(Net::SSLeay::X509_get_subject_name($x509)); if ($subject =~ /CN=(.*?)(?:\/(?:C|ST|L|O)=|\Z)/) { $cert_infos->{subject} = $1; } my @subject_alt_names = Net::SSLeay::X509_get_subjectAltNames($x509); my $append = ''; $cert_infos->{alt_subjects} = ''; for (my $i = 0; $i < $#subject_alt_names; $i += 2) { my ($type, $name) = ($subject_alt_names[$i], $subject_alt_names[$i + 1]); if ($type == &Net::SSLeay::GEN_IPADD) { $name = Socket::inet_ntop(length($name) > 4 ? Socket::AF_INET6 : Socket::AF_INET, $name); } $cert_infos->{alt_subjects} .= $append . $name; $append = ', '; } $cert_infos->{expiration_date} =~ /^(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)Z$/; # 2033-05-16T20:39:37Z my $dt = DateTime->new(year => $1, month => $2, day => $3, hour => $4, minute => $5, second => $6); $cert_infos->{expiration} = $dt->epoch(); return $cert_infos; } sub get_certificate_informations { my ($self, %options) = @_; if (! -r $self->{option_results}->{certificate}) { $self->{output}->add_option_msg(short_msg => "Cannot read file '$self->{option_results}->{certificate}': $!"); $self->{output}->option_exit(); } my $cert_infos = $self->read_certificate(); return $cert_infos; } 1; __END__ =head1 NAME certificate file =head1 CUSTOM FILE OPTIONS certificate file =over 8 =item B<--certificate> Certificate file (PEM or DER). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/protocols/x509/custom/https.pm000066400000000000000000000162271417000230700237520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::x509::custom::https; use strict; use warnings; use centreon::plugins::http; use Net::SSLeay 1.42; use DateTime; use Socket; 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port', }, 'method:s' => { name => 'method' }, 'urlpath:s' => { name => 'url_path' }, 'timeout:s' => { name => 'timeout' }, 'header:s@' => { name => 'header' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'CUSTOM HTTPS OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{option_results}->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{option_results}->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{option_results}->{proto} = 'https'; $self->{option_results}->{url_path} = (defined($self->{option_results}->{url_path})) ? $self->{option_results}->{url_path} : '/'; $self->{option_results}->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 5; if ($self->{option_results}->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify hostname option."); $self->{output}->option_exit(); } $self->{http}->set_options(%{$self->{option_results}}); return 0; } sub pem_type { my ($self, %options) = @_; my $bio_cert = Net::SSLeay::BIO_new(Net::SSLeay::BIO_s_mem()); if (!$bio_cert) { $self->{output}->add_option_msg(short_msg => "Cannot init Net::SSLeay: $!"); $self->{output}->option_exit(); } if (Net::SSLeay::BIO_write($bio_cert, $options{cert}) < 0) { Net::SSLeay::BIO_free($bio_cert); $self->{output}->add_option_msg(short_msg => "Cannot write certificate: $!"); $self->{output}->option_exit(); } my $x509 = Net::SSLeay::PEM_read_bio_X509($bio_cert); Net::SSLeay::BIO_free($bio_cert); if (!$x509) { $self->{output}->add_option_msg(short_msg => "Cannot read certificate: $!"); $self->{output}->option_exit(); } my $cert_infos = {}; $cert_infos->{issuer} = Net::SSLeay::X509_NAME_oneline(Net::SSLeay::X509_get_issuer_name($x509)); $cert_infos->{expiration_date} = Net::SSLeay::P_ASN1_TIME_get_isotime(Net::SSLeay::X509_get_notAfter($x509)); my $subject = Net::SSLeay::X509_NAME_oneline(Net::SSLeay::X509_get_subject_name($x509)); if ($subject =~ /CN=(.*?)(?:\/(?:C|ST|L|O)=|\Z)/) { $cert_infos->{subject} = $1; } my @subject_alt_names = Net::SSLeay::X509_get_subjectAltNames($x509); my $append = ''; $cert_infos->{alt_subjects} = ''; for (my $i = 0; $i < $#subject_alt_names; $i += 2) { my ($type, $name) = ($subject_alt_names[$i], $subject_alt_names[$i + 1]); if ($type == &Net::SSLeay::GEN_IPADD) { $name = Socket::inet_ntop(length($name) > 4 ? Socket::AF_INET6 : Socket::AF_INET, $name); } $cert_infos->{alt_subjects} .= $append . $name; $append = ', '; } $cert_infos->{expiration_date} =~ /^(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)Z$/; # 2033-05-16T20:39:37Z my $dt = DateTime->new(year => $1, month => $2, day => $3, hour => $4, minute => $5, second => $6); $cert_infos->{expiration} = $dt->epoch(); return $cert_infos; } sub socket_type { my ($self, %options) = @_; my $cert_infos = {}; $cert_infos->{subject} = $options{socket}->peer_certificate('commonName'); $cert_infos->{issuer} = $options{socket}->peer_certificate('authority'); my @subject_alt_names = $options{socket}->peer_certificate('subjectAltNames'); my $append = ''; $cert_infos->{alt_subjects} = ''; for (my $i = 0; $i < $#subject_alt_names; $i += 2) { my ($type, $name) = ($subject_alt_names[$i], $subject_alt_names[$i + 1]); if ($type == &Net::SSLeay::GEN_IPADD) { $name = Socket::inet_ntop(length($name) > 4 ? Socket::AF_INET6 : Socket::AF_INET, $name); } $cert_infos->{alt_subjects} .= $append . $name; $append = ', '; } $cert_infos->{expiration_date} = Net::SSLeay::P_ASN1_TIME_get_isotime(Net::SSLeay::X509_get_notAfter($options{socket}->peer_certificate())); $cert_infos->{expiration_date} =~ /^(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)Z$/; # 2033-05-16T20:39:37Z my $dt = DateTime->new(year => $1, month => $2, day => $3, hour => $4, minute => $5, second => $6); $cert_infos->{expiration} = $dt->epoch(); return $cert_infos; } sub get_certificate_informations { my ($self, %options) = @_; $self->{http}->request( certinfo => 1, unknown_status => '', warning_status => '', critical_status => '' ); my ($type, $cert) = $self->{http}->get_certificate(); if (!defined($cert)) { $self->{output}->add_option_msg(short_msg => $self->{http}->get_message()); $self->{output}->option_exit(); } my $cert_infos; if ($type eq 'pem') { $cert_infos = $self->pem_type(cert => $cert); } elsif ($type eq 'socket') { $cert_infos = $self->socket_type(socket => $cert); } return $cert_infos; } 1; __END__ =head1 NAME http connection =head1 CUSTOM HTTPS OPTIONS http connection =over 8 =item B<--hostname> IP Addr/FQDN of the webserver host =item B<--port> Port used by Webserver (Default: 443) =item B<--method> Specify http method used (Default: 'GET') =item B<--urlpath> Set path to get webpage (Default: '/') =item B<--timeout> Threshold for HTTP timeout (Default: 5) =item B<--header> Set HTTP headers (Multiple option) =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/protocols/x509/custom/tcp.pm000066400000000000000000000210461417000230700233710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::x509::custom::tcp; use base qw(centreon::plugins::mode); use strict; use warnings; use Socket; use IO::Socket::INET; use IO::Socket::SSL; use Net::SSLeay 1.42; use DateTime; 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'servername:s' => { name => 'servername' }, 'ssl-opt:s@' => { name => 'ssl_opt' }, 'ssl-ignore-errors' => { name => 'ssl_ignore_errors' }, 'timeout:s' => { name => 'timeout', default => 3 }, 'starttls:s' => { name => 'starttls' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'CUSTOM TCP OPTIONS', once => 1); $self->{output} = $options{output}; return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) && $self->{option_results}->{port} =~ /(\d+)/ ? $1 : ''; $self->{timeout} = (defined($self->{option_results}->{timeout})) && $self->{option_results}->{timeout} =~ /(\d+)/ ? $1 : 3; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --hostname option.'); $self->{output}->option_exit(); } if ($self->{port} eq '') { $self->{output}->add_option_msg(short_msg => "Please set --port option"); $self->{output}->option_exit(); } my $append = ''; foreach (@{$self->{option_results}->{ssl_opt}}) { if ($_ ne '') { $self->{ssl_context} .= $append . $_; $append = ', '; } } return 0; } sub connect_ssl { my ($self, %options) = @_; my $socket; eval { $socket = IO::Socket::SSL->new( PeerHost => $self->{option_results}->{hostname}, PeerPort => $self->{option_results}->{port}, $self->{option_results}->{servername} ? ( SSL_hostname => $self->{option_results}->{servername} ) : (), $self->{option_results}->{timeout} ? ( Timeout => $self->{option_results}->{timeout} ) : () ); }; if ($@) { $self->{output}->add_option_msg(short_msg => sprintf("%s", $@)); $self->{output}->option_exit(); } if (!defined($socket)) { $self->{output}->add_option_msg(short_msg => "Error creating SSL socket: $!, SSL error: $SSL_ERROR"); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{ssl_ignore_errors}) && defined($SSL_ERROR)) { $self->{output}->add_option_msg(short_msg => "SSL error: $SSL_ERROR"); $self->{output}->option_exit(); } return $socket; } sub smtp_plain_com { my ($self, %options) = @_; my $buffer; $options{socket}->recv($buffer, 1024); $options{socket}->send("HELO\r\n"); $options{socket}->recv($buffer, 1024); $options{socket}->send("STARTTLS\r\n"); $options{socket}->recv($buffer, 1024); if ($buffer !~ /^220\s/) { $self->{output}->add_option_msg(short_msg => "Cannot starttls: $buffer"); $self->{output}->option_exit(); } } sub ftp_plain_com { my ($self, %options) = @_; my $buffer; $options{socket}->recv($buffer, 1024); $options{socket}->send("AUTH TLS\r\n"); $options{socket}->recv($buffer, 1024); if ($buffer !~ /^234\s/) { $self->{output}->add_option_msg(short_msg => "Cannot starttls: $buffer"); $self->{output}->option_exit(); } } sub connect_starttls { my ($self, %options) = @_; my $socket = IO::Socket::INET->new( PeerHost => $self->{option_results}->{hostname}, PeerPort => $self->{option_results}->{port}, $self->{option_results}->{timeout} ? ( Timeout => $self->{option_results}->{timeout} ) : () ); if (!defined($socket)) { $self->{output}->add_option_msg(short_msg => "Error creating socket: $!"); $self->{output}->option_exit(); } if ($self->{option_results}->{starttls} eq 'smtp') { $self->smtp_plain_com(socket => $socket); } elsif ($self->{option_results}->{starttls} eq 'ftp') { $self->ftp_plain_com(socket => $socket); } my $rv = IO::Socket::SSL->start_SSL( $socket, $self->{option_results}->{servername} ? ( SSL_hostname => $self->{option_results}->{servername} ) : () ); if (!defined($self->{option_results}->{ssl_ignore_errors}) && !$rv) { $self->{output}->add_option_msg(short_msg => "SSL error: $SSL_ERROR"); $self->{output}->option_exit(); } return $socket; } sub get_certificate_informations { my ($self, %options) = @_; if (defined($self->{ssl_context}) && $self->{ssl_context} ne '') { my $context = new IO::Socket::SSL::SSL_Context(eval $self->{ssl_context}); eval { IO::Socket::SSL::set_default_context($context) }; if ($@) { $self->{output}->add_option_msg(short_msg => sprintf("Error setting SSL context: %s", $@)); $self->{output}->option_exit(); } } my $socket; if (defined($self->{option_results}->{starttls})) { $socket = $self->connect_starttls(); } else { $socket = $self->connect_ssl(); } my $cert_infos = {}; $cert_infos->{subject} = $socket->peer_certificate('commonName'); $cert_infos->{issuer} = $socket->peer_certificate('authority'); my @subject_alt_names = $socket->peer_certificate('subjectAltNames'); my $append = ''; $cert_infos->{alt_subjects} = ''; for (my $i = 0; $i < $#subject_alt_names; $i += 2) { my ($type, $name) = ($subject_alt_names[$i], $subject_alt_names[$i + 1]); if ($type == GEN_IPADD) { $name = Socket::inet_ntop(length($name) > 4 ? Socket::AF_INET6 : Socket::AF_INET, $name); } $cert_infos->{alt_subjects} .= $append . $name; $append = ', '; } $cert_infos->{expiration_date} = Net::SSLeay::P_ASN1_TIME_get_isotime(Net::SSLeay::X509_get_notAfter($socket->peer_certificate())); $cert_infos->{expiration_date} =~ /^(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)Z$/; # 2033-05-16T20:39:37Z my $dt = DateTime->new(year => $1, month => $2, day => $3, hour => $4, minute => $5, second => $6); $cert_infos->{expiration} = $dt->epoch(); return $cert_infos; } 1; __END__ =head1 NAME tcp ssl connections =head1 CUSTOM TCP OPTIONS tcp ssl connection =over 8 =item B<--hostname> IP Addr/FQDN of the host. =item B<--port> Port used by host. =item B<--servername> Servername of the host for SNI support (only with IO::Socket::SSL >= 1.56) (eg: foo.bar.com). =item B<--ssl-opt> Set SSL options. Examples: Do not verify certificate: --ssl-opt="SSL_verify_mode => SSL_VERIFY_NONE" Verify certificate: --ssl-opt="SSL_verify_mode => SSL_VERIFY_PEER" --ssl-opt="SSL_version => TLSv1" =item B<--ssl-ignore-errors> Ignore SSL handshake errors. For example: 'SSL error: SSL wants a read first'. =item B<--timeout> Set timeout in seconds for SSL connection (Default: '3') (only with IO::Socket::SSL >= 1.984). =item B<--starttls> Init plaintext connection and start_SSL after. Can be: 'smtp', 'ftp'. =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/protocols/x509/mode/000077500000000000000000000000001417000230700216545ustar00rootroot00000000000000centreon-plugins-20220113/apps/protocols/x509/mode/certificate.pm000066400000000000000000000104201417000230700244710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::x509::mode::certificate; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf( "Certificate for '%s' expires in '%d' days [%s] - Issuer: '%s'", $self->{result_values}->{subject}, $self->{result_values}->{expiration}, $self->{result_values}->{date}, $self->{result_values}->{issuer} ); if (defined($self->{result_values}->{alt_subjects}) && $self->{result_values}->{alt_subjects} ne '') { $self->{output}->output_add(long_msg => sprintf("Alternative subject names: %s.", $self->{result_values}->{alt_subjects})); } return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{subject} = $options{new_datas}->{$self->{instance} . '_subject'}; $self->{result_values}->{issuer} = $options{new_datas}->{$self->{instance} . '_issuer'}; $self->{result_values}->{expiration} = ($options{new_datas}->{$self->{instance} . '_expiration'} - time()) / 86400; $self->{result_values}->{date} = $options{new_datas}->{$self->{instance} . '_date'}; $self->{result_values}->{alt_subjects} = $options{new_datas}->{$self->{instance} . '_alt_subjects'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 } ]; $self->{maps_counters}->{global} = [ { label => 'status', type => 2, warning_default => '%{expiration} < 60', critical_default => '%{expiration} < 30', set => { key_values => [ { name => 'subject' }, { name => 'issuer' }, { name => 'expiration' }, { name => 'date' }, { name => 'alt_subjects' } ], 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 => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $cert = $options{custom}->get_certificate_informations(); $self->{global} = { subject => defined($cert->{subject}) ? $cert->{subject} : '-', issuer => defined($cert->{issuer}) ? $cert->{issuer} : '-', expiration => $cert->{expiration}, date => $cert->{expiration_date}, alt_subjects => $cert->{alt_subjects} }; } 1; __END__ =head1 MODE Check X509's certificate validity (for SMTPS, POPS, IMAPS, HTTPS) =over 8 =item B<--warning-status> Set warning threshold for status. (Default: '%{expiration} < 60'). Can use special variables like: %{expiration}, %{subject}, %{issuer}, %{alt_subjects}. =item B<--critical-status> Set critical threshold for status. (Default: '%{expiration} < 30'). Can use special variables like: %{expiration}, %{subject}, %{issuer}, %{alt_subjects}. Examples : Raise a critical alarm if certificate expires in less than 30 days or does not cover alternative name 'my.app.com' --critical-status='%{expiration} < 30 || %{alt_subjects} !~ /my.app.com/' =back =cut centreon-plugins-20220113/apps/protocols/x509/plugin.pm000066400000000000000000000026741417000230700225750ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::protocols::x509::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} = { 'certificate' => 'apps::protocols::x509::mode::certificate' }; $self->{custom_modes}->{tcp} = 'apps::protocols::x509::custom::tcp'; $self->{custom_modes}->{https} = 'apps::protocols::x509::custom::https'; $self->{custom_modes}->{file} = 'apps::protocols::x509::custom::file'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check X509's certificate validity. =cut centreon-plugins-20220113/apps/proxmox/000077500000000000000000000000001417000230700177135ustar00rootroot00000000000000centreon-plugins-20220113/apps/proxmox/mg/000077500000000000000000000000001417000230700203165ustar00rootroot00000000000000centreon-plugins-20220113/apps/proxmox/mg/restapi/000077500000000000000000000000001417000230700217655ustar00rootroot00000000000000centreon-plugins-20220113/apps/proxmox/mg/restapi/custom/000077500000000000000000000000001417000230700232775ustar00rootroot00000000000000centreon-plugins-20220113/apps/proxmox/mg/restapi/custom/api.pm000066400000000000000000000222721417000230700244130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Authors : Roman Morandell - ivertix # package apps::proxmox::mg::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use centreon::plugins::statefile; use JSON::XS; use Digest::MD5 qw(md5_hex); 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'url-path:s' => { name => 'url_path' }, 'api-username:s' => { name => 'api_username' }, 'api-password:s' => { name => 'api_password' }, 'realm:s' => { name => 'realm' }, 'timeout:s' => { name => 'timeout' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); $self->{cache} = centreon::plugins::statefile->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 8006; $self->{url_path} = (defined($self->{option_results}->{url_path})) ? $self->{option_results}->{url_path} : '/api2/json'; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : ''; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : ''; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 30; $self->{realm} = (defined($self->{option_results}->{realm})) ? $self->{option_results}->{realm} : 'pmg'; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300' ; $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify hostname option.'); $self->{output}->option_exit(); } if ($self->{api_username} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-username option."); $self->{output}->option_exit(); } if ($self->{api_password} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-password option."); $self->{output}->option_exit(); } $self->{cache}->check_options(option_results => $self->{option_results}); return 0; } sub get_connection_infos { my ($self, %options) = @_; return $self->{hostname} . '_' . $self->{http}->get_port(); } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub get_port { my ($self, %options) = @_; return $self->{port}; } sub json_decode { my ($self, %options) = @_; $options{content} =~ s/\r//mg; my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($options{content}); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } return $decoded; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->set_options(%{$self->{option_results}}); } sub clean_session { my ($self, %options) = @_; my $datas = {}; $options{statefile}->write(data => $datas); $self->{cookie_id} = undef; $self->{cookie_user} = undef; } sub get_session { my ($self, %options) = @_; my $has_cache_file = $options{statefile}->read(statefile => 'proxmox_mg_' . md5_hex($self->{option_results}->{hostname}) . '_' . md5_hex($self->{option_results}->{api_username})); my $cookie_id = $options{statefile}->get(name => 'cookie_id'); if ($has_cache_file == 0 || !defined($cookie_id)) { my ($content) = $self->{http}->request( method => 'POST', url_path => $self->{url_path} . '/access/ticket', post_param => [ 'username=' . $self->{api_username}, 'password=' . $self->{api_password}, 'realm=' . $self->{realm} ], warning_status => '', unknown_status => '', critical_status => '' ); if ($self->{http}->get_code() != 200) { $self->{output}->add_option_msg(short_msg => "Authentication error [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded = $self->json_decode(content => $content); if (!defined($decoded->{data}->{ticket})) { $self->{output}->add_option_msg(short_msg => "Cannot get token"); $self->{output}->option_exit(); } $cookie_id = $decoded->{data}->{ticket}; $options{statefile}->write(data => { cookie_id => $cookie_id }); } $self->{cookie_id} = $cookie_id; } sub request { my ($self, %options) = @_; my $endpoint = $options{full_endpoint}; if (!defined($endpoint)) { $endpoint = $self->{url_path} . $options{endpoint}; } $self->settings(); if (!defined($self->{access_token})) { $self->get_session(statefile => $self->{cache}); } my $content = $self->{http}->request( method => 'GET', url_path => $endpoint, get_param => $options{get_param}, header => [ 'Cookie: PMGAuthCookie=' . $self->{cookie_id} ], warning_status => '', unknown_status => '', critical_status => '' ); # Maybe there is an issue with the token. So we retry. if ($self->{http}->get_code() < 200 || $self->{http}->get_code() >= 300) { $self->clean_session(statefile => $self->{cache}); $self->get_session(statefile => $self->{cache}); $content = $self->{http}->request( url_path => $endpoint, get_param => $options{get_param}, header => [ 'Cookie: PMGAuthCookie=' . $self->{cookie_id} ], unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status} ); } my $decoded = $self->json_decode(content => $content); if (!defined($decoded)) { $self->{output}->add_option_msg(short_msg => 'Error while retrieving data (add --debug option for detailed message)'); $self->{output}->option_exit(); } return $decoded; } 1; __END__ =head1 NAME Proxmog Media Gateway API =head1 SYNOPSIS Proxmog Media Gateway api =head1 REST API OPTIONS =over 8 =item B<--hostname> API hostname. =item B<--url-path> API url path (Default: '/api2/json') =item B<--port> API port (Default: 8806) =item B<--proto> Specify https if needed (Default: 'https') =item B<--api-username> Set API username =item B<--api-password> Set API password =item B<--realm> Set user realm (Default: 'pmg') =item B<--timeout> Set HTTP timeout =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/proxmox/mg/restapi/mode/000077500000000000000000000000001417000230700227115ustar00rootroot00000000000000centreon-plugins-20220113/apps/proxmox/mg/restapi/mode/mail.pm000066400000000000000000000164401417000230700241760ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::proxmox::mg::restapi::mode::mail; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub mails_long_output { my ($self, %options) = @_; return 'checking mail statistics'; } sub prefix_mail_output { my ($self, %options) = @_; return 'number of mails '; } sub prefix_virus_output { my ($self, %options) = @_; return 'number of virus mails '; } sub prefix_spam_output { my ($self, %options) = @_; return 'number of spam mails '; } sub prefix_traffic_output { my ($self, %options) = @_; return 'traffic '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'mails', type => 3, cb_long_output => 'mails_long_output', indent_long_output => ' ', group => [ { name => 'mail', type => 0, display_short => 0, cb_prefix_output => 'prefix_mail_output', skipped_code => { -10 => 1 } }, { name => 'traffic', type => 0, display_short => 0, cb_prefix_output => 'prefix_traffic_output', skipped_code => { -10 => 1 } }, { name => 'spam', type => 0, display_short => 0, cb_prefix_output => 'prefix_spam_output', skipped_code => { -10 => 1 } }, { name => 'virus', type => 0, display_short => 0, cb_prefix_output => 'prefix_virus_output', skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{mail} = [ { label => 'mails-incoming', nlabel => 'mails.incoming.count', set => { key_values => [ { name => 'mail_in' } ], output_template => 'incoming: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'mails-outgoing', nlabel => 'mails.outgoing.count', set => { key_values => [ { name => 'mail_out' } ], output_template => 'outgoing: %s', perfdatas => [ { template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{traffic} = [ { label => 'traffic-in', nlabel => 'mails.traffic.in.bytespersecond', set => { key_values => [ { name => 'bytes_in_psec' } ], output_template => 'in: %.2f %s/s', output_change_bytes => 1, perfdatas => [ { template => '%.2f', unit => 'B/s', min => 0 } ] } }, { label => 'traffic-out', nlabel => 'mails.traffic.out.bytespersecond', set => { key_values => [ { name => 'bytes_out_psec' } ], output_template => 'out: %.2f %s/s', output_change_bytes => 1, perfdatas => [ { template => '%.2f', unit => 'B/s', min => 0 } ] } } ]; $self->{maps_counters}->{spam} = [ { label => 'spam-incoming', nlabel => 'mails.spam.incoming.count', set => { key_values => [ { name => 'spam_in' } ], output_template => 'incoming: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'spam-outgoing', nlabel => 'mails.spam.outgoing.count', set => { key_values => [ { name => 'spam_out' } ], output_template => 'outgoing: %s', perfdatas => [ { template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{virus} = [ { label => 'virus-incoming', nlabel => 'mails.virus.incoming.count', set => { key_values => [ { name => 'virus_in' } ], output_template => 'incoming: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'virus-outgoing', nlabel => 'mails.virus.outgoing.count', set => { key_values => [ { name => 'virus_out' } ], output_template => 'outgoing: %s', perfdatas => [ { template => '%s', min => 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 => { 'hours:s' => { name => 'hours', default => 12 }, 'timespan:s' => { name => 'timespan', default => 1800 } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $datas = $options{custom}->request( endpoint => '/statistics/recent', get_param => [ 'hours=' . $self->{option_results}->{hours}, 'timespan=' . $self->{option_results}->{timespan} ] ); my $result = { mail_in => 0, mail_out => 0, virus_in => 0, virus_out => 0, spam_in => 0, spam_out => 0, bytes_in => 0, bytes_out => 0 }; foreach (@{$datas->{data}}) { $result->{mail_in} += $_->{count_in}; $result->{mail_out} += $_->{count_out}; $result->{spam_in} += $_->{spam_in}; $result->{spam_out} += $_->{spam_out}; $result->{virus_in} += $_->{virus_in}; $result->{virus_out} += $_->{virus_out}; $result->{bytes_in} += $_->{bytes_in}; $result->{bytes_out} += $_->{bytes_out}; } $self->{output}->output_add(short_msg => 'Mail statistics are ok'); $self->{mails} = { global => { mail => { mail_in => $result->{mail_in}, mail_out => $result->{mail_out} }, spam => { spam_in => $result->{spam_in}, spam_out => $result->{spam_out} }, traffic => { bytes_in_psec => $result->{bytes_in} / ($self->{option_results}->{hours} * 3600), bytes_out_psec => $result->{bytes_out} / ($self->{option_results}->{hours} * 3600) }, virus => { virus_in => $result->{virus_in}, virus_out => $result->{virus_out} } } }; } 1; __END__ =head1 MODE Check mail statistics. =over 8 =item B<--hours> How many hours of statistics you want (Default: 12) =item B<--timespan> Timespan for datapoints in hours timeframe (Default: 1800) =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'virus-incoming', 'virus-outgoing', 'traffic-in', 'traffic-out', 'mails-incoming', 'mails-outgoing', 'spam-incoming', 'spam-outgoing'. =back =cut centreon-plugins-20220113/apps/proxmox/mg/restapi/mode/version.pm000066400000000000000000000055021417000230700247360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::proxmox::mg::restapi::mode::version; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_version_output { my ($self, %options) = @_; return sprintf( 'pmg version: %s [release: %s][repoid: %s]', $self->{result_values}->{version}, $self->{result_values}->{release}, $self->{result_values}->{repoid} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'version', type => 0 } ]; $self->{maps_counters}->{version} = [ { label => 'version', type => 2, set => { key_values => [ { name => 'version' }, { name => 'repoid' }, { name => 'release' } ], closure_custom_output => $self->can('custom_version_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->request(endpoint => '/version'); if (defined($result->{version})) { $self->{version} = $result->{version}; } elsif (defined($result->{data}) && defined($result->{data}->{version})) { $self->{version} = $result->{data}; } else { $self->{version} = { version => 'unknown', repoid => 'unknown', release => 'unknown' }; } } 1; __END__ =head1 MODE Check version. =over 8 =item B<--warning-version> Set warning threshold for version. Can used special variables like: %{version}, %{repoid}, %{release} =item B<--critical-version> Set critical threshold for version. Can used special variables like: %{version}, %{repoid}, %{release} =back =cut centreon-plugins-20220113/apps/proxmox/mg/restapi/plugin.pm000066400000000000000000000026301417000230700236220ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Authors : Roman Morandell - ivertix # package apps::proxmox::mg::restapi::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} = '1.0'; $self->{modes} = { 'mail' => 'apps::proxmox::mg::restapi::mode::mail', 'version' => 'apps::proxmox::mg::restapi::mode::version' }; $self->{custom_modes}->{api} = 'apps::proxmox::mg::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Proxmox Mail Gateway using Rest API. =cut centreon-plugins-20220113/apps/proxmox/ve/000077500000000000000000000000001417000230700203255ustar00rootroot00000000000000centreon-plugins-20220113/apps/proxmox/ve/restapi/000077500000000000000000000000001417000230700217745ustar00rootroot00000000000000centreon-plugins-20220113/apps/proxmox/ve/restapi/custom/000077500000000000000000000000001417000230700233065ustar00rootroot00000000000000centreon-plugins-20220113/apps/proxmox/ve/restapi/custom/api.pm000066400000000000000000000411701417000230700244200ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::proxmox::ve::restapi::custom::api; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::http; use centreon::plugins::statefile; use JSON::XS; use Digest::MD5 qw(md5_hex); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port'}, 'proto:s' => { name => 'proto' }, 'api-username:s' => { name => 'api_username' }, 'api-password:s' => { name => 'api_password' }, 'realm:s' => { name => 'realm' }, 'timeout:s' => { name => 'timeout' }, 'reload-cache-time:s' => { name => 'reload_cache_time', default => 7200 } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); $self->{cache} = centreon::plugins::statefile->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 8006; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : ''; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : ''; $self->{realm} = (defined($self->{option_results}->{realm})) ? $self->{option_results}->{realm} : 'pam'; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } if ($self->{api_username} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-username option."); $self->{output}->option_exit(); } if ($self->{api_password} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-password option."); $self->{output}->option_exit(); } $self->{cache}->check_options(option_results => $self->{option_results}); return 0; } sub get_port { my ($self, %options) = @_; return $self->{option_results}->{port}; } sub get_hostnames { my ($self, %options) = @_; return $self->{hostname}; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{warning_status} = ''; $self->{option_results}->{critical_status} = ''; $self->{option_results}->{unknown_status} = '%{http_code} < 200 or %{http_code} >= 300'; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->add_header(key => 'Content-Type', value => 'application/x-www-form-urlencoded'); if (defined($self->{ticket})) { $self->{http}->add_header(key => 'Cookie', value => 'PVEAuthCookie=' . $self->{ticket}); } $self->{http}->set_options(%{$self->{option_results}}); } sub get_ticket { my ($self, %options) = @_; my $has_cache_file = $options{statefile}->read(statefile => 'proxmox_ve_api_' . md5_hex($self->{option_results}->{hostname}) . '_' . md5_hex($self->{option_results}->{api_username})); my $expires_on = $options{statefile}->get(name => 'expires_on'); my $ticket = $options{statefile}->get(name => 'ticket'); if ($has_cache_file == 0 || !defined($ticket) || (($expires_on - time()) < 10)) { my $post_data = 'username=' . $self->{api_username} . '&password=' . $self->{api_password} . '&realm=' . $self->{realm}; $self->settings(); my $content = $self->{http}->request( method => 'POST', query_form_post => $post_data, url_path => '/api2/json/access/ticket' ); my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->output_add(long_msg => $content, debug => 1); $self->{output}->add_option_msg(short_msg => "Cannot decode json response"); $self->{output}->option_exit(); } if (!defined($decoded->{data}->{ticket})) { $self->{output}->output_add(long_msg => $content, debug => 1); $self->{output}->add_option_msg(short_msg => "Error retrieving ticket"); $self->{output}->option_exit(); } $ticket = $decoded->{data}->{ticket}; my $datas = { last_timestamp => time(), ticket => $ticket, expires_on => time() + 7200 }; $options{statefile}->write(data => $datas); } return $ticket; } sub request_api { my ($self, %options) = @_; if (!defined($self->{ticket})) { $self->{ticket} = $self->get_ticket(statefile => $self->{cache}); } $self->settings(); my $content = $self->{http}->request(%options); my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } if (!defined($decoded->{data})) { $self->{output}->add_option_msg(short_msg => "Error while retrieving data (add --debug option for detailed message)"); $self->{output}->option_exit(); } return $decoded->{data}; } sub get_version { my ($self, %options) = @_; my $content = $self->request_api(method => 'GET', url_path =>'/api2/json/version'); return $content->{version}; } sub internal_api_list_vms { my ($self, %options) = @_; my $vm = $self->request_api(method => 'GET', url_path =>'/api2/json/cluster/resources?type=vm'); return $vm; } sub api_list_vms { my ($self, %options) = @_; my $vms = {}; my $list_vms = $self->internal_api_list_vms(); foreach my $vm (@{$list_vms}) { my ($type, $vmid) = split(/\//,$vm->{id}); $vms->{$vm->{id}} = { State => $vm->{status}, Type => $type, Vmid => $vmid, Node => $vm->{node}, Name => $vm->{name}, }; } return $vms; } sub internal_api_list_nodes { my ($self, %options) = @_; my $nodes = $self->request_api(method => 'GET', url_path =>'/api2/json/cluster/resources?type=node'); return $nodes; } sub api_list_nodes { my ($self, %options) = @_; my $nodes = {}; my $list_nodes = $self->internal_api_list_nodes(); foreach my $node (@{$list_nodes}) { $nodes->{$node->{id}} = { State => $node->{status}, Name => $node->{node}, }; } return $nodes; } sub internal_api_list_storages { my ($self, %options) = @_; my $storage = $self->request_api(method => 'GET', url_path =>'/api2/json/cluster/resources?type=storage'); return $storage; } sub api_list_storages { my ($self, %options) = @_; my $storages = {}; my $list_storages = $self->internal_api_list_storages(); foreach my $storage (@{$list_storages}) { $storages->{$storage->{id}} = { State => $storage->{status}, Node => $storage->{node}, Name => $storage->{storage}, }; } return $storages; } sub cache_vms { my ($self, %options) = @_; my $has_cache_file = $options{statefile}->read(statefile => 'cache_proxmox_vm_'.$self->{hostname} . '_' . $self->{port}); my $timestamp_cache = $options{statefile}->get(name => 'last_timestamp'); my $vms = $options{statefile}->get(name => 'vms'); if ($has_cache_file == 0 || !defined($timestamp_cache) || ((time() - $timestamp_cache) > (($options{reload_cache_time})))) { $vms = {}; my $list_vms = $self->internal_api_list_vms(); foreach my $vm (@$list_vms) { $vms->{$vm->{id}} = { State => $vm->{status}, Node => $vm->{node}, Name => $vm->{name} }; } $options{statefile}->write(data => $vms); } return $vms; } sub cache_nodes { my ($self, %options) = @_; my $has_cache_file = $options{statefile}->read(statefile => 'cache_proxmox_node_'.$self->{hostname} . '_' . $self->{port}); my $timestamp_cache = $options{statefile}->get(name => 'last_timestamp'); my $nodes = $options{statefile}->get(name => 'nodes'); if ($has_cache_file == 0 || !defined($timestamp_cache) || ((time() - $timestamp_cache) > (($options{reload_cache_time})))) { $nodes = {}; my $list_nodes = $self->internal_api_list_nodes(); foreach my $node (@{$list_nodes}) { $nodes->{$node->{id}} = { State => $node->{status}, Name => $node->{node}, }; } $options{statefile}->write(data => $nodes); } return $nodes; } sub cache_storages { my ($self, %options) = @_; my $has_cache_file = $options{statefile}->read(statefile => 'cache_proxmox_storage_'.$self->{hostname} . '_' . $self->{port}); my $timestamp_cache = $options{statefile}->get(name => 'last_timestamp'); my $storages = $options{statefile}->get(name => 'storages'); if ($has_cache_file == 0 || !defined($timestamp_cache) || ((time() - $timestamp_cache) > (($options{reload_cache_time})))) { $storages = {}; my $list_storages = $self->internal_api_list_storages(); foreach my $storage (@{$list_storages}) { $storages->{$storage->{id}} = { State => $storage->{status}, Name => $storage->{storage}, }; } $options{statefile}->write(data => $storages); } return $storages; } sub internal_api_get_vm_stats { my ($self, %options) = @_; my $vm_stats = $self->request_api(method => 'GET', url_path => '/api2/json/nodes/' . $options{node_id} . '/' . $options{vm_id} . '/status/current'); return $vm_stats; } sub internal_api_get_node_stats { my ($self, %options) = @_; my (undef, $node) = split(/\//, $options{node_id}); my $node_stats = $self->request_api(method => 'GET', url_path => '/api2/json/nodes/' . $node . '/status'); return $node_stats; } sub internal_api_get_storage_stats { my ($self, %options) = @_; my (undef, $node, $storage) = split(/\//, $options{storage_id}); my $storage_stats = $self->request_api(method => 'GET', url_path => '/api2/json/nodes/' . $node . '/storage/' . $storage . '/status'); return $storage_stats; } sub internal_api_get_vm_node { my ($self, %options) = @_; my $list_vms = $self->internal_api_list_vms(); my $node = ''; foreach my $vm (@{$list_vms}) { if ($vm->{id} eq $options{vm_id}) { $node = $vm->{node}; last; } } return $node; } sub api_get_vms { my ($self, %options) = @_; my $content_total = $self->cache_vms(statefile => $options{statefile}); if (defined($options{vm_id}) && $options{vm_id} ne '') { if (defined($content_total->{ $options{vm_id} })) { $content_total->{ $options{vm_id} }->{Stats} = $self->internal_api_get_vm_stats( node_id => $content_total->{ $options{vm_id} }->{Node}, vm_id => $options{vm_id} ); } } elsif (defined($options{vm_name}) && $options{vm_name} ne '') { my $vm_id; foreach (keys %$content_total) { if ($content_total->{$_}->{Name} eq $options{vm_name}) { $vm_id = $_; last; } } if (defined($vm_id)) { $content_total->{$vm_id}->{Stats} = $self->internal_api_get_vm_stats(node_id => $content_total->{$vm_id}->{Node}, vm_id => $vm_id); } } else { foreach my $vm_id (keys %$content_total) { $content_total->{$vm_id}->{Stats} = $self->internal_api_get_vm_stats(node_id => $content_total->{$vm_id}->{Node}, vm_id => $vm_id); } } return $content_total; } sub api_get_nodes { my ($self, %options) = @_; my $content_total = $self->cache_nodes(statefile => $options{statefile}); if (defined($options{node_id}) && $options{node_id} ne '') { if (defined($content_total->{$options{node_id}})) { $content_total->{$options{node_id}}->{Stats} = $self->internal_api_get_node_stats(node_id => $options{node_id}); } } elsif (defined($options{node_name}) && $options{node_name} ne '') { my $node_id; foreach (keys %{$content_total}) { if ($content_total->{$_}->{Name} eq $options{node_name}) { $node_id = $_; last; } } if (defined($node_id)) { $content_total->{$node_id}->{Stats} = $self->internal_api_get_node_stats(node_id => $node_id); } } else { foreach my $node_id (keys %{$content_total}) { $content_total->{$node_id}->{Stats} = $self->internal_api_get_node_stats(node_id => $node_id); } } return $content_total; } sub api_get_storages { my ($self, %options) = @_; my $content_total = $self->cache_storages(statefile => $options{statefile}); if (defined($options{storage_id}) && $options{storage_id} ne '') { if (defined($content_total->{$options{storage_id}})) { $content_total->{$options{storage_id}}->{Stats} = $self->internal_api_get_storage_stats(storage_id => $options{storage_id}); } } elsif (defined($options{storage_name}) && $options{storage_name} ne '') { my $storage_id; foreach (keys %{$content_total}) { if ($content_total->{$_}->{Name} eq $options{storage_name}) { $storage_id = $_; last; } } if (defined($storage_id)) { $content_total->{$storage_id}->{Stats} = $self->internal_api_get_storage_stats(storage_id => $storage_id); } } else { foreach my $storage_id (keys %{$content_total}) { $content_total->{$storage_id}->{Stats} = $self->internal_api_get_storage_stats(storage_id => $storage_id); } } return $content_total; } 1; __END__ =head1 NAME Proxmox VE Rest API =head1 REST API OPTIONS Proxmox Rest API More Info about Proxmox VE API on https://pve.proxmox.com/wiki/Proxmox_VE_API =over 8 =item B<--hostname> Set hostname or IP of Proxmox VE Cluster node =item B<--port> Set Proxmox VE Port (Default: '8006') =item B<--proto> Specify https if needed (Default: 'https'). =item B<--api-username> Set Proxmox VE Username API user need to have this privileges 'VM.Monitor, VM.Audit, Datastore.Audit, Sys.Audit, Sys.Syslog' =item B<--api-password> Set Proxmox VE Password =item B<--realm> Set Proxmox VE Realm (pam, pve or custom) (Default: 'pam'). =item B<--timeout> Threshold for HTTP timeout. =back =cut centreon-plugins-20220113/apps/proxmox/ve/restapi/mode/000077500000000000000000000000001417000230700227205ustar00rootroot00000000000000centreon-plugins-20220113/apps/proxmox/ve/restapi/mode/listnodes.pm000066400000000000000000000046541417000230700252730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::proxmox::ve::restapi::mode::listnodes; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{nodes} = $options{custom}->api_list_nodes(); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $node_id (sort keys %{$self->{nodes}}) { $self->{output}->output_add( long_msg => '[id = ' . $node_id . "]" . "[name = '" . $self->{nodes}->{$node_id}->{Name} . "']" . "[state = '" . $self->{nodes}->{$node_id}->{State} . "']" ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List nodes:' ); $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 => ['id', 'name', 'state']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $node_id (sort keys %{$self->{nodes}}) { $self->{output}->add_disco_entry( name => $self->{nodes}->{$node_id}->{Name}, status => $self->{nodes}->{$node_id}->{State}, id => $node_id, ); } } 1; __END__ =head1 MODE List nodes =over 8 =back =cut centreon-plugins-20220113/apps/proxmox/ve/restapi/mode/liststorages.pm000066400000000000000000000052261417000230700260060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::proxmox::ve::restapi::mode::liststorages; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{storages} = $options{custom}->api_list_storages(); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $storage_id (sort keys %{$self->{storages}}) { $self->{output}->output_add(long_msg => '[id = ' . $storage_id . "]" . "[name = '" . $self->{storages}->{$storage_id}->{Name} . "']" . "[node = '" . $self->{storages}->{$storage_id}->{Node} . "']" . "[state = '" . $self->{storages}->{$storage_id}->{State} . "']" ); } $self->{output}->output_add(severity => 'OK', short_msg => 'List Storages:'); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } sub disco_format { my ($self, %options) = @_; $self->{output}->add_disco_format(elements => ['id', 'name', 'node', 'status']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $storage_id (sort keys %{$self->{storages}}) { $self->{output}->add_disco_entry( name => $self->{storages}->{$storage_id}->{Name}, node => $self->{storages}->{$storage_id}->{Node}, state => $self->{storages}->{$storage_id}->{State}, id => $storage_id, ); } } 1; __END__ =head1 MODE List storages =over 8 =back =cut centreon-plugins-20220113/apps/proxmox/ve/restapi/mode/listvms.pm000066400000000000000000000054121417000230700247610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::proxmox::ve::restapi::mode::listvms; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{vms} = $options{custom}->api_list_vms(); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $vm_id (sort keys %{$self->{vms}}) { $self->{output}->output_add(long_msg => '[id = ' . $vm_id . "][name = '" . $self->{vms}->{$vm_id}->{Name} . "']" . "[node = '" . $self->{vms}->{$vm_id}->{Node} . "']" . "[state = '" . $self->{vms}->{$vm_id}->{State} . "']" . "[vmid = '" . $self->{vms}->{$vm_id}->{Vmid} . "']" . "[type = '" . $self->{vms}->{$vm_id}->{Type} . "']" ); } $self->{output}->output_add(severity => 'OK', short_msg => 'List VMs:'); $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 => ['id', 'name', 'node' ,'state','type','vmid']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $vm_id (sort keys %{$self->{vms}}) { $self->{output}->add_disco_entry( name => $self->{vms}->{$vm_id}->{Name}, node => $self->{vms}->{$vm_id}->{Node}, state => $self->{vms}->{$vm_id}->{State}, id => $vm_id, type => $self->{vms}->{$vm_id}->{Type}, vmid =>$self->{vms}->{$vm_id}->{Vmid}, ); } } 1; __END__ =head1 MODE List VMs =over 8 =back =cut centreon-plugins-20220113/apps/proxmox/ve/restapi/mode/nodeusage.pm000066400000000000000000000405031417000230700252320ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::proxmox::ve::restapi::mode::nodeusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; return 'state : ' . $self->{result_values}->{state}; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{state} = $options{new_datas}->{$self->{instance} . '_state'}; $self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_name'}; return 0; } sub custom_cpu_calc { my ($self, %options) = @_; my $delta_cpu_total = $options{new_datas}->{$self->{instance} . '_cpu_total_usage'} - $options{old_datas}->{$self->{instance} . '_cpu_total_usage'}; $self->{result_values}->{prct_cpu} = (($delta_cpu_total) * 100); $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub custom_memory_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => 'memory_used', unit => 'B', instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, value => $self->{result_values}->{used}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), min => 0, max => $self->{result_values}->{total} ); } sub custom_memory_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check( value => $self->{result_values}->{prct_used}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_memory_output { my ($self, %options) = @_; my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); return sprintf( 'Memory Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)', $total_size_value . " " . $total_size_unit, $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}, $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free} ); } sub custom_memory_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_memory_total'}; $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_memory_usage'}; $self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used}; $self->{result_values}->{prct_free} = $self->{result_values}->{free} * 100 / $self->{result_values}->{total}; $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; return 0; } sub custom_swap_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => 'swap_used', unit => 'B', instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, value => $self->{result_values}->{used}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), min => 0, max => $self->{result_values}->{total} ); } sub custom_swap_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check( value => $self->{result_values}->{prct_used}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_swap_output { my ($self, %options) = @_; my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); return sprintf( 'Swap Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)', $total_size_value . " " . $total_size_unit, $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}, $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free} ); } sub custom_swap_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_swap_total'}; $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_swap_usage'}; $self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used}; $self->{result_values}->{prct_free} = $self->{result_values}->{free} * 100 / $self->{result_values}->{total}; $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; return 0; } sub custom_fs_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => 'fs_used', unit => 'B', instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, value => $self->{result_values}->{used}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), min => 0, max => $self->{result_values}->{total} ); } sub custom_fs_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check( value => $self->{result_values}->{prct_used}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_fs_output { my ($self, %options) = @_; my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); return sprintf( 'Root Filesystem Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)', $total_size_value . " " . $total_size_unit, $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}, $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free} ); } sub custom_fs_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_fs_total'}; $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_fs_usage'}; $self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used}; $self->{result_values}->{prct_free} = $self->{result_values}->{free} * 100 / $self->{result_values}->{total}; $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'nodes', type => 1, cb_prefix_output => 'prefix_nodes_output', message_multiple => 'All nodes are ok', skipped_code => { -10 => 1, -11 => 1 } }, ]; $self->{maps_counters}->{nodes} = [ { label => 'node-status', threshold => 0, set => { key_values => [ { name => 'state' }, { name => 'name' } ], 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 => \&catalog_status_threshold, } }, { label => 'cpu', set => { key_values => [ { name => 'cpu_total_usage', diff => 1 }, { name => 'cpu_number' }, { name => 'display' } ], output_template => 'CPU Usage : %.2f %%', closure_custom_calc => $self->can('custom_cpu_calc'), output_use => 'prct_cpu', threshold_use => 'prct_cpu', perfdatas => [ { label => 'cpu', value => 'prct_cpu', template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'memory', set => { key_values => [ { name => 'memory_usage' }, { name => 'memory_total' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_memory_calc'), closure_custom_output => $self->can('custom_memory_output'), closure_custom_perfdata => $self->can('custom_memory_perfdata'), closure_custom_threshold_check => $self->can('custom_memory_threshold'), } }, { label => 'fs', set => { key_values => [ { name => 'fs_usage' }, { name => 'fs_total' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_fs_calc'), closure_custom_output => $self->can('custom_fs_output'), closure_custom_perfdata => $self->can('custom_fs_perfdata'), closure_custom_threshold_check => $self->can('custom_fs_threshold'), } }, { label => 'swap', set => { key_values => [ { name => 'swap_usage' }, { name => 'swap_total' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_swap_calc'), closure_custom_output => $self->can('custom_swap_output'), closure_custom_perfdata => $self->can('custom_swap_perfdata'), closure_custom_threshold_check => $self->can('custom_swap_threshold'), } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'node-id:s' => { name => 'node_id' }, 'node-name:s' => { name => 'node_name' }, 'filter-name:s' => { name => 'filter_name' }, 'use-name' => { name => 'use_name' }, 'warning-node-status:s' => { name => 'warning_node_status', default => '' }, 'critical-node-status:s' => { name => 'critical_node_status', default => '' }, }); $self->{statefile_cache_nodes} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_node_status', 'critical_node_status']); $self->{statefile_cache_nodes}->check_options(%options); } sub prefix_nodes_output { my ($self, %options) = @_; return "Node '" . $options{instance_value}->{display} . "' "; } sub manage_selection { my ($self, %options) = @_; $self->{nodes} = {}; my $result = $options{custom}->api_get_nodes( node_id => $self->{option_results}->{node_id}, node_name => $self->{option_results}->{node_name}, statefile => $self->{statefile_cache_nodes} ); foreach my $node_id (keys %{$result}) { next if (!defined($result->{$node_id}->{Stats})); my $name = $result->{$node_id}->{Name}; 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->{nodes}->{$node_id} = { display => defined($self->{option_results}->{use_name}) ? $name : $node_id, name => $name, state => $result->{$node_id}->{State}, cpu_total_usage => $result->{$node_id}->{Stats}->{cpu}, cpu_number => $result->{$node_id}->{Stats}->{cpuinfo}->{cpus}, memory_usage => $result->{$node_id}->{Stats}->{memory}->{used}, memory_total => $result->{$node_id}->{Stats}->{memory}->{total}, swap_usage => $result->{$node_id}->{Stats}->{swap}->{used}, swap_total => defined($result->{$node_id}->{Stats}->{swap}->{total}) && $result->{$node_id}->{Stats}->{swap}->{total} > 0 ? $result->{$node_id}->{Stats}->{swap}->{total} : undef, fs_usage => $result->{$node_id}->{Stats}->{rootfs}->{used}, fs_total => $result->{$node_id}->{Stats}->{rootfs}->{total}, }; } if (scalar(keys %{$self->{nodes}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No node found."); $self->{output}->option_exit(); } my $hostnames = $options{custom}->get_hostnames(); $self->{cache_name} = "proxmox_" . $self->{mode} . '_' .$hostnames . '_' . $options{custom}->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')) . '_' . (defined($self->{option_results}->{node_id}) ? md5_hex($self->{option_results}->{node_id}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{node_name}) ? md5_hex($self->{option_results}->{node_name}) : md5_hex('all')); } 1; __END__ =head1 MODE Check node usage. =over 8 =item B<--node-id> Exact node ID. =item B<--node-name> Exact node name (if multiple names: names separated by ':'). =item B<--use-name> Use node name for perfdata and display. =item B<--filter-name> Filter by node name (can be a regexp). =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^node-status$' =item B<--warning-*> Threshold warning. Can be: 'cpu' (%), 'memory' (%), 'swap' (%), 'fs' (%). =item B<--critical-*> Threshold critical. Can be: 'cpu' (%), 'memory' (%), 'swap' (%), 'fs' (%). =item B<--warning-node-status> Set warning threshold for status (Default: -) Can used special variables like: %{name}, %{state}. =item B<--critical-node-status> Set critical threshold for status (Default: -). Can used special variables like: %{name}, %{state}. =back =cut centreon-plugins-20220113/apps/proxmox/ve/restapi/mode/storageusage.pm000066400000000000000000000225301417000230700257510ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::proxmox::ve::restapi::mode::storageusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); 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} . '_state'}; $self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_name'}; return 0; } sub custom_storage_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => 'storage_used', unit => 'B', instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, value => $self->{result_values}->{used}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), min => 0, max => $self->{result_values}->{total} ); } sub custom_storage_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check(value => $self->{result_values}->{prct_used}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ]); return $exit; } sub custom_storage_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("Storage 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_storage_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_storage_total'}; $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_storage_usage'}; $self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used}; $self->{result_values}->{prct_free} = $self->{result_values}->{free} * 100 / $self->{result_values}->{total}; $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'storages', type => 1, cb_prefix_output => 'prefix_storages_output', message_multiple => 'All storages are ok', skipped_code => { -11 => 1 } }, ]; $self->{maps_counters}->{storages} = [ { label => 'storage-status', threshold => 0, set => { key_values => [ { name => 'state' }, { name => 'name' } ], 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 => \&catalog_status_threshold, } }, { label => 'storage', set => { key_values => [ { name => 'storage_usage' }, { name => 'storage_total' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_storage_calc'), closure_custom_output => $self->can('custom_storage_output'), closure_custom_perfdata => $self->can('custom_storage_perfdata'), closure_custom_threshold_check => $self->can('custom_storage_threshold'), } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { "storage-id:s" => { name => 'storage_id' }, "storage-name:s" => { name => 'storage_name' }, "filter-name:s" => { name => 'filter_name' }, "use-name" => { name => 'use_name' }, "warning-storage-status:s" => { name => 'warning_storage_status', default => '' }, "critical-storage-status:s" => { name => 'critical_storage_status', default => '' }, }); $self->{statefile_cache_storages} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_storage_status', 'critical_storage_status']); $self->{statefile_cache_storages}->check_options(%options); } sub prefix_storages_output { my ($self, %options) = @_; return "Storage '" . $options{instance_value}->{display} . "' "; } sub manage_selection { my ($self, %options) = @_; $self->{storages} = {}; my $result = $options{custom}->api_get_storages( storage_id => $self->{option_results}->{storage_id}, storage_name => $self->{option_results}->{storage_name}, statefile => $self->{statefile_cache_storages} ); foreach my $storage_id (keys %{$result}) { next if (!defined($result->{$storage_id}->{Stats})); my $name = $result->{$storage_id}->{Name}; 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->{storages}->{$storage_id} = { display => defined($self->{option_results}->{use_name}) ? $name : $storage_id, name => $name, state => $result->{$storage_id}->{State}, storage_usage => $result->{$storage_id}->{Stats}->{used}, storage_total => $result->{$storage_id}->{Stats}->{total}, }; } if (scalar(keys %{$self->{storages}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No storage found."); $self->{output}->option_exit(); } my $hostnames = $options{custom}->get_hostnames(); $self->{cache_name} = "proxmox_" . $self->{mode} . '_' .$hostnames . '_' . $options{custom}->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')) . '_' . (defined($self->{option_results}->{storage_id}) ? md5_hex($self->{option_results}->{storage_id}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{storage_name}) ? md5_hex($self->{option_results}->{storage_name}) : md5_hex('all')); } 1; __END__ =head1 MODE Check storage usage. =over 8 =item B<--storage-id> Exact storage ID. =item B<--storage-name> Exact storage name (if multiple names: names separated by ':'). =item B<--use-name> Use storage name for perfdata and display. =item B<--filter-name> Filter by storage name (can be a regexp). =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^storage-status$' =item B<--warning-*> Threshold warning. Can be: 'storage' (%). =item B<--critical-*> Threshold critical. Can be: 'storage' (%). =item B<--warning-storage-status> Set warning threshold for status (Default: -) Can used special variables like: %{name}, %{state}. =item B<--critical-storage-status> Set critical threshold for status (Default: -). Can used special variables like: %{name}, %{state}. =back =cut centreon-plugins-20220113/apps/proxmox/ve/restapi/mode/version.pm000066400000000000000000000031211417000230700247400ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::proxmox::ve::restapi::mode::version; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my $result = $options{custom}->get_version(); $self->{output}->output_add(severity => 'OK', short_msg => "Version is '" . $result . "'"); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE Get Proxmox VE Version =over 8 =back =cut centreon-plugins-20220113/apps/proxmox/ve/restapi/mode/vmusage.pm000066400000000000000000000363201417000230700247310ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::proxmox::ve::restapi::mode::vmusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return 'state : ' . $self->{result_values}->{state}; } sub custom_cpu_calc { my ($self, %options) = @_; my $delta_cpu_total = $options{new_datas}->{$self->{instance} . '_cpu_total_usage'} - $options{old_datas}->{$self->{instance} . '_cpu_total_usage'}; $self->{result_values}->{prct_cpu} = $delta_cpu_total * 100; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub custom_memory_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => 'memory_used', unit => 'B', instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, value => $self->{result_values}->{used}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), min => 0, max => $self->{result_values}->{total} ); } sub custom_memory_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check( value => $self->{result_values}->{prct_used}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_memory_output { my ($self, %options) = @_; my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); return sprintf( 'Memory Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)', $total_size_value . " " . $total_size_unit, $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}, $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free} ); } sub custom_memory_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_memory_total'}; $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_memory_usage'}; $self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used}; $self->{result_values}->{prct_free} = $self->{result_values}->{free} * 100 / $self->{result_values}->{total}; $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; return 0; } sub custom_swap_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => 'swap_used', unit => 'B', instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, value => $self->{result_values}->{used}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), min => 0, max => $self->{result_values}->{total} ); } sub custom_swap_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check(value => $self->{result_values}->{prct_used}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ]); return $exit; } sub custom_swap_output { my ($self, %options) = @_; my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); return sprintf( 'Swap Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)', $total_size_value . " " . $total_size_unit, $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}, $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free} ); } sub custom_swap_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_swap_total'}; $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_swap_usage'}; $self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used}; $self->{result_values}->{prct_free} = $self->{result_values}->{free} * 100 / $self->{result_values}->{total}; $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'vms', type => 1, cb_prefix_output => 'prefix_vms_output', message_multiple => 'All vms are ok', skipped_code => { -11 => 1 } }, { name => 'vms_traffic', type => 1, cb_prefix_output => 'prefix_vms_traffic_output', message_multiple => 'All vm traffics are ok', skipped_code => { -11 => 1 } }, ]; $self->{maps_counters}->{vms} = [ { label => 'vm-status', type => 2, set => { key_values => [ { name => 'state' }, { name => 'name' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'cpu', set => { key_values => [ { name => 'cpu_total_usage', diff => 1 }, { name => 'cpu_number' }, { name => 'display' } ], output_template => 'CPU Usage : %.2f %%', closure_custom_calc => $self->can('custom_cpu_calc'), output_use => 'prct_cpu', threshold_use => 'prct_cpu', perfdatas => [ { label => 'cpu', value => 'prct_cpu', template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'memory', set => { key_values => [ { name => 'memory_usage' }, { name => 'memory_total' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_memory_calc'), closure_custom_output => $self->can('custom_memory_output'), closure_custom_perfdata => $self->can('custom_memory_perfdata'), closure_custom_threshold_check => $self->can('custom_memory_threshold') } }, { label => 'read-iops', set => { key_values => [ { name => 'read_io', per_second => 1 }, { name => 'display' } ], output_template => 'Read IOPs : %.2f', output_error_template => "Read IOPs : %s", perfdatas => [ { label => 'read_iops', template => '%.2f', unit => 'iops', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'write-iops', set => { key_values => [ { name => 'write_io', per_second => 1 }, { name => 'display' } ], output_template => 'Write IOPs : %.2f', output_error_template => "Write IOPs : %s", perfdatas => [ { label => 'write_iops', template => '%.2f', unit => 'iops', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'swap', set => { key_values => [ { name => 'swap_usage' }, { name => 'swap_total' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_swap_calc'), closure_custom_output => $self->can('custom_swap_output'), closure_custom_perfdata => $self->can('custom_swap_perfdata'), closure_custom_threshold_check => $self->can('custom_swap_threshold') } } ]; $self->{maps_counters}->{vms_traffic} = [ { label => 'traffic-in', set => { key_values => [ { name => 'traffic_in', per_second => 1 }, { name => 'display' } ], output_change_bytes => 2, output_template => 'Traffic In : %s %s/s', perfdatas => [ { label => 'traffic_in', template => '%.2f', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'traffic-out', set => { key_values => [ { name => 'traffic_out', per_second => 1 }, { name => 'display' } ], output_change_bytes => 2, output_template => 'Traffic Out : %s %s/s', perfdatas => [ { label => 'traffic_out', template => '%.2f', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'vm-id:s' => { name => 'vm_id' }, 'vm-name:s' => { name => 'vm_name' }, 'filter-name:s' => { name => 'filter_name' }, 'use-name' => { name => 'use_name' } }); $self->{statefile_cache_vms} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{statefile_cache_vms}->check_options(%options); } sub prefix_vms_traffic_output { my ($self, %options) = @_; return "VM '" . $options{instance_value}->{display} . "' "; } sub prefix_vms_output { my ($self, %options) = @_; return "VM '" . $options{instance_value}->{display} . "' "; } sub manage_selection { my ($self, %options) = @_; $self->{vms} = {}; $self->{vms_traffic} = {}; my $result = $options{custom}->api_get_vms( vm_id => $self->{option_results}->{vm_id}, vm_name => $self->{option_results}->{vm_name}, statefile => $self->{statefile_cache_vms} ); foreach my $vm_id (keys %{$result}) { next if (!defined($result->{$vm_id}->{Stats})); my $name = $result->{$vm_id}->{Name}; 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->{vms}->{$vm_id} = { display => defined($self->{option_results}->{use_name}) ? $name : $vm_id, name => $name, state => $result->{$vm_id}->{State}, read_io => $result->{$vm_id}->{Stats}->{diskread}, write_io => $result->{$vm_id}->{Stats}->{diskwrite}, cpu_total_usage => $result->{$vm_id}->{Stats}->{cpu}, cpu_number => $result->{$vm_id}->{Stats}->{cpus}, memory_usage => $result->{$vm_id}->{Stats}->{mem}, memory_total => $result->{$vm_id}->{Stats}->{maxmem}, swap_usage => $result->{$vm_id}->{Stats}->{swap}, swap_total => defined($result->{$vm_id}->{Stats}->{maxswap}) && $result->{$vm_id}->{Stats}->{maxswap} > 0 ? $result->{$vm_id}->{Stats}->{maxswap} : undef }; $self->{vms_traffic}->{$name} = { display => $name, traffic_in => $result->{$vm_id}->{Stats}->{netin} * 8, traffic_out => $result->{$vm_id}->{Stats}->{netout} * 8 }; } if (scalar(keys %{$self->{vms}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No vm found."); $self->{output}->option_exit(); } my $hostnames = $options{custom}->get_hostnames(); $self->{cache_name} = "proxmox_" . $self->{mode} . '_' .$hostnames . '_' . $options{custom}->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')) . '_' . (defined($self->{option_results}->{vm_id}) ? md5_hex($self->{option_results}->{vm_id}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{vm_name}) ? md5_hex($self->{option_results}->{vm_name}) : md5_hex('all')); } 1; __END__ =head1 MODE Check VM usage on Proxmox VE Cluster. =over 8 =item B<--vm-id> Exact VM ID. =item B<--vm-name> Exact VM name (if multiple names: names separated by ':'). =item B<--use-name> Use VM name for perfdata and display. =item B<--filter-name> Filter by vm name (can be a regexp). =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^vm-status$' =item B<--warning-*> Threshold warning. Can be: 'read-iops', 'write-iops', 'traffic-in', 'traffic-out', 'cpu' (%), 'memory' (%), 'swap' (%). =item B<--critical-*> Threshold critical. Can be: 'read-iops', 'write-iops', 'traffic-in', 'traffic-out', 'cpu' (%), 'memory' (%), 'swap' (%). =item B<--warning-vm-status> Set warning threshold for status (Default: -) Can used special variables like: %{name}, %{state}. =item B<--critical-vm-status> Set critical threshold for status (Default: -). Can used special variables like: %{name}, %{state}. =back =cut centreon-plugins-20220113/apps/proxmox/ve/restapi/plugin.pm000066400000000000000000000036441417000230700236370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::proxmox::ve::restapi::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} = '1.0'; $self->{modes} = { 'list-nodes' => 'apps::proxmox::ve::restapi::mode::listnodes', 'list-storages' => 'apps::proxmox::ve::restapi::mode::liststorages', 'list-vms' => 'apps::proxmox::ve::restapi::mode::listvms', 'node-usage' => 'apps::proxmox::ve::restapi::mode::nodeusage', 'storage-usage' => 'apps::proxmox::ve::restapi::mode::storageusage', 'version' => 'apps::proxmox::ve::restapi::mode::version', 'vm-usage' => 'apps::proxmox::ve::restapi::mode::vmusage' }; $self->{custom_modes}->{api} = 'apps::proxmox::ve::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Proxmox VE ressources through its HTTPS remote API. API documentation can be checked at https://pve.proxmox.com/pve-docs/api-viewer/. Requirements: Proxmox VE 5.x. =over 8 =back =cut centreon-plugins-20220113/apps/pvx/000077500000000000000000000000001417000230700170145ustar00rootroot00000000000000centreon-plugins-20220113/apps/pvx/restapi/000077500000000000000000000000001417000230700204635ustar00rootroot00000000000000centreon-plugins-20220113/apps/pvx/restapi/custom/000077500000000000000000000000001417000230700217755ustar00rootroot00000000000000centreon-plugins-20220113/apps/pvx/restapi/custom/api.pm000066400000000000000000000201161417000230700231040ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::pvx::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use DateTime; use JSON::XS; use URI::Encode; 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 => { 'api-key:s' => { name => 'api_key' }, 'hostname:s' => { name => 'hostname' }, 'url-path:s' => { name => 'url_path' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'credentials' => { name => 'credentials' }, 'basic' => { name => 'basic' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'timeout:s' => { name => 'timeout', default => 10 }, 'timeframe:s' => { name => 'timeframe' }, 'timezone:s' => { name => 'timezone', default => 'UTC' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{api_key} = (defined($self->{option_results}->{api_key})) ? $self->{option_results}->{api_key} : undef; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : undef; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{url_path} = (defined($self->{option_results}->{url_path})) ? $self->{option_results}->{url_path} : '/api'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{username} = (defined($self->{option_results}->{username})) ? $self->{option_results}->{username} : undef; $self->{password} = (defined($self->{option_results}->{password})) ? $self->{option_results}->{password} : undef; $self->{credentials} = (defined($self->{option_results}->{credentials})) ? 1 : undef; $self->{basic} = (defined($self->{option_results}->{basic})) ? 1 : undef; $self->{timeframe} = (defined($self->{option_results}->{timeframe})) ? $self->{option_results}->{timeframe} : undef; if (!defined($self->{hostname}) || $self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify hostname option."); $self->{output}->option_exit(); } if (!defined($self->{api_key}) || $self->{api_key} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify api-key option."); $self->{output}->option_exit(); } $self->{timezone} = 'UTC'; if (defined($self->{option_results}->{timezone}) && $self->{option_results}->{timezone} ne '') { $self->{timezone} = $self->{option_results}->{timezone}; } return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{credentials} = $self->{credentials}; $self->{option_results}->{basic} = $self->{basic}; $self->{option_results}->{username} = $self->{username}; $self->{option_results}->{password} = $self->{password}; $self->{option_results}->{warning_status} = ''; $self->{option_results}->{critical_status} = ''; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->add_header(key => 'Content-Type', value => 'application/x-www-form-urlencoded'); $self->{http}->add_header(key => 'PVX-Authorization', value => $self->{api_key}); $self->{http}->set_options(%{$self->{option_results}}); } sub get_connection_info { my ($self, %options) = @_; return $self->{hostname} . ":" . $self->{port}; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub get_port { my ($self, %options) = @_; return $self->{port}; } sub query_range { my ($self, %options) = @_; my $tz = centreon::plugins::misc::set_timezone(name => $self->{timezone}); my $dt = DateTime->now(%$tz); my $start_time = $dt->epoch() - $options{timeframe}; my $end_time = $dt->epoch(); my $uri = URI::Encode->new({encode_reserved => 1}); my $query = sprintf('%s SINCE %s UNTIL %s', $options{query}, $start_time, $end_time); $query .= sprintf(' BY %s', $options{instance}) if (defined($options{instance}) && $options{instance} ne ''); $query .= sprintf(' WHERE %s', $options{filter}) if (defined($options{filter}) && $options{filter} ne ''); $query .= sprintf(' FROM %s', $options{from}) if (defined($options{from}) && $options{from} ne ''); $query .= sprintf(' TOP %s', $options{top}) if (defined($options{top}) && $options{top} ne ''); my $result = $self->get_endpoint(url_path => '/query?expr=' . $uri->encode($query)); return $result->{data}; } sub get_endpoint { my ($self, %options) = @_; $self->settings; my $response = $self->{http}->request(url_path => $self->{url_path} . $options{url_path}); my $content; eval { $content = JSON::XS->new->utf8->decode($response); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } if ($content->{type} eq 'error') { $self->{output}->add_option_msg(short_msg => "Cannot get data: " . $content->{error}); $self->{output}->option_exit(); } return $content->{result}; } 1; __END__ =head1 NAME PVX REST API =head1 SYNOPSIS PVX Rest API custom mode =head1 REST API OPTIONS =over 8 =item B<--timeframe> Set timeframe in seconds (i.e. 3600 to check last hour). =item B<--timezone> Set your timezone. Can use format: 'Europe/London' or '+0100'. =item B<--api-key> PVX API key. =item B<--hostname> PVX hostname. =item B<--url-path> PVX url path (Default: '/api') =item B<--port> API port (Default: 443) =item B<--proto> Specify https if needed (Default: 'https') =item B<--username> Specify username for authentication =item B<--password> Specify password for authentication =item B<--basic> Specify this option if you access the API over basic authentication and don't want a '401 UNAUTHORIZED' error to be logged on your webserver. Specify this option if you access the API over hidden basic authentication or you'll get a '404 NOT FOUND' error. (Use with --credentials) =item B<--timeout> Set HTTP timeout =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/pvx/restapi/mode/000077500000000000000000000000001417000230700214075ustar00rootroot00000000000000centreon-plugins-20220113/apps/pvx/restapi/mode/httphits.pm000066400000000000000000000151441417000230700236210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::pvx::restapi::mode::httphits; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_instances_output { my ($self, %options) = @_; return $options{instance_value}->{instance_label} . " '" . $options{instance_value}->{key} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'instances', type => 1, cb_prefix_output => 'prefix_instances_output', message_multiple => 'All metrics are ok' }, ]; $self->{maps_counters}->{instances} = [ { label => 'ratio', nlabel => 'http.hits.percentage', set => { key_values => [ { name => 'ratio' }, { name => 'key' }, { name => 'instance_label' } ], output_template => 'ratio: %.2f', perfdatas => [ { label => 'ratio', template => '%.2f', min => 0, label_extra_instance => 1, instance_use => 'key' } ] } }, { label => 'hits-error', nlabel => 'http.hits.error.persecond', set => { key_values => [ { name => 'error_hits' }, { name => 'key' }, { name => 'instance_label' } ], output_template => 'hits error: %.3f hits/s', perfdatas => [ { label => 'hits_error', template => '%.3f', min => 0, unit => 'hits/s', label_extra_instance => 1, instance_use => 'key' } ] } }, { label => 'hits', nlabel => 'http.hits.persecond', set => { key_values => [ { name => 'hits' }, { name => 'key' }, { name => 'instance_label' } ], output_template => 'hits: %.3f hits/s', perfdatas => [ { label => 'hits', template => '%.3f', min => 0, unit => 'hits/s', label_extra_instance => 1, instance_use => 'key' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'instance:s' => { name => 'instance', default => 'layer' }, 'top:s' => { name => 'top' }, 'filter:s' => { name => 'filter' }, 'from:s' => { name => 'from', default => 'http' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{from}) || $self->{option_results}->{from} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --from option as a PVQL object."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{instance}) || $self->{option_results}->{instance} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --instance option as a PVQL object."); $self->{output}->option_exit(); } $self->{pvql_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; } sub manage_selection { my ($self, %options) = @_; my $instance_label = $self->{option_results}->{instance}; $instance_label =~ s/\./ /g; $instance_label =~ s/(\w+)/\u\L$1/g; $self->{instances} = {}; my $apps; if ($self->{option_results}->{instance} =~ /application/) { my $results = $options{custom}->get_endpoint(url_path => '/get-configuration'); $apps = $results->{applications}; } my $results = $options{custom}->query_range( query => 'error.hits, hits', instance => $self->{option_results}->{instance}, top => $self->{option_results}->{top}, filter => $self->{option_results}->{filter}, from => $self->{option_results}->{from}, timeframe => $self->{pvql_timeframe}, ); foreach my $result (@{$results}) { next if (!defined(${$result->{key}}[0])); my $instance; $instance = ${$result->{key}}[0]->{value} if (defined(${$result->{key}}[0]->{value})); $instance = ${$result->{key}}[0]->{status} if (defined(${$result->{key}}[0]->{status})); $self->{instances}->{$instance}->{key} = $instance; $self->{instances}->{$instance}->{key} = $apps->{$instance}->{name} if (defined($apps->{$instance}->{name}) && $self->{option_results}->{instance} =~ /application/); $self->{instances}->{$instance}->{error_hits} = (defined(${$result->{values}}[0]->{value})) ? ${$result->{values}}[0]->{value} / $self->{pvql_timeframe} : 0; $self->{instances}->{$instance}->{hits} = ${$result->{values}}[1]->{value} / $self->{pvql_timeframe}; $self->{instances}->{$instance}->{ratio} = (defined(${$result->{values}}[0]->{value})) ? ${$result->{values}}[1]->{value} / (${$result->{values}}[0]->{value} + ${$result->{values}}[1]->{value}) : 1; $self->{instances}->{$instance}->{instance_label} = $instance_label; } if (scalar(keys %{$self->{instances}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No instances or results found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check http hits. =over 8 =item B<--instance> Filter on a specific instance (Must be a PVQL object, Default: 'host') (Object 'application' will be mapped with applications name) =item B<--filter> Add a PVQL filter (Example: --filter='host = "www.lo.ki"') =item B<--from> Add a PVQL from clause to filter on a specific layer (Default: 'http') =item B<--top> Only search for the top X results (top is made on 'hits_error'). =item B<--warning-*> Threshold warning. Can be: 'ratio', 'hits-error' (hits/s), 'hits' (hits/s). =item B<--critical-*> Threshold critical. Can be: 'ratio', 'hits-error' (hits/s), 'hits' (hits/s). =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='ratio' =back =cut centreon-plugins-20220113/apps/pvx/restapi/mode/networkconnection.pm000066400000000000000000000164341417000230700255260ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::pvx::restapi::mode::networkconnection; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_instances_output { my ($self, %options) = @_; return $options{instance_value}->{instance_label} . " '" . $options{instance_value}->{key} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'instances', type => 1, cb_prefix_output => 'prefix_instances_output', message_multiple => 'All connection metrics are ok' }, ]; $self->{maps_counters}->{instances} = [ { label => 'ratio', nlabel => 'connections.ratio.percentage', set => { key_values => [ { name => 'syns_ratio' }, { name => 'key' }, { name => 'instance_label' } ], output_template => 'ratio: %.2f', perfdatas => [ { label => 'ratio', template => '%.2f', min => 0, label_extra_instance => 1, instance_use => 'key' } ] } }, { label => 'attempt', nlabel => 'connections.attempts.persecond', set => { key_values => [ { name => 'syns' }, { name => 'key' }, { name => 'instance_label' } ], output_template => 'connections attempts: %.2f conn/s', perfdatas => [ { label => 'attempt', template => '%.2f', min => 0, unit => 'connections/s', label_extra_instance => 1, instance_use => 'key' } ] } }, { label => 'successful', nlabel => 'connections.successful.persecond', set => { key_values => [ { name => 'ct_count' }, { name => 'key' }, { name => 'instance_label' } ], output_template => 'successful connections: %.2f conn/s', perfdatas => [ { label => 'successful', template => '%.2f', min => 0, unit => 'connections/s', label_extra_instance => 1, instance_use => 'key' } ] } }, { label => 'connection-time', nlabel => 'connection.time.milliseconds', set => { key_values => [ { name => 'ct' }, { name => 'key' }, { name => 'instance_label' } ], output_template => 'average connection time: %.3f ms', perfdatas => [ { label => 'connection_time', template => '%.3f', min => 0, unit => 'ms', label_extra_instance => 1, instance_use => 'key' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'instance:s' => { name => 'instance', default => 'layer' }, 'top:s' => { name => 'top' }, 'filter:s' => { name => 'filter' }, 'from:s' => { name => 'from' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{from}) || $self->{option_results}->{from} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --from option as a PVQL object."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{instance}) || $self->{option_results}->{instance} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --instance option as a PVQL object."); $self->{output}->option_exit(); } $self->{pvql_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; } sub manage_selection { my ($self, %options) = @_; my $instance_label = $self->{option_results}->{instance}; $instance_label =~ s/\./ /g; $instance_label =~ s/(\w+)/\u\L$1/g; $self->{instances} = {}; my $apps; if ($self->{option_results}->{instance} =~ /application/) { my $results = $options{custom}->get_endpoint(url_path => '/get-configuration'); $apps = $results->{applications}; } my $results = $options{custom}->query_range( query => 'syns.ratio, syns, ct.count, ct', instance => $self->{option_results}->{instance}, top => $self->{option_results}->{top}, filter => $self->{option_results}->{filter}, from => $self->{option_results}->{from}, timeframe => $self->{pvql_timeframe}, ); foreach my $result (@{$results}) { next if (!defined(${$result->{key}}[0])); my $instance; $instance = ${$result->{key}}[0]->{value} if (defined(${$result->{key}}[0]->{value})); $instance = ${$result->{key}}[0]->{status} if (defined(${$result->{key}}[0]->{status})); $self->{instances}->{$instance}->{key} = $instance; $self->{instances}->{$instance}->{key} = $apps->{$instance}->{name} if (defined($apps->{$instance}->{name}) && $self->{option_results}->{instance} =~ /application/); $self->{instances}->{$instance}->{syns_ratio} = (defined(${$result->{values}}[0]->{value})) ? ${$result->{values}}[0]->{value} : 1; $self->{instances}->{$instance}->{syns} = ${$result->{values}}[1]->{value} / $self->{pvql_timeframe}; $self->{instances}->{$instance}->{ct_count} = ${$result->{values}}[2]->{value} / $self->{pvql_timeframe}; $self->{instances}->{$instance}->{ct} = (defined(${$result->{values}}[3]->{value})) ? ${$result->{values}}[3]->{value} * 1000 : 0; $self->{instances}->{$instance}->{instance_label} = $instance_label; } if (scalar(keys %{$self->{instances}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No instances or results found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check instances connection metrics. =over 8 =item B<--instance> Filter on a specific instance (Must be a PVQL object, Default: 'layer') (Object 'application' will be mapped with applications name) =item B<--filter> Add a PVQL filter (Example: --filter='application = "mysql"') =item B<--from> Add a PVQL from clause to filter on a specific layer (Example: --from='tcp') =item B<--top> Only search for the top X results (top is made on 'ratio'). =item B<--warning-*> Threshold warning. Can be: 'ratio', 'attempt' (conn/s), 'successful' (conn/s), 'connection-time' (ms). =item B<--critical-*> Threshold critical. Can be: 'ratio', 'attempt' (conn/s), 'successful' (conn/s), 'connection-time' (ms). =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='ratio' =back =cut centreon-plugins-20220113/apps/pvx/restapi/mode/networktraffic.pm000066400000000000000000000210451417000230700247770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::pvx::restapi::mode::networktraffic; 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, cb_init => 'skip_global' }, { name => 'instances', type => 1, cb_prefix_output => 'prefix_instances_output', message_multiple => 'All traffic usage are ok' }, ]; $self->{maps_counters}->{global} = [ { label => 'total-traffic', nlabel => 'traffic.aggregated.bitspersecond', set => { key_values => [ { name => 'total_traffic' } ], output_template => 'Total Traffic: %.2f %s/s', output_change_bytes => 2, perfdatas => [ { template => '%d', min => 0, unit => 'b/s' } ] } }, { label => 'total-server-traffic', nlabel => 'traffic.server.bitspersecond', set => { key_values => [ { name => 'total_server_traffic' } ], output_template => 'Total Server Traffic: %.2f %s/s', output_change_bytes => 2, perfdatas => [ { template => '%d', min => 0, unit => 'b/s' } ] } }, { label => 'total-client-traffic', nlabel => 'traffic.client.bitspersecond', set => { key_values => [ { name => 'total_client_traffic' } ], output_template => 'Total Client Traffic: %.2f %s/s', output_change_bytes => 2, perfdatas => [ { template => '%d', min => 0, unit => 'b/s' } ] } } ]; $self->{maps_counters}->{instances} = [ { label => 'traffic', nlabel => 'instance.traffic.aggregated.bitspersecond', set => { key_values => [ { name => 'traffic' }, { name => 'key' }, { name => 'instance_label' } ], output_template => 'Traffic: %.2f %s/s', output_change_bytes => 2, perfdatas => [ { template => '%d', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'key' } ] } }, { label => 'server-traffic', nlabel => 'instance.traffic.server.bitspersecond', set => { key_values => [ { name => 'server_traffic' }, { name => 'key' }, { name => 'instance_label' } ], output_template => 'Server Traffic: %.2f %s/s', output_change_bytes => 2, perfdatas => [ { template => '%d', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'key' } ] } }, { label => 'client-traffic', nlabel => 'instance.traffic.client.bitspersecond', set => { key_values => [ { name => 'client_traffic' }, { name => 'key' }, { name => 'instance_label' } ], output_template => 'Client Traffic: %.2f %s/s', output_change_bytes => 2, perfdatas => [ { template => '%d', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'key' } ] } } ]; } sub skip_global { my ($self, %options) = @_; scalar(keys %{$self->{instances}}) > 1 ? return(0) : return(1); } sub prefix_instances_output { my ($self, %options) = @_; return $options{instance_value}->{instance_label} . " '" . $options{instance_value}->{key} . "' "; } 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 => { 'instance:s' => { name => 'instance', default => 'layer' }, 'top:s' => { name => 'top' }, 'filter:s' => { name => 'filter' }, 'from:s' => { name => 'from' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{from}) || $self->{option_results}->{from} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --from option as a PVQL object."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{instance}) || $self->{option_results}->{instance} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --instance option as a PVQL object."); $self->{output}->option_exit(); } $self->{pvql_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; } sub manage_selection { my ($self, %options) = @_; my $instance_label = $self->{option_results}->{instance}; $instance_label =~ s/\./ /g; $instance_label =~ s/(\w+)/\u\L$1/g; $self->{instances} = {}; my $apps; if ($self->{option_results}->{instance} =~ /application/) { my $results = $options{custom}->get_endpoint(url_path => '/get-configuration'); $apps = $results->{applications}; } my $results = $options{custom}->query_range( query => 'traffic, server.traffic, client.traffic', instance => $self->{option_results}->{instance}, top => $self->{option_results}->{top}, filter => $self->{option_results}->{filter}, from => $self->{option_results}->{from}, timeframe => $self->{pvql_timeframe}, ); foreach my $result (@{$results}) { next if (!defined(${$result->{key}}[0])); my $instance; $instance = ${$result->{key}}[0]->{value} if (defined(${$result->{key}}[0]->{value})); $instance = ${$result->{key}}[0]->{status} if (defined(${$result->{key}}[0]->{status})); $self->{instances}->{$instance}->{key} = $instance; $self->{instances}->{$instance}->{key} = $apps->{$instance}->{name} if (defined($apps->{$instance}->{name}) && $self->{option_results}->{instance} =~ /application/); $self->{instances}->{$instance}->{traffic} = ${$result->{values}}[0]->{value} * 8 / $self->{pvql_timeframe}; $self->{instances}->{$instance}->{server_traffic} = ${$result->{values}}[1]->{value} * 8 / $self->{pvql_timeframe}; $self->{instances}->{$instance}->{client_traffic} = ${$result->{values}}[2]->{value} * 8 / $self->{pvql_timeframe}; $self->{instances}->{$instance}->{instance_label} = $instance_label; $self->{global}->{total_traffic} += ${$result->{values}}[0]->{value} * 8 / $self->{pvql_timeframe}; $self->{global}->{total_server_traffic} += ${$result->{values}}[1]->{value} * 8 / $self->{pvql_timeframe}; $self->{global}->{total_client_traffic} += ${$result->{values}}[2]->{value} * 8 / $self->{pvql_timeframe}; } if (scalar(keys %{$self->{instances}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No instances or results found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check instances traffic usage. =over 8 =item B<--instance> Filter on a specific instance (Must be a PVQL object, Default: 'layer') (Object 'application' will be mapped with applications name) =item B<--filter> Add a PVQL filter (Example: --filter='application = "mysql"') =item B<--from> Add a PVQL from clause to filter on a specific layer (Example: --from='tcp') =item B<--top> Only search for the top X results (top is made on 'traffic'). =item B<--warning-*> Threshold warning. Can be: 'total-traffic', 'total-client-traffic', 'total-server-traffic', 'traffic', 'client-traffic', 'server-traffic'. =item B<--critical-*> Threshold critical. Can be: 'total-traffic', 'total-client-traffic', 'total-server-traffic', 'traffic', 'client-traffic', 'server-traffic'. =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='total-traffic' =back =cut centreon-plugins-20220113/apps/pvx/restapi/mode/networkuserexperience.pm000066400000000000000000000122501417000230700264050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::pvx::restapi::mode::networkuserexperience; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_instances_output { my ($self, %options) = @_; return $options{instance_value}->{instance_label} . " '" . $options{instance_value}->{key} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'instances', type => 1, cb_prefix_output => 'prefix_instances_output', message_multiple => 'All metrics are ok' }, ]; $self->{maps_counters}->{instances} = [ { label => 'time', nlabel => 'enduser.experience.seconds', set => { key_values => [ { name => 'user_experience' }, { name => 'key' }, { name => 'instance_label' } ], output_template => 'end-user experience: %.3fs', perfdatas => [ { label => 'time', template => '%.3f', min => 0, unit => 's', label_extra_instance => 1, instance_use => 'key' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'instance:s' => { name => 'instance', default => 'layer' }, 'top:s' => { name => 'top' }, 'filter:s' => { name => 'filter' }, 'from:s' => { name => 'from' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{from}) || $self->{option_results}->{from} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --from option as a PVQL object."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{instance}) || $self->{option_results}->{instance} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --instance option as a PVQL object."); $self->{output}->option_exit(); } $self->{pvql_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; } sub manage_selection { my ($self, %options) = @_; my $instance_label = $self->{option_results}->{instance}; $instance_label =~ s/\./ /g; $instance_label =~ s/(\w+)/\u\L$1/g; $self->{instances} = {}; my $apps; if ($self->{option_results}->{instance} =~ /application/) { my $results = $options{custom}->get_endpoint(url_path => '/get-configuration'); $apps = $results->{applications}; } my $results = $options{custom}->query_range( query => 'user.experience', instance => $self->{option_results}->{instance}, top => $self->{option_results}->{top}, filter => $self->{option_results}->{filter}, from => $self->{option_results}->{from}, timeframe => $self->{pvql_timeframe}, ); foreach my $result (@{$results}) { next if (!defined(${$result->{key}}[0])); my $instance; $instance = ${$result->{key}}[0]->{value} if (defined(${$result->{key}}[0]->{value})); $instance = ${$result->{key}}[0]->{status} if (defined(${$result->{key}}[0]->{status})); $self->{instances}->{$instance}->{key} = $instance; $self->{instances}->{$instance}->{key} = $apps->{$instance}->{name} if (defined($apps->{$instance}->{name}) && $self->{option_results}->{instance} =~ /application/); $self->{instances}->{$instance}->{user_experience} = (defined(${$result->{values}}[0]->{value})) ? ${$result->{values}}[0]->{value} : 0; $self->{instances}->{$instance}->{instance_label} = $instance_label; } if (scalar(keys %{$self->{instances}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No instances or results found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check instances connection metrics. =over 8 =item B<--instance> Filter on a specific instance (Must be a PVQL object, Default: 'layer') (Object 'application' will be mapped with applications name) =item B<--filter> Add a PVQL filter (Example: --filter='application = "mysql"') =item B<--from> Add a PVQL from clause to filter on a specific layer (Example: --from='tcp') =item B<--top> Only search for the top X results. =item B<--warning-time> Threshold warning (s). =item B<--critical-time> Threshold critical (s). =back =cut centreon-plugins-20220113/apps/pvx/restapi/plugin.pm000066400000000000000000000030351417000230700223200ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::pvx::restapi::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} = { 'http-hits' => 'apps::pvx::restapi::mode::httphits', 'network-connection' => 'apps::pvx::restapi::mode::networkconnection', 'network-user-experience' => 'apps::pvx::restapi::mode::networkuserexperience', 'network-traffic' => 'apps::pvx::restapi::mode::networktraffic' }; $self->{custom_modes}->{api} = 'apps::pvx::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check PVX (Performance Vision). =cut centreon-plugins-20220113/apps/redis/000077500000000000000000000000001417000230700173055ustar00rootroot00000000000000centreon-plugins-20220113/apps/redis/rlec/000077500000000000000000000000001417000230700202325ustar00rootroot00000000000000centreon-plugins-20220113/apps/redis/rlec/restapi/000077500000000000000000000000001417000230700217015ustar00rootroot00000000000000centreon-plugins-20220113/apps/redis/rlec/restapi/custom/000077500000000000000000000000001417000230700232135ustar00rootroot00000000000000centreon-plugins-20220113/apps/redis/rlec/restapi/custom/api.pm000066400000000000000000000135061417000230700243270ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::redis::rlec::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use JSON::XS; 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 => { 'interval:s@' => { name => 'interval' }, 'hostname:s@' => { name => 'hostname' }, 'port:s@' => { name => 'port' }, 'proto:s@' => { name => 'proto' }, 'username:s@' => { name => 'username' }, 'password:s@' => { name => 'password' }, 'timeout:s@' => { name => 'timeout' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? shift(@{$self->{option_results}->{hostname}}) : undef; $self->{port} = (defined($self->{option_results}->{port})) ? shift(@{$self->{option_results}->{port}}) : 9443; $self->{proto} = (defined($self->{option_results}->{proto})) ? shift(@{$self->{option_results}->{proto}}) : 'https'; $self->{username} = (defined($self->{option_results}->{username})) ? shift(@{$self->{option_results}->{username}}) : ''; $self->{password} = (defined($self->{option_results}->{password})) ? shift(@{$self->{option_results}->{password}}) : ''; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? shift(@{$self->{option_results}->{timeout}}) : 10; $self->{interval} = (defined($self->{option_results}->{interval})) ? shift(@{$self->{option_results}->{interval}}) : '15min'; if (!defined($self->{hostname})) { $self->{output}->add_option_msg(short_msg => "Need to specify hostname option."); $self->{output}->option_exit(); } if (!defined($self->{hostname}) || scalar(@{$self->{option_results}->{hostname}}) == 0) { return 0; } return 1; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{credentials} = 1; $self->{option_results}->{basic} = 1; $self->{option_results}->{username} = $self->{username}; $self->{option_results}->{password} = $self->{password}; $self->{option_results}->{warning_status} = ''; $self->{option_results}->{critical_status} = ''; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->set_options(%{$self->{option_results}}); } sub get_connection_info { my ($self, %options) = @_; return $self->{hostname} . ":" . $self->{port}; } sub get_interval { my ($self, %options) = @_; return $self->{interval}; } sub get { my ($self, %options) = @_; $self->settings(); my $response = $self->{http}->request(url_path => $options{path}); my $content; eval { $content = JSON::XS->new->utf8->decode($response); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } my $return; if (ref($content) eq 'ARRAY') { foreach my $uid (@$content) { if (defined($uid->{errmsg})) { $self->{output}->add_option_msg(short_msg => "Cannot get data: " . $uid->{errmsg}); $self->{output}->option_exit(); } $return->{$uid->{uid}} = $uid; } } else { if (defined($content->{errmsg})) { $self->{output}->add_option_msg(short_msg => "Cannot get data: " . $content->{errmsg}); $self->{output}->option_exit(); } $return = $content; } return $return; } 1; __END__ =head1 NAME RedisLabs Enterprise Cluster REST API =head1 SYNOPSIS RedisLabs Enterprise Cluster Rest API custom mode =head1 REST API OPTIONS =over 8 =item B<--interval> Time interval from which to retrieve statistics (Default: '15min'). Can be : '1sec', '10sec', '5min', '15min', '1hour', '12hour', '1week'. =item B<--hostname> Cluster hostname. =item B<--port> Port used (Default: 9443) =item B<--proto> Specify https if needed (Default: 'https') =item B<--username> Cluster username. =item B<--password> Cluster password. =item B<--timeout> Set HTTP timeout =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/redis/rlec/restapi/mode/000077500000000000000000000000001417000230700226255ustar00rootroot00000000000000centreon-plugins-20220113/apps/redis/rlec/restapi/mode/clusterstats.pm000066400000000000000000000326301417000230700257270ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::redis::rlec::restapi::mode::clusterstats; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_usage_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => $self->{result_values}->{perf}, unit => 'B', value => $self->{result_values}->{used}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{result_values}->{label}, total => $self->{result_values}->{total}, cast_int => 1), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{result_values}->{label}, total => $self->{result_values}->{total}, cast_int => 1), min => 0, max => $self->{result_values}->{total} ); } sub custom_usage_threshold { my ($self, %options) = @_; my ($exit, $threshold_value); $threshold_value = $self->{result_values}->{used}; $threshold_value = $self->{result_values}->{free} if (defined($self->{instance_mode}->{option_results}->{free})); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; $threshold_value = $self->{result_values}->{prct_free} if (defined($self->{instance_mode}->{option_results}->{free})); } $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{result_values}->{label}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{result_values}->{label}, exit_litteral => 'warning' } ]); return $exit; } sub custom_usage_output { my ($self, %options) = @_; my ($used_value, $used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); my ($free_value, $free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); my ($total_value, $total_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); return sprintf( "%s usage: Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", $self->{result_values}->{display}, $total_value . " " . $total_unit, $used_value . " " . $used_unit, $self->{result_values}->{prct_used}, $free_value . " " . $free_unit, $self->{result_values}->{prct_free} ); } sub custom_usage_calc { my ($self, %options) = @_; $self->{result_values}->{label} = $options{extra_options}->{label}; $self->{result_values}->{perf} = $options{extra_options}->{perf}; $self->{result_values}->{display} = $options{extra_options}->{display}; $self->{result_values}->{free} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{free}}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{total}}; if ($self->{result_values}->{total} != 0) { $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}; } else { $self->{result_values}->{used} = '0'; $self->{result_values}->{prct_used} = '0'; $self->{result_values}->{prct_free} = '0'; } return 0; } sub prefix_output { my ($self, %options) = @_; return "Cluster '" . $options{instance_value}->{name} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'cluster', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All cluster counters are ok' } ]; $self->{maps_counters}->{cluster} = [ { label => 'cpu-system', set => { key_values => [ { name => 'cpu_system' } ], output_template => 'Cpu system: %.2f %%', perfdatas => [ { label => 'cpu_system', template => '%.2f', min => 0, max => 100, unit => '%' } ] } }, { label => 'cpu-user', set => { key_values => [ { name => 'cpu_user' } ], output_template => 'Cpu user: %.2f %%', perfdatas => [ { label => 'cpu_user', template => '%.2f', min => 0, max => 100, unit => '%' } ] } }, { label => 'memory', set => { key_values => [ { name => 'free_memory' }, { name => 'total_memory' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { display => 'Ram', label => 'memory', perf => 'memory', free => 'free_memory', total => 'total_memory' }, 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 => 'persistent-storage', set => { key_values => [ { name => 'persistent_storage_free' }, { name => 'persistent_storage_size' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { display => 'Persistent storage', label => 'persistent-storage', perf => 'persistent_storage', free => 'persistent_storage_free', total => 'persistent_storage_size' }, 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 => 'ephemeral-storage', set => { key_values => [ { name => 'ephemeral_storage_free' }, { name => 'ephemeral_storage_size' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { display => 'Ephemeral storage', label => 'ephemeral-storage', perf => 'ephemeral_storage', free => 'ephemeral_storage_free', total => 'ephemeral_storage_size' }, 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 => 'flash-storage', set => { key_values => [ { name => 'bigstore_free' }, { name => 'bigstore_size' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { display => 'Flash storage', label => 'flash-storage', perf => 'flash_storage', free => 'bigstore_free', total => 'bigstore_size' }, 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 => 'flash-iops', set => { key_values => [ { name => 'bigstore_iops' } ], output_template => 'Flash IOPS: %s ops/s', perfdatas => [ { label => 'flash_iops', template => '%s', min => 0, unit => 'ops/s' } ] } }, { label => 'flash-throughput', set => { key_values => [ { name => 'bigstore_throughput' } ], output_template => 'Flash throughput: %s %s/s', output_change_bytes => 1, perfdatas => [ { label => 'flash_throughput', template => '%s', min => 0, unit => 'B/s' } ] } }, { label => 'connections', set => { key_values => [ { name => 'conns' } ], output_template => 'Connections: %s', perfdatas => [ { label => 'connections', template => '%s', min => 0 } ] } }, { label => 'requests', set => { key_values => [ { name => 'total_req' } ], output_template => 'Requests rate: %s ops/s', perfdatas => [ { label => 'requests', template => '%s', min => 0, unit => 'ops/s' } ] } }, { label => 'traffic-in', set => { key_values => [ { name => 'ingress' } ], output_template => 'Traffic In: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'traffic_in', template => '%d', min => 0, unit => 'b/s' } ] } }, { label => 'traffic-out', set => { key_values => [ { name => 'egress' } ], output_template => 'Traffic Out: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'traffic_out', template => '%d', min => 0, unit => 'b/s' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'units:s' => { name => 'units', default => '%' }, 'free' => { name => 'free' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->get(path => '/v1/cluster/stats/last?interval=' . $options{custom}->get_interval()); my $result2 = $options{custom}->get(path => '/v1/cluster'); my $result3 = $options{custom}->get(path => '/v1/nodes'); my $total_memory = 0; my $persistent_storage_size = 0; my $ephemeral_storage_size = 0; my $bigstore_size = 0; foreach my $node (keys %{$result3}) { if (defined($result3->{$node}->{total_memory})) { $total_memory = $total_memory + $result3->{$node}->{total_memory}; } if (defined($result3->{$node}->{persistent_storage_size})) { $persistent_storage_size = $persistent_storage_size + $result3->{$node}->{persistent_storage_size}; } if (defined($result3->{$node}->{ephemeral_storage_size})) { $ephemeral_storage_size = $ephemeral_storage_size + $result3->{$node}->{ephemeral_storage_size}; } if (defined($result3->{$node}->{bigstore_size})) { $bigstore_size = $bigstore_size + $result3->{$node}->{bigstore_size}; } } $self->{cluster}->{$result2->{name}} = { name => $result2->{name}, cpu_system => $result->{cpu_system} * 100, cpu_user => $result->{cpu_user} * 100, free_memory => $result->{free_memory}, total_memory => $total_memory, persistent_storage_free => $result->{persistent_storage_free}, persistent_storage_size => $persistent_storage_size, ephemeral_storage_free => $result->{ephemeral_storage_free}, ephemeral_storage_size => $ephemeral_storage_size, bigstore_free => $result->{bigstore_free}, bigstore_size => $bigstore_size, bigstore_iops => $result->{bigstore_iops}, bigstore_kv_ops => $result->{bigstore_kv_ops}, bigstore_throughput => $result->{bigstore_throughput}, conns => $result->{conns}, total_req => $result->{total_req}, ingress => $result->{ingress_bytes} * 8, egress => $result->{egress_bytes} * 8 }; } 1; __END__ =head1 MODE Check RedisLabs Enterprise Cluster statistics. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^cpu' =item B<--units> Units of thresholds (Default: '%') ('%', 'B'). =item B<--free> Thresholds are on free space left. =item B<--warning-*> Threshold warning. Can be: 'cpu-system', 'cpu-user', 'requests', 'memory', 'flash-storage', 'persistent-storage', 'ephemeral-storage', 'flash-iops', 'flash-throughput', 'connections', 'traffic-in', 'traffic-out'. =item B<--critical-*> Threshold critical. Can be: 'cpu-system', 'cpu-user', 'requests', 'memory', 'flash-storage', 'persistent-storage', 'ephemeral-storage', 'flash-iops', 'flash-throughput', 'connections', 'traffic-in', 'traffic-out'. =back =cut centreon-plugins-20220113/apps/redis/rlec/restapi/mode/databasesstats.pm000066400000000000000000000713671417000230700262070ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::redis::rlec::restapi::mode::databasesstats; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_usage_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => $self->{result_values}->{perf}, unit => 'B', value => $self->{result_values}->{used}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{result_values}->{label}, total => $self->{result_values}->{total}, cast_int => 1), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{result_values}->{label}, total => $self->{result_values}->{total}, cast_int => 1), min => 0, max => $self->{result_values}->{total} ); } sub custom_usage_threshold { my ($self, %options) = @_; my ($exit, $threshold_value); $threshold_value = $self->{result_values}->{used}; $threshold_value = $self->{result_values}->{free} if (defined($self->{instance_mode}->{option_results}->{free})); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; $threshold_value = $self->{result_values}->{prct_free} if (defined($self->{instance_mode}->{option_results}->{free})); } $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{result_values}->{label}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{result_values}->{label}, exit_litteral => 'warning' } ]); return $exit; } sub custom_usage_output { my ($self, %options) = @_; my ($used_value, $used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); my ($free_value, $free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); my ($total_value, $total_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); return sprintf( "%s usage: Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", $self->{result_values}->{display}, $total_value . " " . $total_unit, $used_value . " " . $used_unit, $self->{result_values}->{prct_used}, $free_value . " " . $free_unit, $self->{result_values}->{prct_free} ); } sub custom_usage_calc { my ($self, %options) = @_; $self->{result_values}->{label} = $options{extra_options}->{label}; $self->{result_values}->{perf} = $options{extra_options}->{perf}; $self->{result_values}->{display} = $options{extra_options}->{display}; $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{used}}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{total}}; if ($self->{result_values}->{total} != 0) { $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}; } else { $self->{result_values}->{used} = 0; $self->{result_values}->{prct_used} = 0; $self->{result_values}->{prct_free} = 0; } return 0; } sub custom_status_output { my ($self, %options) = @_; return sprintf( "Status is '%s' [type: %s] [shard list: %s] [backup status: %s] [export status: %s] [import status: %s]", $self->{result_values}->{status}, $self->{result_values}->{type}, $self->{result_values}->{shard_list}, $self->{result_values}->{backup_status}, $self->{result_values}->{export_status}, $self->{result_values}->{import_status} ); } sub custom_cpu_output { my ($self, %options) = @_; return sprintf( "%s CPU usage (user/system): %s/%s %%", $self->{result_values}->{cpu}, $self->{result_values}->{user}, $self->{result_values}->{system} ); } sub custom_cpu_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{display}}; $self->{result_values}->{cpu} = $options{extra_options}->{cpu}; $self->{result_values}->{user} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{user}}; $self->{result_values}->{system} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{system}}; return 0; } sub custom_operations_output { my ($self, %options) = @_; return sprintf( "%s operations rates (hits/misses/requests/responses): %s/%s/%s/%s ops/s", $self->{result_values}->{operation}, $self->{result_values}->{hits}, $self->{result_values}->{misses}, $self->{result_values}->{req}, $self->{result_values}->{res} ); } sub custom_operations_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{display}}; $self->{result_values}->{operation} = $options{extra_options}->{operation}; $self->{result_values}->{hits} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{hits}}; $self->{result_values}->{misses} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{misses}}; $self->{result_values}->{req} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{req}}; $self->{result_values}->{res} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{res}}; return 0; } sub prefix_output { my ($self, %options) = @_; return "Database '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'databases', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All databases counters are ok' } ]; $self->{maps_counters}->{databases} = [ { label => 'status', type => 2, critical_default => '%{status} =~ /creation-failed/i || %{backup_status} =~ /failed/i || %{export_status} =~ /failed/i || %{import_status} =~ /failed/i', set => { key_values => [ { name => 'status' }, { name => 'type' }, { name => 'backup_status' }, { name => 'export_status' }, { name => 'import_status' }, { name => 'shard_list' }, { name => 'display' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'total-cpu', set => { key_values => [ { name => 'shard_cpu_user' }, { name => 'shard_cpu_system' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_cpu_calc'), closure_custom_calc_extra_options => { cpu => 'Total', user => 'shard_cpu_user', system => 'shard_cpu_system', display => 'display' }, closure_custom_output => $self->can('custom_cpu_output'), perfdatas => [ { label => 'total_cpu_user', value => 'user', template => '%s', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' }, { label => 'total_cpu_system', value => 'system', template => '%s', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'fork-cpu', set => { key_values => [ { name => 'fork_cpu_user' }, { name => 'fork_cpu_system' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_cpu_calc'), closure_custom_calc_extra_options => { cpu => 'Fork', user => 'fork_cpu_user', system => 'fork_cpu_system', display => 'display' }, closure_custom_output => $self->can('custom_cpu_output'), perfdatas => [ { label => 'fork_cpu_user', value => 'user', template => '%s', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' }, { label => 'fork_cpu_system', value => 'system', template => '%s', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'main-thread-cpu', set => { key_values => [ { name => 'main_thread_cpu_user' }, { name => 'main_thread_cpu_system' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_cpu_calc'), closure_custom_calc_extra_options => { cpu => 'Main thread', user => 'main_thread_cpu_user', system => 'main_thread_cpu_system', display => 'display' }, closure_custom_output => $self->can('custom_cpu_output'), perfdatas => [ { label => 'main_thread_cpu_user', value => 'user', template => '%s', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' }, { label => 'main_thread_cpu_system', value => 'system', template => '%s', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'memory', set => { key_values => [ { name => 'used_memory' }, { name => 'memory_size' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { display => 'Memory', label => 'memory', perf => 'memory', used => 'used_memory', total => 'memory_size' }, 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 => 'mem-frag-ratio', set => { key_values => [ { name => 'mem_frag_ratio' }, { name => 'display' } ], output_template => 'Memory fragmentation ratio: %s', perfdatas => [ { label => 'mem_frag_ratio', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'connections', set => { key_values => [ { name => 'conns' }, { name => 'display' } ], output_template => 'Connections: %s', perfdatas => [ { label => 'connections', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'total-rates', set => { key_values => [ { name => 'total_hits' }, { name => 'total_misses' }, { name => 'total_req' }, { name => 'total_res' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_operations_calc'), closure_custom_calc_extra_options => { operation => 'Total', hits => 'total_hits', misses => 'total_misses', req => 'total_req', res => 'total_res', display => 'display' }, closure_custom_output => $self->can('custom_operations_output'), perfdatas => [ { label => 'total_hits', value => 'hits', template => '%s', min => 0, unit => 'ops/s', label_extra_instance => 1, instance_use => 'display' }, { label => 'total_misses', value => 'misses', template => '%s', min => 0, unit => 'ops/s', label_extra_instance => 1, instance_use => 'display' }, { label => 'total_req', value => 'req', template => '%s', min => 0, unit => 'ops/s', label_extra_instance => 1, instance_use => 'display' }, { label => 'total_res', value => 'res', template => '%s', min => 0, unit => 'ops/s', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'latency', set => { key_values => [ { name => 'avg_latency' }, { name => 'display' } ], output_template => 'Average latency: %.2f ms', perfdatas => [ { label => 'latency', template => '%.2f', min => 0, unit => 'ms', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'other-rates', set => { key_values => [ { name => 'other_hits' }, { name => 'other_misses' }, { name => 'other_req' }, { name => 'other_res' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_operations_calc'), closure_custom_calc_extra_options => { operation => 'Other', hits => 'other_hits', misses => 'other_misses', req => 'other_req', res => 'other_res', display => 'display' }, closure_custom_output => $self->can('custom_operations_output'), perfdatas => [ { label => 'other_req', value => 'req', template => '%s', min => 0, unit => 'ops/s', label_extra_instance => 1, instance_use => 'display' }, { label => 'other_res', value => 'res', template => '%s', min => 0, unit => 'ops/s', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'other-latency', set => { key_values => [ { name => 'avg_other_latency' }, { name => 'display' } ], output_template => 'Other latency: %.2f ms', perfdatas => [ { label => 'other_latency', template => '%.2f', min => 0, unit => 'ms', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'keys', set => { key_values => [ { name => 'no_of_keys' }, { name => 'display' } ], output_template => 'Total keys: %s', perfdatas => [ { label => 'keys', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'evicted-objects', set => { key_values => [ { name => 'evicted_objects' }, { name => 'display' } ], output_template => 'Evicted objects rate: %s evictions/sec', perfdatas => [ { label => 'evicted_objects', template => '%s', min => 0, unit => 'evictions/sec', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'expired-objects', set => { key_values => [ { name => 'expired_objects' }, { name => 'display' } ], output_template => 'Expired objects rate: %s expirations/sec', perfdatas => [ { label => 'expired_objects', template => '%s', min => 0, unit => 'expirations/sec', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'read-rates', set => { key_values => [ { name => 'read_hits' }, { name => 'read_misses' }, { name => 'read_req' }, { name => 'read_res' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_operations_calc'), closure_custom_calc_extra_options => { operation => 'Read', hits => 'read_hits', misses => 'read_misses', req => 'read_req', res => 'read_res', display => 'display' }, closure_custom_output => $self->can('custom_operations_output'), perfdatas => [ { label => 'read_hits', value => 'hits', template => '%s', min => 0, unit => 'ops/s', label_extra_instance => 1, instance_use => 'display' }, { label => 'read_misses', value => 'misses', template => '%s', min => 0, unit => 'ops/s', label_extra_instance => 1, instance_use => 'display' }, { label => 'read_req', value => 'req', template => '%s', min => 0, unit => 'ops/s', label_extra_instance => 1, instance_use => 'display' }, { label => 'read_res', value => 'res', template => '%s', min => 0, unit => 'ops/s', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'read-latency', set => { key_values => [ { name => 'avg_read_latency' }, { name => 'display' } ], output_template => 'Read latency: %.2f ms', perfdatas => [ { label => 'read_latency', template => '%.2f', min => 0, unit => 'ms', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'write-rates', set => { key_values => [ { name => 'write_hits' }, { name => 'write_misses' }, { name => 'write_req' }, { name => 'write_res' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_operations_calc'), closure_custom_calc_extra_options => { operation => 'Write', hits => 'write_hits', misses => 'write_misses', req => 'write_req', res => 'write_res', display => 'display' }, closure_custom_output => $self->can('custom_operations_output'), perfdatas => [ { label => 'write_hits', value => 'hits', template => '%s', min => 0, unit => 'ops/s', label_extra_instance => 1, instance_use => 'display' }, { label => 'write_misses', value => 'misses', template => '%s', min => 0, unit => 'ops/s', label_extra_instance => 1, instance_use => 'display' }, { label => 'write_req', value => 'req', template => '%s', min => 0, unit => 'ops/s', label_extra_instance => 1, instance_use => 'display' }, { label => 'write_res', value => 'res', template => '%s', min => 0, unit => 'ops/s', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'write-latency', set => { key_values => [ { name => 'avg_write_latency' }, { name => 'display' } ], output_template => 'Write latency: %.2f ms', perfdatas => [ { label => 'write_latency', template => '%.2f', min => 0, unit => 'ms', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'traffic-in', set => { key_values => [ { name => 'ingress' }, { name => 'display' } ], output_template => 'Traffic In: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'traffic_in', template => '%d', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'traffic-out', set => { key_values => [ { name => 'egress' }, { name => 'display' } ], output_template => 'Traffic Out: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'traffic_out', template => '%d', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-database:s' => { name => 'filter_database' }, 'units:s' => { name => 'units', default => '%' }, 'free' => { name => 'free' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->get(path => '/v1/bdbs/stats/last?interval='.$options{custom}->get_interval()); my $result2 = $options{custom}->get(path => '/v1/bdbs'); foreach my $database (keys %{$result}) { if (defined($self->{option_results}->{filter_database}) && $self->{option_results}->{filter_database} ne '' && $database !~ /$self->{option_results}->{filter_database}/) { $self->{output}->output_add(long_msg => "skipping database '" . $database . "': no matching filter.", debug => 1); next; } my $shard_list = '-'; if (@{$result2->{$database}->{shard_list}}) { $shard_list = join(", ", @{$result2->{$database}->{shard_list}}); } $self->{databases}->{$database} = { display => $result2->{$database}->{name}, status => defined($result2->{$database}->{status}) ? $result2->{$database}->{status} : '-', type => defined($result2->{$database}->{type}) ? $result2->{$database}->{type} : '-', backup_status => defined($result2->{$database}->{backup_status}) ? $result2->{$database}->{backup_status} : '-', export_status => defined($result2->{$database}->{export_status}) ? $result2->{$database}->{export_status} : '-', import_status => defined($result2->{$database}->{import_status}) ? $result2->{$database}->{import_status} : '-', shard_list => $shard_list, shard_cpu_user => $result->{$database}->{shard_cpu_user} * 100, shard_cpu_system => $result->{$database}->{shard_cpu_system} * 100, main_thread_cpu_user => $result->{$database}->{main_thread_cpu_user} * 100, main_thread_cpu_system => $result->{$database}->{main_thread_cpu_system} * 100, fork_cpu_user => $result->{$database}->{fork_cpu_user} * 100, fork_cpu_system => $result->{$database}->{fork_cpu_system} * 100, used_memory => $result->{$database}->{used_memory}, memory_size => $result2->{$database}->{memory_size}, mem_frag_ratio => $result->{$database}->{mem_frag_ratio}, conns => $result->{$database}->{conns}, total_req => defined($result->{$database}->{total_req}) ? $result->{$database}->{total_req} : $result->{$database}->{instantaneous_ops_per_sec}, total_res => $result->{$database}->{total_res}, total_hits => $result->{$database}->{read_hits} + $result->{$database}->{write_hits}, total_misses => $result->{$database}->{read_misses} + $result->{$database}->{write_misses}, avg_latency => defined($result2->{$database}->{avg_latency}) ? $result->{$database}->{avg_latency} * 1000 : '0', other_req => $result->{$database}->{other_req}, other_res => $result->{$database}->{other_res}, other_hits => '-', other_misses => '-', avg_other_latency => defined($result2->{$database}->{avg_other_latency}) ? $result->{$database}->{avg_other_latency} * 1000 : '0', no_of_keys => $result->{$database}->{no_of_keys}, evicted_objects => $result->{$database}->{evicted_objects}, expired_objects => $result->{$database}->{expired_objects}, read_hits => $result->{$database}->{read_hits}, read_misses => $result->{$database}->{read_misses}, read_req => $result->{$database}->{read_req}, read_res => $result->{$database}->{read_res}, write_hits => $result->{$database}->{write_hits}, write_misses => $result->{$database}->{write_misses}, write_req => $result->{$database}->{write_req}, write_res => $result->{$database}->{write_res}, avg_read_latency => defined($result2->{$database}->{avg_read_latency}) ? $result->{$database}->{avg_read_latency} * 1000 : '0', avg_write_latency => defined($result2->{$database}->{avg_write_latency}) ? $result->{$database}->{avg_write_latency} * 1000 : '0', ingress => $result->{$database}->{ingress_bytes} * 8, egress => $result->{$database}->{egress_bytes} * 8 }; if (scalar(keys %{$self->{databases}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No databases detected, check your filter ? '); $self->{output}->option_exit(); } } } 1; __END__ =head1 MODE Check RedisLabs Enterprise Cluster databases statistics. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='rate|latency' =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{status}, %{type}, %{backup_status}, %{export_status}, %{shard_list}. 'status' can be: 'pending', 'active', 'active-change-pending', 'delete-pending', 'import-pending', 'creation-failed', 'recovery'. 'type' can be: 'redis', 'memcached'. 'backup_status' can be: 'exporting', 'succeeded', 'failed'. 'export_status' can be: 'exporting', 'succeeded', 'failed'. 'import_status' can be: 'idle', 'initializing', 'importing', 'succeeded', 'failed'. =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /creation-failed/i | %{backup_status} =~ /failed/i | %{export_status} =~ /failed/i | %{import_status} =~ /failed/i'). Can used special variables like: %{status}, %{type}, %{backup_status}, %{export_status}, %{shard_list}. 'status' can be: 'pending', 'active', 'active-change-pending', 'delete-pending', 'import-pending', 'creation-failed', 'recovery'. 'type' can be: 'redis', 'memcached'. 'backup_status' can be: 'exporting', 'succeeded', 'failed'. '' can be: 'exporting', 'succeeded', 'failed'. 'import_status' can be: 'idle', 'initializing', 'importing', 'succeeded', 'failed'. =item B<--warning-*> Threshold warning. Can be: 'total-cpu', 'fork-cpu', 'main-thread-cpu', 'memory', 'mem-frag-ratio', 'connections', 'total-rates', 'latency', 'other-rates', 'other-latency', 'keys', 'evicted-objects', 'expired-objects', 'read-rates', 'read-latency', 'write-rates', 'write-latency', 'traffic-in', 'traffic-out'. =item B<--critical-*> Threshold critical. Can be: 'total-cpu', 'fork-cpu', 'main-thread-cpu', 'memory', 'mem-frag-ratio', 'connections', 'total-rates', 'latency', 'other-rates', 'other-latency', 'keys', 'evicted-objects', 'expired-objects', 'read-rates', 'read-latency', 'write-rates', 'write-latency', 'traffic-in', 'traffic-out'. =back =cut centreon-plugins-20220113/apps/redis/rlec/restapi/mode/listdatabases.pm000066400000000000000000000052221417000230700260070ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::redis::rlec::restapi::mode::listdatabases; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{databases} = $options{custom}->get(path => '/v1/bdbs'); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $database_uid (sort keys %{$self->{databases}}) { $self->{output}->output_add( long_msg => '[uid = ' . $database_uid . "] [name = '" . $self->{databases}->{$database_uid}->{name} . "']" . " [type = '" . $self->{databases}->{$database_uid}->{type} . "']" . " [status = '" . $self->{databases}->{$database_uid}->{status} . "']" ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List databases:' ); $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 => ['uid', 'name', 'type', 'status']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $database_uid (sort keys %{$self->{databases}}) { $self->{output}->add_disco_entry( name => $self->{databases}->{$database_uid}->{name}, type => $self->{databases}->{$database_uid}->{type}, status => $self->{databases}->{$database_uid}->{status}, uid => $database_uid ); } } 1; __END__ =head1 MODE List databases. =over 8 =back =cut centreon-plugins-20220113/apps/redis/rlec/restapi/mode/listnodes.pm000066400000000000000000000044231417000230700251720ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::redis::rlec::restapi::mode::listnodes; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{nodes} = $options{custom}->get(path => '/v1/nodes'); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $node_uid (sort keys %{$self->{nodes}}) { $self->{output}->output_add(long_msg => '[uid = ' . $node_uid . "] [status = '" . $self->{nodes}->{$node_uid}->{status} . "']"); } $self->{output}->output_add( severity => 'OK', short_msg => 'List nodes:' ); $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 => ['uid', 'status']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $node_uid (sort keys %{$self->{nodes}}) { $self->{output}->add_disco_entry( status => $self->{nodes}->{$node_uid}->{status}, uid => $node_uid ); } } 1; __END__ =head1 MODE List nodes. =over 8 =back =cut centreon-plugins-20220113/apps/redis/rlec/restapi/mode/listshards.pm000066400000000000000000000052111417000230700253420ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::redis::rlec::restapi::mode::listshards; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{shards} = $options{custom}->get(path => '/v1/shards'); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $shard_uid (sort keys %{$self->{shards}}) { $self->{output}->output_add( long_msg => '[uid = ' . $shard_uid . "] [role = '" . $self->{shards}->{$shard_uid}->{role} . "']" . " [detailed_status = '" . $self->{shards}->{$shard_uid}->{detailed_status} . "']" . " [status = '" . $self->{shards}->{$shard_uid}->{status} . "']" ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List shards:' ); $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 => ['uid', 'role', 'detailed_status', 'status']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $shard_uid (sort keys %{$self->{shards}}) { $self->{output}->add_disco_entry( role => $self->{shards}->{$shard_uid}->{role}, detailed_status => $self->{shards}->{$shard_uid}->{detailed_status}, status => $self->{shards}->{$shard_uid}->{status}, uid => $shard_uid ); } } 1; __END__ =head1 MODE List shards. =over 8 =back =cut centreon-plugins-20220113/apps/redis/rlec/restapi/mode/nodesstats.pm000066400000000000000000000422061417000230700253560ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::redis::rlec::restapi::mode::nodesstats; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_usage_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => $self->{result_values}->{perf}, unit => 'B', value => $self->{result_values}->{used}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{result_values}->{label}, total => $self->{result_values}->{total}, cast_int => 1), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{result_values}->{label}, total => $self->{result_values}->{total}, cast_int => 1), min => 0, max => $self->{result_values}->{total} ); } sub custom_usage_threshold { my ($self, %options) = @_; my ($exit, $threshold_value); $threshold_value = $self->{result_values}->{used}; $threshold_value = $self->{result_values}->{free} if (defined($self->{instance_mode}->{option_results}->{free})); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; $threshold_value = $self->{result_values}->{prct_free} if (defined($self->{instance_mode}->{option_results}->{free})); } $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{result_values}->{label}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{result_values}->{label}, exit_litteral => 'warning' } ]); return $exit; } sub custom_usage_output { my ($self, %options) = @_; my ($used_value, $used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); my ($free_value, $free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); my ($total_value, $total_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); return sprintf( "%s usage: Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", $self->{result_values}->{display}, $total_value . " " . $total_unit, $used_value . " " . $used_unit, $self->{result_values}->{prct_used}, $free_value . " " . $free_unit, $self->{result_values}->{prct_free} ); } sub custom_usage_calc { my ($self, %options) = @_; $self->{result_values}->{label} = $options{extra_options}->{label}; $self->{result_values}->{perf} = $options{extra_options}->{perf}; $self->{result_values}->{display} = $options{extra_options}->{display}; $self->{result_values}->{free} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{free}}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{total}}; if ($self->{result_values}->{total} != 0) { $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}; } else { $self->{result_values}->{used} = 0; $self->{result_values}->{prct_used} = 0; $self->{result_values}->{prct_free} = 0; } return 0; } sub custom_status_output { my ($self, %options) = @_; return sprintf( "Status is '%s' [shard list: %s] [int addr: %s] [ext addr: %s]", $self->{result_values}->{status}, $self->{result_values}->{shard_list}, $self->{result_values}->{int_addr}, $self->{result_values}->{ext_addr} ); } sub prefix_output { my ($self, %options) = @_; return "Node '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'nodes', type => 1, cb_prefix_output => 'prefix_output', message_separator => ', ', message_multiple => 'All nodes counters are ok' } ]; $self->{maps_counters}->{nodes} = [ { label => 'status', type => 2, critical_default => '%{status} =~ /down/i', set => { key_values => [ { name => 'status' }, { name => 'shard_list' }, { name => 'int_addr' }, { name => 'ext_addr' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'shard-count', set => { key_values => [ { name => 'shard_count' }, { name => 'display' } ], output_template => 'Shard count: %d', perfdatas => [ { label => 'shard_count', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'uptime', set => { key_values => [ { name => 'uptime' }, { name => 'uptime_sec' }, { name => 'display' } ], output_template => 'Uptime: %s', perfdatas => [ { label => 'uptime', template => '%d', min => 0, unit => 's', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'cpu-system', set => { key_values => [ { name => 'cpu_system' }, { name => 'display' } ], output_template => 'Cpu system: %.2f %%', perfdatas => [ { label => 'cpu_system', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'cpu-user', set => { key_values => [ { name => 'cpu_user' }, { name => 'display' } ], output_template => 'Cpu user: %.2f %%', perfdatas => [ { label => 'cpu_user', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'memory', set => { key_values => [ { name => 'free_memory' }, { name => 'total_memory' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { display => 'Ram', label => 'memory', perf => 'memory', free => 'free_memory', total => 'total_memory' }, 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 => 'persistent-storage', set => { key_values => [ { name => 'persistent_storage_free' }, { name => 'persistent_storage_size' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { display => 'Persistent storage', label => 'persistent-storage', perf => 'persistent_storage', free => 'persistent_storage_free', total => 'persistent_storage_size' }, 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 => 'ephemeral-storage', set => { key_values => [ { name => 'ephemeral_storage_free' }, { name => 'ephemeral_storage_size' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { display => 'Ephemeral storage', label => 'ephemeral-storage', perf => 'ephemeral_storage', free => 'ephemeral_storage_free', total => 'ephemeral_storage_size' }, 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 => 'flash-storage', set => { key_values => [ { name => 'bigstore_free' }, { name => 'bigstore_size' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { display => 'Flash storage', label => 'flash-storage', perf => 'flash_storage', free => 'bigstore_free', total => 'bigstore_size' }, 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 => 'flash-iops', set => { key_values => [ { name => 'bigstore_iops' }, { name => 'display' } ], output_template => 'Flash IOPS: %s ops/s', perfdatas => [ { label => 'flash_iops', template => '%s', min => 0, unit => 'ops/s', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'flash-throughput', set => { key_values => [ { name => 'bigstore_throughput' }, { name => 'display' } ], output_template => 'Flash throughput: %s %s/s', output_change_bytes => 1, perfdatas => [ { label => 'flash_throughput', template => '%s', min => 0, unit => 'B/s', label_extra_instance => 1, instance_use => 'display' } ], } }, { label => 'connections', set => { key_values => [ { name => 'conns' }, { name => 'display' } ], output_template => 'Connections: %s', perfdatas => [ { label => 'connections', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'requests', set => { key_values => [ { name => 'total_req' } ], output_template => 'Requests rate: %s ops/s', perfdatas => [ { label => 'requests', template => '%s', min => 0, unit => 'ops/s' } ] } }, { label => 'traffic-in', set => { key_values => [ { name => 'ingress' }, { name => 'display' } ], output_template => 'Traffic In: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'traffic_in', template => '%d', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'traffic-out', set => { key_values => [ { name => 'egress' }, { name => 'display' } ], output_template => 'Traffic Out: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'traffic_out', template => '%d', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-node:s' => { name => 'filter_node' }, 'units:s' => { name => 'units', default => '%' }, 'free' => { name => 'free' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->get(path => '/v1/nodes/stats/last?interval='.$options{custom}->get_interval()); my $result2 = $options{custom}->get(path => '/v1/nodes'); foreach my $node (keys %{$result}) { if (defined($self->{option_results}->{filter_node}) && $self->{option_results}->{filter_node} ne '' && $node !~ /$self->{option_results}->{filter_node}/) { $self->{output}->output_add(long_msg => "skipping node '" . $node . "': no matching filter.", debug => 1); next; } my $shard_list = '-'; if (@{$result2->{$node}->{shard_list}}) { $shard_list = join(", ", @{$result2->{$node}->{shard_list}}); } my $ext_addr = '-'; if (@{$result2->{$node}->{external_addr}}) { $ext_addr = join(", ", @{$result2->{$node}->{external_addr}}); } $self->{nodes}->{$node} = { display => $node, status => defined($result2->{$node}->{status}) ? $result2->{$node}->{status} : '-', shard_list => $shard_list, shard_count => $result2->{$node}->{shard_count}, int_addr => $result2->{$node}->{addr}, ext_addr => $ext_addr, uptime => centreon::plugins::misc::change_seconds(value => $result2->{$node}->{uptime}), uptime_sec => $result2->{$node}->{uptime}, cpu_system => $result->{$node}->{cpu_system} * 100, cpu_user => $result->{$node}->{cpu_user} * 100, free_memory => $result->{$node}->{free_memory}, total_memory => $result2->{$node}->{total_memory}, persistent_storage_free => $result->{$node}->{persistent_storage_free}, persistent_storage_size => $result2->{$node}->{persistent_storage_size}, ephemeral_storage_free => $result->{$node}->{ephemeral_storage_free}, ephemeral_storage_size => $result2->{$node}->{ephemeral_storage_size}, bigstore_free => $result->{$node}->{bigstore_free}, bigstore_size => $result2->{$node}->{bigstore_size}, bigstore_iops => $result->{$node}->{bigstore_iops}, bigstore_throughput => $result->{$node}->{bigstore_throughput}, conns => $result->{$node}->{conns}, total_req => $result->{$node}->{total_req}, ingress => $result->{$node}->{ingress_bytes} * 8, egress => $result->{$node}->{egress_bytes} * 8, }; if (scalar(keys %{$self->{nodes}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No nodes detected, check your filter ? '); $self->{output}->option_exit(); } } } 1; __END__ =head1 MODE Check RedisLabs Enterprise Cluster nodes statistics. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^cpu' =item B<--units> Units of thresholds (Default: '%') ('%', 'B'). =item B<--free> Thresholds are on free space left. =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{status}, %{shard_list}, %{int_addr}, %{ext_addr}. 'status' can be: 'active', 'going_offline', 'offline', 'provisioning', 'decommissioning', 'down'. =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /down/i'). Can used special variables like: %{status}, %{shard_list}, %{int_addr}, %{ext_addr}. 'status' can be: 'active', 'going_offline', 'offline', 'provisioning', 'decommissioning', 'down'. =item B<--warning-*> Threshold warning. Can be: 'cpu-system', 'cpu-user', 'requests', 'memory', 'flash-storage', 'persistent-storage', 'ephemeral-storage', 'flash-iops', 'flash-throughput', 'connections', 'traffic-in', 'traffic-out', 'shard-count', 'uptime'. =item B<--critical-*> Threshold critical. Can be: 'cpu-system', 'cpu-user', 'requests', 'memory', 'flash-storage', 'persistent-storage', 'ephemeral-storage', 'flash-iops', 'flash-throughput', 'connections', 'traffic-in', 'traffic-out', 'shard-count', 'uptime'. =back =cut centreon-plugins-20220113/apps/redis/rlec/restapi/mode/shardsstats.pm000066400000000000000000000464461417000230700255440ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::redis::rlec::restapi::mode::shardsstats; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf( "Status is '%s' (%s) [role: %s] [loading status: %s] [backup status: %s]", $self->{result_values}->{status}, $self->{result_values}->{detailed_status}, $self->{result_values}->{role}, $self->{result_values}->{loading}, $self->{result_values}->{backup} ); if ($self->{result_values}->{role} eq 'slave') { $msg .= sprintf(" [sync status: %s]", $self->{result_values}->{sync}); } return $msg; } sub custom_operations_output { my ($self, %options) = @_; return sprintf( "%s operations rates (hits/misses): %s/%s ops/s", $self->{result_values}->{operation}, $self->{result_values}->{hits}, $self->{result_values}->{misses} ); } sub custom_operations_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{display}}; $self->{result_values}->{operation} = $options{extra_options}->{operation}; $self->{result_values}->{hits} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{hits}}; $self->{result_values}->{misses} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{misses}}; return 0; } sub custom_cpu_output { my ($self, %options) = @_; return sprintf( "%s CPU usage (user/system): %s/%s %%", $self->{result_values}->{cpu}, $self->{result_values}->{user}, $self->{result_values}->{system} ); } sub custom_cpu_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{display}}; $self->{result_values}->{cpu} = $options{extra_options}->{cpu}; $self->{result_values}->{user} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{user}}; $self->{result_values}->{system} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{system}}; return 0; } sub prefix_output { my ($self, %options) = @_; return "Shard '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'shards', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All shards counters are ok' } ]; $self->{maps_counters}->{shards} = [ { label => 'status', type => 2, critical_default => '%{status} =~ /inactive/i || %{backup} =~ /failed/i || %{sync} =~ /link_down/i', set => { key_values => [ { name => 'status' }, { name => 'detailed_status' }, { name => 'role' }, { name => 'loading' }, { name => 'sync' }, { name => 'backup' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'total-cpu', set => { key_values => [ { name => 'shard_cpu_user' }, { name => 'shard_cpu_system' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_cpu_calc'), closure_custom_calc_extra_options => { cpu => 'Total', user => 'shard_cpu_user', system => 'shard_cpu_system', display => 'display' }, closure_custom_output => $self->can('custom_cpu_output'), perfdatas => [ { label => 'total_cpu_user', value => 'user', template => '%s', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' }, { label => 'total_cpu_system', value => 'system', template => '%s', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'fork-cpu', set => { key_values => [ { name => 'fork_cpu_user' }, { name => 'fork_cpu_system' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_cpu_calc'), closure_custom_calc_extra_options => { cpu => 'Fork', user => 'fork_cpu_user', system => 'fork_cpu_system', display => 'display' }, closure_custom_output => $self->can('custom_cpu_output'), perfdatas => [ { label => 'fork_cpu_user', value => 'user', template => '%s', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' }, { label => 'fork_cpu_system', value => 'system', template => '%s', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'main-thread-cpu', set => { key_values => [ { name => 'main_thread_cpu_user' }, { name => 'main_thread_cpu_system' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_cpu_calc'), closure_custom_calc_extra_options => { cpu => 'Main thread', user => 'main_thread_cpu_user', system => 'main_thread_cpu_system', display => 'display' }, closure_custom_output => $self->can('custom_cpu_output'), perfdatas => [ { label => 'main_thread_cpu_user', value => 'user', template => '%s', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' }, { label => 'main_thread_cpu_system', value => 'system', template => '%s', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'memory', set => { key_values => [ { name => 'used_memory' }, { name => 'display' } ], output_template => 'Memory used: %s %s', output_change_bytes => 1, perfdatas => [ { label => 'memory', template => '%s', min => 0, unit => 'B', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'mem-frag-ratio', set => { key_values => [ { name => 'mem_frag_ratio' }, { name => 'display' } ], output_template => 'Memory fragmentation ratio: %s', perfdatas => [ { label => 'mem_frag_ratio', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'connected-clients', set => { key_values => [ { name => 'connected_clients' }, { name => 'display' } ], output_template => 'Connected clients: %s', perfdatas => [ { label => 'connected_clients', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'blocked-clients', set => { key_values => [ { name => 'blocked_clients' }, { name => 'display' } ], output_template => 'Blocked clients: %s', perfdatas => [ { label => 'blocked_clients', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'requests', set => { key_values => [ { name => 'total_req'}, { name => 'display' }], output_template => 'Requests rate: %s ops/s', perfdatas => [ { label => 'requests', template => '%s', min => 0, unit => 'ops/s', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'keys', set => { key_values => [ { name => 'no_of_keys' }, { name => 'display' } ], output_template => 'Total keys: %s', perfdatas => [ { label => 'keys', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'volatile-keys', set => { key_values => [ { name => 'no_of_expires' }, { name => 'display' } ], output_template => 'Volatile keys: %s', perfdatas => [ { label => 'volatile_keys', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'evicted-objects', set => { key_values => [ { name => 'evicted_objects' }, { name => 'display' } ], output_template => 'Evicted objects rate: %s evictions/sec', perfdatas => [ { label => 'evicted_objects', template => '%s', min => 0, unit => 'evictions/sec', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'expired-objects', set => { key_values => [ { name => 'expired_objects' }, { name => 'display' } ], output_template => 'Expired objects rate: %s expirations/sec', perfdatas => [ { label => 'expired_objects', template => '%s', min => 0, unit => 'expirations/sec', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'read-rates', set => { key_values => [ { name => 'read_hits' }, { name => 'read_misses' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_operations_calc'), closure_custom_calc_extra_options => { operation => 'Read', hits => 'read_hits', misses => 'read_misses', display => 'display' }, closure_custom_output => $self->can('custom_operations_output'), perfdatas => [ { label => 'read_hits', value => 'hits', template => '%s', min => 0, unit => 'ops/s', label_extra_instance => 1, instance_use => 'display' }, { label => 'read_misses', value => 'misses', template => '%s', min => 0, unit => 'ops/s', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'write-rates', set => { key_values => [ { name => 'write_hits' }, { name => 'write_misses' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_operations_calc'), closure_custom_calc_extra_options => { operation => 'Write', hits => 'write_hits', misses => 'write_misses', display => 'display' }, closure_custom_output => $self->can('custom_operations_output'), perfdatas => [ { label => 'write_hits', value => 'hits', template => '%s', min => 0, unit => 'ops/s', label_extra_instance => 1, instance_use => 'display' }, { label => 'write_misses', value => 'misses', template => '%s', min => 0, unit => 'ops/s', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'rdb-changes-since-last-save', set => { key_values => [ { name => 'rdb_changes_since_last_save' }, { name => 'display' } ], output_template => 'Rdb changes since last save: %s', perfdatas => [ { label => 'rdb_changes_since_last_save', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'last-save-time', set => { key_values => [ { name => 'last_save_time' }, { name => 'last_save_time_sec' }, { name => 'display' } ], output_template => 'Last same time: %s', perfdatas => [ { label => 'last_save_time', template => '%s', min => 0, unit => 's', label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-shard:s' => { name => 'filter_shard' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->get(path => '/v1/shards/stats/last?interval='.$options{custom}->get_interval()); my $result2 = $options{custom}->get(path => '/v1/shards'); foreach my $shard (keys %{$result}) { if (defined($self->{option_results}->{filter_shard}) && $self->{option_results}->{filter_shard} ne '' && $shard !~ /$self->{option_results}->{filter_shard}/) { $self->{output}->output_add(long_msg => "skipping shard '" . $shard . "': no matching filter.", debug => 1); next; } $self->{shards}->{$shard} = { display => $shard, status => defined($result2->{$shard}->{status}) ? $result2->{$shard}->{status} : '-', detailed_status => defined($result2->{$shard}->{detailed_status}) ? $result2->{$shard}->{detailed_status} : '-', role => defined($result2->{$shard}->{role}) ? $result2->{$shard}->{role} : '-', loading => defined($result2->{$shard}->{loading}->{status}) ? $result2->{$shard}->{loading}->{status} : '-', sync => defined($result2->{$shard}->{sync}->{status}) ? $result2->{$shard}->{sync}->{status} : '-', backup => defined($result2->{$shard}->{backup}->{status}) ? $result2->{$shard}->{backup}->{status} : '-', used_memory => $result->{$shard}->{used_memory}, mem_frag_ratio => $result->{$shard}->{mem_frag_ratio}, shard_cpu_user => $result->{$shard}->{shard_cpu_user} * 100, shard_cpu_system => $result->{$shard}->{shard_cpu_system} * 100, main_thread_cpu_user => $result->{$shard}->{main_thread_cpu_user} * 100, main_thread_cpu_system => $result->{$shard}->{main_thread_cpu_system} * 100, fork_cpu_user => $result->{$shard}->{fork_cpu_user} * 100, fork_cpu_system => $result->{$shard}->{fork_cpu_system} * 100, connected_clients => $result->{$shard}->{connected_clients}, blocked_clients => $result->{$shard}->{blocked_clients}, total_req => defined($result->{$shard}->{total_req}) ? $result->{$shard}->{total_req} : $result->{$shard}->{instantaneous_ops_per_sec}, no_of_keys => $result->{$shard}->{no_of_keys}, no_of_expires => $result->{$shard}->{no_of_expires}, evicted_objects => $result->{$shard}->{evicted_objects}, expired_objects => $result->{$shard}->{expired_objects}, read_hits => $result->{$shard}->{read_hits}, read_misses => $result->{$shard}->{read_misses}, write_hits => $result->{$shard}->{write_hits}, write_misses => $result->{$shard}->{write_misses}, rdb_changes_since_last_save => $result->{$shard}->{rdb_changes_since_last_save}, last_save_time => centreon::plugins::misc::change_seconds(value => time() - $result->{$shard}->{last_save_time}), last_save_time_sec => time() - $result->{$shard}->{last_save_time} }; if (scalar(keys %{$self->{shards}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No shards detected, check your filter ? '); $self->{output}->option_exit(); } } } 1; __END__ =head1 MODE Check RedisLabs Enterprise Cluster shards statistics. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='clients' =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{status}, %{detailed_status}, %{role}, %{loading}, %{sync}, %{backup}. 'status' can be: 'active', 'inactive', 'trimming'. 'detailed_status' can be: 'ok', 'importing', 'timeout', 'loading', 'busy', 'down', 'trimming', 'unknown'. 'role' can be: 'slave', 'master'. 'loading' can be: 'in_progress', 'idle'. 'sync' can be: 'in_progress', 'idle', 'link_down'. 'backup' can be: 'exporting', 'succeeded', 'failed'. =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /inactive/i || %{backup} =~ /failed/i || %{sync} =~ /link_down/i'). Can used special variables like: %{status}, %{detailed_status}, %{role}, %{loading}, %{sync}, %{backup}. 'status' can be: 'active', 'inactive', 'trimming'. 'detailed_status' can be: 'ok', 'importing', 'timeout', 'loading', 'busy', 'down', 'trimming', 'unknown'. 'role' can be: 'slave', 'master'. 'loading' can be: 'in_progress', 'idle'. 'sync' can be: 'in_progress', 'idle', 'link_down'. 'backup' can be: 'exporting', 'succeeded', 'failed'. =item B<--warning-*> Threshold warning. Can be: 'total-cpu', 'fork-cpu', 'main-thread-cpu', 'memory', 'mem-frag-ratio', 'connected-clients', 'blocked-clients', 'request', 'keys', 'evicted-objects', 'expired-objects', 'read-rates', 'write-rates', 'rdb-changes-since-last-save', 'last-save-time', =item B<--critical-*> Threshold critical. Can be: 'total-cpu', 'fork-cpu', 'main-thread-cpu', 'memory', 'mem-frag-ratio', 'connected-clients', 'blocked-clients', 'request', 'keys', 'evicted-objects', 'expired-objects', 'read-rates', 'write-rates', 'rdb-changes-since-last-save', 'last-save-time', =back =cut centreon-plugins-20220113/apps/redis/rlec/restapi/plugin.pm000066400000000000000000000034431417000230700235410ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::redis::rlec::restapi::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} = { 'databases-stats' => 'apps::redis::rlec::restapi::mode::databasesstats', 'cluster-stats' => 'apps::redis::rlec::restapi::mode::clusterstats', 'list-databases' => 'apps::redis::rlec::restapi::mode::listdatabases', 'list-nodes' => 'apps::redis::rlec::restapi::mode::listnodes', 'list-shards' => 'apps::redis::rlec::restapi::mode::listshards', 'nodes-stats' => 'apps::redis::rlec::restapi::mode::nodesstats', 'shards-stats' => 'apps::redis::rlec::restapi::mode::shardsstats' }; $self->{custom_modes}->{api} = 'apps::redis::rlec::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check RedisLabs Enterprise Cluster through HTTP/REST API. =cut centreon-plugins-20220113/apps/redis/sentinel/000077500000000000000000000000001417000230700211265ustar00rootroot00000000000000centreon-plugins-20220113/apps/redis/sentinel/custom/000077500000000000000000000000001417000230700224405ustar00rootroot00000000000000centreon-plugins-20220113/apps/redis/sentinel/custom/cli.pm000066400000000000000000000170601417000230700235510ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::redis::sentinel::custom::cli; use strict; use warnings; use centreon::plugins::ssh; use centreon::plugins::misc; use Digest::MD5 qw(md5_hex); 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 => { 'ssh-hostname:s' => { name => 'ssh_hostname' }, 'server:s' => { name => 'server' }, 'port:s' => { name => 'port' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'tls' => { name => 'tls' }, 'cacert:s' => { name => 'cacert' }, 'insecure' => { name => 'insecure' }, 'timeout:s' => { name => 'timeout' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REDIS SENTINEL OPTIONS', once => 1); $self->{output} = $options{output}; $self->{ssh} = centreon::plugins::ssh->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{ssh_hostname} = defined($self->{option_results}->{ssh_hostname}) && $self->{option_results}->{ssh_hostname} ne '' ? $self->{option_results}->{ssh_hostname} : ''; $self->{server} = defined($self->{option_results}->{server}) && $self->{option_results}->{server} ne '' ? $self->{option_results}->{server} : ''; $self->{port} = defined($self->{option_results}->{port}) && $self->{option_results}->{port} ne '' ? $self->{option_results}->{port} : 26379; $self->{username} = defined($self->{option_results}->{password}) && $self->{option_results}->{username} ne '' ? $self->{option_results}->{username} : ''; $self->{password} = defined($self->{option_results}->{password}) && $self->{option_results}->{password} ne '' ? $self->{option_results}->{password} : ''; $self->{timeout} = defined($self->{option_results}->{timeout}) && $self->{option_results}->{timeout} =~ /(\d+)/ ? $1 : 10; $self->{tls} = defined($self->{option_results}->{tls}) ? 1 : 0; $self->{insecure} = defined($self->{option_results}->{insecure}) ? 1 : 0; $self->{cacert} = defined($self->{option_results}->{cacert}) && $self->{option_results}->{cacert} ne '' ? $self->{option_results}->{cacert} : ''; if ($self->{server} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --server option.'); $self->{output}->option_exit(); } if ($self->{ssh_hostname} ne '') { $self->{option_results}->{hostname} = $self->{ssh_hostname}; $self->{ssh}->check_options(option_results => $self->{option_results}); } if ($self->{username} ne '' && $self->{option_results}->{password} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --password option.'); $self->{output}->option_exit(); } return 0; } sub get_connection_info { my ($self, %options) = @_; my $id = $self->{server} . ':' . $self->{port}; return md5_hex($id); } sub execute_command { my ($self, %options) = @_; my $command_options = "-h '" . $self->{server} . "' -p " . $self->{port}; $command_options .= $self->get_extra_options(); $command_options .= ' --no-raw ' . $options{command}; my $timeout = $self->{timeout}; if (!defined($timeout)) { $timeout = defined($options{timeout}) ? $options{timeout} : 10; } my ($stdout, $exit_code); if ($self->{ssh_hostname} ne '') { ($stdout, $exit_code) = $self->{ssh}->execute( hostname => $self->{ssh_hostname}, sudo => $self->{option_results}->{sudo}, command => 'redis-cli', command_options => $command_options, timeout => $timeout, no_quit => $options{no_quit} ); } else { ($stdout, $exit_code) = centreon::plugins::misc::execute( output => $self->{output}, sudo => $self->{option_results}->{sudo}, options => { timeout => $timeout }, command => 'redis-cli', command_options => $command_options, no_quit => $options{no_quit} ); } $self->{output}->output_add(long_msg => "command response: $stdout", debug => 1); if ($stdout =~ /^NOPERM/m) { $self->{output}->add_option_msg(short_msg => 'Permissions issue'); $self->{output}->option_exit(); } return ($stdout, $exit_code); } sub get_extra_options { my ($self, %options) = @_; my $options = ''; $options .= ' --tls' if ($self->{tls} == 1); $options .= " --cacert '" . $self->{cacert} . "'" if ($self->{cacert} ne ''); $options .= ' --insecure' if ($self->{insecure} == 1); $options .= " --user '" . $self->{username} . "'" if ($self->{username} ne ''); $options .= " -a '" . $self->{password} . "'" if ($self->{password} ne ''); return $options; } sub ckquorum { my ($self, %options) = @_; my ($stdout) = $self->execute_command(command => $options{command}); return $stdout; } sub command { my ($self, %options) = @_; my ($stdout) = $self->execute_command(command => $options{command}); my $results = []; while ($stdout =~ /^\d+\)(.*?)(?=\n\d+\)|\Z$)/msg) { my @lines = split(/\n/, $1); my $entry = {}; while (scalar(@lines) > 0) { my $label = shift(@lines); my $value = shift(@lines); if (defined($label) && defined($value) && $label =~ /\d+\) "(.*)"/) { $label = $1; $entry->{$label} = $1 if ($value =~ /\d+\) "(.*)"/); } } push @$results, $entry; } return $results; } 1; __END__ =head1 NAME redis-cli. =head1 SYNOPSIS redis-cli. =head1 REDIS SENTINEL OPTIONS =over 8 =item B<--server> Sentinel server. =item B<--port> Sentinel port (Default: 26379). =item B<--tls> Establish a secure TLS connection (redis-cli >= 6.x mandatory). =item B<--cacert> CA Certificate file to verify with (redis-cli >= 6.x mandatory). =item B<--insecure> Allow insecure TLS connection by skipping cert validation (Since redis-cli 6.2.0). =item B<--username> Sentinel username (redis-cli >= 6.x mandatory). =item B<--password> Sentinel password. =item B<--ssh-hostname> Remote ssh redis-cli execution. =item B<--timeout> Timeout in seconds for the command (Default: 10). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/redis/sentinel/mode/000077500000000000000000000000001417000230700220525ustar00rootroot00000000000000centreon-plugins-20220113/apps/redis/sentinel/mode/listclusters.pm000066400000000000000000000042521417000230700251530ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::redis::sentinel::mode::listclusters; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; return $options{custom}->command(command => 'sentinel masters'); } sub run { my ($self, %options) = @_; my $results = $self->manage_selection(%options); foreach my $entry (@$results) { $self->{output}->output_add( long_msg => '[name: ' . $entry->{name} . ']' ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List clusters:' ); $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) = @_; my $results = $self->manage_selection(%options); foreach my $entry (@$results) { $self->{output}->add_disco_entry( name => $entry->{name} ); } } 1; __END__ =head1 MODE List clusters. =over 8 =back =cut centreon-plugins-20220113/apps/redis/sentinel/mode/redisclusters.pm000066400000000000000000000212421417000230700253040ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::redis::sentinel::mode::redisclusters; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf( "status: %s [role: %s]", $self->{result_values}->{status}, $self->{result_values}->{role} ); } sub prefix_cluster_output { my ($self, %options) = @_; return "cluster '" . $options{instance} . "' "; } sub cluster_long_output { my ($self, %options) = @_; return "checking cluster '" . $options{instance} . "'"; } sub prefix_instance_output { my ($self, %options) = @_; return "instance '" . $options{instance} . "' "; } sub prefix_global_output { my ($self, %options) = @_; return 'number of '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'clusters', type => 3, cb_prefix_output => 'prefix_cluster_output', cb_long_output => 'cluster_long_output', indent_long_output => ' ', message_multiple => 'All clusters are ok', group => [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } }, { name => 'stddev', type => 0, skipped_code => { -10 => 1 } }, { name => 'instances', type => 1, display_long => 1, cb_prefix_output => 'prefix_instance_output', message_multiple => 'All redis instances are ok', skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'slaves-detected', nlabel => 'cluster.redis.slaves.detected.count', set => { key_values => [ { name => 'num_slaves' } ], output_template => 'detected slaves: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } }, { label => 'redis-sdown', nlabel => 'cluster.redis.subjectively_down.count', set => { key_values => [ { name => 'sdown' } ], output_template => 'subjectively down instances: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } }, { label => 'redis-odown', nlabel => 'cluster.redis.objectively_down.count', set => { key_values => [ { name => 'odown' } ], output_template => 'objectively down instances: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{stddev} = [ { label => 'slave-repl-offset-stddev', nlabel => 'cluster.redis.slave_replication_offset.stddev.count', set => { key_values => [ { name => 'stddev_repl_offset' } ], output_template => 'slave replication offset standard deviation: %.2f', perfdatas => [ { template => '%.2f' } ] } } ]; $self->{maps_counters}->{instances} = [ { label => 'status', type => 2, critical_default => '%{status} =~ /o_down|s_down|master_down|disconnected/i', set => { key_values => [ { name => 'status' }, { name => 'role' }, { name => 'address' }, { name => 'port' }, { name => 'cluster_name' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'redis-ping-ok-latency', nlabel => 'cluster.redis.ping_ok.latency.milliseconds', set => { key_values => [ { name => 'ping_ok_latency' } ], output_template => 'last ok ping: %s ms', perfdatas => [ { template => '%d', min => 0, unit => 's', label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-cluster-name:s' => { name => 'filter_cluster_name' } }); return $self; } sub add_instance { my ($self, %options) = @_; my $key = $options{entry}->{ip} . ':' . $options{entry}->{port}; $self->{clusters}->{ $options{cluster_name} }->{instances}->{$key} = { cluster_name => $options{cluster_name}, address => $options{entry}->{ip}, port => $options{entry}->{port}, role => $options{entry}->{'role-reported'}, status => $options{entry}->{flags}, ping_ok_latency => $options{entry}->{'last-ok-ping-reply'}, slave_repl_offset => $options{entry}->{'slave-repl-offset'} }; $self->{clusters}->{ $options{cluster_name} }->{global}->{sdown}++ if ($options{entry}->{flags} =~ /s_down/); $self->{clusters}->{ $options{cluster_name} }->{global}->{odown}++ if ($options{entry}->{flags} =~ /o_down/); } sub stddev { my ($self, %options) = @_; my $total = 0; my $num = 0; foreach my $entry (values %{$self->{clusters}->{ $options{cluster_name} }->{instances}}) { next if (!defined($entry->{slave_repl_offset})); $total += $entry->{slave_repl_offset}; $num++; } return if ($num <= 1); my $mean = $total / $num; $total = 0; foreach my $entry (values %{$self->{clusters}->{ $options{cluster_name} }->{instances}}) { next if (!defined($entry->{slave_repl_offset})); $total += ($mean - $entry->{slave_repl_offset}) ** 2; } $self->{clusters}->{ $options{cluster_name} }->{stddev} = { stddev_repl_offset => sqrt($total / $num) }; } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->command(command => 'sentinel masters'); $self->{clusters} = {}; foreach my $entry (@$results) { next if (defined($self->{option_results}->{filter_cluster_name}) && $self->{option_results}->{filter_cluster_name} ne '' && $entry->{name} !~ /$self->{option_results}->{filter_cluster_name}/); $self->{clusters}->{ $entry->{name} } = { global => { num_slaves => $entry->{'num-slaves'}, odown => 0, sdown => 0 }, instances => {} }; $self->add_instance(cluster_name => $entry->{name}, entry => $entry); my $replicas = $options{custom}->command(command => 'sentinel replicas ' . $entry->{name}); foreach (@$replicas) { $self->add_instance(cluster_name => $entry->{name}, entry => $_); } $self->stddev(cluster_name => $entry->{name}); } if (scalar(keys %{$self->{clusters}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No redis cluster found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check redis clusters informations. =over 8 =item B<--filter-cluster-name> Filter clusters by name (Can be a regexp). =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{status}, %{role}, %{address}, %{port}, %{cluster_name} =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{status}, %{role}, %{address}, %{port}, %{cluster_name} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /o_down|s_down|master_down|disconnected/i'). Can used special variables like: %{status}, %{role}, %{address}, %{port}, %{cluster_name} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'redis-ping-ok-latency', 'redis-sdown', 'redis-odown', 'slave-repl-offset-stddev', 'slaves-detected'. =back =cut centreon-plugins-20220113/apps/redis/sentinel/mode/sentinelclusters.pm000066400000000000000000000211171417000230700260200ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::redis::sentinel::mode::sentinelclusters; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf( "status: %s", $self->{result_values}->{status} ); } sub prefix_cluster_output { my ($self, %options) = @_; return "cluster '" . $options{instance} . "' "; } sub cluster_long_output { my ($self, %options) = @_; return "checking cluster '" . $options{instance} . "'"; } sub prefix_instance_output { my ($self, %options) = @_; return "instance '" . $options{instance} . "' "; } sub prefix_global_output { my ($self, %options) = @_; return 'number of sentinels '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'clusters', type => 3, cb_prefix_output => 'prefix_cluster_output', cb_long_output => 'cluster_long_output', indent_long_output => ' ', message_multiple => 'All clusters are ok', group => [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } }, { name => 'quorum', type => 0, skipped_code => { -10 => 1 } }, { name => 'instances', type => 1, display_long => 1, cb_prefix_output => 'prefix_instance_output', message_multiple => 'All sentinel instances are ok', skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'sentinels-detected', nlabel => 'cluster.sentinels.detected.count', set => { key_values => [ { name => 'num_sentinels' } ], output_template => 'detected: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } }, { label => 'sentinels-sdown', nlabel => 'cluster.sentinels.subjectively_down.count', set => { key_values => [ { name => 'sdown' } ], output_template => 'subjectively down: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } }, { label => 'sentinels-odown', nlabel => 'cluster.sentinels.objectively_down.count', set => { key_values => [ { name => 'odown' } ], output_template => 'objectively down: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{quorum} = [ { label => 'quorum-status', type => 2, critical_default => '%{status} =~ /noQuorum/', set => { key_values => [ { name => 'status' }, { name => 'cluster_name' } ], output_template => 'quorum status: %s', closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{instances} = [ { label => 'status', type => 2, critical_default => '%{status} =~ /o_down|s_down|master_down|disconnected/i', set => { key_values => [ { name => 'status' }, { name => 'address' }, { name => 'port' }, { name => 'cluster_name' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'sentinel-ping-ok-latency', nlabel => 'cluster.sentinel.ping_ok.latency.milliseconds', set => { key_values => [ { name => 'ping_ok_latency' } ], output_template => 'last ok ping: %s ms', perfdatas => [ { template => '%d', min => 0, unit => 's', label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-cluster-name:s' => { name => 'filter_cluster_name' } }); return $self; } sub add_instance { my ($self, %options) = @_; my $key = $options{entry}->{ip} . ':' . $options{entry}->{port}; $self->{clusters}->{ $options{cluster_name} }->{instances}->{$key} = { cluster_name => $options{cluster_name}, address => $options{entry}->{ip}, port => $options{entry}->{port}, status => $options{entry}->{flags}, ping_ok_latency => $options{entry}->{'last-ok-ping-reply'} }; $self->{clusters}->{ $options{cluster_name} }->{global}->{sdown}++ if ($options{entry}->{flags} =~ /s_down/); $self->{clusters}->{ $options{cluster_name} }->{global}->{odown}++ if ($options{entry}->{flags} =~ /o_down/); } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->command(command => 'sentinel masters'); $self->{clusters} = {}; foreach my $entry (@$results) { next if (defined($self->{option_results}->{filter_cluster_name}) && $self->{option_results}->{filter_cluster_name} ne '' && $entry->{name} !~ /$self->{option_results}->{filter_cluster_name}/); $self->{clusters}->{ $entry->{name} } = { global => { num_sentinels => $entry->{'num-other-sentinels'}, odown => 0, sdown => 0 }, quorum => { status => 'unknown', cluster_name => $entry->{name} }, instances => {} }; my $quorum = $options{custom}->ckquorum(command => 'sentinel ckquorum ' . $entry->{name}); if ($quorum =~ /OK \d+ usable Sentinels/m) { $self->{clusters}->{ $entry->{name} }->{quorum}->{status} = 'ok'; } elsif ($quorum =~ /NOQUORUM \d+ usable Sentinels/m) { $self->{clusters}->{ $entry->{name} }->{quorum}->{status} = 'noQuorum'; } my $sentinels = $options{custom}->command(command => 'sentinel sentinels ' . $entry->{name}); foreach (@$sentinels) { $self->add_instance(cluster_name => $entry->{name}, entry => $_); } } if (scalar(keys %{$self->{clusters}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No sentinel cluster found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check sentinel clusters informations. =over 8 =item B<--filter-cluster-name> Filter clusters by name (Can be a regexp). =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{status}, %{address}, %{port}, %{cluster_name} =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{status}, %{address}, %{port}, %{cluster_name} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /o_down|s_down|master_down|disconnected/i'). Can used special variables like: %{status}, %{address}, %{port}, %{cluster_name} =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{status}, %{address}, %{port}, %{cluster_name} =item B<--warning-quorum-status> Set warning threshold for quorum status. Can used special variables like: %{status}, %{address}, %{port}, %{cluster_name} =item B<--critical-quorum-status> Set critical threshold for quorum status (Default: '%{status} =~ /noQuorum/'). Can used special variables like: %{status}, %{cluster_name} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'sentinel-ping-ok-latency', 'sentinels-sdown', 'sentinels-odown', 'sentinels-detected'. =back =cut centreon-plugins-20220113/apps/redis/sentinel/plugin.pm000066400000000000000000000026341417000230700227670ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::redis::sentinel::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->{modes} = { 'redis-clusters' => 'apps::redis::sentinel::mode::redisclusters', 'list-clusters' => 'apps::redis::sentinel::mode::listclusters', 'sentinel-clusters' => 'apps::redis::sentinel::mode::sentinelclusters' }; $self->{custom_modes}->{cli} = 'apps::redis::sentinel::custom::cli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Redis sentinel. =cut centreon-plugins-20220113/apps/rrdcached/000077500000000000000000000000001417000230700201165ustar00rootroot00000000000000centreon-plugins-20220113/apps/rrdcached/mode/000077500000000000000000000000001417000230700210425ustar00rootroot00000000000000centreon-plugins-20220113/apps/rrdcached/mode/stats.pm000066400000000000000000000173241417000230700225450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::rrdcached::mode::stats; use base qw(centreon::plugins::mode); use strict; use warnings; use IO::Socket; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "host:s" => { name => 'host', default => '127.0.0.1' }, "port:s" => { name => 'port', default => '42217' }, "unix-socket-path:s" => { name => 'unix_socket_path', default => '/var/rrdtool/rrdcached/rrdcached.sock' }, "warning-update:s" => { name => 'warning_update', default => '3000' }, "critical-update:s" => { name => 'critical_update', default => '5000' }, "warning-queue:s" => { name => 'warning_queue', default => '70' }, "critical-queue:s" => { name => 'critical_queue', default => '100' }, "socket-type:s" => { name => 'socket_type', default => 'unix' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (($self->{perfdata}->threshold_validate(label => 'warning-update', value => $self->{option_results}->{warning_update})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning-update threshold '" . $self->{warning} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'critical-update', value => $self->{option_results}->{critical_update})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical threshold '" . $self->{critical} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'warning-queue', value => $self->{option_results}->{warning_queue})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning-queue threshold '" . $self->{warning} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'critical-queue', value => $self->{option_results}->{critical_queue})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical-queue threshold '" . $self->{critical} . "'."); $self->{output}->option_exit(); } } sub run { my ($self, %options) = @_; my $data; my @stat; my @tab; my $queueLenght; my $socket; if ($self->{option_results}->{socket_type} eq 'tcp') { $socket = IO::Socket::INET->new( PeerHost => $self->{option_results}->{host}, PeerPort => $self->{option_results}->{port}, Proto => 'tcp', ); } else { my $SOCK_PATH = $self->{option_results}->{unix_socket_path}; $socket = IO::Socket::UNIX->new( Type => SOCK_STREAM(), Peer => $SOCK_PATH, ); } if (!defined($socket)) { $self->{output}->output_add(severity => 'CRITICAL', short_msg => "Can't connect to socket, is rrdcached running ? is your socket path/address:port correct ?"); $self->{output}->display(); $self->{output}->exit(); } else { $socket->send("STATS\n"); while ($data = <$socket>) { if ($data =~ /(\d+) Statistics follow/) { my $stats_number = $1; if ($stats_number < 9) { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => "Stats available are incomplete, check rrdcached daemon (try again if few moments)"); $self->{output}->display(); $self->{output}->exit(); } } next if $data !~ m/(^UpdatesR|Data|Queue)/; push @tab,$data; $socket->send("QUIT\n"); } close($socket); foreach my $line (@tab) { my ($key, $value) = split (/:\s*/, $line,2); push @stat, $value; $self->{output}->output_add(long_msg => sprintf("%s = %i", $key, $value)); } chomp($stat[0]); my $updatesNotWritten = $stat[1] - $stat[2]; my $exit1 = $self->{perfdata}->threshold_check(value => $updatesNotWritten, threshold => [ { label => 'critical-update', 'exit_litteral' => 'critical' }, { label => 'warning-update', exit_litteral => 'warning' } ]); my $exit2 = $self->{perfdata}->threshold_check(value => $stat[0], threshold => [ { label => 'critical-queue', 'exit_litteral' => 'critical' }, { label => 'warning-queue', exit_litteral => 'warning' } ]); my $exit = $self->{output}->get_most_critical(status => [ $exit1, $exit2 ]); $self->{output}->output_add(severity => $exit, short_msg => sprintf("RRDCached has %i updates waiting and %i node(s) in queue", $updatesNotWritten, $stat[0])); $self->{output}->perfdata_add(label => 'QueueLenght', unit => 'nodes', value => $stat[0], 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 => 'UpdatesWaiting', unit => 'updates', value => $updatesNotWritten, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0); $self->{output}->display(); $self->{output}->exit(); } } 1; __END__ =head1 MODE Check Updates cache of rrdcached daemon (compute delta between UpdatesReceived and DataSetsWritten from the rrdcached socket STATS command) =over 8 =item B<--tcp> Specify this option if TCP socket is used =item B<--host> Host where the socket is (should be set if --tcp is used) (default: 127.0.0.1) =item B<--port> Port where the socket is listening (default: 42217) =item B<--unix> Specify this option if UNIX socket is used =item B<--socket-path> Path to the socket (should be set if --unix is used) (default is /var/rrdtool/rrdcached/rrdcached.sock) =item B<--warning-update> Warning number of cached RRD updates (One update can include several values) =item B<--critical-update> Critical number of cached RRD updates (One update can include several values) =item B<--warning-queue> Warning number of nodes in rrdcached queue =item B<--critical-queue> Critical number of nodes in rrdcached queue =back =cut centreon-plugins-20220113/apps/rrdcached/plugin.pm000066400000000000000000000023101417000230700217460ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::rrdcached::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} = '0.1'; %{$self->{modes}} = ( 'stats' => 'apps::rrdcached::mode::stats', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check RRDCached related informations =cut centreon-plugins-20220113/apps/rudder/000077500000000000000000000000001417000230700174645ustar00rootroot00000000000000centreon-plugins-20220113/apps/rudder/restapi/000077500000000000000000000000001417000230700211335ustar00rootroot00000000000000centreon-plugins-20220113/apps/rudder/restapi/custom/000077500000000000000000000000001417000230700224455ustar00rootroot00000000000000centreon-plugins-20220113/apps/rudder/restapi/custom/api.pm000066400000000000000000000135751417000230700235670ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::rudder::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use DateTime; use JSON::XS; 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 => { 'hostname:s' => { name => 'hostname' }, 'url-path:s' => { name => 'url_path' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'api-token:s' => { name => 'api_token' }, 'timeout:s' => { name => 'timeout' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : undef; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{url_path} = (defined($self->{option_results}->{url_path})) ? $self->{option_results}->{url_path} : '/rudder/api/latest'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{api_token} = (defined($self->{option_results}->{api_token})) ? $self->{option_results}->{api_token} : ''; if (!defined($self->{hostname}) || $self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } if (!defined($self->{api_token}) || $self->{api_token} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-token option."); $self->{output}->option_exit(); } return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{url_path} = $self->{url_path}; $self->{option_results}->{warning_status} = ''; $self->{option_results}->{critical_status} = ''; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); if (defined($self->{access_token})) { $self->{http}->add_header(key => 'X-API-Token', value => $self->{access_token}); } $self->{http}->set_options(%{$self->{option_results}}); } sub get_connection_info { my ($self, %options) = @_; return $self->{hostname} . ":" . $self->{port}; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub get_port { my ($self, %options) = @_; return $self->{port}; } sub get_token { my ($self, %options) = @_; return $self->{option_results}->{api_token}; } sub request_api { my ($self, %options) = @_; if (!defined($self->{access_token})) { $self->{access_token} = $self->get_token(); } $self->settings; $self->{output}->output_add(long_msg => "Query URL: '" . $self->{proto} . "://" . $self->{hostname} . $self->{url_path} . $options{url_path} . "'", debug => 1); my $content = $self->{http}->request(url_path => $self->{url_path} . $options{url_path}); my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } if (!defined($decoded->{result}) || $decoded->{result} ne "success") { $self->{output}->output_add(long_msg => "Error message : " . $decoded->{errorDetails}, debug => 1); $self->{output}->add_option_msg(short_msg => "API return error code '" . $decoded->{result} . "' (add --debug option for detailed message)"); $self->{output}->option_exit(); } return $decoded->{data}; } 1; __END__ =head1 NAME Rudder Rest API =head1 SYNOPSIS Rudder Rest API custom mode =head1 REST API OPTIONS Rudder Rest API =over 8 =item B<--hostname> Rudder API hostname. =item B<--port> API port (Default: 443) =item B<--proto> Specify https if needed (Default: 'https') =item B<--url-path> API URL path (Default: '/rudder/api/latest') =item B<--timeout> Set HTTP timeout =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/rudder/restapi/mode/000077500000000000000000000000001417000230700220575ustar00rootroot00000000000000centreon-plugins-20220113/apps/rudder/restapi/mode/discovery.pm000066400000000000000000000063331417000230700244310ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::rudder::restapi::mode::discovery; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "prettify" => { name => 'prettify' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my @disco_data; my $disco_stats; $disco_stats->{start_time} = time(); my $results = $options{custom}->request_api(url_path => '/nodes'); foreach my $node (@{$results->{nodes}}) { my %node; $node{name} = $node->{hostname}; $node{type} = $node->{machine}->{type}; $node{os} = $node->{os}->{name}; $node{version} = $node->{os}->{version}; $node{status} = $node->{status}; $node{state} = $node->{state}; $node{id} = $node->{id}; $node{ip} = $node->{ipAddresses}; push @disco_data, \%node; } $results = $options{custom}->request_api(url_path => '/nodes/pending'); foreach my $node (@{$results->{nodes}}) { my %node; $node{name} = $node->{hostname}; $node{type} = $node->{machine}->{type}; $node{os} = $node->{os}->{name}; $node{version} = $node->{os}->{version}; $node{status} = $node->{status}; $node{state} = $node->{state}; $node{id} = $node->{id}; $node{ip} = $node->{ipAddresses}; push @disco_data, \%node; } $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; $disco_stats->{discovered_items} = @disco_data; $disco_stats->{results} = \@disco_data; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE Resources discovery. =over 8 =back =cut centreon-plugins-20220113/apps/rudder/restapi/mode/globalcompliance.pm000066400000000000000000000113061417000230700257110ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::rudder::restapi::mode::globalcompliance; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => 'value', instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{detail} : undef, value => $self->{result_values}->{value}, min => 0, max => 100, unit => '%' ); } sub custom_status_output { my ($self, %options) = @_; return sprintf("value is '%.2f%%'", $self->{result_values}->{value}); } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{detail} = $options{new_datas}->{$self->{instance} . '_detail'}; $self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_value'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'compliances', type => 1, cb_prefix_output => 'prefix_compliances_output', message_multiple => 'All compliance details are ok' }, ]; $self->{maps_counters}->{global} = [ { label => 'global-compliance', set => { key_values => [ { name => 'compliance' } ], output_template => 'Global Compliance: %.2f%%', perfdatas => [ { label => 'global_compliance', value => 'compliance', template => '%.2f', min => 0, max => 100, unit => '%' }, ], } }, ]; $self->{maps_counters}->{compliances} = [ { label => 'status', set => { key_values => [ { name => 'value' }, { name => 'detail' } ], closure_custom_calc => $self->can('custom_status_calc'), closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => $self->can('custom_status_perfdata'), closure_custom_threshold_check => \&catalog_status_threshold, } }, ]; } sub prefix_compliances_output { my ($self, %options) = @_; return "Compliance Detail '" . $options{instance_value}->{detail} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "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); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; $self->{compliances} = {}; my $results = $options{custom}->request_api(url_path => '/compliance'); $self->{global}->{compliance} = $results->{globalCompliance}->{compliance}; foreach my $detail (keys %{$results->{globalCompliance}->{complianceDetails}}) { $self->{compliances}->{$detail} = { detail => $detail, value => $results->{globalCompliance}->{complianceDetails}->{$detail}, } } } 1; __END__ =head1 MODE Check global compliance and compliance details. =over 8 =item B<--warning-global-compliance> Set warning threshold on global compliance. =item B<--critical-global-compliance> Set critical threshold on global compliance. =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{detail}, %{value} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{detail}, %{value} Example : --critical-status='%{detail} eq "error" && %{value} > 5' =back =cut centreon-plugins-20220113/apps/rudder/restapi/mode/listnodes.pm000066400000000000000000000112311417000230700244170ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::rudder::restapi::mode::listnodes; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->request_api(url_path => '/nodes'); foreach my $node (@{$results->{nodes}}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $node->{hostname} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $node->{hostname} . "': no matching filter name.", debug => 1); next; } $self->{nodes}->{$node->{id}} = { name => $node->{hostname}, type => $node->{machine}->{type}, os => $node->{os}->{name}, version => $node->{os}->{version}, status => $node->{status}, id => $node->{id}, } } $results = $options{custom}->request_api(url_path => '/nodes/pending'); foreach my $node (@{$results->{nodes}}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $node->{hostname} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $node->{hostname} . "': no matching filter name.", debug => 1); next; } $self->{nodes}->{$node->{id}} = { name => $node->{hostname}, type => $node->{machine}->{type}, os => $node->{os}->{name}, version => $node->{os}->{version}, status => $node->{status}, id => $node->{id}, } } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $node (sort keys %{$self->{nodes}}) { $self->{output}->output_add(long_msg => sprintf("[name = %s] [type = %s] [os = %s] [version = %s] [status = %s] [id = %s]", $self->{nodes}->{$node}->{name}, $self->{nodes}->{$node}->{type}, $self->{nodes}->{$node}->{os}, $self->{nodes}->{$node}->{version}, $self->{nodes}->{$node}->{status}, $self->{nodes}->{$node}->{id})); } $self->{output}->output_add(severity => 'OK', short_msg => 'List nodes:'); $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', 'type', 'os', 'version', 'id']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $node (sort keys %{$self->{nodes}}) { $self->{output}->add_disco_entry( name => $self->{nodes}->{$node}->{name}, type => $self->{nodes}->{$node}->{type}, os => $self->{nodes}->{$node}->{os}, version => $self->{nodes}->{$node}->{version}, status => $self->{nodes}->{$node}->{status}, id => $self->{nodes}->{$node}->{id}, ); } } 1; __END__ =head1 MODE List nodes. =over 8 =item B<--filter-name> Filter node name (can be a regexp). =back =cut centreon-plugins-20220113/apps/rudder/restapi/mode/listrules.pm000066400000000000000000000072051417000230700244470ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::rudder::restapi::mode::listrules; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->request_api(url_path => '/rules'); foreach my $rule (@{$results->{rules}}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $rule->{displayName} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $rule->{hostname} . "': no matching filter name.", debug => 1); next; } my @tags; foreach my $tag (@{$rule->{tags}}) { push @tags, (keys %{$tag})[0] . ':' . (values %{$tag})[0]; } $self->{rules}->{$rule->{id}} = { name => $rule->{displayName}, tags => join(',', @tags), enabled => $rule->{enabled}, id => $rule->{id}, } } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $rule (sort keys %{$self->{rules}}) { $self->{output}->output_add(long_msg => sprintf("[name = %s] [tags = %s] [enabled = %s] [id = %s]", $self->{rules}->{$rule}->{name}, $self->{rules}->{$rule}->{tags}, $self->{rules}->{$rule}->{enabled}, $self->{rules}->{$rule}->{id})); } $self->{output}->output_add(severity => 'OK', short_msg => 'List rules:'); $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', 'tags', 'enabled', 'id']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $rule (sort keys %{$self->{rules}}) { $self->{output}->add_disco_entry( name => $self->{rules}->{$rule}->{name}, tags => $self->{rules}->{$rule}->{tags}, enabled => $self->{rules}->{$rule}->{enabled}, id => $self->{rules}->{$rule}->{id}, ); } } 1; __END__ =head1 MODE List rules. =over 8 =item B<--filter-name> Filter rule name (can be a regexp). =back =cut centreon-plugins-20220113/apps/rudder/restapi/mode/nodecompliance.pm000066400000000000000000000137271417000230700254070ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::rudder::restapi::mode::nodecompliance; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; return sprintf("Compliance: %.2f%%", $self->{result_values}->{compliance}); } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{rule} = $options{new_datas}->{$self->{instance} . '_rule'}; $self->{result_values}->{compliance} = $options{new_datas}->{$self->{instance} . '_compliance'}; $self->{result_values}->{display} = $self->{instance}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'nodes', type => 3, cb_prefix_output => 'prefix_node_output', cb_long_output => 'long_output', message_multiple => 'All nodes compliance are ok', indent_long_output => ' ', group => [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'rules', display_long => 1, cb_prefix_output => 'prefix_rule_output', message_multiple => 'All rules compliance are ok', type => 1 }, ] } ]; $self->{maps_counters}->{global} = [ { label => 'node-compliance', set => { key_values => [ { name => 'compliance' }, { name => 'display' } ], output_template => 'Compliance: %.2f%%', perfdatas => [ { label => 'node_compliance', value => 'compliance', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; $self->{maps_counters}->{rules} = [ { label => 'status', set => { key_values => [ { name => 'compliance' }, { name => 'rule' } ], 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 => \&catalog_status_threshold, } }, ]; } sub prefix_node_output { my ($self, %options) = @_; return "Node '" . $options{instance_value}->{display} . "' [Id: " . $options{instance_value}->{id} . "] "; } sub prefix_rule_output { my ($self, %options) = @_; return "Rule '" . $options{instance_value}->{rule} . "' "; } sub long_output { my ($self, %options) = @_; return "Checking node '" . $options{instance_value}->{display} . "' [Id: " . $options{instance_value}->{id} . "] "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $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); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; $self->{nodes} = {}; my $results = $options{custom}->request_api(url_path => '/compliance/nodes?level=2'); foreach my $node (@{$results->{nodes}}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $node->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $node->{name} . "': no matching filter name.", debug => 1); next; } $self->{nodes}->{$node->{id}}->{id} = $node->{id}; $self->{nodes}->{$node->{id}}->{display} = $node->{name}; $self->{nodes}->{$node->{id}}->{global}->{compliance} = $node->{compliance}; $self->{nodes}->{$node->{id}}->{global}->{display} = $node->{name}; foreach my $rule (@{$node->{rules}}) { $self->{nodes}->{$node->{id}}->{rules}->{$rule->{id}} = { rule => $rule->{name}, compliance => $rule->{compliance}, }; } } if (scalar(keys %{$self->{nodes}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No nodes found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check nodes compliance. =over 8 =item B<--filter-name> Filter node name (regexp can be used) =item B<--warning-node-compliance> Set warning threshold on node compliance. =item B<--critical-node-compliance> Set critical threshold on node compliance. =item B<--warning-status> Set warning threshold for status of rule compliance (Default: ''). Can used special variables like: %{rule}, %{compliance} =item B<--critical-status> Set critical threshold for status of rule compliance (Default: ''). Can used special variables like: %{rule}, %{compliance} Example : --critical-status='%{rule} eq "Global configuration for all nodes" && %{compliance} < 95' =back =cut centreon-plugins-20220113/apps/rudder/restapi/mode/nodesoverallcompliance.pm000066400000000000000000000160331417000230700271500ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::rudder::restapi::mode::nodesoverallcompliance; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_compliance_perfdata { my ($self, %options) = @_; my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } $self->{output}->perfdata_add(label => 'compliance_' . $self->{label}, value => $self->{result_values}->{count}, 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), unit => 'nodes', min => 0, max => $self->{result_values}->{total}); } sub custom_compliance_threshold { my ($self, %options) = @_; my $threshold_value = $self->{result_values}->{count}; if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_count}; } my $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_compliance_output { my ($self, %options) = @_; my $msg = sprintf("%s: %d (%.2f%%)", $self->{result_values}->{output}, $self->{result_values}->{count}, $self->{result_values}->{prct_count}); return $msg; } sub custom_compliance_calc { my ($self, %options) = @_; $self->{result_values}->{label} = $options{extra_options}->{label}; $self->{result_values}->{output} = $options{extra_options}->{output}; $self->{result_values}->{count} = $options{new_datas}->{$self->{instance} . '_' . $self->{result_values}->{label}}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_total'}; $self->{result_values}->{prct_count} = ($self->{result_values}->{total} != 0) ? $self->{result_values}->{count} * 100 / $self->{result_values}->{total} : 0; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_compliance_output' }, ]; $self->{maps_counters}->{global} = [ { label => 'perfect', set => { key_values => [ { name => 'perfect' }, { name => 'total' } ], closure_custom_calc => $self->can('custom_compliance_calc'), closure_custom_calc_extra_options => { label => 'perfect', output => 'Perfect (100%)' }, closure_custom_output => $self->can('custom_compliance_output'), closure_custom_threshold_check => $self->can('custom_compliance_threshold'), closure_custom_perfdata => $self->can('custom_compliance_perfdata') } }, { label => 'good', set => { key_values => [ { name => 'good' }, { name => 'total' } ], closure_custom_calc => $self->can('custom_compliance_calc'), closure_custom_calc_extra_options => { label => 'good', output => 'Good (>75%)' }, closure_custom_output => $self->can('custom_compliance_output'), closure_custom_threshold_check => $self->can('custom_compliance_threshold'), closure_custom_perfdata => $self->can('custom_compliance_perfdata') } }, { label => 'average', set => { key_values => [ { name => 'average' }, { name => 'total' } ], closure_custom_calc => $self->can('custom_compliance_calc'), closure_custom_calc_extra_options => { label => 'average', output => 'Average (>50%)' }, closure_custom_output => $self->can('custom_compliance_output'), closure_custom_threshold_check => $self->can('custom_compliance_threshold'), closure_custom_perfdata => $self->can('custom_compliance_perfdata') } }, { label => 'poor', set => { key_values => [ { name => 'poor' }, { name => 'total' } ], closure_custom_calc => $self->can('custom_compliance_calc'), closure_custom_calc_extra_options => { label => 'poor', output => 'Poor (<50%)' }, closure_custom_output => $self->can('custom_compliance_output'), closure_custom_threshold_check => $self->can('custom_compliance_threshold'), closure_custom_perfdata => $self->can('custom_compliance_perfdata') } }, ]; } sub prefix_compliance_output { my ($self, %options) = @_; return "Nodes Count by Overall Compliance "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "units:s" => { name => 'units', default => '%' }, }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{global} = { perfect => 0, good => 0, average => 0, poor => 0, total => 0 }; my $results = $options{custom}->request_api(url_path => '/compliance/nodes?level=1'); foreach my $node (@{$results->{nodes}}) { $self->{global}->{total}++; $self->{global}->{poor}++ if ($node->{compliance} < 50); $self->{global}->{average}++ if ($node->{compliance} >= 50 && $node->{compliance} < 75); $self->{global}->{good}++ if ($node->{compliance} >= 75 && $node->{compliance} < 100); $self->{global}->{perfect}++ if ($node->{compliance} == 100); } } 1; __END__ =head1 MODE Check nodes count by overall compliance. =over 8 =item B<--warning-*> Threshold warning. Can be: 'perfect', 'good', 'average', 'poor'. =item B<--critical-*> Threshold critical. Can be: 'perfect', 'good', 'average', 'poor'. =item B<--units> Units of thresholds (Default: '%') ('%', 'count'). =back =cut centreon-plugins-20220113/apps/rudder/restapi/mode/rulecompliance.pm000066400000000000000000000142451417000230700254250ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::rudder::restapi::mode::rulecompliance; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; return sprintf("Compliance: %.2f%%", $self->{result_values}->{compliance}); } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{directive} = $options{new_datas}->{$self->{instance} . '_directive'}; $self->{result_values}->{compliance} = $options{new_datas}->{$self->{instance} . '_compliance'}; $self->{result_values}->{display} = $self->{instance}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'rules', type => 3, cb_prefix_output => 'prefix_rule_output', cb_long_output => 'long_output', message_multiple => 'All rules compliance are ok', indent_long_output => ' ', group => [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'directives', display_long => 1, cb_prefix_output => 'prefix_directive_output', message_multiple => 'All directives compliance are ok', type => 1 }, ] } ]; $self->{maps_counters}->{global} = [ { label => 'rule-compliance', set => { key_values => [ { name => 'compliance' } ], output_template => 'Compliance: %.2f%%', perfdatas => [ { label => 'rule_compliance', value => 'compliance', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 }, ], } }, ]; $self->{maps_counters}->{directives} = [ { label => 'status', set => { key_values => [ { name => 'compliance' }, { name => 'directive' } ], 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 => \&catalog_status_threshold, } }, ]; } sub prefix_rule_output { my ($self, %options) = @_; return "Rule '" . $options{instance_value}->{display} . "' [Id: " . $options{instance_value}->{id} . "] "; } sub prefix_directive_output { my ($self, %options) = @_; return "Directive '" . $options{instance_value}->{directive} . "' "; } sub long_output { my ($self, %options) = @_; return "Checking rule '" . $options{instance_value}->{display} . "' [Id: " . $options{instance_value}->{id} . "] "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $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); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; my %rules_mapping; $self->{rules} = {}; my $results = $options{custom}->request_api(url_path => '/rules'); foreach my $rule (@{$results->{rules}}) { $rules_mapping{$rule->{id}} = $rule->{displayName}; } $results = $options{custom}->request_api(url_path => '/compliance/rules?level=2'); foreach my $rule (@{$results->{rules}}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $rules_mapping{$rule->{id}} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $rules_mapping{$rule->{id}} . "': no matching filter name.", debug => 1); next; } $self->{rules}->{$rule->{id}}->{id} = $rule->{id}; $self->{rules}->{$rule->{id}}->{display} = $rules_mapping{$rule->{id}}; $self->{rules}->{$rule->{id}}->{global}->{compliance} = $rule->{compliance}; foreach my $directive (@{$rule->{directives}}) { $self->{rules}->{$rule->{id}}->{directives}->{$directive->{id}} = { directive => $directive->{name}, compliance => $directive->{compliance}, }; } } if (scalar(keys %{$self->{rules}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No rules found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check rules compliance. =over 8 =item B<--filter-name> Filter rule name (regexp can be used) =item B<--warning-rule-compliance> Set warning threshold on rule compliance. =item B<--critical-rule-compliance> Set critical threshold on rule compliance. =item B<--warning-status> Set warning threshold for status of directive compliance (Default: ''). Can used special variables like: %{directive}, %{compliance} =item B<--critical-status> Set critical threshold for status of directive compliance (Default: ''). Can used special variables like: %{directive}, %{compliance} Example : --critical-status='%{directive} eq "Users" && %{compliance} < 85' =back =cut centreon-plugins-20220113/apps/rudder/restapi/mode/statistics.pm000066400000000000000000000111651417000230700246130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::rudder::restapi::mode::statistics; 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 }, ]; $self->{maps_counters}->{global} = [ { label => 'nodes', set => { key_values => [ { name => 'nodes' } ], output_template => 'Nodes: %d', perfdatas => [ { label => 'nodes', value => 'nodes', template => '%d', min => 0 }, ], } }, { label => 'pending-nodes', set => { key_values => [ { name => 'pending_nodes' } ], output_template => 'Pending Nodes: %d', perfdatas => [ { label => 'pending_nodes', value => 'pending_nodes', template => '%d', min => 0 }, ], } }, { label => 'rules', set => { key_values => [ { name => 'rules' } ], output_template => 'Rules: %d', perfdatas => [ { label => 'rules', value => 'rules', template => '%d', min => 0 }, ], } }, { label => 'directives', set => { key_values => [ { name => 'directives' } ], output_template => 'Directives: %d', perfdatas => [ { label => 'directives', value => 'directives', template => '%d', min => 0 }, ], } }, { label => 'groups', set => { key_values => [ { name => 'groups' } ], output_template => 'Groups: %d', perfdatas => [ { label => 'groups', value => 'groups', template => '%d', min => 0 }, ], } }, { label => 'techniques', set => { key_values => [ { name => 'techniques' } ], output_template => 'Techniques: %d', perfdatas => [ { label => 'techniques', value => 'techniques', template => '%d', min => 0 }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; $self->{compliances} = {}; my $results = $options{custom}->request_api(url_path => '/nodes?include=minimal'); $self->{global}->{nodes} = scalar(@{$results->{nodes}}); $results = $options{custom}->request_api(url_path => '/nodes/pending?include=minimal'); $self->{global}->{pending_nodes} = scalar(@{$results->{nodes}}); $results = $options{custom}->request_api(url_path => '/rules'); $self->{global}->{rules} = scalar(@{$results->{rules}}); $results = $options{custom}->request_api(url_path => '/directives'); $self->{global}->{directives} = scalar(@{$results->{directives}}); $results = $options{custom}->request_api(url_path => '/groups'); $self->{global}->{groups} = scalar(@{$results->{groups}}); $results = $options{custom}->request_api(url_path => '/techniques'); $self->{global}->{techniques} = scalar(@{$results->{techniques}}); } 1; __END__ =head1 MODE Check statistics (objects count). =over 8 =item B<--warning-*> Threshold warning. Can be: 'nodes', 'pending-nodes', 'rules', 'directives', 'groups', 'techniques'. =item B<--critical-*> Threshold critical. Can be: 'nodes', 'pending-nodes', 'rules', 'directives', 'groups', 'techniques'. =back =cut centreon-plugins-20220113/apps/rudder/restapi/plugin.pm000066400000000000000000000035621417000230700227750ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::rudder::restapi::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}} = ( 'discovery' => 'apps::rudder::restapi::mode::discovery', 'global-compliance' => 'apps::rudder::restapi::mode::globalcompliance', 'list-nodes' => 'apps::rudder::restapi::mode::listnodes', 'list-rules' => 'apps::rudder::restapi::mode::listrules', 'node-compliance' => 'apps::rudder::restapi::mode::nodecompliance', 'nodes-overall-compliance' => 'apps::rudder::restapi::mode::nodesoverallcompliance', 'rule-compliance' => 'apps::rudder::restapi::mode::rulecompliance', 'statistics' => 'apps::rudder::restapi::mode::statistics', ); $self->{custom_modes}{api} = 'apps::rudder::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Rudder. =cut centreon-plugins-20220113/apps/sahipro/000077500000000000000000000000001417000230700176445ustar00rootroot00000000000000centreon-plugins-20220113/apps/sahipro/restapi/000077500000000000000000000000001417000230700213135ustar00rootroot00000000000000centreon-plugins-20220113/apps/sahipro/restapi/mode/000077500000000000000000000000001417000230700222375ustar00rootroot00000000000000centreon-plugins-20220113/apps/sahipro/restapi/mode/scenario.pm000066400000000000000000000454461417000230700244150ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::sahipro::restapi::mode::scenario; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use centreon::plugins::http; use Time::HiRes; use POSIX qw(strftime); use XML::Simple; use DateTime; my %handlers = (ALRM => {}); sub custom_status_output { my ($self, %options) = @_; return sprintf('status is %s', $self->{result_values}->{status}); } sub custom_status_calc { my ($self, %options) = @_; foreach (keys %{$options{new_datas}}) { if (/$self->{instance}_(step\d+_time)/) { $self->{result_values}->{$1} = $options{new_datas}->{$_}; } } $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; return 0; } sub prefix_global_output { my ($self, %options) = @_; return 'Scenario '; } sub prefix_step_output { my ($self, %options) = @_; return "Step '" . $options{instance_value}->{step} . "' [" . $options{instance_value}->{display} . "] "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } }, { name => 'steps', type => 1, cb_prefix_output => 'prefix_step_output', message_multiple => 'All steps are ok', sort_method => 'num' } ]; $self->{maps_counters}->{global} = [ { label => 'status', type => 2, critical_default => '%{status} ne "SUCCESS"', set => { key_values => [], manual_keys => 1, 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 => \&catalog_status_threshold_ng } }, { label => 'total-time', nlabel => 'scenario.execution.time.seconds', set => { key_values => [ { name => 'time_taken' } ], output_template => 'execution time: %s ms', perfdatas => [ { label => 'total_time', template => '%s', min => 0, unit => 'ms' } ] } }, { label => 'total-steps', nlabel => 'scenario.steps.count', set => { key_values => [ { name => 'total_steps' } ], output_template => 'total steps: %s', perfdatas => [ { label => 'total_steps', template => '%s', min => 0 } ] } }, { label => 'failures', nlabel => 'scenario.failures.count', set => { key_values => [ { name => 'failures' } ], output_template => 'failures: %s', perfdatas => [ { label => 'failures', template => '%s', min => 0 } ] } }, { label => 'errors', nlabel => 'scenario.errors.count', set => { key_values => [ { name => 'errors' } ], output_template => 'errors: %s', perfdatas => [ { label => 'errors', template => '%s', min => 0 } ] } }, ]; $self->{maps_counters}->{steps} = [ { label => 'step-time', nlabel => 'step.execution.time.second', set => { key_values => [ { name => 'time_taken' }, { name => 'step' } ], output_template => 'execution time: %s ms', perfdatas => [ { label => 'step_time', template => '%s', min => 0, unit => 'ms', label_extra_instance => 1, instance_use => 'step' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'sahi-hostname:s' => { name => 'sahi_hostname' }, 'sahi-port:s' => { name => 'sahi_port', default => 9999 }, 'sahi-proto:s' => { name => 'sahi_proto', default => 'http' }, 'sahi-http-timeout:s' => { name => 'sahi_http_timeout', default => 5 }, 'sahi-endpoint:s' => { name => 'sahi_endpoint', default => '/_s_/dyn/' }, 'sahi-suite:s' => { name => 'sahi_suite' }, 'sahi-threads:s' => { name => 'sahi_threads', default => 1 }, 'sahi-startwith:s' => { name => 'sahi_startwith', default => 'BROWSER' }, 'sahi-browsertype:s' => { name => 'sahi_browsertype', default => 'chrome' }, 'sahi-baseurl:s' => { name => 'sahi_baseurl' }, 'timeout:s' => { name => 'timeout' }, 'retries-scenario-status:s' => { name => 'retries_scenario_status' }, 'interval-scenario-status:s' => { name => 'interval_scenario_status', default => 10 }, 'unknown-run-status:s' => { name => 'unknown_run_status', default => '%{http_code} < 200 or %{http_code} >= 300' }, 'warning-run-status:s' => { name => 'warning_run_status' }, 'critical-run-status:s' => { name => 'critical_run_status', default => '' } }); $self->{http} = centreon::plugins::http->new(%options); $self->set_signal_handlers(); return $self; } sub set_signal_handlers { my $self = shift; $SIG{ALRM} = \&class_handle_ALRM; $handlers{ALRM}->{$self} = sub { $self->handle_ALRM() }; } sub class_handle_ALRM { foreach (keys %{$handlers{ALRM}}) { &{$handlers{ALRM}->{$_}}(); } } sub handle_ALRM { my $self = shift; $self->killed_scenario(); $self->{output}->add_option_msg(short_msg => 'Cannot finished scenario execution (timeout received)'); $self->{output}->option_exit(); } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); foreach my $option (('sahi_hostname', 'sahi_suite', 'sahi_startwith', 'sahi_browsertype')) { (my $label = $option) =~ s/_/-/g; if (!defined($self->{option_results}->{$option}) || $self->{option_results}->{$option} eq '') { $self->{output}->add_option_msg(short_msg => 'Please set ' . $label . ' option'); $self->{output}->option_exit(); } } if (!defined($self->{option_results}->{interval_scenario_status}) || $self->{option_results}->{interval_scenario_status} !~ /^\d+$/ || $self->{option_results}->{interval_scenario_status} < 0) { $self->{option_results}->{interval_scenario_status} = 10; } if (!defined($self->{option_results}->{retries_scenario_status}) || $self->{option_results}->{retries_scenario_status} !~ /^\d+$/ || $self->{option_results}->{retries_scenario_status} < 0) { $self->{option_results}->{retries_scenario_status} = 0; } if (defined($self->{option_results}->{timeout}) && $self->{option_results}->{timeout} =~ /^\d+$/ && $self->{option_results}->{timeout} > 0) { alarm($self->{option_results}->{timeout}); } $self->{http}->set_options(port => $self->{option_results}->{sahi_port}, proto => $self->{option_results}->{sahi_proto}); } sub decode_xml_response { my ($self, %options) = @_; my $content; eval { $content = XMLin($options{response}, ForceArray => $options{ForceArray}, KeyAttr => []); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode xml response: $@"); $self->{output}->option_exit(); } return $content; } sub generate_user_defined_id { my ($self, %options) = @_; my ($seconds, $microseconds) = Time::HiRes::gettimeofday(); my $user_defined_id = strftime('%d%B%Y__%H_%M_%S_', localtime($seconds)); $user_defined_id .= $microseconds; return $user_defined_id; } sub time2ms { my ($self, %options) = @_; #2019-02-26 10:38:47.407 return -1 if ($options{time} !~ /^(\d{4})-(\d{2})-(\d{2})\s+(\d{2}):(\d{2}):(\d{2}).(\d+)/); my $dt = DateTime->new(year => $1, month => $2, day => $3, hour => $4, minute => $5, second => $6, nanosecond => $7 * 1000000); return $dt->hires_epoch; } sub killed_scenario { my ($self, %options) = @_; return if (!defined($self->{user_defined_id})); $self->{http}->request( proto => $self->{option_results}->{sahi_proto}, port => $self->{option_results}->{sahi_port}, hostname => $self->{option_results}->{sahi_hostname}, url_path => $self->{option_results}->{sahi_endpoint} . 'SahiEndPoint_killAll', timeout => $self->{option_results}->{sahi_http_timeout}, unknown_status => '', warning_status => '', critical_status => '', get_param => ['userDefinedId=' . $self->{user_defined_id}] ); } sub cleanup_scenario { my ($self, %options) = @_; return if (!defined($self->{user_defined_id})); $self->{http}->request( proto => $self->{option_results}->{sahi_proto}, port => $self->{option_results}->{sahi_port}, hostname => $self->{option_results}->{sahi_hostname}, url_path => $self->{option_results}->{sahi_endpoint} . 'SahiEndPoint_cleanup', timeout => $self->{option_results}->{sahi_http_timeout}, unknown_status => '', warning_status => '', critical_status => '', get_param => ['userDefinedId=' . $self->{user_defined_id}] ); } sub run_scenario { my ($self, %options) = @_; my $user_defined_id = $self->generate_user_defined_id(); my ($content) = $self->{http}->request( proto => $self->{option_results}->{sahi_proto}, port => $self->{option_results}->{sahi_port}, hostname => $self->{option_results}->{sahi_hostname}, url_path => $self->{option_results}->{sahi_endpoint} . 'SahiEndPoint_run', timeout => $self->{option_results}->{sahi_http_timeout}, unknown_status => $self->{option_results}->{unknown_run_status}, warning_status => $self->{option_results}->{warning_run_status}, critical_status => $self->{option_results}->{critical_run_status}, get_param => [ 'threads=' . $self->{option_results}->{sahi_threads}, 'startWith=' . $self->{option_results}->{sahi_startwith}, 'browserType=' . $self->{option_results}->{sahi_browsertype}, 'suite=' . $self->{option_results}->{sahi_suite}, 'baseURL=' . (defined($self->{option_results}->{sahi_baseurl}) ? $self->{option_results}->{sahi_baseurl} : ''), 'userDefinedId=' . $user_defined_id, ] ); if ($self->{http}->get_code() != 200) { $self->{output}->add_option_msg(short_msg => 'run scenario issue:' . $content); $self->{output}->option_exit(); } $self->{user_defined_id} = $user_defined_id; } sub check_scenario_status { my ($self, %options) = @_; my $content; my $retries = 0; while (1) { ($content) = $self->{http}->request( proto => $self->{option_results}->{sahi_proto}, port => $self->{option_results}->{sahi_port}, hostname => $self->{option_results}->{sahi_hostname}, url_path => $self->{option_results}->{sahi_endpoint} . 'SahiEndPoint_status', timeout => $self->{option_results}->{sahi_http_timeout}, unknown_status => '', warning_status => '', critical_status => '', get_param => ['userDefinedId=' . $self->{user_defined_id}] ); if ($self->{http}->get_code() != 200) { if ($retries == $self->{option_results}->{retries_scenario_status}) { $self->{output}->add_option_msg(short_msg => 'check scenario status issue:' . $content); $self->{output}->option_exit(); } $retries++; } else { $retries = 0; } # other state: INITIAL, RUNNING last if ($content =~ /SUCCESS|FAILURE|ABORTED|SKIPPED|USER_ABORTED/); sleep($self->{option_results}->{interval_scenario_status}); } my $status = 'UNKNOWN'; $status = $1 if ($content =~ /(SUCCESS|FAILURE|ABORTED|SKIPPED|USER_ABORTED)/); $self->{global}->{status} = $status; } sub get_suite_report { my ($self, %options) = @_; my ($content) = $self->{http}->request( proto => $self->{option_results}->{sahi_proto}, port => $self->{option_results}->{sahi_port}, hostname => $self->{option_results}->{sahi_hostname}, url_path => $self->{option_results}->{sahi_endpoint} . 'SahiEndPoint_suiteReport', timeout => $self->{option_results}->{sahi_http_timeout}, unknown_status => '', warning_status => '', critical_status => '', get_param => [ 'userDefinedId=' . $self->{user_defined_id}, 'type=xml' ] ); if ($self->{http}->get_code() != 200) { $self->cleanup_option_exit(short_msg => 'get suite report issue:' . $content); } my $response = $self->decode_xml_response(response => $content, ForceArray => ['summary']); if (!defined($response->{suite}->{scriptSummaries}->{summary})) { $self->{output}->output_add(long_msg => $response, debug => 1); $self->cleanup_option_exit(short_msg => 'get suite report issue: unknown response format'); } # in milliseconds $self->{global}->{time_taken} = $response->{suite}->{scriptSummaries}->{summary}->[0]->{TIMETAKEN}; $self->{global}->{total_steps} = $response->{suite}->{scriptSummaries}->{summary}->[0]->{TOTALSTEPS}; $self->{global}->{failures} = $response->{suite}->{scriptSummaries}->{summary}->[0]->{FAILURES}; $self->{global}->{errors} = $response->{suite}->{scriptSummaries}->{summary}->[0]->{ERRORS}; $self->{script_reportid} = $response->{suite}->{scriptSummaries}->{summary}->[0]->{SCRIPTREPORTID}; } sub get_script_report { my ($self, %options) = @_; my ($content) = $self->{http}->request( proto => $self->{option_results}->{sahi_proto}, port => $self->{option_results}->{sahi_port}, hostname => $self->{option_results}->{sahi_hostname}, url_path => $self->{option_results}->{sahi_endpoint} . 'SahiEndPoint_scriptReport', timeout => $self->{option_results}->{sahi_http_timeout}, unknown_status => '', warning_status => '', critical_status => '', get_param => [ 'id=' . $options{id}, 'type=xml' ] ); if ($self->{http}->get_code() != 200) { $self->cleanup_option_exit(short_msg => 'get suite report issue:' . $content); } my $response = $self->decode_xml_response(response => $content, ForceArray => ['step']); if (!defined($response->{steps}->{step})) { $self->{output}->output_add(long_msg => $response, debug => 1); $self->cleanup_option_exit(short_msg => 'get script report issue: unknown response format'); } $self->{steps} = {}; for (my $i = 0; $i < (scalar(@{$response->{steps}->{step}}) - 1); $i++) { my $display = $response->{steps}->{step}->[$i]->{MESSAGETYPE}; $display .= '.' . $response->{steps}->{step}->[$i]->{STEPMESSAGE} if (defined($response->{steps}->{step}->[$i]->{STEPMESSAGE}) && $response->{steps}->{step}->[$i]->{STEPMESSAGE} ne ''); $display =~ s/\|//g; my $current_time = $self->time2ms(time => $response->{steps}->{step}->[$i]->{MESSAGETIMESTAMP}); my $next_time = $self->time2ms(time => $response->{steps}->{step}->[$i + 1]->{MESSAGETIMESTAMP}); my $time_taken = int(($next_time * 1000) - ($current_time * 1000)); $self->{steps}->{$i} = { step => $i, display => $display, time_taken => $time_taken, }; $self->{global}->{'step' . $i . '_time'} = $time_taken; } } sub cleanup_option_exit { my ($self, %options) = @_; $self->cleanup_scenario(); $self->{output}->add_option_msg(short_msg => $options{short_msg}); $self->{output}->option_exit(); } sub manage_selection { my ($self, %options) = @_; $self->{global} = {}; $self->run_scenario(); $self->check_scenario_status(); if ($self->{global}->{status} =~ /FAILURE|SUCCESS/) { $self->get_suite_report(); $self->get_script_report(id => $self->{script_reportid}); } $self->cleanup_scenario(); } 1; __END__ =head1 MODE Check scenario execution. =over 8 =item B<--sahi-hostname> IP Addr/FQDN of the host =item B<--sahi-port> Port used (Default: 9999) =item B<--sahi-proto> Specify https if needed (Default: 'http') =item B<--sahi-endpoint> Specify endpoint (Default: '/_s_/dyn/') =item B<--sahi-suite> Full path to scenario and scenario name (Required) =item B<--sahi-http-timeout> Timeout for each HTTP requests (Default: 5) =item B<--sahi-threads> Number of simultaneous browser instances that can be executed (Default: 1) =item B<--sahi-startwith> Specify the start mode (Default: BROWSER) =item B<--sahi-browsertype> Browser on which scripts will be executed (Default: chrome) =item B<--sahi-baseurl> Url where the script should start =item B<--timeout> Specify the global script timeout. If timeout is reached, scenario is killed. =item B<--retries-scenario-status> Specify the number of retries to get scenario status (if we fail to get the status). =item B<--interval-scenario-status> Specify time interval to get scenario status in seconds (Default: 10). =item B<--unknown-run-status> Threshold unknown for running scenario rest api response. (Default: '%{http_code} < 200 or %{http_code} >= 300') =item B<--warning-run-status> Threshold warning for running scenario rest api response. =item B<--critical-run-status> Threshold critical for running scenario rest api response. =item B<--warning-status> Set warning threshold for scenario status. Can used special variables like: %{status}. =item B<--critical-status> Set critical threshold for scenario status (Default: '%{status} ne "SUCCESS"'). Can used special variables like: %{status}. =item B<--warning-*> B<--critical-*> Set thresholds. Can be: 'total-time', 'total-steps', 'failures', 'errors', 'step-time'. =back =cut centreon-plugins-20220113/apps/sahipro/restapi/plugin.pm000066400000000000000000000023321417000230700231470ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::sahipro::restapi::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} = '0.1'; $self->{modes} = { 'scenario' => 'apps::sahipro::restapi::mode::scenario' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Sahi Pro scenario with Rest API. =cut centreon-plugins-20220113/apps/salesforce/000077500000000000000000000000001417000230700203255ustar00rootroot00000000000000centreon-plugins-20220113/apps/salesforce/restapi/000077500000000000000000000000001417000230700217745ustar00rootroot00000000000000centreon-plugins-20220113/apps/salesforce/restapi/custom/000077500000000000000000000000001417000230700233065ustar00rootroot00000000000000centreon-plugins-20220113/apps/salesforce/restapi/custom/api.pm000066400000000000000000000100161417000230700244130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::salesforce::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use JSON; 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 => { 'hostname:s' => { name => 'hostname' }, 'timeout:s' => { name => 'timeout' }, 'api-version:s' => { name => 'api_version' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : 'api.status.salesforce.com'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{api_version} = (defined($self->{option_results}->{api_version})) ? $self->{option_results}->{api_version} : 'v1'; return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = 443; $self->{option_results}->{proto} = 'https'; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->add_header(key => 'Content-Type', value => 'application/json'); $self->{http}->set_options(%{$self->{option_results}}); } sub request_api { my ($self, %options) = @_; $self->settings(); my $content = $self->{http}->request( method => 'GET', url_path => '/' . $self->{api_version} . $options{path}, critical_status => '', warning_status => '', unknown_status => '' ); my $decoded; eval { $decoded = decode_json($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response"); $self->{output}->option_exit(); } if ($self->{http}->get_code() != 200) { $self->{output}->add_option_msg(short_msg => "Connection issue: " . $decoded->{message}); $self->{output}->option_exit(); } return $decoded; } 1; __END__ =head1 NAME SFDC API boilerplate =head1 SYNOPSIS Get informations from SFDC API =head1 REST API OPTIONS =over 8 =item B<--hostname> Set hostname to query (default: 'api.status.salesforce.com') =item B<--timeout> Set HTTP timeout in seconds (Default: '10'). =item B<--api-version> API version (Default: 'v1'). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/salesforce/restapi/mode/000077500000000000000000000000001417000230700227205ustar00rootroot00000000000000centreon-plugins-20220113/apps/salesforce/restapi/mode/sfdcinstance.pm000066400000000000000000000074421417000230700257310ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::salesforce::restapi::mode::sfdcinstance; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf( "status is '%s' (active:'%s') ", $self->{result_values}->{status}, $self->{result_values}->{active} ); } sub prefix_salesforce_output { my ($self, %options) = @_; return "Salesforce '" . $options{instance_value}->{name} . "' instance "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'salesforce', type => 1, cb_prefix_output => 'prefix_salesforce_output', message_multiple => 'All salesforce instances are ok' } ]; $self->{maps_counters}->{salesforce} = [ { label => 'status', type => 2, critical_default => '%{status} !~ /OK/', set => { key_values => [ { name => 'status' }, { name => 'active' }, { name => 'name' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'incident', nlabel => 'salesforce.incident.current.count', set => { key_values => [ { name => 'incident' } ], output_template => '%s incidents currently', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'instance:s@' => { name => 'instance' }, 'alias' => { name => 'use_alias' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $instance_path = (defined($self->{option_results}->{use_alias})) ? '/instanceAliases/' : '/instances/'; foreach my $instance (@{$self->{option_results}->{instance}}) { my $result = $options{custom}->request_api(path => $instance_path . $instance . '/status'); $self->{salesforce}->{$instance} = { active => $result->{isActive}, incident => scalar(@{$result->{Incidents}}), name => $instance, status => $result->{status} }; } } 1; __END__ =head1 MODE Check instance status and incident count through Salesforce API =over 8 =item B<--instance> Set your instance identifier =item B<--alias> Add this option if your want to use your instance alias =item B<--unknown-status> Set unknown threshold for instance status (Default: ''). =item B<--warning-status> Set warning threshold for instance status (Default: ''). =item B<--critical-status> Set critical threshold for instance status (Default: '%{status} !~ /OK/'). =back =cut centreon-plugins-20220113/apps/salesforce/restapi/plugin.pm000066400000000000000000000024731417000230700236360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::salesforce::restapi::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}} = ( 'sfdc-instance' => 'apps::salesforce::restapi::mode::sfdcinstance', ); $self->{custom_modes}{api} = 'apps::salesforce::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check SFDC service through its status API =cut centreon-plugins-20220113/apps/selenium/000077500000000000000000000000001417000230700200205ustar00rootroot00000000000000centreon-plugins-20220113/apps/selenium/mode/000077500000000000000000000000001417000230700207445ustar00rootroot00000000000000centreon-plugins-20220113/apps/selenium/mode/scenario.pm000066400000000000000000000220701417000230700231060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::selenium::mode::scenario; use base qw(centreon::plugins::mode); use strict; use warnings; use Time::HiRes qw(gettimeofday tv_interval); use XML::XPath; use XML::XPath::XMLParser; use WWW::Selenium; my %handlers = (ALRM => {} ); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "selenium-hostname:s" => { name => 'selenium_hostname', default => 'localhost' }, "selenium-port:s" => { name => 'selenium_port', default => '4444' }, "browser:s" => { name => 'browser', default => '*firefox' }, "directory:s" => { name => 'directory', default => '/var/lib/centreon_waa' }, "scenario:s" => { name => 'scenario' }, "warning:s" => { name => 'warning' }, "critical:s" => { name => 'critical' }, "timeout:s" => { name => 'timeout', default => 50 }, }); $self->set_signal_handlers; return $self; } sub set_signal_handlers { my $self = shift; $SIG{ALRM} = \&class_handle_ALRM; $handlers{ALRM}->{$self} = sub { $self->handle_ALRM() }; } sub class_handle_ALRM { foreach (keys %{$handlers{ALRM}}) { &{$handlers{ALRM}->{$_}}(); } } sub handle_ALRM { my $self = shift; $self->{output}->output_add(severity => 'UNKNOWN', short_msg => sprintf("Cannot finished scenario execution (timeout received)")); $self->{output}->display(); $self->{output}->exit(); } 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}->{timeout}) && $self->{option_results}->{timeout} =~ /^\d+$/ && $self->{option_results}->{timeout} > 0) { alarm($self->{option_results}->{timeout}); } 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 $p = XML::Parser->new(NoLWP => 1); my $filename = $self->{option_results}->{directory} . '/' . $self->{option_results}->{scenario} . '.html'; my $xp = XML::XPath->new(parser => $p, filename => $filename); my $baseurlNode = $xp->find('/html/head/link[@rel="selenium.base"]'); my $baseurl = $baseurlNode->shift->getAttribute('href'); my $listActionNode = $xp->find('/html/body/table/tbody/tr'); my $sel = WWW::Selenium->new( host => $self->{option_results}->{selenium_hostname}, port => $self->{option_results}->{selenium_port}, browser => $self->{option_results}->{browser}, browser_url => $baseurl ); $sel->start; $self->{output}->output_add(long_msg => "Base URL : " . $baseurl); my $timing0 = [gettimeofday]; my ($action, $filter, $value); my $step = $listActionNode->get_nodelist; my $temp_step = 0; my $stepOk = 0; my ($last_echo_msg, $last_cmd); my $exit1 = 'UNKNOWN'; foreach my $actionNode ($listActionNode->get_nodelist) { ($action, $filter, $value) = $xp->find('./td', $actionNode)->get_nodelist; my $trim_action = centreon::plugins::misc::trim($action->string_value); my $trim_filter = centreon::plugins::misc::trim($filter->string_value); my $trim_value = centreon::plugins::misc::trim($value->string_value); $temp_step++; if ($trim_action eq 'pause') { my $sleepTime = 1000; if ($trim_value =~ /^\d+$/) { $sleepTime = $trim_value; } if ($trim_filter =~ /^\d+$/) { $sleepTime = $trim_filter; } sleep($sleepTime / 1000); $stepOk++; $self->{output}->output_add(long_msg => "Step " . $temp_step . " - Pause : " . $sleepTime . "ms"); # It's an echo command => do not send it to Selenium server # and store the associated string so that it can be displayed # in case of a failure as an info message } elsif ($trim_action eq 'echo'){ $last_echo_msg = $trim_filter; # Prevent output breakage in case of echo message contains invalid chars $last_echo_msg =~ s/\||\n/ - /msg; $stepOk += 1; } else { my $exit_command; $last_cmd = $trim_action . ' ' . $trim_filter . ' ' . $trim_value; eval { $exit_command = $sel->do_command($trim_action, $trim_filter, $trim_value); }; $self->{output}->output_add(long_msg => "Step " . $temp_step . " - Command : '" . $trim_action . "'" . " , Filter : '" . $trim_filter . "'" . " , Value : '" . $trim_value . "'"); if (!$@ && $exit_command eq 'OK') { $exit1 = 'OK'; $stepOk++; } else { if ($@) { $self->{output}->output_add(long_msg => "display: $@"); } $exit1 = 'CRITICAL'; last; } } } my $timeelapsed = tv_interval ($timing0, [gettimeofday]); 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 ($exit eq 'OK') { $self->{output}->output_add(severity => $exit, short_msg => sprintf("%d/%d steps (%.3fs)", $stepOk, $step, $timeelapsed)); } else { my $extra_info = $last_cmd; if (defined($last_echo_msg)) { $extra_info .= " - $last_echo_msg"; } $self->{output}->output_add(severity => $exit, short_msg => sprintf("%d/%d steps (%.3fs) - %s", $stepOk, $step, $timeelapsed, $extra_info)); } $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<--selenium-hostname> IP Addr/FQDN of the Selenium server =item B<--selenium-port> Port used by Selenium server =item B<--browser> Browser used by Selenium server (Default : '*firefox') =item B<--directory> Directory where scenarii are stored =item B<--scenario> Scenario used by Selenium server (without extension) =item B<--timeout> Set global execution timeout (Default: 50) =item B<--warning> Threshold warning in seconds (Scenario execution time) =item B<--critical> Threshold critical in seconds (Scenario execution response time) =back =cut centreon-plugins-20220113/apps/selenium/mode/scenariokatalon.pm000066400000000000000000000347661417000230700244770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::selenium::mode::scenariokatalon; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Time::HiRes qw(gettimeofday); use XML::XPath; use WWW::Selenium; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); my %handlers = (ALRM => {} ); sub custom_count_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add(label => $self->{result_values}->{label}, value => $self->{result_values}->{value}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{result_values}->{label}, total => $self->{result_values}->{total}, cast_int => 1), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{result_values}->{label}, total => $self->{result_values}->{total}, cast_int => 1), min => 0, max => $self->{result_values}->{total}); $self->{output}->perfdata_add(label => $self->{result_values}->{label} . '_prct', value => sprintf('%.2f', $self->{result_values}->{value_prct}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{result_values}->{label} . '-prct'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{result_values}->{label} . '-prct'), min => 0, max => 100, unit => '%'); } sub custom_count_threshold { my ($self, %options) = @_; my $exit1 = $self->{perfdata}->threshold_check(value => $self->{result_values}->{value}, threshold => [ { label => 'critical-' . $self->{result_values}->{label}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{result_values}->{label}, exit_litteral => 'warning' } ]); my $exit2 = $self->{perfdata}->threshold_check(value => $self->{result_values}->{value} . '_prct', threshold => [ { label => 'critical-' . $self->{result_values}->{label} . '-prct', exit_litteral => 'critical' }, { label => 'warning-' . $self->{result_values}->{label} . '-prct', exit_litteral => 'warning' } ]); my $exit = $self->{output}->get_most_critical(status => [ $exit1, $exit2 ]); return $exit; } sub custom_count_output { my ($self, %options) = @_; my $msg = sprintf("%s steps : %s/%s (%.2f%%)", ucfirst($self->{result_values}->{label}), $self->{result_values}->{value}, $self->{result_values}->{total}, $self->{result_values}->{value_prct}); return $msg; } sub custom_count_calc { my ($self, %options) = @_; $self->{result_values}->{label} = $options{extra_options}->{label}; $self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_' . $self->{result_values}->{label}}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_total'}; $self->{result_values}->{value_prct} = $self->{result_values}->{value} / $self->{result_values}->{total} * 100; return 0; } sub custom_state_output { my ($self, %options) = @_; my $msg = "state is '" . $self->{result_values}->{state} . "'"; $msg .= " : " . $self->{result_values}->{comment} if (defined($self->{result_values}->{comment}) && $self->{result_values}->{comment} ne ''); return $msg; } sub custom_state_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{command} = $options{new_datas}->{$self->{instance} . '_command'}; $self->{result_values}->{target} = $options{new_datas}->{$self->{instance} . '_target'}; $self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_value'}; $self->{result_values}->{state} = $options{new_datas}->{$self->{instance} . '_state'}; $self->{result_values}->{comment} = $options{new_datas}->{$self->{instance} . '_comment'}; return 0; } sub prefix_output { my ($self, %options) = @_; my $msg = "Step '" . $options{instance_value}->{display} . "' [command: " . $options{instance_value}->{command}; $msg .= ", target: " . $options{instance_value}->{target} if (defined($options{instance_value}->{target}) && $options{instance_value}->{target} ne ''); $msg .= ", value: " . $options{instance_value}->{value} if (defined($options{instance_value}->{value}) && $options{instance_value}->{value} ne ''); $msg .= "] "; return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'steps', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All steps state are ok' }, ]; $self->{maps_counters}->{global} = [ { label => 'successful', set => { key_values => [ { name => 'successful' }, { name => 'total' } ], closure_custom_calc => $self->can('custom_count_calc'), closure_custom_calc_extra_options => { label => 'successful' }, closure_custom_output => $self->can('custom_count_output'), closure_custom_perfdata => $self->can('custom_count_perfdata'), closure_custom_threshold_check => $self->can('custom_count_threshold'), } }, { label => 'failed', set => { key_values => [ { name => 'failed' }, { name => 'total' } ], closure_custom_calc => $self->can('custom_count_calc'), closure_custom_calc_extra_options => { label => 'failed' }, closure_custom_output => $self->can('custom_count_output'), closure_custom_perfdata => $self->can('custom_count_perfdata'), closure_custom_threshold_check => $self->can('custom_count_threshold'), } }, { label => 'time-scenario', set => { key_values => [ { name => 'time_scenario' } ], output_template => 'Total execution time : %.2f ms', perfdatas => [ { label => 'time_scenario', value => 'time_scenario', template => '%.2f', min => 0, unit => 'ms' }, ], } }, ]; $self->{maps_counters}->{steps} = [ { label => 'state', set => { key_values => [ { name => 'state' }, { name => 'command' }, { name => 'target' }, { name => 'value' }, { name => 'comment' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_state_calc'), closure_custom_output => $self->can('custom_state_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold, } }, { label => 'time-step', set => { key_values => [ { name => 'time_step' }, { name => 'display' } ], output_template => 'Execution time : %.2f ms', perfdatas => [ { label => 'time_step', value => 'time_step', template => '%.2f', min => 0, unit => 'ms', label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "selenium-hostname:s" => { name => 'selenium_hostname', default => 'localhost' }, "selenium-port:s" => { name => 'selenium_port', default => '4444' }, "browser:s" => { name => 'browser', default => '*firefox' }, "directory:s" => { name => 'directory', default => '/var/lib/centreon_waa' }, "scenario:s" => { name => 'scenario' }, "force-continue" => { name => 'force_continue' }, "timeout:s" => { name => 'timeout', default => 50 }, "action-timeout:s" => { name => 'action_timeout', default => 10 }, "warning-state:s" => { name => 'warning_state', default => '' }, "critical-state:s" => { name => 'critical_state', default => '%{state} !~ /OK/i' }, }); $self->set_signal_handlers; return $self; } sub set_signal_handlers { my $self = shift; $SIG{ALRM} = \&class_handle_ALRM; $handlers{ALRM}->{$self} = sub { $self->handle_ALRM() }; } sub class_handle_ALRM { foreach (keys %{$handlers{ALRM}}) { &{$handlers{ALRM}->{$_}}(); } } sub handle_ALRM { my $self = shift; $self->{output}->output_add(severity => 'UNKNOWN', short_msg => sprintf("Cannot finished scenario execution (timeout received)")); $self->{output}->display(); $self->{output}->exit(); } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (defined($self->{option_results}->{timeout}) && $self->{option_results}->{timeout} =~ /^\d+$/ && $self->{option_results}->{timeout} > 0) { alarm($self->{option_results}->{timeout}); } if (!defined($self->{option_results}->{scenario})) { $self->{output}->add_option_msg(short_msg => "Please specify a scenario name."); $self->{output}->option_exit(); } $self->change_macros(macros => ['warning_state', 'critical_state']); } sub manage_selection { my ($self, %options) = @_; $self->{global}->{failed} = 0; $self->{global}->{successful} = 0; $self->{global}->{time_scenario} = 0; $self->{selenium} = WWW::Selenium->new( host => $self->{option_results}->{selenium_hostname}, port => $self->{option_results}->{selenium_port}, browser => $self->{option_results}->{browser}, browser_url => "file://localhost" ); my $filename = $self->{option_results}->{directory} . '/' . $self->{option_results}->{scenario} . '.xml'; my $xp = XML::XPath->new(filename => $filename); my $step = 1; $self->{selenium}->start; $self->{selenium}->set_timeout($self->{option_results}->{action_timeout} * 1000); my $actions = $xp->find('/TestCase/selenese'); $self->{global}->{total} = $actions->size; my $start = gettimeofday() * 1000; foreach my $action ($actions->get_nodelist) { my $command = centreon::plugins::misc::trim($xp->find('command', $action)->string_value); my $target = centreon::plugins::misc::trim($xp->find('target', $action)->string_value); my $value = centreon::plugins::misc::trim($xp->find('value', $action)->string_value); $self->{steps}->{$step}->{display} = $step; $self->{steps}->{$step}->{command} = $command; $self->{steps}->{$step}->{target} = $target; $self->{steps}->{$step}->{value} = $value; $self->{steps}->{$step}->{state} = 'OK'; $self->{steps}->{$step}->{comment} = ''; $self->{steps}->{$step}->{time_step} = 0; my $result; my $step_start = gettimeofday() * 1000; eval { if ($command =~ /pause/) { $result = $self->{selenium}->pause($value); } else { $result = $self->{selenium}->do_command($command, $target, $value); } }; $self->{steps}->{$step}->{time_step} = gettimeofday() * 1000 - $step_start; if (!$@) { $self->{global}->{successful}++; } else { $self->{steps}->{$step}->{comment} = $@; $self->{steps}->{$step}->{comment} =~ s/^(.*\n)//;;; $self->{steps}->{$step}->{comment} =~ s/\n//;;; $self->{steps}->{$step}->{state} = 'ERROR'; $self->{global}->{failed}++; last unless $self->{option_results}->{force_continue}; } $step++; } $self->{global}->{time_scenario} = gettimeofday() * 1000 - $start; $self->{selenium}->stop; } 1; __END__ =head1 MODE Play scenario based on Katalon Automation Recorder XML export =over 8 =item B<--selenium-hostname> IP Addr/FQDN of the Selenium server. =item B<--selenium-port> Port used by Selenium server. =item B<--browser> Browser used by Selenium server (Default : '*firefox'). =item B<--directory> Directory where scenarii are stored. =item B<--scenario> Scenario to play (without extension). =item B<--force-continue> Don't stop if error. =item B<--timeout> Set scenario execution timeout in second (Default: 50). =item B<--action-timeout> Set action execution timeout in second (Default: 10). =item B<--warning-*> Threshold warning for steps state count (Can be: 'failed', 'successful'). =item B<--critical-*> Threshold critical for steps state count (Can be: 'failed', 'successful'). =item B<--warning-time-scenario> Threshold warning in milliseconds for scenario execution time. =item B<--critical-time-scenario> Threshold critical in milliseconds for scenario execution time. =item B<--warning-time-step> Threshold warning in milliseconds for step execution time. =item B<--critical-time-step> Threshold critical in milliseconds for step execution time. =item B<--warning-state> Threshold warning for step state. =item B<--critical-state> Threshold critical for step state (Default: '%{state} !~ /OK/i'). =back =cut centreon-plugins-20220113/apps/selenium/plugin.pm000066400000000000000000000024271417000230700216610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::selenium::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::selenium::mode::scenario', 'scenario-katalon' => 'apps::selenium::mode::scenariokatalon', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Selenium server. =cut centreon-plugins-20220113/apps/sendmail/000077500000000000000000000000001417000230700177735ustar00rootroot00000000000000centreon-plugins-20220113/apps/sendmail/snmp/000077500000000000000000000000001417000230700207505ustar00rootroot00000000000000centreon-plugins-20220113/apps/sendmail/snmp/plugin.pm000066400000000000000000000023161417000230700226060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::sendmail::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}} = ( 'mta-usage' => 'snmp_standard::mode::mtausage', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Sendmail MTA server in SNMP. =cut centreon-plugins-20220113/apps/slack/000077500000000000000000000000001417000230700172745ustar00rootroot00000000000000centreon-plugins-20220113/apps/slack/restapi/000077500000000000000000000000001417000230700207435ustar00rootroot00000000000000centreon-plugins-20220113/apps/slack/restapi/custom/000077500000000000000000000000001417000230700222555ustar00rootroot00000000000000centreon-plugins-20220113/apps/slack/restapi/custom/api.pm000066400000000000000000000140251417000230700233660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::slack::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use JSON::XS; use Digest::MD5 qw(md5_hex); 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'timeout:s' => { name => 'timeout' }, 'api-path:s' => { name => 'api_path' }, 'api-token:s' => { name => 'api_token' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : 'slack.com'; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{api_path} = (defined($self->{option_results}->{api_path})) ? $self->{option_results}->{api_path} : '/api'; $self->{api_token} = (defined($self->{option_results}->{api_token})) ? $self->{option_results}->{api_token} : ''; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify hostname option."); $self->{output}->option_exit(); } return 0; } sub get_connection_infos { my ($self, %options) = @_; return md5_hex($self->{option_results}->{api_token}); } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->set_options(%{$self->{option_results}}); } sub request_web_api { my ($self, %options) = @_; if ($self->{api_token} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify api-token option."); $self->{output}->option_exit(); } $self->settings(); my $content = $self->{http}->request( method => defined($options{method}) ? $options{method} : 'GET', url_path => $self->{api_path} . $options{endpoint}, post_param => $options{post_param}, header => [ 'Authorization: Bearer ' . $self->{api_token} ], critical_status => '', warning_status => '', unknown_status => '' ); my $decoded; eval { $decoded = decode_json($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => 'Cannot decode json response'); $self->{output}->option_exit(); } if ($decoded->{ok} !~ /1|true/i) { $self->{output}->add_option_msg(short_msg => "Error: " . $decoded->{error}); $self->{output}->option_exit(); } return $decoded; } sub get_services { my ($self, %options) = @_; my $services = { 'Login/SSO' => 1, 'Messaging' => 1, 'Posts/Files' => 1, 'Calls' => 1, 'Apps/Integrations/APIs' => 1, 'Connections' => 1, 'Link Previews' => 1, 'Notifications' => 1, 'Search' => 1, 'Workspace/Org Administration' => 1 }; return $services; } sub request_status_api { my ($self, %options) = @_; $self->settings(); my $content = $self->{http}->request( full_url => 'https://status.slack.com/api/v2.0.0/current', hostname => '', critical_status => '', warning_status => '', unknown_status => '' ); my $decoded; eval { $decoded = decode_json($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => 'Cannot decode json response'); $self->{output}->option_exit(); } return $decoded; } 1; __END__ =head1 NAME Slack REST API =head1 SYNOPSIS Slack Rest API custom mode =head1 REST API OPTIONS =over 8 =item B<--hostname> Slack API hostname (Default: 'slack.com'). =item B<--api-path> Slack API url path (Default: '/api'). =item B<--api-token> Slack API token of app. =item B<--port> Slack API port =item B<--proto> Specify https if needed (Default: 'https') =item B<--timeout> Set HTTP timeout =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/slack/restapi/mode/000077500000000000000000000000001417000230700216675ustar00rootroot00000000000000centreon-plugins-20220113/apps/slack/restapi/mode/countchannels.pm000066400000000000000000000074761417000230700251070ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::slack::restapi::mode::countchannels; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_output { my ($self, %options) = @_; return sprintf( "Channel '%s' [id: %s] ", $options{instance_value}->{name}, $options{instance_value}->{id} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'channels', type => 1, cb_prefix_output => 'prefix_output' } ]; $self->{maps_counters}->{global} = [ { label => 'count', nlabel => 'channels.total.count', set => { key_values => [ { name => 'count' } ], output_template => 'Number of channels: %d', perfdatas => [ { template => '%d', min => 0 } ] } } ]; $self->{maps_counters}->{channels} = [ { label => 'members', nlabel => 'channel.members.count', set => { key_values => [ { name => 'num_members' }, { name => 'id' }, { name => 'name' } ], output_template => 'members: %s', perfdatas => [ { template => '%d', min => 0, label_extra_instance => 1, instance_use => 'name' } ] } } ]; } 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-channel:s' => { name => 'filter_channel' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->request_web_api(endpoint => '/conversations.list'); $self->{global}->{count} = 0; foreach my $channel (@{$result->{channels}}) { if (defined($self->{option_results}->{filter_channel}) && $self->{option_results}->{filter_channel} ne '' && $channel->{name_normalized} !~ /$self->{option_results}->{filter_channel}/) { $self->{output}->output_add(long_msg => "skipping '" . $channel->{name_normalized} . "': no matching filter name.", debug => 1); next; } $self->{channels}->{ $channel->{id} } = { id => $channel->{id}, name => $channel->{name_normalized}, num_members => $channel->{num_members}, }; $self->{global}->{count}++; } if (scalar(keys %{$self->{channels}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No channels found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check channels. Scope: 'channels.read'. =over 8 =item B<--filter-channel> Filter channels by channel name (can be a regexp). =item B<--warning-count> Threshold warning for channels count. =item B<--critical-count> Threshold critical for channels count. =item B<--warning-members> Threshold warning for members count per channel. =item B<--critical-members> Threshold critical for members count per channel. =back =cut centreon-plugins-20220113/apps/slack/restapi/mode/countmembers.pm000066400000000000000000000063251417000230700247360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::slack::restapi::mode::countmembers; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_output { my ($self, %options) = @_; return "User '" . $options{instance_value}->{real_name} . "' "; } sub custom_info_output { my ($self, %options) = @_; return sprintf("[id: %s] [display name: %s]", $self->{result_values}->{id}, $self->{result_values}->{display_name}); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'members', type => 1, cb_prefix_output => 'prefix_output' } ]; $self->{maps_counters}->{global} = [ { label => 'count', nlabel => 'members.total.count', set => { key_values => [ { name => 'count' } ], output_template => 'Number of members: %d', perfdatas => [ { template => '%d', min => 0 } ] } } ]; $self->{maps_counters}->{members} = [ { label => 'info', display_ok => 0, threshold => 0, set => { key_values => [ { name => 'id' }, { name => 'real_name' }, { name => 'display_name' } ], closure_custom_output => $self->can('custom_info_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 => {}); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->request_web_api(endpoint => '/users.list'); $self->{global}->{count} = 0; foreach my $member (@{$result->{members}}) { $self->{members}->{ $member->{id} } = { id => $member->{id}, real_name => $member->{profile}->{real_name_normalized}, display_name => $member->{profile}->{display_name_normalized} }; $self->{global}->{count}++; } if (scalar(keys %{$self->{members}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No members found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check members count. Scope: 'users.read' =over 8 =item B<--warning-count> Threshold warning for members count. =item B<--critical-count> Threshold critical for members count. =back =cut centreon-plugins-20220113/apps/slack/restapi/mode/listservices.pm000066400000000000000000000051031417000230700247430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::slack::restapi::mode::listservices; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { '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 $results = $options{custom}->get_services(); my $services = {}; foreach my $name (keys %$results) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $name !~ /$self->{option_results}->{filter_name}/); $services->{$name} = $name; } return $services; } sub run { my ($self, %options) = @_; my $services = $self->manage_selection(%options); foreach (sort keys %$services) { $self->{output}->output_add( long_msg => sprintf("[name = %s]", $services->{$_}) ); } $self->{output}->output_add(severity => 'OK', short_msg => 'Slack services:'); $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) = @_; my $services = $self->manage_selection(%options); foreach (sort keys %$services) { $self->{output}->add_disco_entry( name => $services->{$_} ); } } 1; __END__ =head1 MODE List slack services. =over 8 =item B<--filter-name> Filter service name (Can be a regexp). =back =cut centreon-plugins-20220113/apps/slack/restapi/mode/services.pm000066400000000000000000000124431417000230700240540ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::slack::restapi::mode::services; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use DateTime; use centreon::plugins::misc; sub custom_status_output { my ($self, %options) = @_; my $msg = 'status is ' . $self->{result_values}->{status}; if ($self->{result_values}->{since} ne '') { $msg .= sprintf( ' [type: %s][since: %s][message: %s]', $self->{result_values}->{type}, $self->{result_values}->{since}, $self->{result_values}->{message} ); } return $msg; } sub prefix_service_output { my ($self, %options) = @_; return "Service '" . $options{instance_value}->{name} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'services', type => 1, cb_prefix_output => 'prefix_service_output', display_long => 1, cb_long_output => 'long_output', message_multiple => 'All slack services are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'services', nlabel => 'slack.services.count', display_ok => 0, set => { key_values => [ { name => 'total' } ], output_template => '%s Slack services', perfdatas => [ { template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{services} = [ { label => 'status', type => 2, warning_default => '%{status} eq "active" and %{type} eq "incident"', critical_default => '%{status} eq "active" and %{type} eq "outage"', set => { key_values => [ { name => 'status' }, { name => 'type' }, { name => 'name' }, { name => 'message' }, { name => 'since' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $services = $options{custom}->get_services(); my $results = $options{custom}->request_status_api(); $self->{services} = {}; foreach my $name (keys %$services) { next if ( defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $name !~ /$self->{option_results}->{filter_name}/i ); $self->{services}->{lc($name)} = { name => $name, status => 'ok', type => '-', message => '-', since => '' }; } foreach my $entry (@{$results->{active_incidents}}) { next if ($entry->{status} eq 'ok'); next if (!defined($entry->{date_created}) || $entry->{date_created} !~ /^(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)(.*)$/); my $dt = DateTime->new( year => $1, month => $2, day => $3, hour => $4, minute => $5, second => $6, time_zone => $7 ); my $diff_time = time() - $dt->epoch(); foreach (@{$entry->{services}}) { next if (!defined($self->{services}->{ lc($_->{title}) })); $self->{services}->{ lc($_->{title}) }->{status} = $entry->{status}; $self->{services}->{ lc($_->{title}) }->{type} = $entry->{type}; $self->{services}->{ lc($_->{title}) }->{message} = $entry->{title}; $self->{services}->{ lc($_->{title}) }->{since} = centreon::plugins::misc::change_seconds(value => $diff_time); } } $self->{global} = { total => scalar(keys %{$self->{services}}) }; } 1; __END__ =head1 MODE Check Slack services status. =over 8 =item B<--filter-name> Only display the status for a specific servie (Example: --filter-service='connections') =item B<--warning-status> Set warning threshold for the service status (Default: '%{status} eq "active" and %{type} eq "incident"'). =item B<--critical-status> Set warning threshold for the service status (Default: '%{status} eq "active" and %{type} eq "outage"'). =back =cut centreon-plugins-20220113/apps/slack/restapi/plugin.pm000066400000000000000000000027611417000230700226050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::slack::restapi::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} = '1.0'; $self->{modes} = { 'count-channels' => 'apps::slack::restapi::mode::countchannels', 'count-members' => 'apps::slack::restapi::mode::countmembers', 'list-services' => 'apps::slack::restapi::mode::listservices', 'services' => 'apps::slack::restapi::mode::services' }; $self->{custom_modes}->{restapi} = 'apps::slack::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Slack using API. =cut centreon-plugins-20220113/apps/smartermail/000077500000000000000000000000001417000230700205175ustar00rootroot00000000000000centreon-plugins-20220113/apps/smartermail/restapi/000077500000000000000000000000001417000230700221665ustar00rootroot00000000000000centreon-plugins-20220113/apps/smartermail/restapi/custom/000077500000000000000000000000001417000230700235005ustar00rootroot00000000000000centreon-plugins-20220113/apps/smartermail/restapi/custom/api.pm000066400000000000000000000217431417000230700246160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Authors : Roman Morandell - ivertix # package apps::smartermail::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use centreon::plugins::statefile; use JSON::XS; use Digest::MD5 qw(md5_hex); 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'url-path:s' => { name => 'url_path' }, 'api-username:s' => { name => 'api_username' }, 'api-password:s' => { name => 'api_password' }, 'timeout:s' => { name => 'timeout' }, }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); $self->{cache} = centreon::plugins::statefile->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{url_path} = (defined($self->{option_results}->{url_path})) ? $self->{option_results}->{url_path} : '/api/v1'; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : ''; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : ''; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify hostname option.'); $self->{output}->option_exit(); } if ($self->{api_username} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-username option."); $self->{output}->option_exit(); } if ($self->{api_password} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-password option."); $self->{output}->option_exit(); } $self->{cache}->check_options(option_results => $self->{option_results}); return 0; } sub get_connection_infos { my ($self, %options) = @_; return $self->{hostname} . '_' . $self->{http}->get_port(); } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub get_port { my ($self, %options) = @_; return $self->{port}; } sub json_decode { my ($self, %options) = @_; my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($options{content}); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } return $decoded; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->add_header(key => 'Content-Type', value => 'application/json'); $self->{http}->set_options(%{$self->{option_results}}); } sub clean_token { my ($self, %options) = @_; my $datas = {}; $options{statefile}->write(data => $datas); $self->{access_token} = undef; $self->{http}->add_header(key => 'Authorization', value => undef); } sub get_auth_token { my ($self, %options) = @_; my $has_cache_file = $options{statefile}->read(statefile => 'smatermail_api_' . md5_hex($self->{option_results}->{hostname}) . '_' . md5_hex($self->{option_results}->{api_username})); my $expires_on = $options{statefile}->get(name => 'expires_on'); my $access_token = $options{statefile}->get(name => 'access_token'); # Token expires every 15 minutes if ($has_cache_file == 0 || !defined($access_token) || (time() > $expires_on)) { my $json_request = { username => $self->{api_username}, password => $self->{api_password} }; my $encoded; eval { $encoded = encode_json($json_request); }; if ($@) { $self->{output}->add_option_msg(short_msg => 'cannot encode json request'); $self->{output}->option_exit(); } my ($content) = $self->{http}->request( method => 'POST', url_path => $self->{url_path} . '/auth/authenticate-user', query_form_post => $encoded, warning_status => '', unknown_status => '', critical_status => '' ); if ($self->{http}->get_code() != 200) { $self->{output}->add_option_msg(short_msg => "Authentication error [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded = $self->json_decode(content => $content); if (!defined($decoded->{accessToken})) { $self->{output}->add_option_msg(short_msg => "Cannot get token"); $self->{output}->option_exit(); } $access_token = $decoded->{accessToken}; my $datas = { access_token => $access_token, expires_on => time() + 900 }; $options{statefile}->write(data => $datas); } $self->{access_token} = $access_token; $self->{http}->add_header(key => 'Authorization', value => 'Bearer ' . $self->{access_token}); } sub request_api { my ($self, %options) = @_; $self->settings(); if (!defined($self->{access_token})) { $self->get_auth_token(statefile => $self->{cache}); } my $content = $self->{http}->request( method => 'GET', url_path => $self->{url_path} . $options{endpoint}, warning_status => '', unknown_status => '', critical_status => '' ); # Maybe there is an issue with the token. So we retry. if ($self->{http}->get_code() < 200 || $self->{http}->get_code() >= 300) { $self->clean_token(statefile => $self->{cache}); $self->get_auth_token(statefile => $self->{cache}); $content = $self->{http}->request( url_path => $self->{url_path} . $options{endpoint}, warning_status => '', unknown_status => '', critical_status => '' ); } my $decoded = $self->json_decode(content => $content); if (!defined($decoded)) { $self->{output}->add_option_msg(short_msg => 'Error while retrieving data (add --debug option for detailed message)'); $self->{output}->option_exit(); } if ($self->{http}->get_code() < 200 || $self->{http}->get_code() >= 300) { my $message = 'api request error'; if (defined($decoded->{message})) { $message .= ': ' . $decoded->{message}; } $self->{output}->add_option_msg(short_msg => $message); $self->{output}->option_exit(); } return $decoded; } 1; __END__ =head1 NAME SmarterMail API =head1 SYNOPSIS smartermail api =head1 REST API OPTIONS =over 8 =item B<--hostname> API hostname. =item B<--url-path> API url path (Default: '/api/v1') =item B<--port> API port (Default: 443) =item B<--proto> Specify https if needed (Default: 'https') =item B<--api-username> Set API username =item B<--api-password> Set API password =item B<--timeout> Set HTTP timeout =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/smartermail/restapi/mode/000077500000000000000000000000001417000230700231125ustar00rootroot00000000000000centreon-plugins-20220113/apps/smartermail/restapi/mode/licenses.pm000066400000000000000000000066761417000230700252740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Authors : Roman Morandell - ivertix # package apps::smartermail::restapi::mode::licenses; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_upgrade_protection_status_output { my ($self, %options) = @_; return 'upgrade protection status is ' . $self->{result_values}->{upgrade_protection_status}; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, message_separator => ' - ' } ]; $self->{maps_counters}->{global} = [ { label => 'upgrade-protection-status', type => 2, critical_default => '%{upgrade_protection_status} =~ /expired/', set => { key_values => [ { name => 'upgrade_protection_status' } ], closure_custom_perfdata => sub { return 0; }, closure_custom_output => $self->can('custom_upgrade_protection_status_output'), closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'upgrade-protection-expires-days', nlabel => 'license.upgrade.protection.expires.days.count', set => { key_values => [ { name => 'upgrade_protection_expires_days' } ], output_template => 'upgrade protection expires in %d days', perfdatas => [ { template => '%d', min => 0 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->request_api(endpoint => '/settings/sysadmin/license-notifications'); $self->{global} = { upgrade_protection_expires_days => $result->{daysUntilUpgradeProtectionExpires}, upgrade_protection_status => $result->{isUpgradeProtectionExpired} =~ /True|1/i ? 'expired' : 'licensed' }; } 1; __END__ =head1 MODE Check licenses. =over 8 =item B<--unknown-upgrade-protection-status> Set unknown threshold for status. Can used special variables like: %{upgrade_protection_status} =item B<--warning-upgrade-protection-status> Set warning threshold for status. Can used special variables like: %{upgrade_protection_status} =item B<--critical-upgrade-protection-status> Set critical threshold for status (Default: '%{upgrade_protection_status} =~ /expired/'). Can used special variables like: %{upgrade_protection_status} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'upgrade-protection-expires-days'. =back =cut centreon-plugins-20220113/apps/smartermail/restapi/mode/services.pm000066400000000000000000000067621417000230700253060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Authors : Roman Morandell - ivertix # package apps::smartermail::restapi::mode::services; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return 'state is ' . $self->{result_values}->{state}; } sub prefix_service_output { my ($self, %options) = @_; return "Service '" . $options{instance_value}->{display} ."' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'services', type => 1, cb_prefix_output => 'prefix_service_output', message_multiple => 'All services are ok' } ]; $self->{maps_counters}->{services} = [ { label => 'status', type => 2, critical_default => '%{state} !~ /running/', set => { key_values => [ { name => 'state' }, { name => 'display' } ], closure_custom_perfdata => sub { return 0; }, closure_custom_output => $self->can('custom_status_output'), closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-service:s' => { name => 'filter_service' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->request_api(endpoint => '/settings/sysadmin/services'); $self->{services} = {}; foreach my $svc_name (keys %{$results->{services}}) { if (defined($self->{option_results}->{filter_service}) && $self->{option_results}->{filter_service} ne '' && $svc_name !~ /$self->{option_results}->{filter_service}/) { $self->{output}->output_add(long_msg => "skipping '" . $svc_name . "': no matching filter.", debug => 1); next; } $self->{services}->{$svc_name} = { display => $svc_name, state => $results->{services}->{$svc_name} =~ /True|1/i ? 'running' : 'inactive' }; } } 1; __END__ =head1 MODE Check services. =over 8 =item B<--filter-service> Only display some counters (regexp can be used). (Example: --filter-service='spool|smtp|pop') =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{state}, %{display} =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 (Default: '%{state} !~ /running/'). Can used special variables like: %{state}, %{display} =back =cut centreon-plugins-20220113/apps/smartermail/restapi/mode/spools.pm000066400000000000000000000055311417000230700247730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Authors : Roman Morandell - ivertix # package apps::smartermail::restapi::mode::spools; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_spool_output { my ($self, %options) = @_; return "Spool '" . $options{instance_value}->{display} ."' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'spools', type => 1, cb_prefix_output => 'prefix_spool_output', message_multiple => 'All spools are ok' } ]; $self->{maps_counters}->{spools} = [ { label => 'spool-messages', nlabel => 'spool.messages.count', set => { key_values => [ { name => 'messages' }, { name => 'display' } ], output_template => 'messages: %d', perfdatas => [ { template => '%d', min => 0, label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-spool:s' => { name => 'filter_spool' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->request_api(endpoint => '/settings/sysadmin/spool-message-counts'); $self->{spools} = {}; foreach my $name (keys %{$results->{counts}}) { if (defined($self->{option_results}->{filter_spool}) && $self->{option_results}->{filter_spool} ne '' && $name !~ /$self->{option_results}->{filter_spool}/) { $self->{output}->output_add(long_msg => "skipping '" . $name . "': no matching filter.", debug => 1); next; } $self->{spools}->{$name} = { display => $name, messages => $results->{counts}->{$name} }; } } 1; __END__ =head1 MODE Check spools. =over 8 =item B<--filter-spool> Filter spools by name (Can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'spool-messages'. =back =cut centreon-plugins-20220113/apps/smartermail/restapi/plugin.pm000066400000000000000000000027611417000230700240300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Authors : Roman Morandell - ivertix # package apps::smartermail::restapi::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} = '1.0'; $self->{modes} = { 'spools' => 'apps::smartermail::restapi::mode::spools', 'licenses' => 'apps::smartermail::restapi::mode::licenses', 'services' => 'apps::smartermail::restapi::mode::services' }; $self->{custom_modes}->{api} = 'apps::smartermail::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check SmarterMail software using Rest API. =over 8 =back =cut centreon-plugins-20220113/apps/squid/000077500000000000000000000000001417000230700173245ustar00rootroot00000000000000centreon-plugins-20220113/apps/squid/snmp/000077500000000000000000000000001417000230700203015ustar00rootroot00000000000000centreon-plugins-20220113/apps/squid/snmp/mode/000077500000000000000000000000001417000230700212255ustar00rootroot00000000000000centreon-plugins-20220113/apps/squid/snmp/mode/cacheusage.pm000066400000000000000000000073501417000230700236600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::squid::snmp::mode::cacheusage; 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 => ' - ', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'cpu', nlabel => 'cache.cpu.utilization.percentage', set => { key_values => [ { name => 'cacheCpuUsage' } ], output_template => 'Cpu usage: %s %%', perfdatas => [ { label => 'cpu', template => '%s', min => 0, max => 100, unit => '%' } ] } }, { label => 'memory', nlabel => 'cache.memory.usage.bytes', set => { key_values => [ { name => 'cacheMemUsage' } ], output_template => 'Memory usage: %s %s', output_change_bytes => 1, perfdatas => [ { label => 'memory', template => '%s', min => 0, unit => 'B' } ] } }, { label => 'fd', nlabel => 'cache.filedescriptors.count', set => { key_values => [ { name => 'cacheCurrentFileDescrCnt' } ], output_template => 'Number of file descriptors: %s', perfdatas => [ { label => 'fd', template => '%s', min => 0 } ] } }, { label => 'object', nlabel => 'cache.objects.count', set => { key_values => [ { name => 'cacheNumObjCount' } ], output_template => 'Number of object stored: %s', perfdatas => [ { label => 'objects', template => '%s', min => 0 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my %oids = ( cacheMemUsage => '.1.3.6.1.4.1.3495.1.3.1.3.0', cacheCpuUsage => '.1.3.6.1.4.1.3495.1.3.1.5.0', cacheNumObjCount => '.1.3.6.1.4.1.3495.1.3.1.7.0', cacheCurrentFileDescrCnt => '.1.3.6.1.4.1.3495.1.3.1.12.0' ); my $snmp_result = $options{snmp}->get_leef( oids => [ values %oids ], nothing_quit => 1); $snmp_result->{$oids{cacheMemUsage}} *= 1024; $self->{global} = {}; foreach (keys %oids) { $self->{global}->{$_} = $snmp_result->{$oids{$_}} if (defined($snmp_result->{$oids{$_}})); } } 1; __END__ =head1 MODE Check cache 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', 'memory', 'fd', 'object'. =item B<--critical-*> Threshold critical. Can be: 'cpu', 'memory', 'fd', 'object'. =back =cut centreon-plugins-20220113/apps/squid/snmp/mode/protocolstats.pm000066400000000000000000000215071417000230700245100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::squid::snmp::mode::protocolstats; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); sub custom_data_calc { my ($self, %options) = @_; my $delta_value = $options{new_datas}->{$self->{instance} . '_cacheHttpHits'} - $options{old_datas}->{$self->{instance} . '_cacheHttpHits'}; my $delta_total = $options{new_datas}->{$self->{instance} . '_cacheProtoClientHttpRequests'} - $options{old_datas}->{$self->{instance} . '_cacheProtoClientHttpRequests'}; $self->{result_values}->{hits_prct} = 100; if ($delta_total > 0) { $self->{result_values}->{hits_prct} = $delta_value * 100 / $delta_total; } return 0; } sub prefix_http_output { my ($self, %options) = @_; return "HTTP "; } sub prefix_icp_output { my ($self, %options) = @_; return "ICP "; } sub prefix_server_output { my ($self, %options) = @_; return "Server "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global_http', type => 0, cb_prefix_output => 'prefix_http_output', skipped_code => { -10 => 1 } }, { name => 'global_icp', type => 0, cb_prefix_output => 'prefix_icp_output', skipped_code => { -10 => 1 } }, { name => 'global', type => 0, cb_prefix_output => 'prefix_server_output', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global_http} = [ { label => 'http-hits-rate', nlabel => 'http.hits.percentage', set => { key_values => [ { name => 'cacheProtoClientHttpRequests', diff => 1 }, { name => 'cacheHttpHits', diff => 1 } ], closure_custom_calc => $self->can('custom_data_calc'), output_template => 'hits rate: %.2f %%', output_use => 'hits_prct', threshold_use => 'hits_prct', perfdatas => [ { label => 'http_hits_rate', template => '%.2f', min => 0, max => 100, unit => '%' } ] } }, { label => 'http-errors', nlabel => 'http.errors.count', set => { key_values => [ { name => 'cacheHttpErrors', diff => 1 } ], output_template => 'errors: %s', perfdatas => [ { label => 'http_errors', template => '%s', min => 0 } ] } }, { label => 'http-traffic-in', nlabel => 'http.traffic.in.bitspersecond', set => { key_values => [ { name => 'cacheHttpInKb', per_second => 1 } ], output_template => 'traffic in: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'http_traffic_in', template => '%s', min => 0, unit => 'b/s' } ] } }, { label => 'http-traffic-out', nlabel => 'http.traffic.out.bitspersecond', set => { key_values => [ { name => 'cacheHttpOutKb', per_second => 1 } ], output_template => 'traffic out: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'http_traffic_out', template => '%s', min => 0, unit => 'b/s' } ] } } ]; $self->{maps_counters}->{global_icp} = [ { label => 'icp-traffic-in', nlabel => 'icp.traffic.in.bitspersecond', set => { key_values => [ { name => 'cacheIcpKbRecv', per_second => 1 } ], output_template => 'traffic in: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'icp_traffic_in', template => '%s', min => 0, unit => 'b/s' } ] } }, { label => 'icp-traffic-out', nlabel => 'icp.traffic.out.bitspersecond', set => { key_values => [ { name => 'cacheIcpKbSent', per_second => 1 } ], output_template => 'traffic out: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'icp_traffic_out', template => '%s', min => 0, unit => 'b/s' } ] } } ]; $self->{maps_counters}->{global} = [ { label => 'server-traffic-in', nlabel => 'cache.server.traffic.in.bitspersecond', set => { key_values => [ { name => 'cacheServerInKb', per_second => 1 } ], output_template => 'traffic in: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'server_traffic_in', template => '%s', min => 0, unit => 'b/s' } ] } }, { label => 'server-traffic-out', nlabel => 'cache.server.traffic.out.bitspersecond', set => { key_values => [ { name => 'cacheServerOutKb', per_second => 1 } ], output_template => 'traffic out: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'server_traffic_out', template => '%s', min => 0, unit => 'b/s' } ] } }, { label => 'clients', nlabel => 'cache.clients.count', set => { key_values => [ { name => 'cacheClients' } ], output_template => 'current number of clients: %s', perfdatas => [ { label => 'clients', template => '%s', min => 0 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my %oids = ( cacheProtoClientHttpRequests => '.1.3.6.1.4.1.3495.1.3.2.1.1.0', cacheHttpHits => '.1.3.6.1.4.1.3495.1.3.2.1.2.0', cacheHttpErrors => '.1.3.6.1.4.1.3495.1.3.2.1.3.0', cacheHttpInKb => '.1.3.6.1.4.1.3495.1.3.2.1.4.0', cacheHttpOutKb => '.1.3.6.1.4.1.3495.1.3.2.1.5.0', cacheIcpKbSent => '.1.3.6.1.4.1.3495.1.3.2.1.8.0', cacheIcpKbRecv => '.1.3.6.1.4.1.3495.1.3.2.1.9.0', cacheServerInKb => '.1.3.6.1.4.1.3495.1.3.2.1.12.0', cacheServerOutKb => '.1.3.6.1.4.1.3495.1.3.2.1.13.0', cacheClients => '.1.3.6.1.4.1.3495.1.3.2.1.15.0', ); my $snmp_result = $options{snmp}->get_leef(oids => [ values %oids ], nothing_quit => 1); $self->{global_http} = { cacheProtoClientHttpRequests => $snmp_result->{$oids{cacheProtoClientHttpRequests}}, cacheHttpHits => $snmp_result->{$oids{cacheHttpHits}}, cacheHttpErrors => $snmp_result->{$oids{cacheHttpErrors}}, cacheHttpInKb => $snmp_result->{$oids{cacheHttpInKb}} * 1024 * 8, cacheHttpOutKb => $snmp_result->{$oids{cacheHttpOutKb}} * 1024 * 8, }; $self->{global_icp} = { cacheIcpKbSent => $snmp_result->{$oids{cacheIcpKbSent}} * 1024 * 8, cacheIcpKbRecv => $snmp_result->{$oids{cacheIcpKbRecv}} * 1024 * 8, }; $self->{global} = { cacheServerInKb => $snmp_result->{$oids{cacheServerInKb}} * 1024 * 8, cacheServerOutKb => $snmp_result->{$oids{cacheServerOutKb}} * 1024 * 8, cacheClients => $snmp_result->{$oids{cacheClients}}, }; $self->{cache_name} = "squid_" . $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')); } 1; __END__ =head1 MODE Check protocol statistics. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='http' =item B<--warning-*> Threshold warning. Can be: 'http-hits-rate', 'http-errors', 'http-traffic-in', 'http-traffic-out', 'icp-traffic-in', 'icp-traffic-out', 'server-traffic-in', 'server-traffic-out', 'clients'. =item B<--critical-*> Threshold critical. Can be: 'http-hits-rate', 'http-errors', 'http-traffic-in', 'http-traffic-out', 'icp-traffic-in', 'icp-traffic-out', 'server-traffic-in', 'server-traffic-out', 'clients'. =back =cut centreon-plugins-20220113/apps/squid/snmp/plugin.pm000066400000000000000000000024201417000230700221330ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::squid::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} = { 'cache-usage' => 'apps::squid::snmp::mode::cacheusage', 'protocol-stats' => 'apps::squid::snmp::mode::protocolstats' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Squid proxy in SNMP. =cut centreon-plugins-20220113/apps/tomcat/000077500000000000000000000000001417000230700174665ustar00rootroot00000000000000centreon-plugins-20220113/apps/tomcat/jmx/000077500000000000000000000000001417000230700202645ustar00rootroot00000000000000centreon-plugins-20220113/apps/tomcat/jmx/mode/000077500000000000000000000000001417000230700212105ustar00rootroot00000000000000centreon-plugins-20220113/apps/tomcat/jmx/mode/connectorusage.pm000066400000000000000000000235461417000230700245770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::tomcat::jmx::mode::connectorusage; 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 => 'tomcatconnector', type => 1, cb_prefix_output => 'prefix_connector_output', message_multiple => 'All connectors are ok' }, ]; $self->{maps_counters}->{tomcatconnector} = [ { label => 'threads-count', set => { key_values => [ { name => 'currentThreadCount' }, { name => 'maxThreads' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { label_ref => 'currentThreadCount', message => 'Current Threads' }, closure_custom_output => $self->can('custom_usage_output'), closure_custom_threshold_check => $self->can('custom_usage_threshold'), closure_custom_perfdata => $self->can('custom_usage_perfdata'), } }, { label => 'threads-busy', set => { key_values => [ { name => 'currentThreadsBusy' }, { name => 'maxThreads' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { label_ref => 'currentThreadsBusy', message => 'Current Busy Threads' }, closure_custom_output => $self->can('custom_usage_output'), closure_custom_threshold_check => $self->can('custom_usage_threshold'), closure_custom_perfdata => $self->can('custom_usage_perfdata'), } }, { label => 'request-count', set => { key_values => [ { name => 'requestCount', diff => 1 }, { name => 'display' } ], output_template => 'Request Count : %s', perfdatas => [ { label => 'request_count', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'traffic-in', set => { key_values => [ { name => 'bytesReceived', per_second => 1 }, { name => 'display' } ], output_change_bytes => 2, output_template => 'Traffic In : %s %s/s', perfdatas => [ { label => 'traffic_in', template => '%.2f', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'traffic-out', set => { key_values => [ { name => 'bytesSent', per_second => 1 }, { name => 'display' } ], output_change_bytes => 2, output_template => 'Traffic Out : %s %s/s', perfdatas => [ { label => 'traffic_out', template => '%.2f', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display' }, ], } } ]; } sub custom_usage_perfdata { my ($self, %options) = @_; my $use_th = 1; $use_th = 0 if ($self->{instance_mode}->{option_results}->{units} eq '%' && $self->{result_values}->{max} <= 0); my $value_perf = $self->{result_values}->{used}; my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%' && $self->{result_values}->{max} > 0) { $total_options{total} = $self->{result_values}->{max}; $total_options{cast_int} = 1; } my $label = $self->{label}; $label =~ s/-/_/g; $self->{output}->perfdata_add( label => $label, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, value => $value_perf, warning => $use_th == 1 ? $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, %total_options) : undef, critical => $use_th == 1 ? $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, %total_options) : undef, min => 0, max => $self->{result_values}->{max} > 0 ? $self->{result_values}->{max} : undef ); } sub custom_usage_threshold { my ($self, %options) = @_; # Cannot use percent without total return 'ok' if ($self->{result_values}->{max} <= 0 && $self->{instance_mode}->{option_results}->{units} eq '%'); my ($exit, $threshold_value); $threshold_value = $self->{result_values}->{used}; if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; } $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel}, exit_litteral => 'warning' } ]); return $exit; } sub custom_usage_output { my ($self, %options) = @_; my $msg; if ($self->{result_values}->{max} > 0) { $msg = sprintf("%s Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", $self->{result_values}->{message}, $self->{result_values}->{max}, $self->{result_values}->{used}, $self->{result_values}->{prct_used}, $self->{result_values}->{max} - $self->{result_values}->{used}, 100 - $self->{result_values}->{prct_used}); } else { $msg = sprintf("%s : %s", $self->{result_values}->{message}, $self->{result_values}->{used}); } return $msg; } sub custom_usage_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{message} = $options{extra_options}->{message}; $self->{result_values}->{max} = $options{new_datas}->{$self->{instance} . '_maxThreads'}; $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{label_ref}}; if ($self->{result_values}->{max} > 0) { $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{max}; } return 0; } sub prefix_connector_output { my ($self, %options) = @_; return "Connector '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'units:s' => { name => 'units', default => '%' }, }); return $self; } sub manage_selection { my ($self, %options) = @_; # Tomcat: Catalina # Jboss: jboss.web $self->{request} = [ { mbean => "*:name=*,type=ThreadPool", attributes => [ { name => 'currentThreadCount' }, { name => 'currentThreadsBusy' }, { name => 'maxThreads' } ] }, { mbean => "*:name=*,type=GlobalRequestProcessor", attributes => [ { name => 'bytesReceived' }, { name => 'bytesSent' }, { name => 'requestCount' } ] } ]; my $result = $options{custom}->get_attributes(request => $self->{request}, nothing_quit => 1); $self->{tomcatconnector} = {}; foreach my $key (keys %$result) { $key =~ /name=(.*?),type=(.*)/; my ($connector, $type) = ($1, $2); # double quote nivo du name si existe $connector =~ s/^"(.*)"$/$1/g; if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $connector !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $connector . "': no matching filter.", debug => 1); next; } $result->{$key}->{bytesSent} *= 8 if (defined($result->{$key}->{bytesSent})); $result->{$key}->{bytesReceived} *= 8 if (defined($result->{$key}->{bytesReceived})); $self->{tomcatconnector}->{$connector} = { display => $connector } if (!defined($self->{tomcatconnector}->{$connector})); $self->{tomcatconnector}->{$connector} = { %{$self->{tomcatconnector}->{$connector}}, %{$result->{$key}} }; } $self->{cache_name} = "tomcat_" . $self->{mode} . '_' . md5_hex($options{custom}->get_connection_info()) . '_' . (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 connector usage. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='threads-busy' =item B<--filter-name> Filter connector name (can be a regexp). =item B<--warning-*> Threshold warning. Can be: 'threads-count', 'threads-busy', 'request-count', 'traffic-in', 'traffic-out'. =item B<--critical-*> Threshold critical. Can be: 'threads-count', 'threads-busy', 'request-count', 'traffic-in', 'traffic-out'. =item B<--units> Units of thresholds (Default: '%') ('%', 'absolute'). =back =cut centreon-plugins-20220113/apps/tomcat/jmx/mode/datasourceusage.pm000066400000000000000000000214651417000230700247350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::tomcat::jmx::mode::datasourceusage; 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 => 'datasource', type => 1, cb_prefix_output => 'prefix_ds_output', message_multiple => 'All datasources are ok' } ]; $self->{maps_counters}->{datasource} = [ { label => 'num-active', set => { key_values => [ { name => 'numActive' }, { name => 'maxActive' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { label_ref => 'Active', message => 'Current Num Active' }, closure_custom_output => $self->can('custom_usage_output'), closure_custom_threshold_check => $self->can('custom_usage_threshold'), closure_custom_perfdata => $self->can('custom_usage_perfdata') } }, { label => 'num-idle', set => { key_values => [ { name => 'numIdle' }, { name => 'maxIdle' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { label_ref => 'Idle', message => 'Current Num Idle' }, closure_custom_output => $self->can('custom_usage_output'), closure_custom_threshold_check => $self->can('custom_usage_threshold'), closure_custom_perfdata => $self->can('custom_usage_perfdata') } } ]; } sub custom_usage_perfdata { my ($self, %options) = @_; my $use_th = 1; $use_th = 0 if ($self->{instance_mode}->{option_results}->{units} eq '%' && $self->{result_values}->{max} <= 0); my $value_perf = $self->{result_values}->{used}; my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%' && $self->{result_values}->{max} > 0) { $total_options{total} = $self->{result_values}->{max}; $total_options{cast_int} = 1; } my $label = $self->{label}; $label =~ s/-/_/g; $self->{output}->perfdata_add( label => $label, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, value => $value_perf, warning => $use_th == 1 ? $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, %total_options) : undef, critical => $use_th == 1 ? $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, %total_options) : undef, min => 0, max => $self->{result_values}->{max} > 0 ? $self->{result_values}->{max} : undef ); } sub custom_usage_threshold { my ($self, %options) = @_; # Cannot use percent without total return 'ok' if ($self->{result_values}->{max} <= 0 && $self->{instance_mode}->{option_results}->{units} eq '%'); my ($exit, $threshold_value); $threshold_value = $self->{result_values}->{used}; if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; } $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel}, exit_litteral => 'warning' } ]); return $exit; } sub custom_usage_output { my ($self, %options) = @_; my $msg; if ($self->{result_values}->{max} > 0) { $msg = sprintf("%s Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", $self->{result_values}->{message}, $self->{result_values}->{max}, $self->{result_values}->{used}, $self->{result_values}->{prct_used}, $self->{result_values}->{max} - $self->{result_values}->{used}, 100 - $self->{result_values}->{prct_used}); } else { $msg = sprintf("%s : %s", $self->{result_values}->{message}, $self->{result_values}->{used}); } return $msg; } sub custom_usage_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{message} = $options{extra_options}->{message}; $self->{result_values}->{max} = $options{new_datas}->{$self->{instance} . '_max' . $options{extra_options}->{label_ref}}; $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_num' . $options{extra_options}->{label_ref}}; if ($self->{result_values}->{max} > 0) { $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{max}; } return 0; } sub prefix_ds_output { my ($self, %options) = @_; return "Datasource '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'units:s' => { name => 'units', default => '%' } }); return $self; } sub manage_selection { my ($self, %options) = @_; # maxActive or maxTotal $self->{request} = [ { mbean => "*:type=DataSource,class=*,context=*,host=*,name=*", attributes => [ { name => 'numActive' }, { name => 'numIdle' }, { name => 'maxIdle' }, { name => 'maxTotal' }, { name => 'maxActive' } ] }, { mbean => "*:type=DataSource,class=*,path=*,host=*,name=*", attributes => [ { name => 'numActive' }, { name => 'numIdle' }, { name => 'maxIdle' }, { name => 'maxTotal' }, { name => 'maxActive' } ] }, { mbean => "*:type=DataSource,class=*,name=*", attributes => [ { name => 'numActive' }, { name => 'numIdle' }, { name => 'maxIdle' }, { name => 'maxTotal' }, { name => 'maxActive' } ] } ]; my $result = $options{custom}->get_attributes(request => $self->{request}, nothing_quit => 1); $self->{datasource} = {}; foreach my $key (keys %$result) { my ($ds_name, $append) = ('', ''); if ($key =~ /(?:[:,])host=(.*?)(?:,|$)/) { $ds_name = $1; $append = '.'; } if ($key =~ /(?:[:,])(?:path|context)=(.*?)(?:,|$)/) { $ds_name .= $append . $1; $append = '.'; } $key =~ /(?:[:,])name=(.*?)(?:,|$)/; my $tmp_name = $1; $tmp_name =~ s/^"(.*)"$/$1/; $ds_name .= $append . $tmp_name; if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $ds_name !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $ds_name . "': no matching filter.", debug => 1); next; } $self->{datasource}->{$ds_name} = { display => $ds_name, numActive => $result->{$key}->{numActive}, maxActive => defined($result->{$key}->{maxTotal}) ? $result->{$key}->{maxTotal} : $result->{$key}->{maxActive}, numIdle => $result->{$key}->{numIdle}, maxIdle => $result->{$key}->{maxIdle} }; } $self->{cache_name} = 'tomcat_' . $self->{mode} . '_' . md5_hex($options{custom}->get_connection_info()) . '_' . (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 data sources usage. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='num-active' =item B<--filter-name> Filter datasource name (can be a regexp). =item B<--warning-*> Threshold warning. Can be: 'num-active', 'num-idle'. =item B<--critical-*> Threshold critical. Can be: 'num-active', 'num-idle'. =item B<--units> Units of thresholds (Default: '%') ('%', 'absolute'). =back =cut centreon-plugins-20220113/apps/tomcat/jmx/mode/listdatasources.pm000066400000000000000000000106521417000230700247630ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::tomcat::jmx::mode::listdatasources; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-host:s' => { name => 'filter_host' }, 'filter-path:s' => { name => 'filter_path' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; my $mbeans = $options{custom}->get_attributes( request => [ { mbean => "*:type=DataSource,class=*,context=*,host=*,name=*", attributes => [ { name => 'numActive' } ] }, { mbean => "*:type=DataSource,class=*,path=*,host=*,name=*", attributes => [ { name => 'numActive' } ] }, { mbean => "*:type=DataSource,class=*,name=*", attributes => [ { name => 'numActive' } ] } ] ); my $results = {}; foreach my $mbean (keys %$mbeans) { my ($ds_name, $path, $host, $append) = ('', '', '', ''); if ($mbean =~ /(?:[:,])host=(.*?)(?:,|$)/) { $host = $1; $ds_name = $host; $append = '.'; } if ($mbean =~ /(?:[:,])(?:path|context)=(.*?)(?:,|$)/) { $path = $1; $ds_name .= $append . $path; $append = '.'; } $mbean =~ /(?:[:,])name=(.*?)(?:,|$)/; my $name = $1; $name =~ s/^"(.*)"$/$1/; $ds_name .= $append . $name; if (defined($self->{option_results}->{filter_host}) && $self->{option_results}->{filter_host} ne '' && $host !~ /$self->{option_results}->{filter_host}/) { $self->{output}->output_add(long_msg => "skipping '" . $host . "': no matching filter.", debug => 1); next; } if (defined($self->{option_results}->{filter_path}) && $self->{option_results}->{filter_path} ne '' && $path !~ /$self->{option_results}->{filter_path}/) { $self->{output}->output_add(long_msg => "skipping '" . $path . "': no matching filter.", debug => 1); next; } $results->{$ds_name} = { host => $host, path => $path, name => $name, fullname => $ds_name }; } return $results; } sub run { my ($self, %options) = @_; my $results = $self->manage_selection(%options); foreach my $instance (sort keys %$results) { $self->{output}->output_add( long_msg => '[host = ' . $results->{$instance}->{host} . "]" . " [path = '" . $results->{$instance}->{path} . "']" . " [name = '" . $results->{$instance}->{name} . "']" ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List data sources:' ); $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 => ['host', 'path', 'name', 'fullname']); } sub disco_show { my ($self, %options) = @_; my $results = $self->manage_selection(%options); foreach my $instance (sort keys %$results) { $self->{output}->add_disco_entry( %{$results->{$instance}} ); } } 1; __END__ =head1 MODE List data sources. =over 8 =item B<--filter-host> Filter by virtual host name (can be a regexp). =item B<--filter-path> Filter by application name (can be a regexp). =back =cut centreon-plugins-20220113/apps/tomcat/jmx/mode/listwebapps.pm000066400000000000000000000075671417000230700241220ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::tomcat::jmx::mode::listwebapps; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-host:s" => { name => 'filter_host' }, "filter-path:s" => { name => 'filter_path' }, }); $self->{webapps} = {}; return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{request} = [ { mbean => "*:context=*,host=*,type=Manager", attributes => [ { name => 'activeSessions' } ] }, { mbean => "*:path=*,host=*,type=Manager", attributes => [ { name => 'activeSessions' } ] }, ]; my $result = $options{custom}->get_attributes(request => $self->{request}); foreach my $mbean (keys %{$result}) { $mbean =~ /(?:[:,])host=(.*?)(?:,|$)/; my $host = $1; $mbean =~ /(?:[:,])(?:path|context)=(.*?)(?:,|$)/; my $path = $1; if (defined($self->{option_results}->{filter_host}) && $self->{option_results}->{filter_host} ne '' && $host !~ /$self->{option_results}->{filter_host}/) { $self->{output}->output_add(long_msg => "skipping '" . $host . "': no matching filter.", debug => 1); next; } if (defined($self->{option_results}->{filter_path}) && $self->{option_results}->{filter_path} ne '' && $path !~ /$self->{option_results}->{filter_path}/) { $self->{output}->output_add(long_msg => "skipping '" . $path . "': no matching filter.", debug => 1); next; } $self->{webapps}->{$host . '.' . $path} = { host => $host, path => $path, }; } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $instance (sort keys %{$self->{webapps}}) { $self->{output}->output_add(long_msg => '[host = ' . $self->{webapps}->{$instance}->{host} . "]" . " [path = '" . $self->{webapps}->{$instance}->{path} . "']" ); } $self->{output}->output_add(severity => 'OK', short_msg => 'List webapps:'); $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 => ['host', 'path']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $instance (sort keys %{$self->{webapps}}) { $self->{output}->add_disco_entry( %{$self->{webapps}->{$instance}} ); } } 1; __END__ =head1 MODE List webapps. =over 8 =item B<--filter-host> Filter by virtual host name (can be a regexp). =item B<--filter-path> Filter by application name (can be a regexp). =back =cut centreon-plugins-20220113/apps/tomcat/jmx/mode/webappssessions.pm000066400000000000000000000176771417000230700250200ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::tomcat::jmx::mode::webappssessions; 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 => 'webapps', type => 1, cb_prefix_output => 'prefix_webapps_output', message_multiple => 'All webapp sessions are ok' }, ]; $self->{maps_counters}->{webapps} = [ { label => 'sessions-active', set => { key_values => [ { name => 'activeSessions' }, { name => 'maxActiveSessions' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { label_ref => 'currentThreadCount', message => 'Current Threads' }, closure_custom_output => $self->can('custom_usage_output'), closure_custom_threshold_check => $self->can('custom_usage_threshold'), closure_custom_perfdata => $self->can('custom_usage_perfdata'), } }, { label => 'sessions-count', set => { key_values => [ { name => 'sessionCounter', diff => 1 }, { name => 'display' } ], output_template => 'Sessions Count : %s', perfdatas => [ { label => 'sessions_count', value => 'sessionCounter', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub custom_usage_perfdata { my ($self, %options) = @_; my $use_th = 1; $use_th = 0 if ($self->{instance_mode}->{option_results}->{units} eq '%' && $self->{result_values}->{max} <= 0); my $value_perf = $self->{result_values}->{used}; my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%' && $self->{result_values}->{max} > 0) { $total_options{total} = $self->{result_values}->{max}; $total_options{cast_int} = 1; } my $label = $self->{label}; $label =~ s/-/_/g; $self->{output}->perfdata_add( label => $label, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, value => $value_perf, warning => $use_th == 1 ? $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, %total_options) : undef, critical => $use_th == 1 ? $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, %total_options) : undef, min => 0, max => $self->{result_values}->{max} > 0 ? $self->{result_values}->{max} : undef ); } sub custom_usage_threshold { my ($self, %options) = @_; # Cannot use percent without total return 'ok' if ($self->{result_values}->{max} <= 0 && $self->{instance_mode}->{option_results}->{units} eq '%'); my ($exit, $threshold_value); $threshold_value = $self->{result_values}->{used}; if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; } $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel}, exit_litteral => 'warning' } ]); return $exit; } sub custom_usage_output { my ($self, %options) = @_; my $msg; if ($self->{result_values}->{max} > 0) { $msg = sprintf("Current Active Sessions Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", $self->{result_values}->{max}, $self->{result_values}->{used}, $self->{result_values}->{prct_used}, $self->{result_values}->{max} - $self->{result_values}->{used}, 100 - $self->{result_values}->{prct_used}); } else { $msg = sprintf("Current Active Sessions : %s", $self->{result_values}->{used}); } return $msg; } sub custom_usage_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{max} = $options{new_datas}->{$self->{instance} . '_maxActiveSessions'}; $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_activeSessions'}; if ($self->{result_values}->{max} > 0) { $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{max}; } return 0; } sub prefix_webapps_output { my ($self, %options) = @_; return "Webapp '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "units:s" => { name => 'units', default => '%' }, }); return $self; } sub manage_selection { my ($self, %options) = @_; # can be path or context # Tomcat: Catalina:context=/xxxxx,host=localhost,type=Manager # Jboss: jboss.web:host=localhost,path=/invoker,type=Manager # maxActiveSessions = -1 (no limit) $self->{request} = [ { mbean => "*:context=*,host=*,type=Manager", attributes => [ { name => 'activeSessions' }, { name => 'sessionCounter' }, { name => 'maxActiveSessions' } ] }, { mbean => "*:path=*,host=*,type=Manager", attributes => [ { name => 'activeSessions' }, { name => 'sessionCounter' }, { name => 'maxActiveSessions' } ] }, ]; my $result = $options{custom}->get_attributes(request => $self->{request}, nothing_quit => 1); $self->{webapps} = {}; foreach my $key (keys %$result) { $key =~ /(?:[:,])host=(.*?)(?:,|$)/; my $webapps = $1; $key =~ /(?:[:,])(?:path|context)=(.*?)(?:,|$)/; $webapps .= '.' . $1; if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $webapps !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $webapps . "': no matching filter.", debug => 1); next; } $self->{webapps}->{$webapps} = { display => $webapps, %{$result->{$key}} }; } $self->{cache_name} = "tomcat_" . $self->{mode} . '_' . md5_hex($options{custom}->get_connection_info()) . '_' . (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 webapps session usage. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='sessions-active' =item B<--filter-name> Filter webapps name (can be a regexp). =item B<--warning-*> Threshold warning. Can be: 'sessions-count', 'sessions-active'. =item B<--critical-*> Threshold critical. Can be: 'sessions-count', 'sessions-active'. =item B<--units> Units of thresholds (Default: '%') ('%', 'absolute'). =back =cut centreon-plugins-20220113/apps/tomcat/jmx/plugin.pm000066400000000000000000000042351417000230700221240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::tomcat::jmx::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} = { 'class-count' => 'centreon::common::jvm::mode::classcount', 'connector-usage' => 'apps::tomcat::jmx::mode::connectorusage', 'cpu-load' => 'centreon::common::jvm::mode::cpuload', 'datasource-usage' => 'apps::tomcat::jmx::mode::datasourceusage', 'fd-usage' => 'centreon::common::jvm::mode::fdusage', 'gc-usage' => 'centreon::common::jvm::mode::gcusage', 'list-datasources' => 'apps::tomcat::jmx::mode::listdatasources', 'list-webapps' => 'apps::tomcat::jmx::mode::listwebapps', 'load-average' => 'centreon::common::jvm::mode::loadaverage', 'memory' => 'centreon::common::jvm::mode::memory', 'memory-detailed' => 'centreon::common::jvm::mode::memorydetailed', 'threads' => 'centreon::common::jvm::mode::threads', 'webapps-sessions' => 'apps::tomcat::jmx::mode::webappssessions' }; $self->{custom_modes}->{jolokia} = 'centreon::common::protocols::jmx::custom::jolokia'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Tomcat in JMX. Need Jolokia agent. =cut centreon-plugins-20220113/apps/tomcat/web/000077500000000000000000000000001417000230700202435ustar00rootroot00000000000000centreon-plugins-20220113/apps/tomcat/web/mode/000077500000000000000000000000001417000230700211675ustar00rootroot00000000000000centreon-plugins-20220113/apps/tomcat/web/mode/applications.pm000066400000000000000000000157531417000230700242260ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::tomcat::web::mode::applications; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use centreon::plugins::http; sub custom_status_output { my ($self, %options) = @_; return 'state: ' . $self->{result_values}->{state}; } sub prefix_application_output { my ($self, %options) = @_; return "Application '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'application', type => 1, cb_prefix_output => 'prefix_application_output', message_multiple => 'All applications are ok' } ]; $self->{maps_counters}->{application} = [ { label => 'status', type => 2, unknown_default => '%{state} ne "running"', critical_default => '%{state} eq "stopped"', set => { key_values => [ { name => 'state' }, { name => 'contextpath' }, { name => 'display' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'sessions-active', nlabel => 'application.sessions.active.count', set => { key_values => [ { name => 'sessions' }, { name => 'display' } ], output_template => 'active sessions: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } } ]; } 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port', default => '8080' }, 'proto:s' => { name => 'proto' }, 'credentials' => { name => 'credentials' }, 'basic' => { name => 'basic' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'timeout:s' => { name => 'timeout' }, 'urlpath:s' => { name => 'url_path', default => '/manager/text/list' }, 'filter-name:s' => { name => 'filter_name' }, 'filter-path:s' => { name => 'filter_path', }, 'unknown-http-status:s' => { name => 'unknown_http_status', default => '%{http_code} < 200 or %{http_code} >= 300' }, 'warning-http-status:s' => { name => 'warning_http_status', default => '' }, 'critical-http-status:s' => { name => 'critical_http_status', default => '' } }); $self->{http} = centreon::plugins::http->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{http}->set_options(%{$self->{option_results}}); } sub manage_selection { my ($self, %options) = @_; my $webcontent = $self->{http}->request( unknown_status => $self->{option_results}->{unknown_http_status}, warning_status => $self->{option_results}->{warning_http_status}, critical_status => $self->{option_results}->{critical_http_status} ); $self->{application} = {}; while ($webcontent =~ /^(.*?)\s*:\s*(.*?)\s*:\s*(.*?)\s*:\s*(.*)/mg) { my ($context, $state, $sessions, $contextpath) = ($1, $2, $3, $4); next if (defined($self->{option_results}->{filter_path}) && $self->{option_results}->{filter_path} ne '' && $contextpath !~ /$self->{option_results}->{filter_path}/); next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $context !~ /$self->{option_results}->{filter_name}/); $self->{application}->{$context} = { display => $context, state => $state, sessions => $sessions, contextpath => $contextpath }; } if (scalar(keys %{$self->{application}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No application found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check Tomcat Application Status by Tomcat Manager =over 8 =item B<--hostname> IP Address or FQDN of the Tomcat Application Server =item B<--port> Port used by Tomcat =item B<--proto> Protocol used http or https =item B<--credentials> Specify this option if you access server-status page with authentication =item B<--username> Specify username for authentication (Mandatory if --credentials is specified) =item B<--password> Specify password for authentication (Mandatory if --credentials is specified) =item B<--basic> Specify this option if you access server-status page over basic authentication and don't want a '401 UNAUTHORIZED' error to be logged on your webserver. Specify this option if you access server-status page over hidden basic authentication or you'll get a '404 NOT FOUND' error. (Use with --credentials) =item B<--timeout> Threshold for HTTP timeout =item B<--urlpath> Path to the Tomcat Manager List (Default: Tomcat 7 '/manager/text/list') Tomcat 6: '/manager/list' Tomcat 7: '/manager/text/list' =item B<--filter-name> Filter context name (regexp can be used) =item B<--filter-path> Filter Context Path (regexp can be used). Can be for example: '/STORAGE/context/test1'. =item B<--unknown-http-status> Threshold unknown for http response code (Default: '%{http_code} < 200 or %{http_code} >= 300') =item B<--warning-http-status> Threshold warning for http response code =item B<--critical-http-status> Threshold critical for http response code =item B<--unknown-status> Set unknown threshold for status (Default: '%{state} ne "running"'). Can used special variables like: %{state}, %{display} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{state}, %{display} =item B<--critical-status> Set critical threshold for status (Default: '%{state} eq "stopped"'). Can used special variables like: %{state}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'sessions-active'. =back =cut centreon-plugins-20220113/apps/tomcat/web/mode/connectors.pm000066400000000000000000000405761417000230700237160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::tomcat::web::mode::connectors; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::http; use Digest::MD5 qw(md5_hex); use XML::XPath; use URI::Escape; sub custom_traffic_output { my ($self, %options) = @_; my ($traffic_value, $traffic_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{traffic}, network => 1); my ($total_value, $total_unit); if (defined($self->{result_values}->{speed}) && $self->{result_values}->{speed} =~ /[0-9]/) { ($total_value, $total_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{speed}, network => 1); } my $msg = sprintf( "Traffic %s : %s/s (%s on %s)", ucfirst($self->{result_values}->{label}), $traffic_value . $traffic_unit, defined($self->{result_values}->{traffic_prct}) ? sprintf("%.2f%%", $self->{result_values}->{traffic_prct}) : '-', defined($total_value) ? $total_value . $total_unit : '-' ); return $msg; } sub custom_traffic_calc { my ($self, %options) = @_; $self->{result_values}->{label} = $options{extra_options}->{label_ref}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; my $diff_traffic = $options{new_datas}->{$self->{instance} . '_' . $self->{result_values}->{label}} - $options{old_datas}->{$self->{instance} . '_' . $self->{result_values}->{label}}; $self->{result_values}->{traffic} = $diff_traffic / $options{delta_time}; if (defined($self->{instance_mode}->{option_results}->{'speed_' . $self->{result_values}->{label}}) && $self->{instance_mode}->{option_results}->{'speed_' . $self->{result_values}->{label}} =~ /[0-9]/) { $self->{result_values}->{traffic_prct} = $self->{result_values}->{traffic} * 100 / ($self->{instance_mode}->{option_results}->{'speed_' . $self->{result_values}->{label}} * 1000 * 1000); $self->{result_values}->{speed} = $self->{instance_mode}->{option_results}->{'speed_' . $self->{result_values}->{label}} * 1000 * 1000; } elsif (defined($options{extra_options}->{type}) && $options{extra_options}->{type} eq 'prct') { return -10; } return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'connector', type => 1, cb_prefix_output => 'prefix_connector_output', message_multiple => 'All connectors are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{connector} = [ { label => 'threads-current', nlabel => 'connector.threads.current.count', set => { key_values => [ { name => 'currentThreadCount' }, { name => 'maxThreads' }, { name => 'display' } ], output_template => 'Threads Current : %s', perfdatas => [ { label => 'threads_current', template => '%.2f', min => 0, max => 'maxThreads', label_extra_instance => 1 } ] } }, { label => 'threads-busy', nlabel => 'connector.threads.busy.count', set => { key_values => [ { name => 'currentThreadsBusy' }, { name => 'maxThreads' }, { name => 'display' } ], output_template => 'Threads Busy : %s', perfdatas => [ { label => 'threads_busy', template => '%.2f', min => 0, max => 'maxThreads', label_extra_instance => 1 } ] } }, { label => 'traffic-in', nlabel => 'connector.traffic.in.bitspersecond', set => { key_values => [ { name => 'in', diff => 1 }, { name => 'display' } ], closure_custom_calc => $self->can('custom_traffic_calc'), closure_custom_calc_extra_options => { label_ref => 'in' }, closure_custom_output => $self->can('custom_traffic_output'), threshold_use => 'traffic', perfdatas => [ { label => 'traffic_in', value => 'traffic', template => '%.2f', min => 0, max => 'speed', unit => 'b/s', label_extra_instance => 1 } ] } }, { label => 'traffic-in-prct', display_ok => 0, nlabel => 'connector.traffic.in.percent', set => { key_values => [ { name => 'in', diff => 1 }, { name => 'display' } ], closure_custom_calc => $self->can('custom_traffic_calc'), closure_custom_calc_extra_options => { label_ref => 'in', type => 'prct' }, output_template => 'Traffic In Used : %.2f %%', output_use => 'traffic_prct', threshold_use => 'traffic_prct', perfdatas => [ { label => 'traffic_in_prct', value => 'traffic_prct', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 }, ], } }, { label => 'traffic-out', nlabel => 'connector.traffic.out.bitspersecond', set => { key_values => [ { name => 'out', diff => 1 }, { name => 'display' } ], closure_custom_calc => $self->can('custom_traffic_calc'), closure_custom_calc_extra_options => { label_ref => 'out' }, closure_custom_output => $self->can('custom_traffic_output'), threshold_use => 'traffic', perfdatas => [ { label => 'traffic_out', value => 'traffic', template => '%.2f', min => 0, max => 'speed', unit => 'b/s', label_extra_instance => 1 } ] } }, { label => 'traffic-out-prct', display_ok => 0, nlabel => 'connector.traffic.out.percent', set => { key_values => [ { name => 'out', diff => 1 }, { name => 'display' } ], closure_custom_calc => $self->can('custom_traffic_calc'), closure_custom_calc_extra_options => { label_ref => 'out', type => 'prct' }, output_template => 'Traffic Out Used : %.2f %%', output_use => 'traffic_prct', threshold_use => 'traffic_prct', perfdatas => [ { label => 'traffic_out_prct', value => 'traffic_prct', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 } ] } }, { label => 'requests-processingtime-total', nlabel => 'connector.requests.processingtime.total.milliseconds', set => { key_values => [ { name => 'requestInfo_processingTime', diff => 1 }, { name => 'display' } ], output_template => 'Requests Total Processing Time : %s ms', perfdatas => [ { label => 'requests_processingtime_total', template => '%s', min => 0, unit => 'ms', label_extra_instance => 1 } ] } }, { label => 'requests-errors', nlabel => 'connector.requests.errors.count', set => { key_values => [ { name => 'requestInfo_errorCount', diff => 1 }, { name => 'display' } ], output_template => 'Requests Errors : %s', perfdatas => [ { label => 'requests_errors', template => '%s', min => 0, label_extra_instance => 1 } ] } }, { label => 'requests-total', nlabel => 'connector.requests.total.count', set => { key_values => [ { name => 'requestInfo_requestCount', diff => 1 }, { name => 'display' } ], output_template => 'Requests Total : %s', perfdatas => [ { label => 'requests_total', template => '%s', min => 0, label_extra_instance => 1 } ] } } ]; } sub prefix_connector_output { my ($self, %options) = @_; return "Connector '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port', default => '8080' }, 'proto:s' => { name => 'proto' }, 'credentials' => { name => 'credentials' }, 'basic' => { name => 'basic' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'timeout:s' => { name => 'timeout' }, 'urlpath:s' => { name => 'url_path', default => '/manager/status?XML=true' }, 'filter-name:s' => { name => 'filter_name' }, 'speed-in:s' => { name => 'speed_in' }, 'speed-out:s' => { name => 'speed_out' }, }); $self->{http} = centreon::plugins::http->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{hostname} = $self->{option_results}->{hostname}; if (!defined($self->{hostname})) { $self->{hostname} = 'me'; } $self->{http}->set_options(%{$self->{option_results}}); } my %xpath_to_check = ( requestInfo_maxTime => '/status/connector/requestInfo/@maxTime', requestInfo_processingTime => '/status/connector/requestInfo/@processingTime', requestInfo_requestCount => '/status/connector/requestInfo/@requestCount', requestInfo_errorCount => '/status/connector/requestInfo/@errorCount', maxThreads => '/status/connector/threadInfo/@maxThreads', currentThreadCount => '/status/connector/threadInfo/@currentThreadCount', currentThreadsBusy => '/status/connector/threadInfo/@currentThreadsBusy', in => '/status/connector/requestInfo/@bytesReceived', out => '/status/connector/requestInfo/@bytesSent', ); sub manage_selection { my ($self, %options) = @_; #EXAMPLE 1: # # # # # # # # # # # # # #EXAMPLE 2: # # # # # # # # # # # # # # # # # # # # # my $webcontent = $self->{http}->request(); #GET XML DATA my $xpath = XML::XPath->new(xml => $webcontent); my %xpath_check_results; $self->{connector} = {}; foreach my $label (keys %xpath_to_check) { my $singlepath = $xpath_to_check{$label}; my $nodeset = $xpath->find($singlepath); foreach my $node ($nodeset->get_nodelist()) { my $connector_name = $node->getParentNode()->getParentNode()->getAttribute("name"); $connector_name =~ s/^["'\s]+//; $connector_name =~ s/["'\s]+$//; $connector_name = uri_unescape($connector_name); if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $connector_name !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $connector_name . "': no matching filter.", debug => 1); next; } $self->{connector}->{$connector_name} = { display => $connector_name } if (!defined($self->{connector}->{$connector_name})); my $value = $node->string_value(); if ($value =~ /^"?([0-9.]+)"?$/) { $self->{connector}->{$connector_name}->{$label} = $1; if ($label =~ /^in|out/) { $self->{connector}->{$connector_name}->{$label} *= 8; } } } } if (scalar(keys %{$self->{connector}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No information found."); $self->{output}->option_exit(); } $self->{cache_name} = "tomcat_web_" . $self->{mode} . '_' . $self->{option_results}->{hostname} . '_' . $self->{http}->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 Tomcat Application Servers Connectors =over 8 =item B<--hostname> IP Address or FQDN of the Tomcat Application Server =item B<--port> Port used by Tomcat =item B<--proto> Protocol used http or https =item B<--credentials> Specify this option if you access server-status page with authentication =item B<--username> Specify username for authentication (Mandatory if --credentials is specified) =item B<--password> Specify password for authentication (Mandatory if --credentials is specified) =item B<--basic> Specify this option if you access server-status page over basic authentication and don't want a '401 UNAUTHORIZED' error to be logged on your webserver. Specify this option if you access server-status page over hidden basic authentication or you'll get a '404 NOT FOUND' error. (Use with --credentials) =item B<--timeout> Threshold for HTTP timeout =item B<--urlpath> Path to the Tomcat Manager XML (Default: '/manager/status?XML=true') =item B<--filter-name> Filter by connector name (can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'traffic-in' (b), 'traffic-in-prct' (%), 'traffic-out' (b), 'traffic-out-prct' (%), 'threads-current', 'threads-busy', 'requests-processingtime-total' (ms), 'requests-errors', 'requests-total'. =item B<--speed-in> Set interface speed for incoming traffic (in Mb). =item B<--speed-out> Set interface speed for outgoing traffic (in Mb). =back =cut centreon-plugins-20220113/apps/tomcat/web/mode/listapplication.pm000066400000000000000000000130351417000230700247260ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::tomcat::web::mode::listapplication; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::http; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port', default => '8080' }, 'proto:s' => { name => 'proto' }, 'credentials' => { name => 'credentials' }, 'basic' => { name => 'basic' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'timeout:s' => { name => 'timeout' }, 'urlpath:s' => { name => 'url_path', default => '/manager/text/list' }, 'filter-name:s' => { name => 'filter_name', }, 'filter-state:s' => { name => 'filter_state', }, 'filter-path:s' => { name => 'filter_path', }, }); $self->{result} = {}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); $self->{http}->set_options(%{$self->{option_results}}); } sub manage_selection { my ($self, %options) = @_; my $webcontent = $self->{http}->request(); while ($webcontent =~ /^(.*?):(.*?):(.*?):(.*)/mg) { my ($context, $state, $sessions, $contextpath) = ($1, $2, $3, $4); if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $context !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "Skipping context '" . $context . "': no matching filter name"); next; } if (defined($self->{option_results}->{filter_state}) && $self->{option_results}->{filter_state} ne '' && $state !~ /$self->{option_results}->{filter_state}/) { $self->{output}->output_add(long_msg => "Skipping context '" . $context . "': no matching filter state"); next; } if (defined($self->{option_results}->{filter_path}) && $self->{option_results}->{filter_path} ne '' && $contextpath !~ /$self->{option_results}->{filter_path}/) { $self->{output}->output_add(long_msg => "Skipping context '" . $context . "': no matching filter path"); next; } $self->{result}->{$context} = {state => $state, sessions => $sessions, contextpath => $contextpath}; } } sub run { my ($self, %options) = @_; $self->manage_selection(); foreach my $name (sort(keys %{$self->{result}})) { $self->{output}->output_add(long_msg => "'" . $name . "' [state = " . $self->{result}->{$name}->{state} . ']'); } $self->{output}->output_add(severity => 'OK', short_msg => 'List Contexts:'); $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->manage_selection(); foreach my $name (sort(keys %{$self->{result}})) { $self->{output}->add_disco_entry( name => $name, state => $self->{result}->{$name}->{state} ); } } 1; __END__ =head1 MODE List Tomcat Application Server Contexts =over 8 =item B<--hostname> IP Address or FQDN of the Tomcat Application Server =item B<--port> Port used by Tomcat =item B<--proto> Protocol used http or https =item B<--credentials> Specify this option if you access server-status page with authentication =item B<--username> Specify username for authentication (Mandatory if --credentials is specified) =item B<--password> Specify password for authentication (Mandatory if --credentials is specified) =item B<--basic> Specify this option if you access server-status page over basic authentication and don't want a '401 UNAUTHORIZED' error to be logged on your webserver. Specify this option if you access server-status page over hidden basic authentication or you'll get a '404 NOT FOUND' error. (Use with --credentials) =item B<--timeout> Threshold for HTTP timeout =item B<--url-path> Path to the Tomcat Manager List (Default: Tomcat 7 '/manager/text/list') Tomcat 6: '/manager/list' Tomcat 7: '/manager/text/list' =item B<--filter-name> Filter Context name (regexp can be used). =item B<--filter-state> Filter state (regexp can be used). Can be for example: 'running' or 'stopped'. =item B<--filter-path> Filter Context Path (regexp can be used). Can be for example: '/STORAGE/context/test1'. =back =cut centreon-plugins-20220113/apps/tomcat/web/mode/memory.pm000066400000000000000000000207511417000230700230420ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::tomcat::web::mode::memory; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::http; use XML::XPath; sub custom_memory_output { my ($self, %options) = @_; return sprintf( "Memory Total: %s %s Used: %s %s (%.2f%%) Free: %s %s (%.2f%%)", $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}), $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}), $self->{result_values}->{prct_used}, $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}), $self->{result_values}->{prct_free} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ { label => 'usage', nlabel => 'memory.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_memory_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1 } ] } }, { label => 'usage-free', display_ok => 0, nlabel => 'memory.free.bytes', set => { key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_memory_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1 } ] } }, { label => 'usage-prct', display_ok => 0, nlabel => 'memory.usage.percentage', set => { key_values => [ { name => 'prct_used' } ], output_template => 'Memory Used : %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port', default => '8080' }, 'proto:s' => { name => 'proto' }, 'credentials' => { name => 'credentials' }, 'basic' => { name => 'basic' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'timeout:s' => { name => 'timeout' }, 'urlpath:s' => { name => 'url_path', default => '/manager/status?XML=true' } }); $self->{http} = centreon::plugins::http->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{http}->set_options(%{$self->{option_results}}); } my %xpath_to_check = ( memMax => '/status/jvm/memory/@max', memFree => '/status/jvm/memory/@free', memTotal => '/status/jvm/memory/@total', ); sub manage_selection { my ($self, %options) = @_; my $webcontent = $self->{http}->request(); #EXAMPLE 1: # # # # # # # # # # # # # #EXAMPLE 2: # # # # # # # # # # # # # # # # # # # # # my $result = {}; my $xpath = XML::XPath->new(xml => $webcontent); foreach my $xpath_check (keys %xpath_to_check) { my $nodeset = $xpath->find($xpath_to_check{$xpath_check}); foreach my $node ($nodeset->get_nodelist()) { my $value = $node->string_value(); if ($value =~ /^"?([0-9.]+)"?$/) { $result->{$xpath_check} = $1; } }; }; if (!defined($result->{memTotal}) || !defined($result->{memFree})) { $self->{output}->add_option_msg(short_msg => "some informations missing."); $self->{output}->option_exit(); } my $total = $result->{memTotal}; $self->{global} = { total => $total, free => $result->{memFree}, used => $total - $result->{memFree}, prct_free => $result->{memFree} * 100 / $total, prct_used => ($result->{memTotal} - $result->{memFree}) * 100 / $total, }; }; 1; __END__ =head1 MODE Check Tomcat Application Servers Memory Usage =over 8 =item B<--hostname> IP Address or FQDN of the Tomcat Application Server =item B<--port> Port used by Tomcat =item B<--proto> Protocol used http or https =item B<--credentials> Specify this option if you access server-status page with authentication =item B<--username> Specify username for authentication (Mandatory if --credentials is specified) =item B<--password> Specify password for authentication (Mandatory if --credentials is specified) =item B<--basic> Specify this option if you access server-status page over basic authentication and don't want a '401 UNAUTHORIZED' error to be logged on your webserver. Specify this option if you access server-status page over hidden basic authentication or you'll get a '404 NOT FOUND' error. (Use with --credentials) =item B<--timeout> Threshold for HTTP timeout =item B<--urlpath> Path to the Tomcat Manager XML (Default: '/manager/status?XML=true') =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'usage' (B), 'usage-free' (B), 'usage-prct' (%). =back =cut centreon-plugins-20220113/apps/tomcat/web/plugin.pm000066400000000000000000000027051417000230700221030ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::tomcat::web::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} = '0.1'; %{$self->{modes}} = ( 'applications' => 'apps::tomcat::web::mode::applications', 'connectors' => 'apps::tomcat::web::mode::connectors', 'list-application' => 'apps::tomcat::web::mode::listapplication', 'memory' => 'apps::tomcat::web::mode::memory', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Tomcat Application Server through Manager Webpage =cut centreon-plugins-20220113/apps/toshiba/000077500000000000000000000000001417000230700176305ustar00rootroot00000000000000centreon-plugins-20220113/apps/toshiba/storemate/000077500000000000000000000000001417000230700216335ustar00rootroot00000000000000centreon-plugins-20220113/apps/toshiba/storemate/sql/000077500000000000000000000000001417000230700224325ustar00rootroot00000000000000centreon-plugins-20220113/apps/toshiba/storemate/sql/mode/000077500000000000000000000000001417000230700233565ustar00rootroot00000000000000centreon-plugins-20220113/apps/toshiba/storemate/sql/mode/maintenanceplan.pm000066400000000000000000000150001417000230700270450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::toshiba::storemate::sql::mode::maintenanceplan; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::statefile; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); use DateTime; sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("alarm [workstation: %s] [text: %s] %s", $self->{result_values}->{workstation_id}, $self->{result_values}->{description}, $self->{result_values}->{generation_time}); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{description} = $options{new_datas}->{$self->{instance} . '_description'}; $self->{result_values}->{workstation_id} = $options{new_datas}->{$self->{instance} . '_workstation_id'}; $self->{result_values}->{since} = $options{new_datas}->{$self->{instance} . '_since'}; $self->{result_values}->{generation_time} = $options{new_datas}->{$self->{instance} . '_generation_time'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'alarms', type => 2, message_multiple => '0 problem(s) detected', display_counter_problem => { label => 'alerts', min => 0 }, group => [ { name => 'alarm', skipped_code => { -11 => 1 } } ] } ]; $self->{maps_counters}->{alarm} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'description' }, { name => 'workstation_id' }, { name => 'since' }, { name => 'generation_time' } ], 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 => \&catalog_status_threshold, } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "database:s" => { name => 'database', default => 'Framework' }, "warning-status:s" => { name => 'warning_status', default => '' }, "critical-status:s" => { name => 'critical_status', default => '1 == 1' }, "memory" => { name => 'memory' }, "timezone:s" => { name => 'timezone' }, }); centreon::plugins::misc::mymodule_load(output => $self->{output}, module => 'DateTime', error_msg => "Cannot load module 'DateTime'."); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->check_options(%options); } $self->{option_results}->{timezone} = 'GMT' if (!defined($self->{option_results}->{timezone}) || $self->{option_results}->{timezone} eq ''); } sub manage_selection { my ($self, %options) = @_; $self->{sql} = $options{sql}; $self->{sql}->connect(); $self->{sql}->query(query => "SELECT CONVERT(varchar, LOGDATE, 120) as LOGDATE, WORKSTATION_ID, USER_ID, DESCRIPTION, DESCRIPTION_PARAMETERS FROM " . $self->{option_results}->{database} . ".dbo.log WHERE (TYPE <> 1) AND (DESCRIPTION_PARAMETERS LIKE N'\%FO\%') AND (TASKNAME = 'FOCleanup')"); $self->{alarms}->{global} = { alarm => {} }; my $last_time; if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->read(statefile => 'cache_toshiba_storemate_' . $self->{mode} . '_' . $self->{sql}->get_unique_id4save()); $last_time = $self->{statefile_cache}->get(name => 'last_time'); } my ($i, $current_time) = (1, time()); my $tz = centreon::plugins::misc::set_timezone(name => $self->{option_results}->{timezone}); while (my $row = $self->{sql}->fetchrow_hashref()) { # date form: 2017-09-22 01:01:08.133 $row->{LOGDATE} =~ /^(\d+)-(\d+)-(\d+)\s+(\d+)[:\/](\d+)[:\/](\d+)/; my $dt = DateTime->new(year => $1, month => $2, day => $3, hour => $4, minute => $5, second => $6, %$tz); next if (defined($self->{option_results}->{memory}) && defined($last_time) && $last_time > $dt->epoch); my $diff_time = $current_time - $dt->epoch; $self->{alarms}->{global}->{alarm}->{$i} = { description => $row->{DESCRIPTION}, workstation_id => $row->{WORKSTATION_ID}, since => $diff_time, generation_time => centreon::plugins::misc::change_seconds(value => $diff_time) }; $i++; } if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->write(data => { last_time => $current_time }); } } 1; __END__ =head1 MODE Check the maintenance plan error logs. =over 8 =item B<--database> Database name (default: 'Framework'). =item B<--warning-status> Set warning threshold for status (Default: '') Can used special variables like: %{description}, %{workstation_id}, %{since} =item B<--critical-status> Set critical threshold for status (Default: '1 == 1'. We match all errors). Can used special variables like: %{description}, %{workstation_id}, %{since} =item B<--timezone> Timezone of time options. Default is 'GMT'. =item B<--memory> Only check new alarms. =back =cut centreon-plugins-20220113/apps/toshiba/storemate/sql/mode/posstatus.pm000066400000000000000000000243421417000230700257660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::toshiba::storemate::sql::mode::posstatus; 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, cb_prefix_output => 'prefix_global_output' }, { name => 'state', type => 0, cb_prefix_output => 'prefix_state_output' }, { name => 'merchandise', type => 0, cb_prefix_output => 'prefix_merchandise_output' }, { name => 'transaction', type => 0, cb_prefix_output => 'prefix_transaction_output' }, ]; $self->{maps_counters}->{global} = [ { label => 'total', set => { key_values => [ { name => 'total' } ], output_template => 'total : %s', perfdatas => [ { label => 'total', value => 'total', template => '%s', min => 0 }, ], } }, { label => 'online', set => { key_values => [ { name => 'online' } ], output_template => 'online : %s', perfdatas => [ { label => 'online', value => 'online', template => '%s', min => 0 }, ], } }, { label => 'offline', set => { key_values => [ { name => 'offline' } ], output_template => 'offline : %s', perfdatas => [ { label => 'offline', value => 'offline', template => '%s', min => 0 }, ], } }, ]; $self->{maps_counters}->{state} = [ { label => 'state-unknown', set => { key_values => [ { name => 'unknown' } ], output_template => 'unknown : %s', perfdatas => [ { label => 'state_unknown', value => 'unknown', template => '%s', min => 0 }, ], } }, { label => 'state-signoff', set => { key_values => [ { name => 'signoff' } ], output_template => 'signed off : %s', perfdatas => [ { label => 'state_signoff', value => 'signoff', template => '%s', min => 0 }, ], } }, { label => 'state-signon', set => { key_values => [ { name => 'signon' } ], output_template => 'signed on : %s', perfdatas => [ { label => 'state_signon', value => 'signon', template => '%s', min => 0 }, ], } }, { label => 'state-closed', set => { key_values => [ { name => 'closed' } ], output_template => 'closed : %s', perfdatas => [ { label => 'state_closed', value => 'closed', template => '%s', min => 0 }, ], } }, { label => 'state-paused', set => { key_values => [ { name => 'paused' } ], output_template => 'paused : %s', perfdatas => [ { label => 'state_paused', value => 'paused', template => '%s', min => 0 }, ], } }, ]; $self->{maps_counters}->{merchandise} = [ { label => 'merchandise-rep-unknown', set => { key_values => [ { name => 'unknown' } ], output_template => 'unknown : %s', perfdatas => [ { label => 'merchandise_rep_unknown', value => 'unknown', template => '%s', min => 0 }, ], } }, { label => 'merchandise-rep-ok', set => { key_values => [ { name => 'ok' } ], output_template => 'ok : %s', perfdatas => [ { label => 'merchandise_rep_ok', value => 'ok', template => '%s', min => 0 }, ], } }, { label => 'merchandise-rep-suspended', set => { key_values => [ { name => 'suspended' } ], output_template => 'suspended : %s', perfdatas => [ { label => 'merchandise_rep_suspended', value => 'suspended', template => '%s', min => 0 }, ], } }, { label => 'merchandise-rep-error', set => { key_values => [ { name => 'error' } ], output_template => 'error : %s', perfdatas => [ { label => 'merchandise_rep_error', value => 'error', template => '%s', min => 0 }, ], } }, ]; $self->{maps_counters}->{transaction} = [ { label => 'transaction-rep-unknown', set => { key_values => [ { name => 'unknown' } ], output_template => 'unknown : %s', perfdatas => [ { label => 'transaction_rep_unknown', value => 'unknown', template => '%s', min => 0 }, ], } }, { label => 'transaction-rep-ok', set => { key_values => [ { name => 'ok' } ], output_template => 'ok : %s', perfdatas => [ { label => 'transaction_rep_ok', value => 'ok', template => '%s', min => 0 }, ], } }, { label => 'transaction-rep-suspended', set => { key_values => [ { name => 'suspended' } ], output_template => 'suspended : %s', perfdatas => [ { label => 'transaction_rep_suspended', value => 'suspended', template => '%s', min => 0 }, ], } }, { label => 'transaction-rep-error', set => { key_values => [ { name => 'error' } ], output_template => 'error : %s', perfdatas => [ { label => 'transaction_rep_error', value => 'error', template => '%s', min => 0 }, ], } }, ]; } sub prefix_global_output { my ($self, %options) = @_; return "Points of sale "; } sub prefix_state_output { my ($self, %options) = @_; return "State "; } sub prefix_merchandise_output { my ($self, %options) = @_; return "Merchandise replication "; } sub prefix_transaction_output { my ($self, %options) = @_; return "Transaction replication "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "database:s" => { name => 'database', default => 'Framework' }, }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{sql} = $options{sql}; $self->{sql}->connect(); $self->{sql}->query(query => "SELECT WORKSTATION_ID, ONLINE, FO_STATE, MERCHANDISE_REPLICATION, TRANSACTION_REPLICATION FROM " . $self->{option_results}->{database} . ".dbo.WORKSTATION_STATUS"); $self->{global} = { total => 0, online => 0, offline => 0 }; $self->{state} = { unknown => 0, signoff => 0, signon => 0, closed => 0, paused => 0 }; $self->{merchandise} = { unknown => 0, ok => 0, suspended => 0, error => 0 }; $self->{transaction} = { unknown => 0, ok => 0, suspended => 0, error => 0 }; my %map_status = (0 => 'offline', 1 => 'online'); my %map_state = (0 => 'unknown', 1 => 'signoff', 2 => 'signon', 3 => 'closed', 4 => 'paused'); my %map_merch_rep_status = (0 => 'unknown', 1 => 'ok', 2 => 'suspended', 3 => 'error'); my %map_trans_rep_status = (0 => 'unknown', 1 => 'ok', 2 => 'suspended', 3 => 'error'); while (my $row = $self->{sql}->fetchrow_hashref()) { $self->{global}->{total}++; $self->{global}->{$map_status{$row->{ONLINE}}}++ if (defined($map_status{$row->{ONLINE}})); $self->{state}->{$map_state{$row->{FO_STATE}}}++ if (defined($map_state{$row->{FO_STATE}})); $self->{merchandise}->{$map_merch_rep_status{$row->{MERCHANDISE_REPLICATION}}}++ if (defined($map_merch_rep_status{$row->{MERCHANDISE_REPLICATION}})); $self->{transaction}->{$map_trans_rep_status{$row->{TRANSACTION_REPLICATION}}}++ if (defined($map_trans_rep_status{$row->{TRANSACTION_REPLICATION}})); } } 1; __END__ =head1 MODE Check points of sale status =over 8 =item B<--database> Database name (default: 'Framework'). =item B<--warning-*> Threshold warning. Can be: 'online, offline, state-unknown, state-signoff, state-signon, state-closed, state-paused, merchandise-rep-unknown, merchandise-rep-ok, merchandise-rep-suspended, merchandise-rep-error, transaction-rep-unknown, transaction-rep-ok, transaction-rep-suspended, transaction-rep-error'. =item B<--critical-*> Threshold critical. Can be: 'online, offline, state-unknown, state-signoff, state-signon, state-closed, state-paused, merchandise-rep-unknown, merchandise-rep-ok, merchandise-rep-suspended, merchandise-rep-error, transaction-rep-unknown, transaction-rep-ok, transaction-rep-suspended, transaction-rep-error'. =back =cut centreon-plugins-20220113/apps/varnish/000077500000000000000000000000001417000230700176515ustar00rootroot00000000000000centreon-plugins-20220113/apps/varnish/local/000077500000000000000000000000001417000230700207435ustar00rootroot00000000000000centreon-plugins-20220113/apps/varnish/local/mode/000077500000000000000000000000001417000230700216675ustar00rootroot00000000000000centreon-plugins-20220113/apps/varnish/local/mode/stats.pm000066400000000000000000000420551417000230700233710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::varnish::local::mode::stats; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use JSON::XS; sub configure_varnish_stats { my ($self, %options) = @_; $self->{varnish_stats} = [ { entry => 'client_conn', nlabel => 'connections.client.accepted.persecond', display_ok => 1, per_second => 1 }, { entry => 'client_drop', nlabel => 'connections.client.dropped.persecond', display_ok => 1, per_second => 1 }, { entry => 'client_req', nlabel => 'connections.client.request.received.persecond', display_ok => 1, per_second => 1 }, { entry => 'client_drop_late', nlabel => 'connections.client.dropped.late.persecond', display_ok => 0, per_second => 1 }, { entry => 'client_req_400', nlabel => 'connections.client.request400.received.persecond', display_ok => 0, per_second => 1 }, { entry => 'client_req_411', nlabel => 'connections.client.request411.received.persecond', display_ok => 0, per_second => 1 }, { entry => 'client_req_413', nlabel => 'connections.client.request413.received.persecond', display_ok => 0, per_second => 1 }, { entry => 'client_req_417', nlabel => 'connections.client.request417.received.persecond', display_ok => 0, per_second => 1 }, { entry => 'backend_conn', nlabel => 'backends.connections.success.persecond', display_ok => 0, per_second => 1 }, { entry => 'backend_unhealthy', nlabel => 'backends.connections.unhealthy.persecond', display_ok => 0, per_second => 1 }, { entry => 'backend_busy', nlabel => 'backends.connections.busy.persecond', display_ok => 0, per_second => 1 }, { entry => 'backend_fail', nlabel => 'backends.connections.fail.persecond', display_ok => 0, per_second => 1 }, { entry => 'backend_reuse', nlabel => 'backends.connections.reuse.persecond', display_ok => 0, per_second => 1 }, { entry => 'backend_recycle', nlabel => 'backends.connections.recycle.persecond', display_ok => 0, per_second => 1 }, { entry => 'backend_retry', nlabel => 'backends.connections.retry.persecond', display_ok => 0, per_second => 1 }, { entry => 'backend_req', nlabel => 'backends.requests.persecond', display_ok => 0, per_second => 1 }, { entry => 'cache_hit', nlabel => 'cache.hit.persecond', display_ok => 0, per_second => 1 }, { entry => 'cache_hitpass', nlabel => 'cache.hitpass.persecond', display_ok => 0, per_second => 1 }, { entry => 'cache_miss', nlabel => 'cache.miss.persecond', display_ok => 0, per_second => 1 }, { entry => 'n_sess_mem', nlabel => 'structure.session.memory.count', display_ok => 0 }, { entry => 'n_sess', nlabel => 'structure.session.count', display_ok => 0 }, { entry => 'n_sess', nlabel => 'structure.session.count', display_ok => 0 }, { entry => 'n_object', nlabel => 'structure.object.count', display_ok => 0 }, { entry => 'n_vampireobject', nlabel => 'object.unresurrected.count', display_ok => 0 }, { entry => 'n_objectcore', nlabel => 'structure.objectcore.count', display_ok => 0 }, { entry => 'n_objecthead', nlabel => 'structure.objecthead.count', display_ok => 0 }, { entry => 'n_waitinglist', nlabel => 'structure.waitinglist.count', display_ok => 0 }, { entry => 'n_vbc', nlabel => 'structure.vbc.count', display_ok => 0 }, { entry => 'n_backend', nlabel => 'backend.count', display_ok => 0 }, { entry => 'n_expired', nlabel => 'object.expired.count', display_ok => 0 }, { entry => 'n_lru_nuked', nlabel => 'object.lru.nuked.count', display_ok => 0 }, { entry => 'n_lru_moved', nlabel => 'object.lru.moved.count', display_ok => 0 }, { entry => 'n_objsendfile', nlabel => 'object.sent.file.persecond', display_ok => 0, per_second => 1 }, { entry => 'n_objwrite', nlabel => 'object.sent.write.persecond', display_ok => 0, per_second => 1 }, { entry => 'n_objoverflow', nlabel => 'object.overflow.workspace.persecond', display_ok => 0, per_second => 1 }, { entry => 'shm_records', nlabel => 'shm.records.persecond', display_ok => 0, per_second => 1 }, { entry => 'shm_writes', nlabel => 'shm.writes.persecond', display_ok => 0, per_second => 1 }, { entry => 'shm_flushes', nlabel => 'shm.flushes.persecond', display_ok => 0, per_second => 1 }, { entry => 'shm_cont', nlabel => 'shm.contentions.persecond', display_ok => 0, per_second => 1 }, { entry => 'shm_cycles', nlabel => 'shm.cycles.persecond', display_ok => 0, per_second => 1 }, { entry => 'sms_nreq', nlabel => 'sms.allocator.requests.persecond', display_ok => 0, per_second => 1 }, { entry => 'sms_nobj', nlabel => 'sms.outstanding.allocations.count', display_ok => 0 }, { entry => 'sms_nbytes', nlabel => 'sms.outstanding.bytes', display_ok => 0, custom_output => $self->can('custom_output_scale_bytes') }, { entry => 'sms_balloc', nlabel => 'sms.outstanding.allocated.bytes', display_ok => 0, custom_output => $self->can('custom_output_scale_bytes') }, { entry => 'sms_bfree', nlabel => 'sms.outstanding.freed.bytes', display_ok => 0, custom_output => $self->can('custom_output_scale_bytes') }, { entry => 'fetch_head', nlabel => 'fetch.head.persecond', display_ok => 0, per_second => 1 }, { entry => 'fetch_length', nlabel => 'fetch.length.persecond', display_ok => 0, per_second => 1 }, { entry => 'fetch_chunked', nlabel => 'fetch.chunked.persecond', display_ok => 0, per_second => 1 }, { entry => 'fetch_eof', nlabel => 'fetch.eof.persecond', display_ok => 0, per_second => 1 }, { entry => 'fetch_bad', nlabel => 'fetch.badheaders.persecond', display_ok => 0, per_second => 1 }, { entry => 'fetch_close', nlabel => 'fetch.close.persecond', display_ok => 0, per_second => 1 }, { entry => 'fetch_oldhttp', nlabel => 'fetch.oldhttp.persecond', display_ok => 0, per_second => 1 }, { entry => 'fetch_zero', nlabel => 'fetch.zero.persecond', display_ok => 0, per_second => 1 }, { entry => 'fetch_failed', nlabel => 'fetch.failed.persecond', display_ok => 0, per_second => 1 }, { entry => 'fetch_1xx', nlabel => 'fetch.1xx.persecond', display_ok => 0, per_second => 1 }, { entry => 'fetch_204', nlabel => 'fetch.204.persecond', display_ok => 0, per_second => 1 }, { entry => 'fetch_304', nlabel => 'fetch.304.persecond', display_ok => 0, per_second => 1 }, { entry => 'n_ban', nlabel => 'ban.total.active.count', display_ok => 0 }, { entry => 'n_ban_add', nlabel => 'ban.new.added.persecond', display_ok => 0, per_second => 1 }, { entry => 'n_ban_retire', nlabel => 'ban.old.deleted.persecond', display_ok => 0, per_second => 1 }, { entry => 'n_ban_obj_test', nlabel => 'ban.object.tested.persecond', display_ok => 0, per_second => 1 }, { entry => 'n_ban_re_test', nlabel => 'ban.object.tested.regexp.persecond', display_ok => 0, per_second => 1 }, { entry => 'n_ban_dups', nlabel => 'ban.duplicate.removed.persecond', display_ok => 0, per_second => 1 }, { entry => 'dir_dns_lookups', nlabel => 'dns.director.lookups.persecond', display_ok => 0, per_second => 1 }, { entry => 'dir_dns_failed', nlabel => 'dns.director.lookups.failed.persecond', display_ok => 0, per_second => 1 }, { entry => 'dir_dns_hit', nlabel => 'dns.director.lookups.cachehit.persecond', display_ok => 0, per_second => 1 }, { entry => 'dir_dns_cache_full', nlabel => 'dns.director.cache.full.persecond', display_ok => 0, per_second => 1 }, { entry => 'esi_errors', nlabel => 'esi.parse.errors.persecond', display_ok => 0, per_second => 1 }, { entry => 'esi_warnings', nlabel => 'esi.parse.warnings.persecond', display_ok => 0, per_second => 1 }, { entry => 'hcb_nolock', nlabel => 'hck.lookups.nolock.persecond', display_ok => 0, per_second => 1 }, { entry => 'hcb_lock', nlabel => 'hck.lookups.lock.persecond', display_ok => 0, per_second => 1 }, { entry => 'hcb_insert', nlabel => 'hck.inserts.persecond', display_ok => 0, per_second => 1 }, { entry => 'n_vcl', nlabel => 'vlc.total.count', display_ok => 0, diff => 1 }, { entry => 'n_vcl_avail', nlabel => 'vlc.available.count', display_ok => 0, diff => 1 }, { entry => 'n_vcl_discard', nlabel => 'vlc.discarded.count', display_ok => 0, diff => 1 }, { entry => 'sess_conn', nlabel => 'sessions.accepted.count', display_ok => 0, diff => 1 }, { entry => 'sess_drop', nlabel => 'sessions.dropped.count', display_ok => 0, diff => 1 }, { entry => 'sess_fail', nlabel => 'sessions.failed.count', display_ok => 0, diff => 1 }, { entry => 'sess_pipe_overflow', nlabel => 'sessions.pipe.overflow.count', display_ok => 0, diff => 1 }, { entry => 'sess_queued', nlabel => 'sessions.queued.count', display_ok => 0, diff => 1 }, { entry => 'sess_readahead', nlabel => 'sessions.readahead.count', display_ok => 0, diff => 1 }, { entry => 'sess_closed', nlabel => 'sessions.closed.count', display_ok => 0, diff => 1 }, { entry => 'sess_herd', nlabel => 'sessions.herd.count', display_ok => 0, diff => 1 }, { entry => 'sess_linger', nlabel => 'sessions.linger.count', display_ok => 0, diff => 1 }, { entry => 'sess_closed', nlabel => 'sessions.closed.count', display_ok => 0, diff => 1 }, { entry => 'sess_pipeline', nlabel => 'sessions.pipeline.count', display_ok => 0, diff => 1 }, { entry => 'threads', nlabel => 'threads.total.count', display_ok => 0 }, { entry => 'threads_created', nlabel => 'threads.created.count', display_ok => 0, diff => 1 }, { entry => 'threads_limited', nlabel => 'threads.limited.count', display_ok => 0, diff => 1 }, { entry => 'threads_destroyed', nlabel => 'threads.destroyed.count', display_ok => 0, diff => 1 }, { entry => 'threads_failed', nlabel => 'threads.failed.count', display_ok => 0, diff => 1 }, { entry => 'thread_queue_len', nlabel => 'threads.queue.length.count', display_ok => 0 }, { entry => 's_sess', nlabel => 'total.sessions.seen.count', display_ok => 0, diff => 1 }, { entry => 's_req', nlabel => 'total.requests.count', display_ok => 0, diff => 1 }, { entry => 's_fetch', nlabel => 'total.backends.fetch.count', display_ok => 0, diff => 1 }, { entry => 'n_wrk', nlabel => 'workers.threads.count', display_ok => 0 }, { entry => 'n_wrk_create', nlabel => 'workers.threads.created.count', display_ok => 0, diff => 1 }, { entry => 'n_wrk_failed', nlabel => 'workers.threads.failed.count', display_ok => 0, diff => 1 }, { entry => 'n_wrk_max', nlabel => 'workers.threads.limited.count', display_ok => 0, diff => 1 }, { entry => 'n_wrk_lqueue', nlabel => 'workers.requests.queue.length.count', display_ok => 0, diff => 1 }, { entry => 'n_wrk_queued', nlabel => 'workers.requests.queued.count', display_ok => 0, diff => 1 }, { entry => 'n_wrk_drop', nlabel => 'workers.requests.dropped.count', display_ok => 0, diff => 1 }, { entry => 's0.g_space', category => 'SMA', nlabel => 'storage.space.free.bytes', display_ok => 0, custom_output => $self->can('custom_output_scale_bytes') }, ]; } sub custom_output_scale_bytes { my ($self, %options) = @_; my $label = $self->{label}; $label =~ s/-/_/g; my ($value, $unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{$label }); return sprintf('%s: %.2f %s', $self->{result_values}->{$label . '_description'}, $value, $unit); } sub custom_output_second { my ($self, %options) = @_; my $label = $self->{label}; $label =~ s/-/_/g; return sprintf('%s: %.2f/s', $self->{result_values}->{$label . '_description'}, $self->{result_values}->{$label}); } sub custom_output { my ($self, %options) = @_; my $label = $self->{label}; $label =~ s/-/_/g; return sprintf('%s: %s', $self->{result_values}->{$label . '_description'}, $self->{result_values}->{$label}); } sub set_counters { my ($self, %options) = @_; $self->configure_varnish_stats(); $self->{maps_counters_type} = [ { name => 'global', type => 0, skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = []; foreach (@{$self->{varnish_stats}}) { my $label = $_->{entry}; $label =~ s/_/-/g; push @{$self->{maps_counters}->{global}}, { label => $label, nlabel => $_->{nlabel}, display_ok => $_->{display_ok}, set => { key_values => [ { name => $_->{entry}, diff => $_->{diff}, per_second => $_->{per_second} }, { name => $_->{entry}. '_description' } ], closure_custom_output => defined($_->{custom_output}) ? $_->{custom_output} : (defined($_->{per_second}) ? $self->can('custom_output_second') : $self->can('custom_output')), perfdatas => [ { label => $_->{entry}, template => defined($_->{per_second}) ? '%.2f' : '%s', min => 0 } ] } } ; } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub check_varnish_old { my ($self, %options) = @_; return if (!defined($options{json}->{uptime})); # "cache_hit": {"value": 56320, "flag": "a", "description": "Cache hits"}, # "cache_hitpass": {"value": 0, "flag": "a", "description": "Cache hits for pass"}, # "SMA.s0.g_space": {"type": "SMA", "ident": "s0", "value": 2147483648, "flag": "i", "description": "Bytes available"}, foreach (@{$self->{varnish_stats}}) { my $entry = defined($_->{category}) ? $_->{category} . '.' . $_->{entry} : $_->{entry}; next if (!defined($options{json}->{$entry})); $self->{global}->{$_->{entry}} = $options{json}->{$entry}->{value}; $self->{global}->{$_->{entry} . '_description'} = $options{json}->{$entry}->{description}; } } sub check_varnish_new { my ($self, %options) = @_; my $counters = $options{json}; $counters = $counters->{counters} if (defined($counters->{counters})); # since varnish 6.6.x return if (!defined($counters->{'MAIN.uptime'})); # "MAIN.cache_hit": {"type": "MAIN", "value": 18437, "flag": "a", "description": "Cache hits"}, # "MAIN.cache_hitpass": {"type": "MAIN", "value": 3488, "flag": "a", "description": "Cache hits for pass"}, # "MAIN.cache_miss": {"type": "MAIN", "value": 5782, "flag": "a", "description": "Cache misses"}, # "SMA.s0.g_space": { "description": "Bytes available", "flag": "g", "format": "B", "value": 4244053932 }, foreach (@{$self->{varnish_stats}}) { my $category = defined($_->{category}) ? $_->{category} : 'MAIN'; next if (!defined($counters->{ $category . '.' . $_->{entry} })); $self->{global}->{$_->{entry}} = $counters->{ $category . '.' . $_->{entry} }->{value}; $self->{global}->{$_->{entry} . '_description'} = $counters->{ $category . '.' . $_->{entry} }->{description}; } } sub manage_selection { my ($self, %options) = @_; my ($stdout) = $options{custom}->execute_command( command => 'varnishstat', command_path => '/usr/bin', command_options => '-1 -j 2>&1' ); $self->{global} = {}; my $content; eval { $content = JSON::XS->new->utf8->decode($stdout); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } $self->check_varnish_old(json => $content); $self->check_varnish_new(json => $content); $self->{cache_name} = 'cache_varnish_' . $self->{mode} . '_' . (defined($self->{option_results}->{hostname}) ? md5_hex($self->{option_results}->{hostname}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); }; 1; __END__ =head1 MODE Check statistics with varnishstat command. Command used: /usr/bin/varnishstat -1 -j 2>&1 =over 8 =item B<--warning-[countername]> B<--critical-[countername]> Thresholds. Use option --list-counters to see available counters =back =cut centreon-plugins-20220113/apps/varnish/local/plugin.pm000066400000000000000000000024421417000230700226010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::varnish::local::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} = { 'stats' => 'apps::varnish::local::mode::stats' }; $self->{custom_modes}->{cli} = 'centreon::plugins::script_custom::cli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Varnish Cache with varnishstat Command =cut centreon-plugins-20220113/apps/video/000077500000000000000000000000001417000230700173055ustar00rootroot00000000000000centreon-plugins-20220113/apps/video/openheadend/000077500000000000000000000000001417000230700215575ustar00rootroot00000000000000centreon-plugins-20220113/apps/video/openheadend/snmp/000077500000000000000000000000001417000230700225345ustar00rootroot00000000000000centreon-plugins-20220113/apps/video/openheadend/snmp/mode/000077500000000000000000000000001417000230700234605ustar00rootroot00000000000000centreon-plugins-20220113/apps/video/openheadend/snmp/mode/nodeusage.pm000066400000000000000000000141661417000230700260000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::video::openheadend::snmp::mode::nodeusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = 'dependancy status : ' . $self->{result_values}->{dep_status}; return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{dep_status} = $options{new_datas}->{$self->{instance} . '_nodeDepStatus'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'node', type => 1, cb_prefix_output => 'prefix_node_output', message_multiple => 'All nodes are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{node} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'nodeDepStatus' }, { 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 => \&catalog_status_threshold, } }, { label => 'bitrate', set => { key_values => [ { name => 'nodeBitrate' }, { name => 'display' } ], output_template => 'bitRate : %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'bitrate', value => 'nodeBitrate', template => '%d', unit => 'b/s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $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 => '%{dep_status} =~ /false/i' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub prefix_node_output { my ($self, %options) = @_; return "Node '" . $options{instance_value}->{display} . "' "; } my %map_type = (1 => 'net', 2 => 'dvb', 3 => 'file', 4 => 'circular-file', 5 => 'directory', 6 => 'asi-rx', 7 => 'rtsp', 8 => 'jpeg', 9 => 'video', 10 => 'audio', 11 => 'video-rx', 12 => 'extract' ); my %map_status = (1 => 'true', 2 => 'false'); my $mapping = { nodeType => { oid => '.1.3.6.1.4.1.35902.1.4.1.1.3', map => \%map_type }, nodeDepStatus => { oid => '.1.3.6.1.4.1.35902.1.4.1.1.5', map => \%map_status }, nodeName => { oid => '.1.3.6.1.4.1.35902.1.4.1.1.7' }, nodeBitrate => { oid => '.1.3.6.1.4.1.35902.1.4.2.1.9' }, }; sub manage_selection { my ($self, %options) = @_; $self->{node} = {}; my $snmp_result = $options{snmp}->get_multiple_table( oids => [ { oid => $mapping->{nodeType}->{oid} }, { oid => $mapping->{nodeDepStatus}->{oid} }, { oid => $mapping->{nodeName}->{oid} }, { oid => $mapping->{nodeBitrate}->{oid} }, ], return_type => 1, nothing_quit => 1); foreach my $oid (keys %{$snmp_result}) { next if ($oid !~ /^$mapping->{nodeName}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $result->{nodeName} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{nodeName} . "': no matching filter.", debug => 1); next; } $result->{nodeBitrate} = !defined($result->{nodeBitrate}) || $result->{nodeBitrate} == 0 ? undef : $result->{nodeBitrate}; $self->{node}->{$instance} = { display => $result->{nodeName}, %$result }; } if (scalar(keys %{$self->{node}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No node found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check node usage. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^status$' =item B<--filter-name> Filter node name (can be a regexp). =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{dep_status}, %{display} =item B<--critical-status> Set critical threshold for status (Default: '%{dep_status} =~ /false/i'). Can used special variables like: %{dep_status}, %{display} =item B<--warning-*> Threshold warning. Can be: 'bitrate'. =item B<--critical-*> Threshold critical. Can be: 'bitrate'. =back =cut centreon-plugins-20220113/apps/video/openheadend/snmp/mode/operationstatus.pm000066400000000000000000000142531417000230700272670ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::video::openheadend::snmp::mode::operationstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = 'status : ' . $self->{result_values}->{dep_status}; return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_operationOpStatus'}; $self->{result_values}->{dep_status} = $options{new_datas}->{$self->{instance} . '_operationDepStatus'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'operation', type => 1, cb_prefix_output => 'prefix_operation_output', message_multiple => 'All operations are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{operation} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'operationOpStatus' }, { name => 'operationDepStatus' }, { 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 => \&catalog_status_threshold, } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-id:s" => { name => 'filter_id' }, "warning-status:s" => { name => 'warning_status', default => '' }, "critical-status:s" => { name => 'critical_status', default => '%{status} =~ /false/i' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub prefix_operation_output { my ($self, %options) = @_; return "Operation '" . $options{instance_value}->{display} . "' "; } my %map_type = (1 => 'demux', 2 => 'monitor-pid', 3 => 'monitor-type', 4 => 'playout-file', 5 => 'playout-circular-file', 6 => 'monitor-sid', 7 => 'playout-directory', 8 => 'hint', 9 => 'transcode-avc', 10 => 'transcode-mp2', 11 => 'transcode-aac', 12 => 'transmit-input', 13 => 'transmit-output', 14 => 'transcode-a52', 15 => 'grid-input', 16 => 'grid-acquire-mono', 17 => 'grid-acquire-stereo', 18 => 'acquire-mono', 19 => 'acquire-stereo', 20 => 'mux-input', 21 => 'remap-pid', 22 => 'remap-sid', 23 => 'mosaic', 24 => 'hint-scte35', ); my %map_status = (1 => 'true', 2 => 'false'); my $mapping = { operationType => { oid => '.1.3.6.1.4.1.35902.1.6.1.1.3', map => \%map_type }, operationDepStatus => { oid => '.1.3.6.1.4.1.35902.1.6.1.1.5', map => \%map_status }, operationOpStatus => { oid => '.1.3.6.1.4.1.35902.1.6.1.1.7', map => \%map_status }, }; sub manage_selection { my ($self, %options) = @_; $self->{operation} = {}; my $snmp_result = $options{snmp}->get_multiple_table( oids => [ { oid => $mapping->{operationType}->{oid} }, { oid => $mapping->{operationDepStatus}->{oid} }, { oid => $mapping->{operationOpStatus}->{oid} }, ], return_type => 1, nothing_quit => 1); foreach my $oid (keys %{$snmp_result}) { next if ($oid !~ /^$mapping->{operationOpStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); if (defined($self->{option_results}->{filter_id}) && $self->{option_results}->{filter_id} ne '' && $instance !~ /$self->{option_results}->{filter_id}/) { $self->{output}->output_add(long_msg => "skipping '" . $instance . "': no matching filter.", debug => 1); next; } if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' && $result->{operationType} !~ /$self->{option_results}->{filter_type}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{operationType} . "': no matching filter.", debug => 1); next; } $self->{operation}->{$instance} = { display => $instance, %$result }; } if (scalar(keys %{$self->{operation}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No operation found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check operation status. =over 8 =item B<--filter-id> Filter by operation ID (can be a regexp). =item B<--filter-type> Filter by operation type (can be a regexp). =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{status}, %{dep_status}, %{display} =item B<--critical-status> Set critical threshold for status (Default: '%{dep_status} =~ /false/i'). Can used special variables like: %{status}, %{dep_status}, %{display} =back =cut centreon-plugins-20220113/apps/video/openheadend/snmp/plugin.pm000066400000000000000000000025001417000230700243650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::video::openheadend::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}} = ( 'node-usage' => 'apps::video::openheadend::snmp::mode::nodeusage', 'operation-status' => 'apps::video::openheadend::snmp::mode::operationstatus', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check OpenHeadend in SNMP. =cut centreon-plugins-20220113/apps/video/zixi/000077500000000000000000000000001417000230700202705ustar00rootroot00000000000000centreon-plugins-20220113/apps/video/zixi/restapi/000077500000000000000000000000001417000230700217375ustar00rootroot00000000000000centreon-plugins-20220113/apps/video/zixi/restapi/custom/000077500000000000000000000000001417000230700232515ustar00rootroot00000000000000centreon-plugins-20220113/apps/video/zixi/restapi/custom/api.pm000066400000000000000000000114551417000230700243660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::video::zixi::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use JSON::XS; 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 => { 'hostname:s@' => { name => 'hostname' }, 'port:s@' => { name => 'port' }, 'proto:s@' => { name => 'proto' }, 'username:s@' => { name => 'username' }, 'password:s@' => { name => 'password' }, 'timeout:s@' => { name => 'timeout' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? shift(@{$self->{option_results}->{hostname}}) : undef; $self->{port} = (defined($self->{option_results}->{port})) ? shift(@{$self->{option_results}->{port}}) : 4444; $self->{proto} = (defined($self->{option_results}->{proto})) ? shift(@{$self->{option_results}->{proto}}) : 'http'; $self->{username} = (defined($self->{option_results}->{username})) ? shift(@{$self->{option_results}->{username}}) : ''; $self->{password} = (defined($self->{option_results}->{password})) ? shift(@{$self->{option_results}->{password}}) : ''; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? shift(@{$self->{option_results}->{timeout}}) : 10; if (!defined($self->{hostname})) { $self->{output}->add_option_msg(short_msg => "Need to specify hostname option."); $self->{output}->option_exit(); } if (!defined($self->{hostname}) || scalar(@{$self->{option_results}->{hostname}}) == 0) { return 0; } return 1; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{credentials} = 1; $self->{option_results}->{basic} = 1; $self->{option_results}->{username} = $self->{username}; $self->{option_results}->{password} = $self->{password}; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->set_options(%{$self->{option_results}}); } sub get { my ($self, %options) = @_; $self->settings(); my $response = $self->{http}->request( url_path => $options{path}, critical_status => '', warning_status => '' ); my $content; eval { $content = JSON::XS->new->utf8->decode($response); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } if (defined($content->{errmsg})) { $self->{output}->add_option_msg(short_msg => "Cannot get data: " . $content->{errmsg}); $self->{output}->option_exit(); } return $content; } 1; __END__ =head1 NAME Zixi REST API =head1 SYNOPSIS Zixi Rest API custom mode =head1 REST API OPTIONS =over 8 =item B<--hostname> Zixi hostname. =item B<--port> Port used (Default: 4444) =item B<--proto> Specify https if needed (Default: 'http') =item B<--username> Zixi username. =item B<--password> Zixi password. =item B<--timeout> Set HTTP timeout =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/video/zixi/restapi/mode/000077500000000000000000000000001417000230700226635ustar00rootroot00000000000000centreon-plugins-20220113/apps/video/zixi/restapi/mode/broadcasterinputusage.pm000066400000000000000000000170341417000230700276240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::video::zixi::restapi::mode::broadcasterinputusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = 'status : ' . $self->{result_values}->{status} . ' [error: ' . $self->{result_values}->{error} . ']'; return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; $self->{result_values}->{source} = $options{new_datas}->{$self->{instance} . '_source'}; $self->{result_values}->{error} = $options{new_datas}->{$self->{instance} . '_error'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'input', type => 1, cb_prefix_output => 'prefix_input_output', message_multiple => 'All inputs are ok', skipped_code => { -11 => 1 } }, ]; $self->{maps_counters}->{input} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'source' }, { name => 'error' } ], 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 => \&catalog_status_threshold, } }, { label => 'traffic-in', set => { key_values => [ { name => 'traffic_in', per_second => 1 }, { name => 'source' } ], output_change_bytes => 2, output_template => 'Traffic In : %s %s/s', perfdatas => [ { label => 'traffic_in', template => '%.2f', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'source' }, ], } }, { label => 'traffic-out', set => { key_values => [ { name => 'traffic_out', per_second => 1 }, { name => 'source' } ], output_change_bytes => 2, output_template => 'Traffic Out : %s %s/s', perfdatas => [ { label => 'traffic_out', template => '%.2f', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'source' }, ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-source:s' => { name => 'filter_source' }, 'warning-status:s' => { name => 'warning_status' }, 'critical-status:s' => { name => 'critical_status', default => '%{status} !~ /Connecting|Connected/i || %{error} !~ /none/i' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub prefix_input_output { my ($self, %options) = @_; return "Input '" . $options{instance_value}->{source} . "' "; } my %mapping_input_status = (0 => 'none', 1 => 'unknown', 2 => 'resolve error', 3 => 'timeout', 4 => 'network error', 5 => 'protocol error', 6 => 'server is full', 7 => 'connection rejected', 8 => 'authentication error', 9 => 'license error', 10 => 'end of file', 11 => 'flood error', 12 => 'redirect', 13 => 'stopped', 14 => 'limit', 15 => 'not found', 16 => 'not supported', 17 => 'local file system error', 18 => 'remote file system error', 19 => 'stream replaced', 20 => 'p2p abort', 21 => 'compression error', 22 => 'source collision error', 23 => 'adaptive', 24 => 'tcp connection error', 25 => 'rtmp connection error', 26 => 'rtmp handshake error', 27 => 'tcp connection closed', 28 => 'rtmp stream error', 29 => 'rtmp publish error', 30 => 'rtmp stream closed', 31 => 'rtmp play error', 32 => 'rtmp protocol error', 33 => 'rtmp analyze timeout', 34 => 'busy', 35 => 'encryption error', 36 => 'transcoder error', 37 => 'error in invocation a transcoder subprocess', 38 => 'error communicating with a transcoder subprocess', 39 => 'error in RTMP Akamai authentication', 40 => 'maximum outputs for the source reached', 41 => 'generic error', 42 => 'zero bitrate warning', 43 => 'low bitrate warning', 44 => 'multicast join failed', ); sub manage_selection { my ($self, %options) = @_; $self->{input} = {}; my $result = $options{custom}->get(path => '/zixi/streams.json?complete=1'); foreach my $entry (@{$result->{streams}}) { if (defined($self->{option_results}->{filter_source}) && $self->{option_results}->{filter_source} ne '' && $entry->{source} !~ /$self->{option_results}->{filter_source}/) { $self->{output}->output_add(long_msg => "skipping '" . $entry->{source} . "': no matching filter.", debug => 1); next; } $self->{input}->{$entry->{id}} = { source => $entry->{source}, status => $entry->{status}, error => $mapping_input_status{$entry->{error_code}}, traffic_in => $entry->{stats}->{net_recv}->{bytes} * 8, traffic_out => $entry->{stats}->{net_send}->{bytes} * 8, }; } if (scalar(keys %{$self->{input}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No input found."); $self->{output}->option_exit(); } $self->{cache_name} = "zixi_" . $self->{mode} . '_' . $options{custom}->{hostname} . '_' . $options{custom}->{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 input usage. =over 8 =item B<--filter-source> Filter source (can be a regexp). =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^status$' =item B<--warning-*> Threshold warning. Can be: 'traffic-in', 'traffic-out'. =item B<--critical-*> Threshold critical. Can be: 'traffic-in', 'traffic-out'. =item B<--warning-status> Set warning threshold for status (Default: -) Can used special variables like: %{source}, %{status}, %{error}. =item B<--critical-status> Set critical threshold for status (Default: '%{status} !~ /Connecting|Connected/i || %{error} !~ /none/i'). Can used special variables like: %{source}, %{status}, %{error}. =back =cut centreon-plugins-20220113/apps/video/zixi/restapi/mode/broadcasterlicenseusage.pm000066400000000000000000000237031417000230700301070ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::video::zixi::restapi::mode::broadcasterlicenseusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $info = $self->{result_values}->{info} eq '' ? '-' : $self->{result_values}->{info}; my $error = $self->{result_values}->{error} eq '' ? '-' : $self->{result_values}->{error}; my $msg = 'information : ' . $info . ' [error: ' . $error . ']'; return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{info} = $options{new_datas}->{$self->{instance} . '_info'}; $self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_name'}; $self->{result_values}->{error} = $options{new_datas}->{$self->{instance} . '_error'}; return 0; } sub custom_usage_perfdata { my ($self, %options) = @_; my $label = 'used'; my $value_perf = $self->{result_values}->{used}; if (defined($self->{instance_mode}->{option_results}->{free})) { $label = 'free'; $value_perf = $self->{result_values}->{free}; } my %total_options = (); if ($self->{result_values}->{total} =~ /[0-9]/ && $self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } $self->{output}->perfdata_add( label => $label, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, 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} =~ /[0-9]/ ? $self->{result_values}->{total} : undef ); } sub custom_usage_threshold { my ($self, %options) = @_; my ($exit, $threshold_value); $threshold_value = $self->{result_values}->{used}; $threshold_value = $self->{result_values}->{free} if (defined($self->{instance_mode}->{option_results}->{free})); if ($self->{result_values}->{total} =~ /[0-9]/ && $self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; $threshold_value = $self->{result_values}->{prct_free} if (defined($self->{instance_mode}->{option_results}->{free})); } $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel}, exit_litteral => 'warning' } ]); return $exit; } sub custom_usage_output { my ($self, %options) = @_; my $msg = sprintf("Total: %s Used: %s (%s) Free: %s (%s)", $self->{result_values}->{total}, $self->{result_values}->{used}, defined($self->{result_values}->{prct_used}) ? sprintf("%.2f%%", $self->{result_values}->{prct_used}) : '-', defined($self->{result_values}->{free}) ? $self->{result_values}->{free} : '-', defined($self->{result_values}->{prct_free}) ? sprintf("%.2f%%", $self->{result_values}->{prct_free}) : '-'); return $msg; } sub custom_usage_calc { my ($self, %options) = @_; return -10 if ($options{new_datas}->{$self->{instance} . '_info'} =~ /disabled/i || $options{new_datas}->{$self->{instance} . '_used'} eq '' || ($options{new_datas}->{$self->{instance} . '_used'} =~ /^0$/ && $options{new_datas}->{$self->{instance} . '_limit'} =~ /^0$/)); $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_limit'}; $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_used'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_name'}; # Can be 'unlimited' if ($self->{result_values}->{total} =~ /[0-9]/) { $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; $self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used}; $self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used}; if ($self->{result_values}->{free} < 0) { $self->{result_values}->{free} = 0; $self->{result_values}->{prct_free} = 0; } } return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'license', type => 1, cb_prefix_output => 'prefix_license_output', message_multiple => 'All licenses are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{license} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'info' }, { name => 'name' }, { name => 'error' } ], 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 => \&catalog_status_threshold, } }, { label => 'usage', set => { key_values => [ { name => 'used' }, { name => 'limit' }, { name => 'name' }, { name => 'info' } ], 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 => 'days', set => { key_values => [ { name => 'days' } ], output_template => '%d days remaining before expiration', closure_custom_perfdata => sub { return 0; }, } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "warning-status:s" => { name => 'warning_status' }, "critical-status:s" => { name => 'critical_status' }, "units:s" => { name => 'units', default => '%' }, "free" => { name => 'free' }, }); centreon::plugins::misc::mymodule_load(output => $self->{output}, module => 'Date::Parse', error_msg => "Cannot load module 'Date::Parse'."); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub prefix_license_output { my ($self, %options) = @_; return "License '" . $options{instance_value}->{name} . "' "; } sub manage_selection { my ($self, %options) = @_; $self->{license} = {}; my $result = $options{custom}->get(path => '/licensing_info'); my $current_time = time(); foreach my $entry (@{$result->{lics}}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $entry->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $entry->{name} . "': no matching filter.", debug => 1); next; } # Format 09-dec-2017. Can be also 'permanent' (so dont care) my $days_remaining; if ($entry->{exp} =~ /\d+-\S+-\d+/) { my $create_time = Date::Parse::str2time($entry->{exp}); $days_remaining = ($create_time - $current_time) / 86400; } $self->{license}->{$entry->{name}} = { %{$entry}, days => $days_remaining }; } if (scalar(keys %{$self->{license}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No license found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check license usage. =over 8 =item B<--filter-source> Filter source (can be a regexp). =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^status$' =item B<--warning-*> Threshold warning. Can be: 'usage', 'days'. =item B<--critical-*> Threshold critical. Can be: 'usage', 'days'. =item B<--units> Units of thresholds (Default: '%') ('%', 'absolute'). =item B<--free> Thresholds are on free license left. =item B<--warning-status> Set warning threshold for status (Default: -) Can used special variables like: %{name}, %{error}, %{info}. =item B<--critical-status> Set critical threshold for status (Default: -). Can used special variables like: %{name}, %{error}, %{info}. =back =cut centreon-plugins-20220113/apps/video/zixi/restapi/mode/broadcasteroutputusage.pm000066400000000000000000000201061417000230700300170ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::video::zixi::restapi::mode::broadcasteroutputusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = 'status : ' . $self->{result_values}->{status} . ' [error: ' . $self->{result_values}->{error} . ']'; return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; $self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_name'}; $self->{result_values}->{error} = $options{new_datas}->{$self->{instance} . '_error'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'output_stream', type => 1, cb_prefix_output => 'prefix_output_output', message_multiple => 'All outputs are ok', skipped_code => { -11 => 1 } }, ]; $self->{maps_counters}->{output_stream} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'name' }, { name => 'error' } ], 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 => \&catalog_status_threshold } }, { label => 'traffic-in', set => { key_values => [ { name => 'traffic_in', per_second => 1 }, { name => 'name' } ], output_change_bytes => 2, output_template => 'Traffic In : %s %s/s', perfdatas => [ { label => 'traffic_in', template => '%.2f', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'name' } ] } }, { label => 'traffic-out', set => { key_values => [ { name => 'traffic_out', per_second => 1 }, { name => 'name' } ], output_change_bytes => 2, output_template => 'Traffic Out : %s %s/s', perfdatas => [ { label => 'traffic_out', template => '%.2f', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'name' } ] } }, { label => 'dropped-in', set => { key_values => [ { name => 'dropped_in', diff => 1 }, { name => 'name' } ], output_template => 'Packets Dropped In : %s', perfdatas => [ { label => 'dropped_in', template => '%.2f', min => 0, label_extra_instance => 1, instance_use => 'name' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'warning-status:s' => { name => 'warning_status' }, 'critical-status:s' => { name => 'critical_status', default => '%{status} !~ /Connecting|Connected/i || %{error} !~ /none/i' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub prefix_output_output { my ($self, %options) = @_; return "Output '" . $options{instance_value}->{name} . "' "; } my %mapping_output_status = (0 => 'none', 1 => 'unknown', 2 => 'resolve error', 3 => 'timeout', 4 => 'network error', 5 => 'protocol error', 6 => 'server is full', 7 => 'connection rejected', 8 => 'authentication error', 9 => 'license error', 10 => 'end of file', 11 => 'flood error', 12 => 'redirect', 13 => 'stopped', 14 => 'limit', 15 => 'not found', 16 => 'not supported', 17 => 'local file system error', 18 => 'remote file system error', 19 => 'stream replaced', 20 => 'p2p abort', 21 => 'compression error', 22 => 'source collision error', 23 => 'adaptive', 24 => 'tcp connection error', 25 => 'rtmp connection error', 26 => 'rtmp handshake error', 27 => 'tcp connection closed', 28 => 'rtmp stream error', 29 => 'rtmp publish error', 30 => 'rtmp stream closed', 31 => 'rtmp play error', 32 => 'rtmp protocol error', 33 => 'rtmp analyze timeout', 34 => 'busy', 35 => 'encryption error', 36 => 'transcoder error', 37 => 'error in invocation a transcoder subprocess', 38 => 'error communicating with a transcoder subprocess', 39 => 'error in RTMP Akamai authentication', 40 => 'maximum outputs for the source reached', 41 => 'generic error', 42 => 'zero bitrate warning', 43 => 'low bitrate warning', 44 => 'multicast join failed', ); sub manage_selection { my ($self, %options) = @_; $self->{output_stream} = {}; my $result = $options{custom}->get(path => '/zixi/outputs.json?complete=1'); foreach my $entry (@{$result->{outputs}}) { my $name = $entry->{name} . '/' . $entry->{requested_stream_id}; 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->{output_stream}->{$entry->{id}} = { name => $name, status => $entry->{status}, error => $mapping_output_status{$entry->{error_code}}, traffic_in => $entry->{stats}->{net_recv}->{bytes} * 8, traffic_out => $entry->{stats}->{net_send}->{bytes} * 8, dropped_in => $entry->{stats}->{net_recv}->{dropped}, }; } if (scalar(keys %{$self->{output_stream}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No output found."); $self->{output}->option_exit(); } $self->{cache_name} = "zixi_" . $self->{mode} . '_' . $options{custom}->{hostname} . '_' . $options{custom}->{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 output usage. =over 8 =item B<--filter-name> Filter name (can be a regexp). =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^status$' =item B<--warning-*> Threshold warning. Can be: 'traffic-in', 'traffic-out', 'dropped-in'. =item B<--critical-*> Threshold critical. Can be: 'traffic-in', 'traffic-out', 'dropped-in'. =item B<--warning-status> Set warning threshold for status (Default: -) Can used special variables like: %{name}, %{status}, %{error}. =item B<--critical-status> Set critical threshold for status (Default: '%{status} !~ /Connecting|Connected/i || %{error} !~ /none/i'). Can used special variables like: %{name}, %{status}, %{error}. =back =cut centreon-plugins-20220113/apps/video/zixi/restapi/mode/broadcastersystemusage.pm000066400000000000000000000063051417000230700300100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::video::zixi::restapi::mode::broadcastersystemusage; 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-load', set => { key_values => [ { name => 'cpu_load' } ], output_template => 'Cpu Load : %.2f %%', perfdatas => [ { label => 'cpu_load', value => 'cpu_load', template => '%.2f', min => 0, max => 100, unit => '%' }, ], } }, { label => 'memory-usage', set => { key_values => [ { name => 'memory_used' } ], output_template => 'Memory Used : %.2f %%', perfdatas => [ { label => 'memory_used', value => 'memory_used', template => '%.2f', min => 0, max => 100, unit => '%' }, ], } }, { label => 'disk-usage', set => { key_values => [ { name => 'disk_used' } ], output_template => 'Disk Used : %.2f %%', perfdatas => [ { label => 'disk_used', value => 'disk_used', template => '%.2f', min => 0, max => 100, unit => '%' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->get(path => '/sys_load.json'); $self->{global} = { disk_used => $result->{disk_space}, cpu_load => $result->{cpu_load}, memory_used => $result->{memory_use} }; } 1; __END__ =head1 MODE Check system usage. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^disk-usage$' =item B<--warning-*> Threshold warning. Can be: 'disk-usage' (%), 'memory-usage' (%), 'cpu-load' (%). =item B<--critical-*> Threshold critical. Can be: 'disk-usage' (%), 'memory-usage' (%), 'cpu-load' (%). =back =cut centreon-plugins-20220113/apps/video/zixi/restapi/mode/feederinputusage.pm000066400000000000000000000130501417000230700265570ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::video::zixi::restapi::mode::feederinputusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = 'active : ' . $self->{result_values}->{active} . ' [error: ' . ($self->{result_values}->{error} ne '' ? $self->{result_values}->{error} : '-') . ']'; return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{active} = $options{new_datas}->{$self->{instance} . '_active'}; $self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_name'}; $self->{result_values}->{error} = $options{new_datas}->{$self->{instance} . '_error'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'input', type => 1, cb_prefix_output => 'prefix_input_output', message_multiple => 'All inputs are ok', skipped_code => { -11 => 1 } }, ]; $self->{maps_counters}->{input} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'active' }, { name => 'name' }, { name => 'error' } ], 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 => 'traffic-in', set => { key_values => [ { name => 'traffic_in', per_second => 1 }, { name => 'name' } ], output_change_bytes => 2, output_template => 'Traffic In : %s %s/s', perfdatas => [ { label => 'traffic_in', template => '%.2f', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'name' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'warning-status:s' => { name => 'warning_status' }, 'critical-status:s' => { name => 'critical_status' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub prefix_input_output { my ($self, %options) = @_; return "Input '" . $options{instance_value}->{name} . "' "; } sub manage_selection { my ($self, %options) = @_; $self->{input} = {}; my $result = $options{custom}->get(path => '/inputs_data'); foreach my $entry (@{$result->{inputs}}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $entry->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $entry->{source} . "': no matching filter.", debug => 1); next; } $self->{input}->{$entry->{name}} = { name => $entry->{name}, active => $entry->{active} == 0 ? 'false' : 'true', error => $entry->{error}, traffic_in => $entry->{bytes} * 8, }; } if (scalar(keys %{$self->{input}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No input found."); $self->{output}->option_exit(); } $self->{cache_name} = "zixi_" . $self->{mode} . '_' . $options{custom}->{hostname} . '_' . $options{custom}->{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 feeder input usage. =over 8 =item B<--filter-name> Filter name (can be a regexp). =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^status$' =item B<--warning-*> Threshold warning. Can be: 'traffic-in'. =item B<--critical-*> Threshold critical. Can be: 'traffic-in'. =item B<--warning-status> Set warning threshold for status (Default: -) Can used special variables like: %{name}, %{active}, %{error}. =item B<--critical-status> Set critical threshold for status (Default: -). Can used special variables like: %{name}, %{active}, %{error}. =back =cut centreon-plugins-20220113/apps/video/zixi/restapi/mode/feederoutputusage.pm000066400000000000000000000130771417000230700267710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::video::zixi::restapi::mode::feederoutputusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = 'active : ' . $self->{result_values}->{active} . ' [error: ' . ($self->{result_values}->{error} ne '' ? $self->{result_values}->{error} : '-') . ']'; return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{active} = $options{new_datas}->{$self->{instance} . '_active'}; $self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_name'}; $self->{result_values}->{error} = $options{new_datas}->{$self->{instance} . '_error'}; $self->{result_values}->{con_stat} = $options{new_datas}->{$self->{instance} . '_con_stat'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'output_stream', type => 1, cb_prefix_output => 'prefix_output_output', message_multiple => 'All outputs are ok' }, ]; $self->{maps_counters}->{output_stream} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'active' }, { name => 'name' }, { name => 'error' }, { name => 'con_stat' } ], 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 => \&catalog_status_threshold, } }, { label => 'current-bitrate', set => { key_values => [ { name => 'bitrate' }, { name => 'name' } ], output_change_bytes => 2, output_template => 'Current Bitrate : %s %s/s', perfdatas => [ { label => 'current_bitrate', value => 'bitrate', template => '%.2f', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'name' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "warning-status:s" => { name => 'warning_status' }, "critical-status:s" => { name => 'critical_status' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub prefix_output_output { my ($self, %options) = @_; return "Output '" . $options{instance_value}->{name} . "' "; } sub manage_selection { my ($self, %options) = @_; $self->{output_stream} = {}; my $result = $options{custom}->get(path => '/outs'); foreach my $entry (@{$result->{outs}}) { $entry->{name} = centreon::plugins::misc::trim($entry->{name}); if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $entry->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $entry->{source} . "': no matching filter.", debug => 1); next; } $self->{output_stream}->{$entry->{name}} = { name => $entry->{name}, active => $entry->{active} == 0 ? 'false' : 'true', error => $entry->{error}, con_stat => $entry->{con_stat}, bitrate => $entry->{bitrate}, }; } if (scalar(keys %{$self->{output_stream}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No output found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check feeder output usage. =over 8 =item B<--filter-source> Filter source (can be a regexp). =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^status$' =item B<--warning-*> Threshold warning. Can be: 'current-birate'. =item B<--critical-*> Threshold critical. Can be: 'current-birate'. =item B<--warning-status> Set warning threshold for status (Default: -) Can used special variables like: %{name}, %{active}, %{error}, %{con_stat}. =item B<--critical-status> Set critical threshold for status (Default: -). Can used special variables like: %{name}, %{active}, %{error}, %{con_stat}. =back =cut centreon-plugins-20220113/apps/video/zixi/restapi/plugin.pm000066400000000000000000000035021417000230700235730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::video::zixi::restapi::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} = '1.0'; %{$self->{modes}} = ( 'broadcaster-input-usage' => 'apps::video::zixi::restapi::mode::broadcasterinputusage', 'broadcaster-license-usage' => 'apps::video::zixi::restapi::mode::broadcasterlicenseusage', 'broadcaster-output-usage' => 'apps::video::zixi::restapi::mode::broadcasteroutputusage', 'broadcaster-system-usage' => 'apps::video::zixi::restapi::mode::broadcastersystemusage', 'feeder-input-usage' => 'apps::video::zixi::restapi::mode::feederinputusage', 'feeder-output-usage' => 'apps::video::zixi::restapi::mode::feederoutputusage', ); $self->{custom_modes}{api} = 'apps::video::zixi::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Zixi through HTTP/REST API. =cut centreon-plugins-20220113/apps/virtualization/000077500000000000000000000000001417000230700212635ustar00rootroot00000000000000centreon-plugins-20220113/apps/virtualization/hpe/000077500000000000000000000000001417000230700220375ustar00rootroot00000000000000centreon-plugins-20220113/apps/virtualization/hpe/simplivity/000077500000000000000000000000001417000230700242505ustar00rootroot00000000000000centreon-plugins-20220113/apps/virtualization/hpe/simplivity/restapi/000077500000000000000000000000001417000230700257175ustar00rootroot00000000000000centreon-plugins-20220113/apps/virtualization/hpe/simplivity/restapi/custom/000077500000000000000000000000001417000230700272315ustar00rootroot00000000000000centreon-plugins-20220113/apps/virtualization/hpe/simplivity/restapi/custom/api.pm000066400000000000000000000232141417000230700303420ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Authors : Roman Morandell - ivertix # package apps::virtualization::hpe::simplivity::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use centreon::plugins::statefile; use JSON::XS; use Digest::MD5 qw(md5_hex); 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'api-username:s' => { name => 'api_username' }, 'api-password:s' => { name => 'api_password' }, 'timeout:s' => { name => 'timeout' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'OMNISTACK REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); $self->{cache} = centreon::plugins::statefile->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : ''; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : ''; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify hostname option.'); $self->{output}->option_exit(); } if ($self->{api_username} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-username option."); $self->{output}->option_exit(); } if ($self->{api_password} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-password option."); $self->{output}->option_exit(); } $self->{cache}->check_options(option_results => $self->{option_results}); return 0; } sub get_connection_infos { my ($self, %options) = @_; return $self->{hostname} . '_' . $self->{http}->get_port(); } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub get_port { my ($self, %options) = @_; return $self->{port}; } sub json_decode { my ($self, %options) = @_; my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($options{content}); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } return $decoded; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->set_options(%{$self->{option_results}}); } sub clean_token { my ($self, %options) = @_; my $datas = {}; $options{statefile}->write(data => $datas); $self->{access_token} = undef; $self->{http}->add_header(key => 'Authorization', value => undef); } sub get_auth_token { my ($self, %options) = @_; my $has_cache_file = $options{statefile}->read(statefile => 'hpe_simplivity_api_' . md5_hex($self->{option_results}->{hostname}) . '_' . md5_hex($self->{option_results}->{api_username})); my $access_token = $options{statefile}->get(name => 'access_token'); my $expires_on = $options{statefile}->get(name => 'expires_on'); my $md5_secret_cache = $self->{cache}->get(name => 'md5_secret'); my $md5_secret = md5_hex($self->{api_username} . $self->{api_password}); if ($has_cache_file == 0 || !defined($access_token) || (time() > $expires_on) || (defined($md5_secret_cache) && $md5_secret_cache ne $md5_secret)) { my ($content) = $self->{http}->request( method => 'POST', url_path => '/api/oauth/token', post_param => [ 'grant_type=password', 'username=' . $self->{api_username}, 'password=' . $self->{api_password} ], warning_status => '', unknown_status => '', critical_status => '' ); if ($self->{http}->get_code() != 200) { $self->{output}->add_option_msg(short_msg => "Authentication error [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded = $self->json_decode(content => $content); if (!defined($decoded->{access_token})) { $self->{output}->add_option_msg(short_msg => "Cannot get token"); $self->{output}->option_exit(); } $access_token = $decoded->{access_token}; my $datas = { access_token => $access_token, expires_on => time() + $decoded->{expires_in}, md5_secret => $md5_secret }; $options{statefile}->write(data => $datas); } $self->{access_token} = $access_token; $self->{http}->add_header(key => 'Authorization', value => 'Bearer ' . $self->{access_token}); } sub request_api { my ($self, %options) = @_; $self->settings(); if (!defined($self->{access_token})) { $self->get_auth_token(statefile => $self->{cache}); } my $content = $self->{http}->request( method => 'GET', url_path => $options{endpoint}, get_param => $options{get_param}, warning_status => '', unknown_status => '', critical_status => '' ); # Maybe there is an issue with the token. So we retry. if ($self->{http}->get_code() < 200 || $self->{http}->get_code() >= 300) { $self->clean_token(statefile => $self->{cache}); $self->get_auth_token(statefile => $self->{cache}); $content = $self->{http}->request( url_path => $options{endpoint}, get_param => $options{get_param}, warning_status => '', unknown_status => '', critical_status => '' ); } my $decoded = $self->json_decode(content => $content); if (!defined($decoded)) { $self->{output}->add_option_msg(short_msg => 'Error while retrieving data (add --debug option for detailed message)'); $self->{output}->option_exit(); } if ($self->{http}->get_code() < 200 || $self->{http}->get_code() >= 300) { my $message = 'api request error'; if (defined($decoded->{message})) { $message .= ': ' . $decoded->{message}; } $self->{output}->add_option_msg(short_msg => $message); $self->{output}->option_exit(); } return $decoded; } sub get_hosts { my ($self, %options) = @_; return $self->request_api( endpoint => '/api/hosts', get_param => ['show_optional_fields=true', 'offset=0', 'limit=5000'] ); } sub get_host_hardware { my ($self, %options) = @_; return $self->request_api( endpoint => '/api/hosts/' . $options{id} . '/hardware', get_param => [] ); } sub get_omnistack_clusters { my ($self, %options) = @_; return $self->request_api( endpoint => '/api/omnistack_clusters', get_param => ['show_optional_fields=true', 'offset=0', 'limit=5000'] ); } sub get_virtual_machines { my ($self, %options) = @_; return $self->request_api( endpoint => '/api/virtual_machines', get_param => ['show_optional_fields=true', 'offset=0', 'limit=5000'] ); } 1; __END__ =head1 NAME OmniStack API =head1 SYNOPSIS OmniStack api =head1 OMNISTACK REST API OPTIONS =over 8 =item B<--hostname> OmniStack API hostname. =item B<--port> OmniStack API port (Default: 443) =item B<--proto> Specify https if needed (Default: 'https') =item B<--api-username> OmniStack API username =item B<--api-password> OmniStack API password =item B<--timeout> Set HTTP timeout =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/virtualization/hpe/simplivity/restapi/mode/000077500000000000000000000000001417000230700266435ustar00rootroot00000000000000centreon-plugins-20220113/apps/virtualization/hpe/simplivity/restapi/mode/discovery.pm000066400000000000000000000100271417000230700312100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::virtualization::hpe::simplivity::restapi::mode::discovery; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'resource-type:s' => { name => 'resource_type' }, 'prettify' => { name => 'prettify' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{resource_type}) || $self->{option_results}->{resource_type} eq '') { $self->{option_results}->{resource_type} = 'host'; } if ($self->{option_results}->{resource_type} !~ /^host|vm$/) { $self->{output}->add_option_msg(short_msg => 'unknown resource type'); $self->{output}->option_exit(); } } sub discovery_vm { my ($self, %options) = @_; my $vms = $options{custom}->get_virtual_machines(); my $disco_data = []; foreach my $vm (@{$vms->{virtual_machines}}) { my $node = {}; $node->{id} = $vm->{id}; $node->{name} = $vm->{name}; $node->{host_name} = $vm->{host_name}; $node->{state} = lc($vm->{state}); $node->{omnistack_cluster_name} = $vm->{omnistack_cluster_name}; push @$disco_data, $node; } return $disco_data; } sub discovery_host { my ($self, %options) = @_; my $hosts = $options{custom}->get_hosts(); my $disco_data = []; foreach my $host (@{$hosts->{hosts}}) { my $node = {}; $node->{uuid} = $host->{id}; $node->{name} = $host->{name}; $node->{model} = $host->{model}; $node->{state} = lc($host->{state}); $node->{management_ip} = $host->{management_ip}; $node->{omnistack_cluster_name} = $host->{omnistack_cluster_name}; push @$disco_data, $node; } return $disco_data; } sub run { my ($self, %options) = @_; my $disco_stats; $disco_stats->{start_time} = time(); my $results = []; if ($self->{option_results}->{resource_type} eq 'vm') { $results = $self->discovery_vm( custom => $options{custom} ); } else { $results = $self->discovery_host( custom => $options{custom} ); } $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; $disco_stats->{discovered_items} = scalar(@$results); $disco_stats->{results} = $results; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE Resources discovery. =over 8 =item B<--resource-type> Choose the type of resources to discover (Can be: 'vm', 'host'). =back =cut centreon-plugins-20220113/apps/virtualization/hpe/simplivity/restapi/mode/hosts.pm000066400000000000000000000257371417000230700303570ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Authors : Roman Morandell - ivertix # package apps::virtualization::hpe::simplivity::restapi::mode::hosts; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub prefix_global_output { my ($self, %options) = @_; return 'number of hosts '; } sub prefix_components_output { my ($self, %options) = @_; return 'number of components '; } sub host_long_output { my ($self, %options) = @_; return sprintf( "checking host '%s'", $options{instance} ); } sub prefix_host_output { my ($self, %options) = @_; return sprintf( "host '%s' ", $options{instance} ); } sub prefix_ldrive_output { my ($self, %options) = @_; return "logical drive '" . $options{instance} . "' "; } sub prefix_pdrive_output { my ($self, %options) = @_; return "physical drive '" . $options{instance} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } }, { name => 'hosts', type => 3, cb_prefix_output => 'prefix_host_output', cb_long_output => 'host_long_output', indent_long_output => ' ', message_multiple => 'All hosts are ok', group => [ { name => 'host_status', type => 0, skipped_code => { -10 => 1 } }, { name => 'components', type => 0, cb_prefix_output => 'prefix_components_output', skipped_code => { -10 => 1 } }, { name => 'raid', type => 0, skipped_code => { -10 => 1 } }, { name => 'ldrives', display_long => 1, cb_prefix_output => 'prefix_ldrive_output', message_multiple => 'logical drives are ok', type => 1, skipped_code => { -10 => 1 } }, { name => 'pdrives', display_long => 1, cb_prefix_output => 'prefix_pdrive_output', message_multiple => 'physical drives are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{global} = []; foreach ('alive', 'faulty', 'managed', 'removed', 'suspected', 'unknown') { push @{$self->{maps_counters}->{global}}, { label => 'hosts-' . $_, nlabel => 'hosts.' . $_ . '.count', display_ok => 0, set => { key_values => [ { name => $_ } ], output_template => $_ . ': %s', perfdatas => [ { template => '%s' } ] } }; } $self->{maps_counters}->{components} = []; foreach ('green', 'yellow', 'red', 'unknown') { push @{$self->{maps_counters}->{components}}, { label => 'host-components-' . $_, nlabel => 'host.components.' . $_ . '.count', display_ok => 0, set => { key_values => [ { name => $_ } ], output_template => $_ . ': %s', perfdatas => [ { template => '%s', label_extra_instance => 1 } ] } }; } $self->{maps_counters}->{host_status} = [ { label => 'host-status', type => 2, unknown_default => '%{status} =~ /unknown/', warning_default => '%{status} =~ /suspected/', critical_default => '%{status} =~ /faulty/', set => { key_values => [ { name => 'status' }, { name => 'name' } ], output_template => 'status: %s', closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{raid} = [ { label => 'raid-status', type => 2, unknown_default => '%{status} =~ /unknown/', warning_default => '%{status} =~ /yellow/', critical_default => '%{status} =~ /red/', set => { key_values => [ { name => 'status' }, { name => 'name' } ], output_template => 'raid card status: %s', closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{ldrives} = [ { label => 'logical-drive-status', type => 2, unknown_default => '%{status} =~ /unknown/', warning_default => '%{status} =~ /yellow/', critical_default => '%{status} =~ /red/', set => { key_values => [ { name => 'status' }, { name => 'name' } ], output_template => 'status: %s', closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{pdrives} = [ { label => 'physical-drive-status', type => 2, unknown_default => '%{status} =~ /unknown/', warning_default => '%{status} =~ /yellow/', critical_default => '%{status} =~ /red/', set => { key_values => [ { name => 'status' }, { name => 'name' } ], output_template => 'status: %s', closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $hosts = $options{custom}->get_hosts(); $self->{global} = { alive => 0, faulty => 0, managed => 0, removed => 0, suspected => 0, unknown => 0 }; $self->{hosts} = {}; foreach my $host (@{$hosts->{hosts}}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $host->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $host->{name} . "': no matching filter.", debug => 1); next; } $host->{state} = lc($host->{state}); $self->{global}->{ $host->{state} }++; $self->{hosts}->{ $host->{name} } = { host_status => { status => $host->{state}, name => $host->{name} }, components => { green => 0, yellow => 0, red => 0, unknown => 0 }, ldrives => {}, pdrives => {} }; my $hw = $options{custom}->get_host_hardware(id => $host->{id}); $self->{hosts}->{ $host->{name} }->{raid} = { status => lc($hw->{host}->{raid_card}->{status}) }; $self->{hosts}->{ $host->{name} }->{components}->{ lc($hw->{host}->{raid_card}->{status}) }++; foreach my $ldrive (@{$hw->{host}->{logical_drives}}) { $ldrive->{name} = $1 if ($ldrive->{name} =~ /Logical\s+Drive\s+(\d+)/); $self->{hosts}->{ $host->{name} }->{components}->{ lc($ldrive->{status}) }++; $self->{hosts}->{ $host->{name} }->{ldrives}->{ $ldrive->{name} } = { name => $ldrive->{name}, status => lc($ldrive->{status}) }; foreach my $entry (@{$ldrive->{drive_sets}}) { foreach my $pdrive (@{$entry->{physical_drives}}) { $self->{hosts}->{ $host->{name} }->{components}->{ lc($pdrive->{status}) }++; my $name = $ldrive->{name} . ':' . $pdrive->{drive_position}; $self->{hosts}->{ $host->{name} }->{pdrives}->{$name} = { name => $name, status => lc($pdrive->{status}) }; } } } } } 1; __END__ =head1 MODE Check hosts. =over 8 =item B<--filter-name> Filter hosts by name. =item B<--unknown-host-status> Set unknown threshold for status (Default: '%{status} =~ /unknown/'). Can used special variables like: %{status}, %{name} =item B<--warning-host-status> Set warning threshold for status (Default: '%{status} =~ /suspected/'). Can used special variables like: %{status}, %{name} =item B<--critical-host-status> Set critical threshold for status (Default: '%{status} =~ /faulty/'). Can used special variables like: %{status}, %{name} =item B<--unknown-raid-status> Set unknown threshold for component status (Default: '%{status} =~ /unknown/'). Can used special variables like: %{status}, %{name} =item B<--warning-raid-status> Set warning threshold for component status (Default: '%{status} =~ /yellow/'). Can used special variables like: %{status}, %{name} =item B<--critical-raid-status> Set critical threshold for component status (Default: '%{status} =~ /red/'). Can used special variables like: %{status}, %{name} =item B<--unknown-logical-drive-status> Set unknown threshold for component status (Default: '%{status} =~ /unknown/'). Can used special variables like: %{status}, %{name} =item B<--warning-logical-drive-status> Set warning threshold for component status (Default: '%{status} =~ /yellow/'). Can used special variables like: %{status}, %{name} =item B<--critical-logical-drive-status> Set critical threshold for component status (Default: '%{status} =~ /red/'). Can used special variables like: %{status}, %{name} =item B<--unknown-physical-drive-status> Set unknown threshold for component status (Default: '%{status} =~ /unknown/'). Can used special variables like: %{status}, %{name} =item B<--warning-physical-drive-status> Set warning threshold for component status (Default: '%{status} =~ /yellow/'). Can used special variables like: %{status}, %{name} =item B<--critical-physical-drive-status> Set critical threshold for component status (Default: '%{status} =~ /red/'). Can used special variables like: %{status}, %{name} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'hosts-alive', 'hosts-faulty', 'hosts-managed', 'hosts-removed', 'hosts-suspected', 'hosts-unknown', 'host-components-green', 'host-components-yellow', 'host-components-red', 'host-components-unknown'. =back =cut centreon-plugins-20220113/apps/virtualization/hpe/simplivity/restapi/mode/listhosts.pm000066400000000000000000000054341417000230700312430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::virtualization::hpe::simplivity::restapi::mode::listhosts; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { '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 $hosts = $options{custom}->get_hosts(); my $results = []; foreach my $host (@{$hosts->{hosts}}) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $host->{name} !~ /$self->{option_results}->{filter_name}/); push @$results, { id => $host->{id}, name => $host->{name}, status => lc($host->{state}) }; } return $results; } sub run { my ($self, %options) = @_; my $hosts = $self->manage_selection(%options); foreach my $host (@$hosts) { $self->{output}->output_add( long_msg => sprintf( "[id: %s][name: %s][status: %s]", $host->{id}, $host->{name}, $host->{status} ) ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List hosts:' ); $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 => ['id', 'name', 'status']); } sub disco_show { my ($self, %options) = @_; my $hosts = $self->manage_selection(%options); foreach my $host (@$hosts) { $self->{output}->add_disco_entry(%$host); } } 1; __END__ =head1 MODE List hosts. =over 8 =item B<--filter-name> Filter host name (Can be a regexp). =back =cut centreon-plugins-20220113/apps/virtualization/hpe/simplivity/restapi/mode/omnistackclusters.pm000066400000000000000000000170431417000230700327630ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Authors : Roman Morandell - ivertix # package apps::virtualization::hpe::simplivity::restapi::mode::omnistackclusters; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_space_usage_output { my ($self, %options) = @_; my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total_space}); my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used_space}); my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free_space}); return sprintf( 'space usage total: %s used: %s (%.2f%%) free: %s (%.2f%%)', $total_size_value . " " . $total_size_unit, $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used_space}, $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free_space} ); } sub prefix_ratio_output { my ($self, %options) = @_; return 'ratio '; } sub cluster_long_output { my ($self, %options) = @_; return sprintf( "checking cluster '%s'", $options{instance}, ); } sub prefix_cluster_output { my ($self, %options) = @_; return sprintf( "cluster '%s' ", $options{instance} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'clusters', type => 3, cb_prefix_output => 'prefix_cluster_output', cb_long_output => 'cluster_long_output', indent_long_output => ' ', message_multiple => 'All omnistack clusters are ok', group => [ { name => 'ratio', type => 0, cb_prefix_output => 'prefix_ratio_output', skipped_code => { -10 => 1 } }, { name => 'space', type => 0, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{space} = [ { label => 'space-usage', nlabel => 'omnistack_cluster.space.usage.bytes', set => { key_values => [ { name => 'used_space' }, { name => 'free_space' }, { name => 'prct_used_space' }, { name => 'prct_free_space' }, { name => 'total_space' } ], closure_custom_output => $self->can('custom_space_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total_space', unit => 'B', cast_int => 1, label_extra_instance => 1 } ] } }, { label => 'space-usage-free', nlabel => 'omnistack_cluster.space.free.bytes', display_ok => 0, set => { key_values => [ { name => 'free_space' }, { name => 'used_space' }, { name => 'prct_used_space' }, { name => 'prct_free_space' }, { name => 'total_space' } ], closure_custom_output => $self->can('custom_space_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total_space', unit => 'B', cast_int => 1, label_extra_instance => 1 } ] } }, { label => 'space-usage-prct', nlabel => 'omnistack_cluster.space.usage.percentage', display_ok => 0, set => { key_values => [ { name => 'prct_used_space' }, { name => 'used_space' }, { name => 'free_space' }, { name => 'prct_free_space' }, { name => 'total_space' } ], closure_custom_output => $self->can('custom_space_usage_output'), perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{ratio} = [ { label => 'ratio-deduplication', nlabel => 'omnistack_cluster.ratio.deduplication.count', set => { key_values => [ { name => 'deduplication' } ], output_template => 'deduplication: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } }, { label => 'ratio-compression', nlabel => 'omnistack_cluster.ratio.compression.count', set => { key_values => [ { name => 'compression' } ], output_template => 'compression: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } }, { label => 'ratio-efficiency', nlabel => 'omnistack_cluster.ratio.efficiency.count', set => { key_values => [ { name => 'efficiency' } ], output_template => 'efficiency: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $clusters = $options{custom}->get_omnistack_clusters(); $self->{clusters} = {}; foreach my $cluster (@{$clusters->{omnistack_clusters}}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $cluster->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $cluster->{name} . "': no matching filter.", debug => 1); next; } $self->{clusters}->{ $cluster->{name} } = { ratio => {}, space => { total_space => $cluster->{allocated_capacity}, used_space => $cluster->{used_capacity}, free_space => $cluster->{allocated_capacity} - $cluster->{used_capacity}, prct_used_space => $cluster->{used_capacity} * 100 / $cluster->{allocated_capacity}, prct_free_space => 100 - ($cluster->{used_capacity} * 100 / $cluster->{allocated_capacity}) } }; $self->{clusters}->{ $cluster->{name} }->{ratio}->{efficiency} = $1 if ($cluster->{efficiency_ratio} =~ /^\s*([0-9\.]+)\s*:/); $self->{clusters}->{ $cluster->{name} }->{ratio}->{deduplication} = $1 if ($cluster->{deduplication_ratio} =~ /^\s*([0-9\.]+)\s*:/); $self->{clusters}->{ $cluster->{name} }->{ratio}->{compression} = $1 if ($cluster->{compression_ratio} =~ /^\s*([0-9\.]+)\s*:/); } } 1; __END__ =head1 MODE Check omnistack clusters. =over 8 =item B<--filter-name> Filter clusters by name. =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'space-usage', 'space-usage-free', 'space-usage-prct', 'ratio-compression', 'ratio-deduplication', 'ratio-efficiency'. =back =cut centreon-plugins-20220113/apps/virtualization/hpe/simplivity/restapi/mode/virtualmachines.pm000066400000000000000000000160321417000230700324010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Authors : Roman Morandell - ivertix # package apps::virtualization::hpe::simplivity::restapi::mode::virtualmachines; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_space_usage_output { my ($self, %options) = @_; my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total_space}); my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used_space}); my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free_space}); return sprintf( 'space usage total: %s used: %s (%.2f%%) free: %s (%.2f%%)', $total_size_value . " " . $total_size_unit, $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used_space}, $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free_space} ); } sub vm_long_output { my ($self, %options) = @_; return sprintf( "checking virtual machine '%s'", $options{instance} ); } sub prefix_vm_output { my ($self, %options) = @_; return sprintf( "virtual machine '%s' ", $options{instance} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'vm', type => 3, cb_prefix_output => 'prefix_vm_output', cb_long_output => 'vm_long_output', indent_long_output => ' ', message_multiple => 'All virtual machines are ok', group => [ { name => 'status', type => 0, skipped_code => { -10 => 1 } }, { name => 'space', type => 0, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{status} = [ { label => 'ha-status', type => 2, unknown_default => '%{ha_status} =~ /unknown/', warning_default => '%{ha_status} =~ /degraded/', set => { key_values => [ { name => 'ha_status' }, { name => 'vm_name' } ], output_template => 'high-availability status: %s', closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{space} = [ { label => 'space-usage', nlabel => 'virtual_machine.space.usage.bytes', set => { key_values => [ { name => 'used_space' }, { name => 'free_space' }, { name => 'prct_used_space' }, { name => 'prct_free_space' }, { name => 'total_space' } ], closure_custom_output => $self->can('custom_space_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total_space', unit => 'B', cast_int => 1, label_extra_instance => 1 } ] } }, { label => 'space-usage-free', nlabel => 'virtual_machine.space.free.bytes', display_ok => 0, set => { key_values => [ { name => 'free_space' }, { name => 'used_space' }, { name => 'prct_used_space' }, { name => 'prct_free_space' }, { name => 'total_space' } ], closure_custom_output => $self->can('custom_space_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total_space', unit => 'B', cast_int => 1, label_extra_instance => 1 } ] } }, { label => 'space-usage-prct', nlabel => 'virtual_machine.space.usage.percentage', display_ok => 0, set => { key_values => [ { name => 'prct_used_space' }, { name => 'used_space' }, { name => 'free_space' }, { name => 'prct_free_space' }, { name => 'total_space' } ], closure_custom_output => $self->can('custom_space_usage_output'), perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-vm-name:s' => { name => 'filter_vm_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $vms = $options{custom}->get_virtual_machines(); $self->{vm} = {}; foreach my $vm (@{$vms->{virtual_machines}}) { if (defined($self->{option_results}->{filter_vm_name}) && $self->{option_results}->{filter_vm_name} ne '' && $vm->{name} !~ /$self->{option_results}->{filter_vm_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $vm->{name} . "': no matching filter.", debug => 1); next; } $self->{vm}->{ $vm->{id} . ':' . $vm->{name} } = { status => { vm_name => $vm->{id} . ':' . $vm->{name}, ha_status => lc($vm->{ha_status}) }, space => { total_space => $vm->{hypervisor_allocated_capacity}, used_space => $vm->{hypervisor_allocated_capacity} - $vm->{hypervisor_free_space}, free_space => $vm->{hypervisor_free_space}, prct_used_space => ($vm->{hypervisor_allocated_capacity} - $vm->{hypervisor_free_space}) * 100 / $vm->{hypervisor_allocated_capacity}, prct_free_space => $vm->{hypervisor_free_space} * 100 / $vm->{hypervisor_allocated_capacity} } }; } } 1; __END__ =head1 MODE Check virtual machines. =over 8 =item B<--filter-name> Filter virtual machines by virtual machine name. =item B<--unknown-ha-status> Set unknown threshold for status (Default: '%{status} =~ /unknown/'). Can used special variables like: %{ha_status}, %{vm_name} =item B<--warning-ha-status> Set warning threshold for status (Default: '%{status} =~ /degraded/'). Can used special variables like: %{ha_status}, %{vm_name} =item B<--critical-ha-status> Set critical threshold for status. Can used special variables like: %{ha_status}, %{vm_name} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'space-usage', 'space-usage-free', 'space-usage-prct'. =back =cut centreon-plugins-20220113/apps/virtualization/hpe/simplivity/restapi/plugin.pm000066400000000000000000000034551417000230700275620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Authors : Roman Morandell - ivertix # package apps::virtualization::hpe::simplivity::restapi::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->{modes} = { 'discovery' => 'apps::virtualization::hpe::simplivity::restapi::mode::discovery', 'hosts' => 'apps::virtualization::hpe::simplivity::restapi::mode::hosts', 'list-hosts' => 'apps::virtualization::hpe::simplivity::restapi::mode::listhosts', 'omnistack-clusters' => 'apps::virtualization::hpe::simplivity::restapi::mode::omnistackclusters', 'virtual-machines' => 'apps::virtualization::hpe::simplivity::restapi::mode::virtualmachines' }; $self->{custom_modes}->{api} = 'apps::virtualization::hpe::simplivity::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check HPE Simplivity using OmniStack Rest API. =over 8 =back =cut centreon-plugins-20220113/apps/virtualization/ovirt/000077500000000000000000000000001417000230700224265ustar00rootroot00000000000000centreon-plugins-20220113/apps/virtualization/ovirt/custom/000077500000000000000000000000001417000230700237405ustar00rootroot00000000000000centreon-plugins-20220113/apps/virtualization/ovirt/custom/api.pm000066400000000000000000000250061417000230700250520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::virtualization::ovirt::custom::api; use strict; use warnings; use DateTime; use centreon::plugins::http; use centreon::plugins::statefile; use JSON::XS; use URI::Encode; use Digest::MD5 qw(md5_hex); 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 => { 'api-username:s' => { name => 'api_username' }, 'api-password:s' => { name => 'api_password' }, 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'timeout:s' => { name => 'timeout' }, 'reload-cache-time:s' => { name => 'reload_cache_time' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); $self->{cache} = centreon::plugins::statefile->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : ''; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : ''; $self->{reload_cache_time} = (defined($self->{option_results}->{reload_cache_time})) ? $self->{option_results}->{reload_cache_time} : 180; $self->{cache}->check_options(option_results => $self->{option_results}); return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{warning_status} = ''; $self->{option_results}->{critical_status} = ''; $self->{option_results}->{unknown_status} = '%{http_code} < 200 or %{http_code} > 400'; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->add_header(key => 'Content-Type', value => 'application/x-www-form-urlencoded'); if (defined($self->{access_token})) { $self->{http}->add_header(key => 'Authorization', value => 'Bearer ' . $self->{access_token}); } $self->{http}->set_options(%{$self->{option_results}}); } sub get_access_token { my ($self, %options) = @_; my $has_cache_file = $options{statefile}->read(statefile => 'ovirt_api_' . md5_hex($self->{hostname}) . '_' . md5_hex($self->{api_username})); my $expires_on = $options{statefile}->get(name => 'expires_on'); my $access_token = $options{statefile}->get(name => 'access_token'); if ($has_cache_file == 0 || !defined($access_token) || (($expires_on - time()) < 10)) { my $uri = URI::Encode->new({encode_reserved => 1}); my $encoded_username = $uri->encode($self->{api_username}); my $encoded_password = $uri->encode($self->{api_password}); my $post_data = 'grant_type=password' . '&scope=ovirt-app-api' . '&username=' . $encoded_username . '&password=' . $encoded_password; $self->settings(); my $content = $self->{http}->request( method => 'POST', query_form_post => $post_data, url_path => '/ovirt-engine/sso/oauth/token' ); if (!defined($content) || $content eq '') { $self->{output}->add_option_msg(short_msg => "Authentification endpoint returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->output_add(long_msg => $content, debug => 1); $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } if (defined($decoded->{error_code})) { $self->{output}->output_add(long_msg => "Error message : " . $decoded->{error}, debug => 1); $self->{output}->add_option_msg(short_msg => "Authentification endpoint returns error code '" . $decoded->{error_code} . "' (add --debug option for detailed message)"); $self->{output}->option_exit(); } $access_token = $decoded->{access_token}; my $datas = { last_timestamp => time(), access_token => $decoded->{access_token}, expires_on => substr($decoded->{exp}, 0, -3) }; $options{statefile}->write(data => $datas); } return $access_token; } sub request_api { my ($self, %options) = @_; if (!defined($self->{access_token})) { $self->{access_token} = $self->get_access_token(statefile => $self->{cache}); } $self->settings(); $self->{output}->output_add(long_msg => "URL: '" . $self->{proto} . '://' . $self->{hostname} . ':' . $self->{port} . $options{url_path} . "'", debug => 1); my $content = $self->{http}->request(%options); if (!defined($content) || $content eq '') { $self->{output}->add_option_msg(short_msg => "API returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->output_add(long_msg => $content, debug => 1); $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } if (defined($decoded->{error_code})) { $self->{output}->output_add(long_msg => "Error message : " . $decoded->{error}, debug => 1); $self->{output}->add_option_msg(short_msg => "API returns error code '" . $decoded->{error_code} . "' (add --debug option for detailed message)"); $self->{output}->option_exit(); } return $decoded; } sub list_vms { my ($self, %options) = @_; my $url_path = '/ovirt-engine/api/vms'; my $response = $self->request_api(method => 'GET', url_path => $url_path); return $response->{vm}; } sub list_hosts { my ($self, %options) = @_; my $url_path = '/ovirt-engine/api/hosts'; my $response = $self->request_api(method => 'GET', url_path => $url_path); return $response->{host}; } sub get_host_statistics { my ($self, %options) = @_; my $url_path = '/ovirt-engine/api/hosts/' . $options{id} . '/statistics'; my $response = $self->request_api(method => 'GET', url_path => $url_path); return $response->{statistic}; } sub cache_hosts { my ($self, %options) = @_; $self->{cache_hosts} = centreon::plugins::statefile->new(output => $self->{output}); $self->{cache_hosts}->check_options(option_results => $self->{option_results}); my $has_cache_file = $self->{cache_hosts}->read(statefile => 'cache_ovirt_hosts_' . md5_hex($self->{hostname}) . '_' . md5_hex($self->{api_username})); my $timestamp_cache = $self->{cache_hosts}->get(name => 'last_timestamp'); my $hosts = $self->{cache_hosts}->get(name => 'hosts'); if ($has_cache_file == 0 || !defined($timestamp_cache) || ((time() - $timestamp_cache) > (($self->{reload_cache_time}) * 60))) { $hosts = []; my $datas = { last_timestamp => time(), hosts => $hosts }; my $list = $self->list_hosts(); foreach (@{$list}) { push @{$hosts}, { id => $_->{id}, name => $_->{name} }; } $self->{cache_hosts}->write(data => $datas); } return $hosts; } sub list_clusters { my ($self, %options) = @_; my $url_path = '/ovirt-engine/api/clusters'; my $response = $self->request_api(method => 'GET', url_path => $url_path); return $response->{cluster}; } sub list_datacenters { my ($self, %options) = @_; my $url_path = '/ovirt-engine/api/datacenters'; my $response = $self->request_api(method => 'GET', url_path => $url_path); return $response->{data_center}; } 1; __END__ =head1 NAME oVirt Rest API =head1 REST API OPTIONS oVirt Rest API =over 8 =item B<--hostname> oVirt hostname. =item B<--port> Port used (Default: 443) =item B<--proto> Specify https if needed (Default: 'https') =item B<--api-username> oVirt API username. =item B<--api-password> oVirt API password. =item B<--timeout> Set timeout in seconds (Default: 10). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/virtualization/ovirt/mode/000077500000000000000000000000001417000230700233525ustar00rootroot00000000000000centreon-plugins-20220113/apps/virtualization/ovirt/mode/cpuhost.pm000066400000000000000000000104261417000230700254000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::virtualization::ovirt::mode::cpuhost; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'host', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All hosts are ok' }, ]; $self->{maps_counters}->{host} = [ { label => 'cpu-user', nlabel => 'host.cpu.user.utilization.percentage', set => { key_values => [ { name => 'user' }, { name => 'display' } ], output_template => 'user: %.2f %%', perfdatas => [ { value => 'user', template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'cpu-system', nlabel => 'host.cpu.system.utilization.percentage', set => { key_values => [ { name => 'system' }, { name => 'display' } ], output_template => 'system: %.2f %%', perfdatas => [ { value => 'system', template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub prefix_output { my ($self, %options) = @_; return "Host '" . $options{instance_value}->{display} . "' CPU utilization "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "filter-id:s" => { name => 'filter_id' }, }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{host} = {}; if (!defined($self->{cache_hosts})) { $self->{cache_hosts} = $options{custom}->cache_hosts(); } foreach my $host (@{$self->{cache_hosts}}) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $host->{name} !~ /$self->{option_results}->{filter_name}/); next if (defined($self->{option_results}->{filter_id}) && $self->{option_results}->{filter_id} ne '' && $host->{id} !~ /$self->{option_results}->{filter_id}/); my $stats = $options{custom}->get_host_statistics(id => $host->{id}); foreach my $stat (@{$stats}) { next if ($stat->{name} !~ /^cpu\.current\..*/); $self->{host}->{$host->{id}}->{display} = $host->{name}; $self->{host}->{$host->{id}}->{user} = $stat->{values}->{value}[0]->{datum} if ($stat->{name} =~ /^cpu.current.user$/); $self->{host}->{$host->{id}}->{system} = $stat->{values}->{value}[0]->{datum} if ($stat->{name} =~ /^cpu.current.system$/); } } if (scalar(keys %{$self->{host}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No hosts found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check host cpu utilization. =over 8 =item B<--filter-name> Filter host name (Can be a regexp). =item B<--filter-id> Filter host id (Can be a regexp). =item B<--warning-*> Threshold warning. Can be: 'host-cpu-user-utilization-percentage', 'host-cpu-system-utilization-percentage'. =item B<--critical-*> Threshold critical. Can be: 'host-cpu-user-utilization-percentage', 'host-cpu-system-utilization-percentage'. =back =cut centreon-plugins-20220113/apps/virtualization/ovirt/mode/listclusters.pm000066400000000000000000000050461417000230700264550ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::virtualization::ovirt::mode::listclusters; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{clusters} = $options{custom}->list_clusters(); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $cluster (@{$self->{clusters}}) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $cluster->{name} !~ /$self->{option_results}->{filter_name}/); $self->{output}->output_add(long_msg => sprintf("[id = %s][name = %s]", $cluster->{id}, $cluster->{name})); } $self->{output}->output_add(severity => 'OK', short_msg => 'List clusters:'); $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 => ['id', 'name']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $cluster (@{$self->{clusters}}) { $self->{output}->add_disco_entry( id => $cluster->{id}, name => $cluster->{name}, ); } } 1; __END__ =head1 MODE List clusters. =over 8 =item B<--filter-name> Filter cluster name (Can be a regexp). =back =cut centreon-plugins-20220113/apps/virtualization/ovirt/mode/listdatacenters.pm000066400000000000000000000051231417000230700271020ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::virtualization::ovirt::mode::listdatacenters; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{datacenters} = $options{custom}->list_datacenters(); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $datacenter (@{$self->{datacenters}}) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $datacenter->{name} !~ /$self->{option_results}->{filter_name}/); $self->{output}->output_add(long_msg => sprintf("[id = %s][name = %s]", $datacenter->{id}, $datacenter->{name})); } $self->{output}->output_add(severity => 'OK', short_msg => 'List datacenters:'); $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 => ['id', 'name']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $datacenter (@{$self->{datacenters}}) { $self->{output}->add_disco_entry( id => $datacenter->{id}, name => $datacenter->{name}, ); } } 1; __END__ =head1 MODE List datacenters. =over 8 =item B<--filter-name> Filter datacenter name (Can be a regexp). =back =cut centreon-plugins-20220113/apps/virtualization/ovirt/mode/listhosts.pm000066400000000000000000000053001417000230700257420ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::virtualization::ovirt::mode::listhosts; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{hosts} = $options{custom}->list_hosts(); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $host (@{$self->{hosts}}) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $host->{name} !~ /$self->{option_results}->{filter_name}/); $self->{output}->output_add(long_msg => sprintf("[id = %s][name = %s][address = %s][status = %s]", $host->{id}, $host->{name}, $host->{address}, $host->{status})); } $self->{output}->output_add(severity => 'OK', short_msg => 'List hosts:'); $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 => ['id', 'name', 'address', 'status']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $host (@{$self->{hosts}}) { $self->{output}->add_disco_entry( id => $host->{id}, name => $host->{name}, address => $host->{address}, status => $host->{status}, ); } } 1; __END__ =head1 MODE List hosts. =over 8 =item B<--filter-name> Filter host name (Can be a regexp). =back =cut centreon-plugins-20220113/apps/virtualization/ovirt/plugin.pm000066400000000000000000000030731417000230700242650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::virtualization::ovirt::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} = '1.0'; %{$self->{modes}} = ( 'cpu-host' => 'apps::virtualization::ovirt::mode::cpuhost', 'list-clusters' => 'apps::virtualization::ovirt::mode::listclusters', 'list-datacenters' => 'apps::virtualization::ovirt::mode::listdatacenters', 'list-hosts' => 'apps::virtualization::ovirt::mode::listhosts', ); $self->{custom_modes}{api} = 'apps::virtualization::ovirt::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check oVirt using API. =cut centreon-plugins-20220113/apps/vmware/000077500000000000000000000000001417000230700175005ustar00rootroot00000000000000centreon-plugins-20220113/apps/vmware/connector/000077500000000000000000000000001417000230700214725ustar00rootroot00000000000000centreon-plugins-20220113/apps/vmware/connector/custom/000077500000000000000000000000001417000230700230045ustar00rootroot00000000000000centreon-plugins-20220113/apps/vmware/connector/custom/connector.pm000066400000000000000000000305321417000230700253370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::custom::connector; use strict; use warnings; use JSON; use ZMQ::LibZMQ4; use ZMQ::Constants qw(:all); use UUID; 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 => { 'connector-hostname:s@' => { name => 'connector_hostname' }, 'connector-port:s@' => { name => 'connector_port' }, 'vsphere-address:s@' => { name => 'vsphere_address' }, 'vsphere-username:s@' => { name => 'vsphere_username' }, 'vsphere-password:s@' => { name => 'vsphere_password' }, 'container:s@' => { name => 'container' }, 'timeout:s@' => { name => 'timeout' }, 'sampling-period:s@' => { name => 'sampling_period' }, 'time-shift:s@' => { name => 'time_shift' }, 'case-insensitive' => { name => 'case_insensitive' }, 'unknown-connector-status:s' => { name => 'unknown_connector_status' }, 'warning-connector-status:s' => { name => 'warning_connector_status' }, 'critical-connector-status:s' => { name => 'critical_connector_status' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'CONNECTOR OPTIONS', once => 1); $self->{output} = $options{output}; $self->{json_send} = {}; $self->{result} = undef; return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{connector_hostname} = (defined($self->{option_results}->{connector_hostname})) ? shift(@{$self->{option_results}->{connector_hostname}}) : undef; $self->{connector_port} = (defined($self->{option_results}->{connector_port})) ? shift(@{$self->{option_results}->{connector_port}}) : 5700; $self->{container} = (defined($self->{option_results}->{container})) ? shift(@{$self->{option_results}->{container}}) : 'default'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? shift(@{$self->{option_results}->{timeout}}) : undef; $self->{vsphere_address} = (defined($self->{option_results}->{vsphere_address})) ? shift(@{$self->{option_results}->{vsphere_address}}) : undef; $self->{vsphere_username} = (defined($self->{option_results}->{vsphere_username})) ? shift(@{$self->{option_results}->{vsphere_username}}) : undef; $self->{vsphere_password} = (defined($self->{option_results}->{vsphere_password})) ? shift(@{$self->{option_results}->{vsphere_password}}) : undef; $self->{sampling_period} = (defined($self->{option_results}->{sampling_period})) ? shift(@{$self->{option_results}->{sampling_period}}) : undef; $self->{time_shift} = (defined($self->{option_results}->{time_shift})) ? shift(@{$self->{option_results}->{time_shift}}) : 0; $self->{unknown_connector_status} = (defined($self->{option_results}->{unknown_connector_status})) ? $self->{option_results}->{unknown_connector_status} : '%{code} < 0 || (%{code} > 0 && %{code} < 200)'; $self->{warning_connector_status} = (defined($self->{option_results}->{warning_connector_status})) ? $self->{option_results}->{warning_connector_status} : ''; $self->{critical_connector_status} = (defined($self->{option_results}->{critical_connector_status})) ? $self->{option_results}->{critical_connector_status} : ''; $self->{case_insensitive} = (defined($self->{option_results}->{case_insensitive})) ? $self->{option_results}->{case_insensitive} : undef; $self->{connector_port} = 5700 if ($self->{connector_port} eq ''); $self->{container} = 'default' if ($self->{container} eq ''); if (!defined($self->{connector_hostname}) || $self->{connector_hostname} eq '') { $self->{output}->add_option_msg(short_msg => 'Please set option --connector-hostname.'); $self->{output}->option_exit(); } if (defined($self->{timeout}) && $self->{timeout} =~ /^\d+$/ && $self->{timeout} > 0) { $self->{timeout} = $self->{timeout}; } else { $self->{timeout} = 50; } if (!defined($self->{connector_hostname}) || scalar(@{$self->{option_results}->{connector_hostname}}) == 0) { return 0; } return 1; } sub add_params { my ($self, %options) = @_; $self->{json_send}->{command} = $options{command} if (defined($options{command})); foreach (keys %{$options{params}}) { $self->{json_send}->{$_} = $options{params}->{$_}; } } sub connector_response { my ($self, %options) = @_; if (!defined($options{response})) { $self->{output}->add_option_msg(short_msg => "Cannot read response: $!"); $self->{output}->option_exit(); } my $data = zmq_msg_data($options{response}); if ($data !~ /^RESPSERVER (.*)/msi) { $self->{output}->add_option_msg(short_msg => "Response not formatted: $data"); $self->{output}->option_exit(); } my $json = $1; eval { $self->{output}->output_add(long_msg => $json, debug => 1); $self->{result} = JSON->new->utf8->decode($json); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json result: $@"); $self->{output}->option_exit(); } } sub connector_response_status { my ($self, %options) = @_; if (!defined($self->{result})) { $self->{output}->add_option_msg(short_msg => 'Cannot get response (timeout received)'); $self->{output}->option_exit(); } if (!defined($self->{result}->{code})) { $self->{output}->add_option_msg(short_msg => 'response format incorrect - need connector vmware version >= 3.x.x'); $self->{output}->option_exit(); } foreach (('unknown_connector_status', 'warning_connector_status', 'critical_connector_status')) { $self->{$_} =~ s/%\{(.*?)\}/\$values->{$1}/g; } # Check response my $status = 'ok'; if (defined($self->{critical_connector_status}) && $self->{critical_connector_status} ne '' && $self->{output}->test_eval(test => $self->{critical_connector_status}, values => $self->{result})) { $status = 'critical'; } elsif (defined($self->{warning_connector_status}) && $self->{warning_connector_status} ne '' && $self->{output}->test_eval(test => $self->{warning_connector_status}, values => $self->{result})) { $status = 'warning'; } elsif (defined($self->{unknown_connector_status}) && $self->{unknown_connector_status} ne '' && $self->{output}->test_eval(test => $self->{unknown_connector_status}, values => $self->{result})) { $status = 'unknown'; } if (!$self->{output}->is_status(value => $status, compare => 'ok', litteral => 1)) { $self->{output}->output_add(long_msg => $self->{result}->{extra_message}, debug => 1); $self->{output}->output_add( severity => $status, short_msg => $self->{result}->{short_message} ); $self->{output}->display(); $self->{output}->exit(); } } sub entity_is_connected { my ($self, %options) = @_; if ($options{state} !~ /^connected$/i) { return 0; } return 1; } sub vm_is_running { my ($self, %options) = @_; if ($options{power} !~ /^poweredOn$/i) { return 0; } return 1; } sub get_id { my ($self, %options) = @_; return $self->{connector_hostname} . '.' . $self->{connector_port} . '.' . $self->{container}; } sub strip_cr { my ($self, %options) = @_; $options{value} =~ s/^\s+.*\s+$//mg; $options{value} =~ s/\r//mg; $options{value} =~ s/\n/ -- /mg; return $options{value}; } sub execute { my ($self, %options) = @_; $self->add_params(%options); # Build request my $uuid; UUID::generate($uuid); $self->{uuid} = $uuid; $self->{json_send}->{identity} = 'client-' . unpack('H*', $self->{uuid}); $self->{json_send}->{connector_hostname} = $self->{connector_hostname}; $self->{json_send}->{connector_port} = $self->{connector_port}; $self->{json_send}->{container} = $self->{container}; $self->{json_send}->{vsphere_address} = $self->{vsphere_address}; $self->{json_send}->{vsphere_username} = $self->{vsphere_username}; $self->{json_send}->{vsphere_password} = $self->{vsphere_password}; $self->{json_send}->{sampling_period} = $self->{sampling_period}; $self->{json_send}->{time_shift} = $self->{time_shift}; $self->{json_send}->{case_insensitive} = $self->{case_insensitive}; # Init my $context = zmq_init(); $self->{requester} = zmq_socket($context, ZMQ_DEALER); if (!defined($self->{requester})) { $self->{output}->add_option_msg(short_msg => "Cannot create socket: $!"); $self->{output}->option_exit(); } my $flag = ZMQ_NOBLOCK | ZMQ_SNDMORE; zmq_setsockopt($self->{requester}, ZMQ_IDENTITY, "client-" . $self->{uuid}); zmq_setsockopt($self->{requester}, ZMQ_LINGER, 0); # we discard zmq_connect($self->{requester}, 'tcp://' . $self->{connector_hostname} . ':' . $self->{connector_port}); zmq_sendmsg($self->{requester}, "REQCLIENT " . JSON->new->utf8->encode($self->{json_send}), ZMQ_NOBLOCK); my @poll = ( { socket => $self->{requester}, events => ZMQ_POLLIN, callback => sub { my $response = zmq_recvmsg($self->{requester}); zmq_close($self->{requester}); $self->connector_response(response => $response); }, }, ); zmq_poll(\@poll, $self->{timeout} * 1000); zmq_close($self->{requester}); $self->connector_response_status(); return $self->{result}; } 1; __END__ =head1 NAME VMWare connector library =head1 SYNOPSIS my vmware connector =head1 CONNECTOR OPTIONS =over 8 =item B<--connector-hostname> Connector hostname (required). =item B<--connector-port> Connector port (default: 5700). =item B<--container> Container to use (it depends of the connector configuration). =item B<--vsphere-address> Address of vpshere/ESX to connect. =item B<--vsphere-username> Username of vpshere/ESX connection (with --vsphere-address). =item B<--vsphere-password> Password of vpshere/ESX connection (with --vsphere-address). =item B<--timeout> Set global execution timeout (Default: 50) =item B<--sampling-period> Choose the sampling period (can change the default sampling for counters). Should be not different than 300 or 20. =item B<--time-shift> Can shift the time. We the following option you can average X counters values (default: 0). =item B<--case-insensitive> Searchs are case insensitive. =item B<--unknown-connector-status> Set unknown threshold for connector status (Default: '%{code} < 0 || (%{code} > 0 && %{code} < 200)'). Can used special variables like: %{code}, %{short_message}, %{extra_message}. =item B<--warning-connector-status> Set warning threshold for connector status (Default: ''). Can used special variables like: %{code}, %{short_message}, %{extra_message}. =item B<--critical-connector-status> Set critical threshold for connector status (Default: ''). Can used special variables like: %{code}, %{short_message}, %{extra_message}. =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/vmware/connector/mode/000077500000000000000000000000001417000230700224165ustar00rootroot00000000000000centreon-plugins-20220113/apps/vmware/connector/mode/alarmdatacenter.pm000066400000000000000000000246131417000230700261110ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::alarmdatacenter; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::statefile; sub custom_status_threshold { my ($self, %options) = @_; my $status = 'ok'; if (defined($self->{instance_mode}->{option_results}->{'critical-' . $self->{label}}) && $self->{instance_mode}->{option_results}->{'critical-' . $self->{label}} ne '' && $self->eval(value => $self->{instance_mode}->{option_results}->{'critical-' . $self->{label}})) { $self->{instance_mode}->{dc_critical}++; $status = 'critical'; } elsif (defined($self->{instance_mode}->{option_results}->{'warning-' . $self->{label}}) && $self->{instance_mode}->{option_results}->{'warning-' . $self->{label}} ne '' && $self->eval(value => $self->{instance_mode}->{option_results}->{'warning-' . $self->{label}})) { $self->{instance_mode}->{dc_warning}++; $status = 'warning'; } return $status; } sub custom_status_output { my ($self, %options) = @_; return sprintf( 'alarm [%s] [%s] [%s] [%s] %s/%s', $self->{result_values}->{status}, $self->{result_values}->{type}, $self->{result_values}->{entity_name}, $self->{result_values}->{time}, $self->{result_values}->{name}, $self->{result_values}->{description} ); } sub custom_dcmetrics_perfdata { my ($self, %options) = @_; my $extra_label; # We do it manually. Because we have only 1 instance in group. if (scalar(keys %{$self->{instance_mode}->{datacenter}}) > 1 || $self->{output}->use_new_perfdata()) { $extra_label = $self->{result_values}->{name}; } $self->{output}->perfdata_add( label => 'alarm_' . $self->{result_values}->{label_ref}, nlabel => 'datacenter.alarms.' . $self->{result_values}->{label_ref} . '.current.count', instances => $extra_label, value => $self->{result_values}->{alarm_value}, min => 0 ); } sub custom_dcmetrics_calc { my ($self, %options) = @_; $self->{result_values}->{label_ref} = $options{extra_options}->{label_ref}; $self->{result_values}->{alarm_value} = $self->{instance_mode}->{'dc_' . $options{extra_options}->{label_ref}}; $self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_name'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'datacenter', type => 2, cb_prefix_output => 'prefix_datacenter_output', cb_long_output => 'datacenter_long_output', message_multiple => 'All datacenters are ok', group => [ { name => 'alarm', cb_init => 'alarm_reset', skipped_code => { -11 => 1 } }, { name => 'dc_metrics', display => 0, skipped_code => { -11 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'total-alarm-warning', nlabel => 'datacenter.alarms.warning.current.count', set => { key_values => [ { name => 'yellow' } ], output_template => '%s warning alarm(s) found(s)', perfdatas => [ { label => 'total_alarm_warning', template => '%s', min => 0 } ] } }, { label => 'total-alarm-critical', nlabel => 'datacenter.alarms.critical.current.count', set => { key_values => [ { name => 'red' } ], output_template => '%s critical alarm(s) found(s)', perfdatas => [ { label => 'total_alarm_critical', template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{alarm} = [ { label => 'status', type => 2, warning_default => '%{status} =~ /yellow/i', critical_default => '%{status} =~ /red/i', set => { key_values => [ { name => 'entity_name' }, { name => 'status' }, { name => 'time' }, { name => 'description' }, { name => 'name' }, { name => 'type' }, { name => 'since' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => $self->can('custom_status_threshold') } }, ]; $self->{maps_counters}->{dc_metrics} = [ { label => 'alarm-warning', type => 2, set => { key_values => [ { name => 'name' } ], output_template => '', closure_custom_threshold_check => sub { return 'ok' }, closure_custom_calc => $self->can('custom_dcmetrics_calc'), closure_custom_calc_extra_options => { label_ref => 'warning' }, closure_custom_perfdata => $self->can('custom_dcmetrics_perfdata') } }, { label => 'alarm-critical', type => 2, set => { key_values => [ { name => 'name' } ], output_template => '', closure_custom_threshold_check => sub { return 'ok' }, closure_custom_calc => $self->can('custom_dcmetrics_calc'), closure_custom_calc_extra_options => { label_ref => 'critical' }, closure_custom_perfdata => $self->can('custom_dcmetrics_perfdata') } } ]; } sub prefix_datacenter_output { my ($self, %options) = @_; return "Datacenter '" . $options{instance_value}->{display} . "' "; } sub alarm_reset { my ($self, %options) = @_; $self->{dc_warning} = 0; $self->{dc_critical} = 0; } sub datacenter_long_output { my ($self, %options) = @_; return "checking datacenter '" . $options{instance_value}->{display} . "'"; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'datacenter:s' => { name => 'datacenter' }, 'filter' => { name => 'filter' }, 'filter-time:s' => { name => 'filter_time' }, 'memory' => { name => 'memory' } }); centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'Date::Parse', error_msg => "Cannot load module 'Date::Parse'." ); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->check_options(%options); } } sub manage_selection { my ($self, %options) = @_; $self->{global} = { yellow => 0, red => 0 }; $self->{datacenter} = {}; my $response = $options{custom}->execute(params => $self->{option_results}, command => 'alarmdatacenter'); my $last_time; if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->read(statefile => "cache_vmware_" . $options{custom}->get_id() . '_' . $self->{mode}); $last_time = $self->{statefile_cache}->get(name => 'last_time'); } my ($i, $current_time) = (1, time()); foreach my $datacenter_id (keys %{$response->{data}}) { my $datacenter_name = $response->{data}->{$datacenter_id}->{name}; $self->{datacenter}->{$datacenter_name} = { display => $datacenter_name, alarm => {}, dc_metrics => { 1 => { name => $datacenter_name } } }; foreach (keys %{$response->{data}->{$datacenter_id}->{alarms}}) { my $create_time = Date::Parse::str2time($response->{data}->{$datacenter_id}->{alarms}->{$_}->{time}); if (!defined($create_time)) { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => "Can't Parse date '" . $response->{data}->{$datacenter_id}->{alarms}->{$_}->{time} . "'"); next; } next if (defined($self->{option_results}->{memory}) && defined($last_time) && $last_time > $create_time); my $diff_time = $current_time - $create_time; if (defined($self->{option_results}->{filter_time}) && $self->{option_results}->{filter_time} ne '') { next if ($diff_time > $self->{option_results}->{filter_time}); } $self->{datacenter}->{$datacenter_name}->{alarm}->{$i} = { %{$response->{data}->{$datacenter_id}->{alarms}->{$_}}, since => $diff_time }; $self->{global}->{$response->{data}->{$datacenter_id}->{alarms}->{$_}->{status}}++; $i++; } } if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->write(data => { last_time => $current_time }); } } 1; __END__ =head1 MODE Check datacenter alarms (red an yellow). =over 8 =item B<--datacenter> Datacenter to check. If not set, we check all datacenters. =item B<--filter> Datacenter is a regexp. =item B<--filter-time> Don't check alarm older (value in seconds). =item B<--memory> Check new alarms only. =item B<--warning-status> Set warning threshold for status (Default: '%{status} =~ /yellow/i). Can used special variables like: %{status}, %{name}, %{entity}, %{type}. =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /red/i'). Can used special variables like: %{status}, %{name}, %{entity}, %{type}. =item B<--warning-*> Threshold warning. Can be: 'total-alarm-warning', 'total-alarm-critical'. =item B<--critical-*> Threshold critical. Can be: 'total-alarm-warning', 'total-alarm-critical'. =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/alarmhost.pm000066400000000000000000000251351417000230700247540ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::alarmhost; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::statefile; sub custom_status_threshold { my ($self, %options) = @_; my $status = 'ok'; if (defined($self->{instance_mode}->{option_results}->{'critical-' . $self->{label}}) && $self->{instance_mode}->{option_results}->{'critical-' . $self->{label}} ne '' && $self->eval(value => $self->{instance_mode}->{option_results}->{'critical-' . $self->{label}})) { $self->{instance_mode}->{host_critical}++; $status = 'critical'; } elsif (defined($self->{instance_mode}->{option_results}->{'warning-' . $self->{label}}) && $self->{instance_mode}->{option_results}->{'warning-' . $self->{label}} ne '' && $self->eval(value => $self->{instance_mode}->{option_results}->{'warning-' . $self->{label}})) { $self->{instance_mode}->{host_warning}++; $status = 'warning'; } return $status; } sub custom_status_output { my ($self, %options) = @_; return sprintf( "alarm [%s] [%s] [%s] [%s] %s/%s", $self->{result_values}->{status}, $self->{result_values}->{type}, $self->{result_values}->{entity_name}, $self->{result_values}->{time}, $self->{result_values}->{name}, $self->{result_values}->{description} ); } sub custom_esxhost_perfdata { my ($self, %options) = @_; my $extra_label; # We do it manually. Because we have only 1 instance in group. if (scalar(keys %{$self->{instance_mode}->{esxhost}}) > 1 || $self->{output}->use_new_perfdata()) { $extra_label = $self->{result_values}->{name}; } $self->{output}->perfdata_add( label => 'alarm_' . $self->{result_values}->{label_ref}, nlabel => 'host.alarms.' . $self->{result_values}->{label_ref} . '.current.count', instances => $extra_label, value => $self->{result_values}->{alarm_value}, min => 0 ); } sub custom_esxhost_calc { my ($self, %options) = @_; $self->{result_values}->{label_ref} = $options{extra_options}->{label_ref}; $self->{result_values}->{alarm_value} = $self->{instance_mode}->{'host_' . $options{extra_options}->{label_ref}}; $self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_name'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'esxhost', type => 2, cb_prefix_output => 'prefix_esxhost_output', cb_long_output => 'esxhost_long_output', message_multiple => 'All hosts are ok', group => [ { name => 'alarm', cb_init => 'alarm_reset', skipped_code => { -11 => 1 } }, { name => 'esxhost_metrics', display => 0, skipped_code => { -11 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'total-alarm-warning', nlabel => 'host.alarms.warning.current.count', set => { key_values => [ { name => 'yellow' } ], output_template => '%s warning alarm(s) found(s)', perfdatas => [ { label => 'total_alarm_warning', template => '%s', min => 0 } ] } }, { label => 'total-alarm-critical', nlabel => 'host.alarms.critical.current.count', set => { key_values => [ { name => 'red' } ], output_template => '%s critical alarm(s) found(s)', perfdatas => [ { label => 'total_alarm_critical', template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{alarm} = [ { label => 'status', type => 2, warning_default => '%{status} =~ /yellow/i', critical_default => '%{status} =~ /red/i', set => { key_values => [ { name => 'entity_name' }, { name => 'status' }, { name => 'time' }, { name => 'description' }, { name => 'name' }, { name => 'type' }, { name => 'since' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => $self->can('custom_status_threshold') } } ]; $self->{maps_counters}->{esxhost_metrics} = [ { label => 'alarm-warning', type => 2, set => { key_values => [ { name => 'name' } ], output_template => '', closure_custom_threshold_check => sub { return 'ok' }, closure_custom_calc => $self->can('custom_esxhost_calc'), closure_custom_calc_extra_options => { label_ref => 'warning' }, closure_custom_perfdata => $self->can('custom_esxhost_perfdata') } }, { label => 'alarm-critical', type => 2, set => { key_values => [ { name => 'name' } ], output_template => '', closure_custom_threshold_check => sub { return 'ok' }, closure_custom_calc => $self->can('custom_esxhost_calc'), closure_custom_calc_extra_options => { label_ref => 'critical' }, closure_custom_perfdata => $self->can('custom_esxhost_perfdata') } } ]; } sub prefix_esxhost_output { my ($self, %options) = @_; return "Host '" . $options{instance_value}->{display} . "' "; } sub alarm_reset { my ($self, %options) = @_; $self->{host_warning} = 0; $self->{host_critical} = 0; } sub esxhost_long_output { my ($self, %options) = @_; return "checking host '" . $options{instance_value}->{display} . "'"; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'esx-hostname:s' => { name => 'esx_hostname' }, 'filter' => { name => 'filter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' }, 'scope-cluster:s' => { name => 'scope_cluster' }, 'filter-time:s' => { name => 'filter_time' }, 'memory' => { name => 'memory' } }); centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'Date::Parse', error_msg => "Cannot load module 'Date::Parse'." ); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->check_options(%options); } } sub manage_selection { my ($self, %options) = @_; $self->{global} = { yellow => 0, red => 0 }; $self->{esxhost} = {}; my $response = $options{custom}->execute( params => $self->{option_results}, command => 'alarmhost' ); my $last_time; if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->read(statefile => "cache_vmware_" . $options{custom}->get_id() . '_' . $self->{mode}); $last_time = $self->{statefile_cache}->get(name => 'last_time'); } my ($i, $current_time) = (1, time()); foreach my $esxhost_id (keys %{$response->{data}}) { my $esxhost_name = $response->{data}->{$esxhost_id}->{name}; $self->{esxhost}->{$esxhost_name} = { display => $esxhost_name, alarm => {}, esxhost_metrics => { 1 => { name => $esxhost_name } } }; foreach (keys %{$response->{data}->{$esxhost_id}->{alarms}}) { my $create_time = Date::Parse::str2time($response->{data}->{$esxhost_id}->{alarms}->{$_}->{time}); if (!defined($create_time)) { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => "Can't Parse date '" . $response->{data}->{$esxhost_id}->{alarms}->{$_}->{time} . "'"); next; } next if (defined($self->{option_results}->{memory}) && defined($last_time) && $last_time > $create_time); my $diff_time = $current_time - $create_time; if (defined($self->{option_results}->{filter_time}) && $self->{option_results}->{filter_time} ne '') { next if ($diff_time > $self->{option_results}->{filter_time}); } $self->{esxhost}->{$esxhost_name}->{alarm}->{$i} = { %{$response->{data}->{$esxhost_id}->{alarms}->{$_}}, since => $diff_time }; $self->{global}->{$response->{data}->{$esxhost_id}->{alarms}->{$_}->{status}}++; $i++; } } if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->write(data => { last_time => $current_time }); } } 1; __END__ =head1 MODE Check ESX host alarms (red an yellow). =over 8 =item B<--esx-hostname> ESX hostname to check. If not set, we check all ESX. =item B<--filter> Datacenter is a regexp. =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =item B<--scope-cluster> Search in following cluster(s) (can be a regexp). =item B<--filter-time> Don't check alarm older (value in seconds). =item B<--memory> Check new alarms only. =item B<--warning-status> Set warning threshold for status (Default: '%{status} =~ /yellow/i). Can used special variables like: %{status}, %{name}, %{entity}, %{type}. =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /red/i'). Can used special variables like: %{status}, %{name}, %{entity}, %{type}. =item B<--warning-*> Threshold warning. Can be: 'total-alarm-warning', 'total-alarm-critical'. =item B<--critical-*> Threshold critical. Can be: 'total-alarm-warning', 'total-alarm-critical'. =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/countvmhost.pm000066400000000000000000000167121417000230700253540ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::countvmhost; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return 'status ' . $self->{result_values}->{status}; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_state'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'host', type => 1, cb_prefix_output => 'prefix_host_output', message_multiple => 'All ESX Hosts are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'total-on', nlabel => 'host.vm.poweredon.current.count', set => { key_values => [ { name => 'poweredon' }, { name => 'total' } ], output_template => '%s VM(s) poweredon', perfdatas => [ { label => 'poweredon', template => '%s', min => 0, max => 'total' } ] } }, { label => 'total-off', nlabel => 'host.vm.poweredoff.current.count', set => { key_values => [ { name => 'poweredoff' }, { name => 'total' } ], output_template => '%s VM(s) poweredoff', perfdatas => [ { label => 'poweredoff', template => '%s', min => 0, max => 'total' } ] } }, { label => 'total-suspended', nlabel => 'host.vm.suspended.current.count', set => { key_values => [ { name => 'suspended' }, { name => 'total' } ], output_template => '%s VM(s) suspended', perfdatas => [ { label => 'suspended', template => '%s', min => 0, max => 'total' } ] } } ]; $self->{maps_counters}->{host} = [ { label => 'status', type => 2, unknown_default => '%{status} !~ /^connected$/i', set => { key_values => [ { name => 'state' } ], 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 => \&catalog_status_threshold_ng } }, { label => 'on', nlabel => 'host.vm.poweredon.current.count', set => { key_values => [ { name => 'poweredon' }, { name => 'total' } ], output_template => '%s VM(s) poweredon', perfdatas => [ { label => 'poweredon', template => '%s', min => 0, max => 'total', label_extra_instance => 1 } ] } }, { label => 'off', nlabel => 'host.vm.poweredoff.current.count', set => { key_values => [ { name => 'poweredoff' }, { name => 'total' } ], output_template => '%s VM(s) poweredoff', perfdatas => [ { label => 'poweredoff', template => '%s', min => 0, max => 'total', label_extra_instance => 1 } ] } }, { label => 'suspended', nlabel => 'host.vm.suspended.current.count', set => { key_values => [ { name => 'suspended' }, { name => 'total' } ], output_template => '%s VM(s) suspended', perfdatas => [ { label => 'suspended', template => '%s', min => 0, max => 'total', label_extra_instance => 1 } ] } } ]; } sub prefix_host_output { my ($self, %options) = @_; return "Host '" . $options{instance_value}->{display} . "' : "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'esx-hostname:s' => { name => 'esx_hostname' }, 'filter' => { name => 'filter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' }, 'scope-cluster:s' => { name => 'scope_cluster' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{global} = { poweredon => 0, poweredoff => 0, suspended => 0, total => 0 }; $self->{host} = {}; my $response = $options{custom}->execute( params => $self->{option_results}, command => 'countvmhost' ); foreach my $host_id (keys %{$response->{data}}) { my $host_name = $response->{data}->{$host_id}->{name}; $self->{host}->{$host_name} = { display => $host_name, state => $response->{data}->{$host_id}->{state}, poweredon => $response->{data}->{$host_id}->{poweredon}, poweredoff => $response->{data}->{$host_id}->{poweredoff}, suspended => $response->{data}->{$host_id}->{suspended}, total => $response->{data}->{$host_id}->{poweredon} + $response->{data}->{$host_id}->{poweredoff} + $response->{data}->{$host_id}->{suspended}, }; $self->{global}->{poweredon} += $response->{data}->{$host_id}->{poweredon} if (defined($response->{data}->{$host_id}->{poweredon})); $self->{global}->{poweredoff} += $response->{data}->{$host_id}->{poweredoff} if (defined($response->{data}->{$host_id}->{poweredoff})); $self->{global}->{suspended} += $response->{data}->{$host_id}->{suspended} if (defined($response->{data}->{$host_id}->{suspended})); } $self->{global}->{total} = $self->{global}->{poweredon} + $self->{global}->{poweredoff} + $self->{global}->{suspended}; } 1; __END__ =head1 MODE Check number of vm running/off on ESX hosts. =over 8 =item B<--esx-hostname> ESX hostname to check. If not set, we check all ESX. =item B<--filter> ESX hostname is a regexp. =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =item B<--scope-cluster> Search in following cluster(s) (can be a regexp). =item B<--unknown-status> Set warning threshold for status (Default: '%{status} !~ /^connected$/i'). Can used special variables like: %{status} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{status} =item B<--warning-*> Threshold warning. Can be: 'total-on', 'total-off', 'total-suspended', 'on', 'off', 'suspended'. =item B<--critical-*> Threshold critical. Can be: 'total-on', 'total-off', 'total-suspended', 'on', 'off', 'suspended'. =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/cpucluster.pm000066400000000000000000000074771417000230700251640ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::cpucluster; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_cluster_output { my ($self, %options) = @_; return "Cluster '" . $options{instance} . "' : "; } sub cluster_long_output { my ($self, %options) = @_; return "checking cluster '" . $options{instance} . "'"; } sub prefix_cpu_output { my ($self, %options) = @_; return "cpu total average: "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'clusters', type => 3, cb_prefix_output => 'prefix_cluster_output', cb_long_output => 'cluster_long_output', indent_long_output => ' ', message_multiple => 'All clusters are ok', group => [ { name => 'cpu', cb_prefix_output => 'prefix_cpu_output', type => 0, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{cpu} = [ { label => 'total-cpu', nlabel => 'cluster.cpu.utilization.percentage', set => { key_values => [ { name => 'cpu_average' } ], output_template => '%s %%', perfdatas => [ { template => '%s', unit => '%', min => 0, max => 100, label_extra_instance => 1 } ] } }, { label => 'total-cpu-mhz', nlabel => 'cluster.cpu.utilization.mhz', set => { key_values => [ { name => 'cpu_average_mhz' } ], output_template => '%s MHz', perfdatas => [ { template => '%s', unit => 'MHz', min => 0, label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'cluster-name:s' => { name => 'cluster_name' }, 'filter' => { name => 'filter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{host} = {}; my $response = $options{custom}->execute( params => $self->{option_results}, command => 'cpucluster' ); $self->{clusters} = {}; foreach my $cluster_id (keys %{$response->{data}}) { my $cluster_name = $response->{data}->{$cluster_id}->{name}; $self->{clusters}->{$cluster_name} = { cpu => { cpu_average => $response->{data}->{$cluster_id}->{'cpu.usage.average'}, cpu_average_mhz => $response->{data}->{$cluster_id}->{'cpu.usagemhz.average'} } }; } } 1; __END__ =head1 MODE Check cluster cpu usage. =over 8 =item B<--cluster-name> cluster to check. If not set, we check all clusters. =item B<--filter> Cluster name is a regexp. =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'total-cpu', 'total-cpu-mhz'. =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/cpuhost.pm000066400000000000000000000155711417000230700244520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::cpuhost; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); 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} . '_state'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'host', type => 3, cb_prefix_output => 'prefix_host_output', cb_long_output => 'host_long_output', indent_long_output => ' ', message_multiple => 'All ESX hosts are ok', group => [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'global_cpu', cb_prefix_output => 'prefix_global_cpu_output', type => 0, skipped_code => { -10 => 1 } }, { name => 'cpu', display_long => 0, cb_prefix_output => 'prefix_cpu_output', message_multiple => 'All CPUs are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'status', type => 2, unknown_default => '%{status} !~ /^connected$/i', set => { key_values => [ { name => 'state' } ], 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 => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{global_cpu} = [ { label => 'total-cpu', nlabel => 'host.cpu.utilization.percentage', set => { key_values => [ { name => 'cpu_average' } ], output_template => '%s %%', perfdatas => [ { label => 'cpu_total', template => '%s', unit => '%', min => 0, max => 100, label_extra_instance => 1 } ] } }, { label => 'total-cpu-mhz', nlabel => 'host.cpu.utilization.mhz', set => { key_values => [ { name => 'cpu_average_mhz' }, { name => 'cpu_average_mhz_max' } ], output_template => '%s MHz', perfdatas => [ { label => 'cpu_total_MHz', template => '%s', unit => 'MHz', min => 0, max => 'cpu_average_mhz_max', label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{cpu} = [ { label => 'cpu', nlabel => 'host.core.cpu.utilization.percentage', set => { key_values => [ { name => 'cpu_usage' }, { name => 'display' } ], output_template => 'usage : %s', perfdatas => [ { label => 'cpu', template => '%s', unit => '%', min => 0, max => 100, label_extra_instance => 1 } ] } } ]; } sub prefix_host_output { my ($self, %options) = @_; return "Host '" . $options{instance_value}->{display} . "' : "; } sub host_long_output { my ($self, %options) = @_; return "checking host '" . $options{instance_value}->{display} . "'"; } sub prefix_global_cpu_output { my ($self, %options) = @_; return "cpu total average : "; } 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; $options{options}->add_options(arguments => { "esx-hostname:s" => { name => 'esx_hostname' }, "filter" => { name => 'filter' }, "scope-datacenter:s" => { name => 'scope_datacenter' }, "scope-cluster:s" => { name => 'scope_cluster' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{host} = {}; my $response = $options{custom}->execute(params => $self->{option_results}, command => 'cpuhost'); foreach my $host_id (keys %{$response->{data}}) { my $host_name = $response->{data}->{$host_id}->{name}; $self->{host}->{$host_name} = { display => $host_name, cpu => {}, global => { state => $response->{data}->{$host_id}->{state}, }, global_cpu => { cpu_average => $response->{data}->{$host_id}->{'cpu.usage.average'}, cpu_average_mhz => $response->{data}->{$host_id}->{'cpu.usagemhz.average'}, cpu_average_mhz_max => defined($response->{data}->{$host_id}->{numCpuCores}) ? $response->{data}->{$host_id}->{numCpuCores} * $response->{data}->{$host_id}->{cpuMhz} : undef, }, }; foreach my $cpu_id (sort keys %{$response->{data}->{$host_id}->{cpu}}) { $self->{host}->{$host_name}->{cpu}->{$cpu_id} = { display => $cpu_id, cpu_usage => $response->{data}->{$host_id}->{cpu}->{$cpu_id} }; } } } 1; __END__ =head1 MODE Check ESX cpu usage. =over 8 =item B<--esx-hostname> ESX hostname to check. If not set, we check all ESX. =item B<--filter> ESX hostname is a regexp. =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =item B<--scope-cluster> Search in following cluster(s) (can be a regexp). =item B<--unknown-status> Set warning threshold for status (Default: '%{status} !~ /^connected$/i'). Can used special variables like: %{status} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{status} =item B<--warning-*> Threshold warning. Can be: 'total-cpu', 'total-cpu-mhz', 'cpu'. =item B<--critical-*> Threshold critical. Can be: 'total-cpu', 'total-cpu-mhz', 'cpu'. =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/cpuvm.pm000066400000000000000000000206431417000230700241130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::cpuvm; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; my $msg = '[connection state ' . $self->{result_values}->{connection_state} . '][power state ' . $self->{result_values}->{power_state} . ']'; return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'vm', type => 3, cb_prefix_output => 'prefix_vm_output', cb_long_output => 'vm_long_output', indent_long_output => ' ', message_multiple => 'All virtual machines are ok', group => [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'global_cpu', cb_prefix_output => 'prefix_global_cpu_output', type => 0, skipped_code => { -10 => 1 } }, { name => 'cpu', display_long => 0, cb_prefix_output => 'prefix_cpu_output', message_multiple => 'All CPUs are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'status', type => 2, unknown_default => '%{connection_state} !~ /^connected$/i or %{power_state} !~ /^poweredOn$/i', set => { key_values => [ { name => 'connection_state' }, { name => 'power_state' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{global_cpu} = [ { label => 'total-cpu', nlabel => 'vm.cpu.utilization.percentage', set => { key_values => [ { name => 'cpu_average' } ], output_template => '%s %%', perfdatas => [ { label => 'cpu_total', template => '%s', unit => '%', min => 0, max => 100, label_extra_instance => 1 } ] } }, { label => 'total-cpu-mhz', nlabel => 'vm.cpu.utilization.mhz', set => { key_values => [ { name => 'cpu_average_mhz' } ], output_template => '%s MHz', perfdatas => [ { label => 'cpu_total_MHz', template => '%s', unit => 'MHz', min => 0, label_extra_instance => 1 } ] } }, { label => 'cpu-ready', nlabel => 'vm.cpu.ready.percentage', set => { key_values => [ { name => 'cpu_ready' } ], output_template => 'ready %s %%', perfdatas => [ { label => 'cpu_ready', template => '%s', unit => '%', min => 0, max => 100, label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{cpu} = [ { label => 'cpu', nlabel => 'vm.core.cpu.utilization.percentage', set => { key_values => [ { name => 'cpu_usage' }, { name => 'display' } ], output_template => 'usage : %s MHz', perfdatas => [ { label => 'cpu', template => '%s', unit => 'MHz', min => 0, label_extra_instance => 1 } ] } } ]; } sub prefix_vm_output { my ($self, %options) = @_; my $msg = "Virtual machine '" . $options{instance_value}->{display} . "'"; if (defined($options{instance_value}->{config_annotation})) { $msg .= ' [annotation: ' . $options{instance_value}->{config_annotation} . ']'; } $msg .= ' : '; return $msg; } sub vm_long_output { my ($self, %options) = @_; my $msg = "checking virtual machine '" . $options{instance_value}->{display} . "'"; if (defined($options{instance_value}->{config_annotation})) { $msg .= ' [annotation: ' . $options{instance_value}->{config_annotation} . ']'; } return $msg; } sub prefix_global_cpu_output { my ($self, %options) = @_; return "cpu total average : "; } 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; $options{options}->add_options(arguments => { 'vm-hostname:s' => { name => 'vm_hostname' }, 'filter' => { name => 'filter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' }, 'scope-cluster:s' => { name => 'scope_cluster' }, 'scope-host:s' => { name => 'scope_host' }, 'display-description' => { name => 'display_description' }, 'filter-description:s' => { name => 'filter_description' }, 'filter-os:s' => { name => 'filter_os' }, 'filter-uuid:s' => { name => 'filter_uuid' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{vm} = {}; my $response = $options{custom}->execute( params => $self->{option_results}, command => 'cpuvm' ); foreach my $vm_id (keys %{$response->{data}}) { my $vm_name = $response->{data}->{$vm_id}->{name}; $self->{vm}->{$vm_name} = { display => $vm_name, cpu => {}, global => { connection_state => $response->{data}->{$vm_id}->{connection_state}, power_state => $response->{data}->{$vm_id}->{power_state}, }, global_cpu => { cpu_average => $response->{data}->{$vm_id}->{'cpu.usage.average'}, cpu_average_mhz => $response->{data}->{$vm_id}->{'cpu.usagemhz.average'}, cpu_ready => $response->{data}->{$vm_id}->{'cpu_ready'}, }, }; if (defined($self->{option_results}->{display_description})) { $self->{vm}->{$vm_name}->{config_annotation} = $options{custom}->strip_cr(value => $response->{data}->{$vm_id}->{'config.annotation'}); } foreach my $cpu_id (sort keys %{$response->{data}->{$vm_id}->{cpu}}) { $self->{vm}->{$vm_name}->{cpu}->{$cpu_id} = { display => $cpu_id, cpu_usage => $response->{data}->{$vm_id}->{cpu}->{$cpu_id} }; } } } 1; __END__ =head1 MODE Check virtual machine cpu usage. =over 8 =item B<--vm-hostname> VM hostname to check. If not set, we check all VMs. =item B<--filter> VM hostname is a regexp. =item B<--filter-description> Filter also virtual machines description (can be a regexp). =item B<--filter-os> Filter also virtual machines OS name (can be a regexp). =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =item B<--scope-cluster> Search in following cluster(s) (can be a regexp). =item B<--scope-host> Search in following host(s) (can be a regexp). =item B<--unknown-status> Set warning threshold for status (Default: '%{connection_state} !~ /^connected$/i or %{power_state} !~ /^poweredOn$/i'). Can used special variables like: %{connection_state}, %{power_state} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{connection_state}, %{power_state} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{connection_state}, %{power_state} =item B<--warning-*> Threshold warning. Can be: 'total-cpu', 'total-cpu-mhz', 'cpu-ready', 'cpu'. =item B<--critical-*> Threshold critical. Can be: 'total-cpu', 'total-cpu-mhz', 'cpu-ready', 'cpu'. =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/datastorecountvm.pm000066400000000000000000000164661417000230700263730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::datastorecountvm; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return 'accessible ' . $self->{result_values}->{accessible}; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'datastore', type => 1, cb_prefix_output => 'prefix_datastore_output', message_multiple => 'All Datastores are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'total-on', nlabel => 'datastore.vm.poweredon.current.count', set => { key_values => [ { name => 'poweredon' }, { name => 'total' } ], output_template => '%s VM(s) poweredon', perfdatas => [ { label => 'poweredon', template => '%s', min => 0, max => 'total' } ] } }, { label => 'total-off', nlabel => 'datastore.vm.poweredoff.current.count', set => { key_values => [ { name => 'poweredoff' }, { name => 'total' } ], output_template => '%s VM(s) poweredoff', perfdatas => [ { label => 'poweredoff', template => '%s', min => 0, max => 'total' } ] } }, { label => 'total-suspended', nlabel => 'datastore.vm.suspended.current.count', set => { key_values => [ { name => 'suspended' }, { name => 'total' } ], output_template => '%s VM(s) suspended', perfdatas => [ { label => 'suspended', template => '%s', min => 0, max => 'total' } ] } } ]; $self->{maps_counters}->{datastore} = [ { label => 'status', type => 2, unknown_default => '%{accessible} !~ /^true|1$/i', set => { key_values => [ { name => 'accessible' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'on', nlabel => 'datastore.vm.poweredon.current.count', set => { key_values => [ { name => 'poweredon' }, { name => 'total' } ], output_template => '%s VM(s) poweredon', perfdatas => [ { label => 'poweredon', template => '%s', min => 0, max => 'total', label_extra_instance => 1 } ] } }, { label => 'off', nlabel => 'datastore.vm.poweredoff.current.count', set => { key_values => [ { name => 'poweredoff' }, { name => 'total' } ], output_template => '%s VM(s) poweredoff', perfdatas => [ { label => 'poweredoff', template => '%s', min => 0, max => 'total', label_extra_instance => 1 } ] } }, { label => 'suspended', nlabel => 'datastore.vm.suspended.current.count', set => { key_values => [ { name => 'suspended' }, { name => 'total' } ], output_template => '%s VM(s) suspended', perfdatas => [ { label => 'suspended', template => '%s', min => 0, max => 'total', label_extra_instance => 1 } ] } } ]; } sub prefix_datastore_output { my ($self, %options) = @_; return "Datastore '" . $options{instance_value}->{display} . "' : "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'datastore-name:s' => { name => 'datastore_name' }, 'filter' => { name => 'filter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{global} = { poweredon => 0, poweredoff => 0, suspended => 0, total => 0 }; $self->{datastore} = {}; my $response = $options{custom}->execute( params => $self->{option_results}, command => 'datastorecountvm' ); foreach my $ds_id (keys %{$response->{data}}) { my $ds_name = $response->{data}->{$ds_id}->{name}; $self->{datastore}->{$ds_name} = { display => $ds_name, accessible => $response->{data}->{$ds_id}->{accessible}, poweredon => $response->{data}->{$ds_id}->{poweredon}, poweredoff => $response->{data}->{$ds_id}->{poweredoff}, suspended => $response->{data}->{$ds_id}->{suspended}, total => $response->{data}->{$ds_id}->{poweredon} + $response->{data}->{$ds_id}->{poweredoff} + $response->{data}->{$ds_id}->{suspended}, }; $self->{global}->{poweredon} += $response->{data}->{$ds_id}->{poweredon} if (defined($response->{data}->{$ds_id}->{poweredon})); $self->{global}->{poweredoff} += $response->{data}->{$ds_id}->{poweredoff} if (defined($response->{data}->{$ds_id}->{poweredoff})); $self->{global}->{suspended} += $response->{data}->{$ds_id}->{suspended} if (defined($response->{data}->{$ds_id}->{suspended})); } $self->{global}->{total} = $self->{global}->{poweredon} + $self->{global}->{poweredoff} + $self->{global}->{suspended}; } 1; __END__ =head1 MODE Check number of vm running/off on datastores. =over 8 =item B<--datastore-name> datastore name to check. =item B<--filter> Datastore name is a regexp. =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =item B<--unknown-status> Set warning threshold for status (Default: '%{accessible} !~ /^true|1$/i'). Can used special variables like: %{accessible} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{accessible} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{accessible} =item B<--warning-*> Threshold warning. Can be: 'total-on', 'total-off', 'total-suspended', 'on', 'off', 'suspended'. =item B<--critical-*> Threshold critical. Can be: 'total-on', 'total-off', 'total-suspended', 'on', 'off', 'suspended'. =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/datastorehost.pm000066400000000000000000000144731417000230700256510ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::datastorehost; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return 'status ' . $self->{result_values}->{status}; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_state'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'host', type => 3, cb_prefix_output => 'prefix_host_output', cb_long_output => 'host_long_output', indent_long_output => ' ', message_multiple => 'All ESX hosts are ok', group => [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'datastore', cb_prefix_output => 'prefix_datastore_output', message_multiple => 'All datastores latencies are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'status', type => 2, unknown_default => '%{status} !~ /^connected$/i', set => { key_values => [ { name => 'state' } ], 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 => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{datastore} = [ { label => 'read-latency', nlabel => 'host.datastore.latency.read.milliseconds', set => { key_values => [ { name => 'read_latency' }, { name => 'display' } ], output_template => 'read : %s ms', perfdatas => [ { label => 'trl', template => '%s', unit => 'ms', min => 0, label_extra_instance => 1 } ] } }, { label => 'write-latency', nlabel => 'host.datastore.latency.write.milliseconds', set => { key_values => [ { name => 'write_latency' }, { name => 'display' } ], output_template => 'write : %s ms', perfdatas => [ { label => 'twl', template => '%s', unit => 'ms', min => 0, label_extra_instance => 1 } ] } } ]; } sub prefix_host_output { my ($self, %options) = @_; return "Host '" . $options{instance_value}->{display} . "' : "; } sub host_long_output { my ($self, %options) = @_; return "checking host '" . $options{instance_value}->{display} . "'"; } sub prefix_datastore_output { my ($self, %options) = @_; return "datastore '" . $options{instance_value}->{display} . "' latency : "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'esx-hostname:s' => { name => 'esx_hostname' }, 'filter' => { name => 'filter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' }, 'scope-cluster:s' => { name => 'scope_cluster' }, 'datastore-name:s' => { name => 'datastore_name' }, 'filter-datastore:s' => { name => 'filter_datastore' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{host} = {}; my $response = $options{custom}->execute( params => $self->{option_results}, command => 'datastorehost' ); foreach my $host_id (keys %{$response->{data}}) { my $host_name = $response->{data}->{$host_id}->{name}; $self->{host}->{$host_name} = { display => $host_name, datastore => {}, global => { state => $response->{data}->{$host_id}->{state}, }, }; foreach my $ds_id (sort keys %{$response->{data}->{$host_id}->{datastore}}) { $self->{host}->{$host_name}->{datastore}->{$ds_id} = { display => $ds_id, read_latency => $response->{data}->{$host_id}->{datastore}->{$ds_id}->{'datastore.totalReadLatency.average'}, write_latency => $response->{data}->{$host_id}->{datastore}->{$ds_id}->{'datastore.totalWriteLatency.average'}, }; } } } 1; __END__ =head1 MODE Check ESX datastore latency. =over 8 =item B<--esx-hostname> ESX hostname to check. If not set, we check all ESX. =item B<--filter> ESX hostname is a regexp. =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =item B<--scope-cluster> Search in following cluster(s) (can be a regexp). =item B<--datastore-name> Datastore to check. If not set, we check all datastores. =item B<--filter-datastore> Datastore name is a regexp. =item B<--unknown-status> Set warning threshold for status (Default: '%{status} !~ /^connected$/i'). Can used special variables like: %{status} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{status} =item B<--warning-*> Threshold warning. Can be: 'read-latency', 'write-latency'. =item B<--critical-*> Threshold critical. Can be: 'read-latency', 'write-latency'. =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/datastoreio.pm000066400000000000000000000140461417000230700252770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::datastoreio; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return 'accessible ' . $self->{result_values}->{accessible}; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'datastore', type => 1, cb_prefix_output => 'prefix_datastore_output', message_multiple => 'All datastores are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'total-read', nlabel => 'datastore.read.usage.bytespersecond', set => { key_values => [ { name => 'read' } ], output_template => 'Total rate of reading data: %s %s/s', output_change_bytes => 1, perfdatas => [ { label => 'total_read_rate', template => '%s', unit => 'B/s', min => 0 } ] } }, { label => 'total-write', nlabel => 'datastore.write.usage.bytespersecond', set => { key_values => [ { name => 'write' } ], output_template => 'Total rate of writing data: %s %s/s', output_change_bytes => 1, perfdatas => [ { label => 'total_write_rate', template => '%s', unit => 'B/s', min => 0 } ] } } ]; $self->{maps_counters}->{datastore} = [ { label => 'status', type => 2, unknown_default => '%{accessible} !~ /^true|1$/i', set => { key_values => [ { name => 'accessible' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'read', nlabel => 'datastore.read.usage.bytespersecond', set => { key_values => [ { name => 'read' } ], output_template => 'rate of reading data: %s %s/s', output_change_bytes => 1, perfdatas => [ { label => 'read_rate', template => '%s', unit => 'B/s', min => 0, label_extra_instance => 1 } ] } }, { label => 'write', nlabel => 'datastore.write.usage.bytespersecond', set => { key_values => [ { name => 'write' } ], output_template => 'rate of writing data: %s %s/s', output_change_bytes => 1, perfdatas => [ { label => 'write_rate', template => '%s', unit => 'B/s', min => 0, label_extra_instance => 1 } ] } } ]; } sub prefix_datastore_output { my ($self, %options) = @_; return "Datastore '" . $options{instance_value}->{display} . "' : "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'datastore-name:s' => { name => 'datastore_name' }, 'filter' => { name => 'filter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{global} = { read => 0, write => 0 }; $self->{datastore} = {}; my $response = $options{custom}->execute( params => $self->{option_results}, command => 'datastoreio' ); foreach my $ds_id (keys %{$response->{data}}) { my $ds_name = $response->{data}->{$ds_id}->{name}; $self->{datastore}->{$ds_name} = { display => $ds_name, accessible => $response->{data}->{$ds_id}->{accessible}, read => $response->{data}->{$ds_id}->{'datastore.read.average'}, write => $response->{data}->{$ds_id}->{'datastore.write.average'}, }; $self->{global}->{read} += $response->{data}->{$ds_id}->{'datastore.read.average'} if (defined($response->{data}->{$ds_id}->{'datastore.read.average'})); $self->{global}->{write} += $response->{data}->{$ds_id}->{'datastore.write.average'} if (defined($response->{data}->{$ds_id}->{'datastore.write.average'})); } } 1; __END__ =head1 MODE Check datastore IO. =over 8 =item B<--datastore-name> datastore name to list. =item B<--filter> Datastore name is a regexp. =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =item B<--unknown-status> Set warning threshold for status (Default: '%{accessible} !~ /^true|1$/i'). Can used special variables like: %{accessible} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{accessible} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{accessible} =item B<--warning-*> Threshold warning. Can be: 'total-read', 'total-write', 'read', 'write'. =item B<--critical-*> Threshold critical. Can be: 'total-read', 'total-write', 'read', 'write'. =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/datastoreiops.pm000066400000000000000000000203241417000230700256360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::datastoreiops; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return 'accessible ' . $self->{result_values}->{accessible}; } sub prefix_datastore_output { my ($self, %options) = @_; return "Datastore '" . $options{instance_value}->{display} . "' : "; } sub datastore_long_output { my ($self, %options) = @_; return "checking datastore '" . $options{instance_value}->{display} . "'"; } sub prefix_vm_output { my ($self, %options) = @_; return "virtual machine '" . $options{instance_value}->{display} . "' "; } sub prefix_global_iops_output { my ($self, %options) = @_; return 'Total '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global_iops', type => 0, cb_prefix_output => 'prefix_global_iops_output', skipped_code => { -10 => 1 } }, { name => 'datastore', type => 3, cb_prefix_output => 'prefix_datastore_output', cb_long_output => 'datastore_long_output', indent_long_output => ' ', message_multiple => 'All datastores are ok', group => [ { name => 'ds_global', type => 0, skipped_code => { -10 => 1 } }, { name => 'ds_global_iops', type => 0, skipped_code => { -10 => 1 } }, { name => 'vm', cb_prefix_output => 'prefix_vm_output', message_multiple => 'All virtual machines IOPs are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{global_iops} = [ { label => 'read-total', nlabel => 'datastores.read.usage.iops', set => { key_values => [ { name => 'read' } ], output_template => 'read: %s iops', perfdatas => [ { label => 'total_riops', template => '%s', unit => 'iops', min => 0 } ] } }, { label => 'write-total', nlabel => 'datastores.write.usage.iops', set => { key_values => [ { name => 'write' } ], output_template => 'write: %s iops', perfdatas => [ { label => 'total_wiops', template => '%s', unit => 'iops', min => 0 } ] } } ]; $self->{maps_counters}->{ds_global} = [ { label => 'status', type => 2, unknown_default => '%{accessible} !~ /^true|1$/i', set => { key_values => [ { name => 'accessible' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{ds_global_iops} = [ { label => 'read', nlabel => 'datastore.read.usage.iops', set => { key_values => [ { name => 'read' } ], output_template => '%s read iops', perfdatas => [ { label => 'riops', template => '%s', unit => 'iops', min => 0, label_extra_instance => 1 } ] } }, { label => 'write', nlabel => 'datastore.write.usage.iops', set => { key_values => [ { name => 'write' } ], output_template => '%s write iops', perfdatas => [ { label => 'wiops', template => '%s', unit => 'iops', min => 0, label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{vm} = [ { label => 'read-vm', nlabel => 'datastore.vm.read.usage.iops', set => { key_values => [ { name => 'read' } ], output_template => '%s read iops', perfdatas => [ { label => 'vm_riops', template => '%s', unit => 'iops', min => 0, label_extra_instance => 1 } ] } }, { label => 'write-vm', nlabel => 'datastore.vm.write.usage.iops', set => { key_values => [ { name => 'write' } ], output_template => '%s write iops', perfdatas => [ { label => 'vm_wiops', template => '%s', unit => 'iops', min => 0, label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'datastore-name:s' => { name => 'datastore_name' }, 'filter' => { name => 'filter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' }, 'detail-iops-min:s' => { name => 'detail_iops_min', default => 50 } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{datastore} = {}; my $response = $options{custom}->execute( params => $self->{option_results}, command => 'datastoreiops' ); if ($response->{code} == 200) { $self->{output}->output_add( severity => 'OK', short_msg => $response->{short_message} ); $self->{output}->display(); $self->{output}->exit(); } $self->{global_iops} = { write => 0, read => 0 }; foreach my $ds_id (keys %{$response->{data}}) { my $ds_name = $response->{data}->{$ds_id}->{name}; $self->{datastore}->{$ds_name} = { display => $ds_name, vm => {}, ds_global => { accessible => $response->{data}->{$ds_id}->{accessible} }, ds_global_iops => { write => $response->{data}->{$ds_id}->{'disk.numberWrite.summation'}, read => $response->{data}->{$ds_id}->{'disk.numberRead.summation'} } }; $self->{global_iops}->{write} += $response->{data}->{$ds_id}->{'disk.numberWrite.summation'}; $self->{global_iops}->{read} += $response->{data}->{$ds_id}->{'disk.numberRead.summation'}; foreach my $vm_name (sort keys %{$response->{data}->{$ds_id}->{vm}}) { $self->{datastore}->{$ds_name}->{vm}->{$vm_name} = { display => $vm_name, write => $response->{data}->{$ds_id}->{vm}->{$vm_name}->{'disk.numberWrite.summation'}, read => $response->{data}->{$ds_id}->{vm}->{$vm_name}->{'disk.numberRead.summation'} }; } } } 1; __END__ =head1 MODE Check datastore IOPs. =over 8 =item B<--datastore-name> datastore name to list. =item B<--filter> Datastore name is a regexp. =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =item B<--detail-iops-min> Only display VMs with iops higher value (default: 50). =item B<--unknown-status> Set warning threshold for status (Default: '%{accessible} !~ /^true|1$/i'). Can used special variables like: %{accessible} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{accessible} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{accessible} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'read-total', 'write-total', 'read', 'write', 'read-vm', 'write-vm'. =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/datastoresnapshot.pm000066400000000000000000000134401417000230700265240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::datastoresnapshot; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return 'accessible ' . $self->{result_values}->{accessible}; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'datastore', type => 3, cb_prefix_output => 'prefix_datastore_output', cb_long_output => 'datastore_long_output', indent_long_output => ' ', message_multiple => 'All datastores are ok', group => [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'global_snapshot', type => 0, skipped_code => { -10 => 1 } }, { name => 'files', cb_prefix_output => 'prefix_files_output', message_multiple => 'All snapshot files are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'status', type => 2, unknown_default => '%{accessible} !~ /^true|1$/i', set => { key_values => [ { name => 'accessible' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{global_snapshot} = [ { label => 'total', nlabel => 'datastore.snapshots.usage.bytes', set => { key_values => [ { name => 'total' } ], output_template => 'total snapshots [size = %s %s]', output_change_bytes => 1, perfdatas => [ { label => 'total_size', template => '%s', unit => 'B', min => 0, label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{files} = [ { label => 'snapshot', nlabel => 'datastore.snapshot.usage.bytes', set => { key_values => [ { name => 'total' } ], output_template => '[size = %s %s]', output_change_bytes => 1, closure_custom_perfdata => sub { return 0; } } } ]; } sub prefix_datastore_output { my ($self, %options) = @_; return "Datastore '" . $options{instance_value}->{display} . "' : "; } sub datastore_long_output { my ($self, %options) = @_; return "checking datastore '" . $options{instance_value}->{display} . "'"; } sub prefix_files_output { my ($self, %options) = @_; return sprintf("file snapshot [%s]=>[%s] ", $options{instance_value}->{folder_path}, $options{instance_value}->{path}); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'datastore-name:s' => { name => 'datastore_name' }, 'filter' => { name => 'filter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{datastore} = {}; my $response = $options{custom}->execute( params => $self->{option_results}, command => 'datastoresnapshot' ); my $i = 0; foreach my $ds_id (keys %{$response->{data}}) { my $ds_name = $response->{data}->{$ds_id}->{name}; $self->{datastore}->{$ds_name} = { display => $ds_name, files => {}, global => { accessible => $response->{data}->{$ds_id}->{accessible}, }, global_snapshot => { total => 0 } }; foreach (@{$response->{data}->{$ds_id}->{snapshost}}) { $self->{datastore}->{$ds_name}->{files}->{$i} = { folder_path => $_->{folder_path}, path => $_->{path}, total => $_->{size} }; $self->{datastore}->{$ds_name}->{global_snapshot}->{total} += $_->{size}; $i++; } } } 1; __END__ =head1 MODE Check snapshots usage on datastores. =over 8 =item B<--datastore-name> datastore name to list. =item B<--filter> Datastore name is a regexp. =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =item B<--unknown-status> Set warning threshold for status (Default: '%{accessible} !~ /^true|1$/i'). Can used special variables like: %{accessible} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{accessible} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{accessible} =item B<--warning-*> Threshold warning. Can be: 'total', 'snapshot'. =item B<--critical-*> Threshold critical. Can be: 'total', 'snapshot'. =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/datastoreusage.pm000066400000000000000000000261441417000230700257760ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::datastoreusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return 'accessible ' . $self->{result_values}->{accessible}; } sub custom_usage_output { my ($self, %options) = @_; my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total_space}); my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used_space}); my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free_space}); 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_space}, $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free_space} ); return $msg; } sub custom_provisioned_output { my ($self, %options) = @_; my ($total_uncomitted_value, $total_uncommitted_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total_uncommitted}); my $msg = sprintf( 'Provisioned: %s (%.2f%%)', $total_uncomitted_value . " " . $total_uncommitted_unit, $self->{result_values}->{prct_uncommitted} ); return $msg; } sub custom_provisioned_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{total_space} = $options{new_datas}->{$self->{instance} . '_total_space'}; if ($self->{result_values}->{total_space} <= 0) { return -10; } $self->{result_values}->{total_uncommitted} = ($self->{result_values}->{total_space} - $options{new_datas}->{$self->{instance} . '_free_space'}) + $options{new_datas}->{$self->{instance} . '_uncommitted'}; $self->{result_values}->{prct_uncommitted} = $self->{result_values}->{total_uncommitted} * 100 / $self->{result_values}->{total_space}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'datastore', type => 1, cb_prefix_output => 'prefix_datastore_output', message_multiple => 'All datastores are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{datastore} = [ { label => 'status', type => 2, unknown_default => '%{accessible} !~ /^true|1$/i', set => { key_values => [ { name => 'accessible' }, { name => 'display' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'usage', nlabel => 'datastore.space.usage.bytes', set => { key_values => [ { name => 'used_space' }, { name => 'free_space' }, { name => 'prct_used_space' }, { name => 'prct_free_space' }, { name => 'total_space' }, { name => 'display' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { label => 'used', template => '%d', min => 0, max => 'total_space', unit => 'B', cast_int => 1, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'usage-free', nlabel => 'datastore.space.free.bytes', display_ok => 0, set => { key_values => [ { name => 'free_space' }, { name => 'used_space' }, { name => 'prct_used_space' }, { name => 'prct_free_space' }, { name => 'total_space' }, { name => 'display' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { label => 'free', template => '%d', min => 0, max => 'total_space', unit => 'B', cast_int => 1, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'usage-prct', nlabel => 'datastore.space.usage.percentage', display_ok => 0, set => { key_values => [ { name => 'prct_used_space' }, { name => 'free_space' }, { name => 'used_space' }, { name => 'prct_free_space' }, { name => 'total_space' }, { name => 'display' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { label => 'used_prct', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'provisioned', nlabel => 'datastore.space.provisioned.bytes', set => { key_values => [ { name => 'display' }, { name => 'uncommitted' }, { name => 'total_space' }, { name => 'free_space' } ], closure_custom_calc => $self->can('custom_provisioned_calc'), closure_custom_output => $self->can('custom_provisioned_output'), threshold_use => 'prct_uncommitted', perfdatas => [ { label => 'provisioned', value => 'total_uncommitted', template => '%s', unit => 'B', min => 0, max => 'total_space', label_extra_instance => 1 } ] } } ]; } sub prefix_datastore_output { my ($self, %options) = @_; return "Datastore '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'datastore-name:s' => { name => 'datastore_name' }, 'filter' => { name => 'filter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' }, 'filter-host:s' => { name => 'filter_host' }, 'units:s' => { name => 'units', default => '' }, 'free' => { name => 'free' }, 'refresh' => { name => 'refresh' } }); return $self; } sub check_options { my ($self, %options) = @_; # Compatibility $self->compat_threshold_counter(%options, compat => { th => [ [ 'usage', { free => 'usage-free', prct => 'usage-prct'} ], [ 'instance-datastore-space-usage-bytes', { free => 'instance-datastore-space-free-bytes', prct => 'instance-datastore-space-usage-percentage' } ] ], units => $options{option_results}->{units}, free => $options{option_results}->{free} } ); $self->SUPER::check_options(%options); } 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'}; if ($self->{result_values}->{total} <= 0) { $self->{error_msg} = 'size is 0'; return -20; } $self->{result_values}->{free} = $options{new_datas}->{$self->{instance} . '_free'}; $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 manage_selection { my ($self, %options) = @_; my $response = $options{custom}->execute( params => $self->{option_results}, command => 'datastoreusage' ); $self->{datastore} = {}; foreach my $ds_id (keys %{$response->{data}}) { my $ds_name = $response->{data}->{$ds_id}->{name}; if (defined($response->{data}->{$ds_id}->{hosts}) && defined($self->{option_results}->{filter_host}) && $self->{option_results}->{filter_host} ne '') { my $filtered = 0; foreach (@{$response->{data}->{$ds_id}->{hosts}}) { $filtered = 1 if (/$self->{option_results}->{filter_host}/); } next if ($filtered == 0); } $self->{datastore}->{$ds_name} = { display => $ds_name, accessible => $response->{data}->{$ds_id}->{accessible} }; if (!defined($response->{data}->{$ds_id}->{size}) || $response->{data}->{$ds_id}->{size} <= 0) { $self->{output}->output_add(long_msg => "skipping datastore '" . $ds_name . "': no total size"); next; } $self->{datastore}->{$ds_name}->{used_space} = $response->{data}->{$ds_id}->{size} - $response->{data}->{$ds_id}->{free}; $self->{datastore}->{$ds_name}->{free_space} = $response->{data}->{$ds_id}->{free}; $self->{datastore}->{$ds_name}->{total_space} = $response->{data}->{$ds_id}->{size}; $self->{datastore}->{$ds_name}->{prct_used_space} = ($response->{data}->{$ds_id}->{size} - $response->{data}->{$ds_id}->{free}) * 100 / $response->{data}->{$ds_id}->{size}; $self->{datastore}->{$ds_name}->{prct_free_space} = $response->{data}->{$ds_id}->{free} * 100 / $response->{data}->{$ds_id}->{size}; $self->{datastore}->{$ds_name}->{uncommitted} = $response->{data}->{$ds_id}->{uncommitted}; } } 1; __END__ =head1 MODE Check datastore usage. =over 8 =item B<--datastore-name> datastore name to list. =item B<--filter> Datastore name is a regexp. =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =item B<--filter-host> Filter datastores attached to hosts (can be a regexp). =item B<--refresh> Explicitly ask vmware to refreshes free-space and capacity values (slower). =item B<--unknown-status> Set warning threshold for status (Default: '%{accessible} !~ /^true|1$/i'). Can used special variables like: %{accessible} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{accessible} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{accessible} =item B<--warning-*> B<--critical-*> Thresholds. Can be: Can be: 'usage' (B), 'usage-free' (B), 'usage-prct' (%), 'provisioned'. =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/datastorevm.pm000066400000000000000000000206311417000230700253070ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::datastorevm; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return '[connection state ' . $self->{result_values}->{connection_state} . '][power state ' . $self->{result_values}->{power_state} . ']'; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'vm', type => 3, cb_prefix_output => 'prefix_vm_output', cb_long_output => 'vm_long_output', indent_long_output => ' ', message_multiple => 'All virtual machines are ok', group => [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'global_vm', type => 0, skipped_code => { -10 => 1 } }, { name => 'datastore', cb_prefix_output => 'prefix_datastore_output', message_multiple => 'All datastores are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'status', type => 2, unknown_default => '%{connection_state} !~ /^connected$/i or %{power_state} !~ /^poweredOn$/i', set => { key_values => [ { name => 'connection_state' }, { name => 'power_state' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{global_vm} = [ { label => 'max-total-latency', nlabel => 'vm.datastore.latency.max.milliseconds', set => { key_values => [ { name => 'total_latency' } ], output_template => 'max total latency is %s ms', perfdatas => [ { label => 'max_total_latency', template => '%s', unit => 'ms', min => 0, label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{datastore} = [ { label => 'read', nlabel => 'vm.datastore.read.usage.iops', set => { key_values => [ { name => 'read' } ], output_template => '%s read iops', perfdatas => [ { label => 'riops', template => '%s', unit => 'iops', min => 0, label_extra_instance => 1 } ] } }, { label => 'write', nlabel => 'vm.datastore.write.usage.iops', set => { key_values => [ { name => 'write' } ], output_template => '%s write iops', perfdatas => [ { label => 'wiops', template => '%s', unit => 'iops', min => 0, max => 'write', label_extra_instance => 1 } ] } } ]; } sub prefix_vm_output { my ($self, %options) = @_; my $msg = "Virtual machine '" . $options{instance_value}->{display} . "'"; if (defined($options{instance_value}->{config_annotation})) { $msg .= ' [annotation: ' . $options{instance_value}->{config_annotation} . ']'; } $msg .= ' : '; return $msg; } sub vm_long_output { my ($self, %options) = @_; my $msg = "checking virtual machine '" . $options{instance_value}->{display} . "'"; if (defined($options{instance_value}->{config_annotation})) { $msg .= ' [annotation: ' . $options{instance_value}->{config_annotation} . ']'; } return $msg; } sub prefix_datastore_output { my ($self, %options) = @_; return "datastore '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'vm-hostname:s' => { name => 'vm_hostname' }, 'filter' => { name => 'filter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' }, 'scope-cluster:s' => { name => 'scope_cluster' }, 'scope-host:s' => { name => 'scope_host' }, 'filter-description:s' => { name => 'filter_description' }, 'filter-os:s' => { name => 'filter_os' }, 'filter-uuid:s' => { name => 'filter_uuid' }, 'display-description' => { name => 'display_description' }, 'datastore-name:s' => { name => 'datastore_name' }, 'filter-datastore:s' => { name => 'filter_datastore' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{vm} = {}; my $response = $options{custom}->execute( params => $self->{option_results}, command => 'datastorevm' ); if ($response->{code} == 200) { $self->{output}->output_add( severity => 'OK', short_msg => $response->{short_message} ); $self->{output}->display(); $self->{output}->exit(); } foreach my $vm_id (keys %{$response->{data}}) { my $vm_name = $response->{data}->{$vm_id}->{name}; $self->{vm}->{$vm_name} = { display => $vm_name, datastore => {}, global => { connection_state => $response->{data}->{$vm_id}->{connection_state}, power_state => $response->{data}->{$vm_id}->{power_state}, }, global_vm => { total_latency => $response->{data}->{$vm_id}->{'disk.maxTotalLatency.latest'}, } }; if (defined($self->{option_results}->{display_description})) { $self->{vm}->{$vm_name}->{config_annotation} = $options{custom}->strip_cr(value => $response->{data}->{$vm_id}->{'config.annotation'}); } foreach my $ds_name (sort keys %{$response->{data}->{$vm_id}->{datastore}}) { $self->{vm}->{$vm_name}->{datastore}->{$ds_name} = { display => $ds_name, read => $response->{data}->{$vm_id}->{datastore}->{$ds_name}->{'disk.numberRead.summation'}, write => $response->{data}->{$vm_id}->{datastore}->{$ds_name}->{'disk.numberWrite.summation'}, }; } } } 1; __END__ =head1 MODE Check virtual machine IOPs on datastore(s). =over 8 =item B<--vm-hostname> VM hostname to check. If not set, we check all VMs. =item B<--filter> VM hostname is a regexp. =item B<--filter-description> Filter also virtual machines description (can be a regexp). =item B<--filter-os> Filter also virtual machines OS name (can be a regexp). =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =item B<--scope-cluster> Search in following cluster(s) (can be a regexp). =item B<--scope-host> Search in following host(s) (can be a regexp). =item B<--datastore-name> Datastore to check. If not set, we check all datastores. =item B<--filter-datastore> Datastore name is a regexp. =item B<--display-description> Display virtual machine description. =item B<--unknown-status> Set warning threshold for status (Default: '%{connection_state} !~ /^connected$/i or %{power_state} !~ /^poweredOn$/i'). Can used special variables like: %{connection_state}, %{power_state} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{connection_state}, %{power_state} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{connection_state}, %{power_state} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'max-total-latency', 'read', 'write'. =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/devicevm.pm000066400000000000000000000155671417000230700245740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::devicevm; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return '[connection state ' . $self->{result_values}->{connection_state} . '][power state ' . $self->{result_values}->{power_state} . ']'; } sub custom_device_output { my ($self, %options) = @_; return sprintf("%s %s device connected", $self->{result_values}->{device_connected}, $self->{instance_mode}->{option_results}->{device}); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'vm', type => 1, cb_prefix_output => 'prefix_vm_output', message_multiple => 'All virtual machines are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'total-device-connected', nlabel => 'vm.devices.connected.count', set => { key_values => [ { name => 'device_connected' } ], closure_custom_output => $self->can('custom_device_output'), perfdatas => [ { label => 'total_device_connected', template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{vm} = [ { label => 'status', type => 2, unknown_default => '%{connection_state} !~ /^connected$/i', set => { key_values => [ { name => 'connection_state' }, { name => 'power_state' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'device-connected', nlabel => 'vm.devices.connected.count', set => { key_values => [ { name => 'device_connected' }, { name => 'display' } ], oclosure_custom_output => $self->can('custom_device_output'), perfdatas => [ { label => 'device_connected', template => '%s', min => 0, label_extra_instance => 1 } ] } } ]; } sub prefix_vm_output { my ($self, %options) = @_; my $msg = "Virtual machine '" . $options{instance_value}->{display} . "'"; if (defined($options{instance_value}->{config_annotation})) { $msg .= ' [annotation: ' . $options{instance_value}->{config_annotation} . ']'; } $msg .= ' : '; return $msg; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "vm-hostname:s" => { name => 'vm_hostname' }, "filter" => { name => 'filter' }, "scope-datacenter:s" => { name => 'scope_datacenter' }, "scope-cluster:s" => { name => 'scope_cluster' }, "scope-host:s" => { name => 'scope_host' }, "filter-description:s" => { name => 'filter_description' }, "filter-os:s" => { name => 'filter_os' }, "filter-uuid:s" => { name => 'filter_uuid' }, "display-description" => { name => 'display_description' }, "device:s" => { name => 'device' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{device}) || $self->{option_results}->{device} eq '') { $self->{output}->add_option_msg(short_msg => 'Please set device option.'); $self->{output}->option_exit(); } } sub manage_selection { my ($self, %options) = @_; $self->{global} = { device_connected => 0 }; $self->{vm} = {}; my $response = $options{custom}->execute( params => $self->{option_results}, command => 'devicevm' ); foreach my $vm_id (keys %{$response->{data}}) { my $vm_name = $response->{data}->{$vm_id}->{name}; $self->{vm}->{$vm_name} = { display => $vm_name, connection_state => $response->{data}->{$vm_id}->{connection_state}, power_state => $response->{data}->{$vm_id}->{power_state}, device_connected => $response->{data}->{$vm_id}->{total_device_connected} }; if (defined($self->{option_results}->{display_description})) { $self->{vm}->{$vm_name}->{config_annotation} = $options{custom}->strip_cr(value => $response->{data}->{$vm_id}->{'config.annotation'}); } $self->{global}->{device_connected} += $self->{vm}->{$vm_name}->{device_connected}; } } 1; __END__ =head1 MODE Check virtual machine device connected. =over 8 =item B<--vm-hostname> VM hostname to check. If not set, we check all VMs. =item B<--filter> VM hostname is a regexp. =item B<--filter-description> Filter also virtual machines description (can be a regexp). =item B<--filter-os> Filter also virtual machines OS name (can be a regexp). =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =item B<--scope-cluster> Search in following cluster(s) (can be a regexp). =item B<--scope-host> Search in following host(s) (can be a regexp). =item B<--display-description> Display virtual machine description. =item B<--device> Device to check (Required) (Example: --device='VirtualCdrom'). =item B<--unknown-status> Set warning threshold for status (Default: '%{connection_state} !~ /^connected$/i'). Can used special variables like: %{connection_state} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{connection_state} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{connection_state} =item B<--warning-*> Threshold warning. Can be: 'total-device-connected', 'device-connected'. =item B<--critical-*> Threshold critical. Can be: 'total-device-connected', 'device-connected'. =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/discovery.pm000066400000000000000000000043251417000230700247670ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::discovery; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'resource-type:s' => { name => 'resource_type' }, 'prettify' => { name => 'prettify' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my $response = $options{custom}->execute(params => $self->{option_results}, command => 'discovery', force_response => 1); my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($response->{data}); } else { $encoded_data = JSON::XS->new->utf8->encode($response->{data}); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); } 1; __END__ =head1 MODE Resources discovery. =over 8 =item B<--resource-type> Choose the type of resources to discover (Can be: 'esx', 'vm') (Mandatory). =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/getmap.pm000066400000000000000000000060621417000230700242350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::getmap; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'esx-hostname:s' => { name => 'esx_hostname' }, 'filter' => { name => 'filter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' }, 'scope-cluster:s' => { name => 'scope_cluster' }, 'vm-no' => { name => 'vm_no' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my $response = $options{custom}->execute(params => $self->{option_results}, command => 'getmap'); foreach my $host_id (sort { $response->{data}->{$a}->{name} cmp $response->{data}->{$b}->{name} } keys %{$response->{data}}) { $self->{output}->output_add(long_msg => sprintf(" %s [v%s] %s", $response->{data}->{$host_id}->{name}, $response->{data}->{$host_id}->{version}, defined($self->{option_results}->{vm_no}) ? '' : ':')); foreach my $vm_id (sort { $response->{data}->{$host_id}->{vm}->{$a}->{name} cmp $response->{data}->{$host_id}->{vm}->{$b}->{name} } keys %{$response->{data}->{$host_id}->{vm}}) { $self->{output}->output_add(long_msg => sprintf(" %s [%s]", $response->{data}->{$host_id}->{vm}->{$vm_id}->{name}, $response->{data}->{$host_id}->{vm}->{$vm_id}->{power_state})); } } $self->{output}->output_add(severity => 'OK', short_msg => 'List ESX host(s):'); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE List ESX hosts and Virtual machines. =over 8 =item B<--esx-hostname> ESX hostname to list. If not set, we list all ESX. =item B<--filter> ESX hostname is a regexp. =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =item B<--scope-cluster> Search in following cluster(s) (can be a regexp). =item B<--vm-no> Don't list virtual machines. =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/healthhost.pm000066400000000000000000000314121417000230700251200ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::healthhost; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return 'status ' . $self->{result_values}->{status}; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_state'}; return 0; } sub custom_summary_output { my ($self, %options) = @_; my $msg; if ($self->{result_values}->{type} ne '') { $msg = $self->{result_values}->{type} . " sensor " . $self->{result_values}->{name} . ": ". $self->{result_values}->{summary}; } else { $msg = $self->{result_values}->{name} . ": ". $self->{result_values}->{summary}; } return $msg; } sub prefix_host_output { my ($self, %options) = @_; return "Host '" . $options{instance_value}->{display} . "' : "; } sub host_long_output { my ($self, %options) = @_; return "checking host '" . $options{instance_value}->{display} . "'"; } sub prefix_global_cpu_output { my ($self, %options) = @_; return "cpu total average : "; } sub prefix_cpu_output { my ($self, %options) = @_; return "cpu '" . $options{instance_value}->{display} . "' "; } sub prefix_sensor_output { my ($self, %options) = @_; return "sensor '" . $options{instance} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'host', type => 3, cb_prefix_output => 'prefix_host_output', cb_long_output => 'host_long_output', indent_long_output => ' ', message_multiple => 'All ESX hosts are ok', group => [ { name => 'global_host', type => 0, skipped_code => { -10 => 1 } }, { name => 'global_problems', type => 0, skipped_code => { -10 => 1 } }, { name => 'global_summary', type => 1 }, { name => 'sensors_temp', display_long => 1, cb_prefix_output => 'prefix_sensor_output', message_multiple => 'temperature sensors are ok', type => 1, skipped_code => { -10 => 1 } }, { name => 'sensors_fan', display_long => 1, cb_prefix_output => 'prefix_sensor_output', message_multiple => 'fan sensors are ok', type => 1, skipped_code => { -10 => 1 } }, { name => 'sensors_voltage', display_long => 1, cb_prefix_output => 'prefix_sensor_output', message_multiple => 'voltage sensors are ok', type => 1, skipped_code => { -10 => 1 } }, { name => 'sensors_power', display_long => 1, cb_prefix_output => 'prefix_sensor_output', message_multiple => 'power sensors are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'total-problems', nlabel => 'host.health.problems.current.count', set => { key_values => [ { name => 'total_problems' }, { name => 'total' } ], output_template => '%s total health issue(s) found', perfdatas => [ { template => '%s', min => 0, max => 'total' } ] } } ]; $self->{maps_counters}->{global_host} = [ { label => 'status', type => 2, unknown_default => '%{status} !~ /^connected$/i', set => { key_values => [ { name => 'state' } ], 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 => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{global_problems} = [ { label => 'ok', threshold => 0, set => { key_values => [ { name => 'ok' } ], output_template => '%s health checks are green', closure_custom_perfdata => sub { return 0; } } }, { label => 'problems', nlabel => 'host.health.problems.current.count', set => { key_values => [ { name => 'total_problems' }, { name => 'total' } ], output_template => '%s total health issue(s) found', perfdatas => [ { template => '%s', min => 0, max => 'total', label_extra_instance => 1 } ] } }, { label => 'problems-yellow', nlabel => 'host.health.yellow.current.count', set => { key_values => [ { name => 'yellow' }, { name => 'total' } ], output_template => '%s yellow health issue(s) found', perfdatas => [ { template => '%s', min => 0, max => 'total', label_extra_instance => 1 } ] } }, { label => 'problems-red', nlabel => 'host.health.red.current.count', set => { key_values => [ { name => 'red' }, { name => 'total' } ], output_template => '%s red health issue(s) found', perfdatas => [ { template => '%s', min => 0, max => 'total', label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{global_summary} = [ { label => 'global-summary', threshold => 0, set => { key_values => [ { name => 'type' }, { name => 'name' }, { name => 'summary' } ], closure_custom_output => $self->can('custom_summary_output'), closure_custom_perfdata => sub { return 0; } } } ]; $self->{maps_counters}->{sensors_temp} = [ { label => 'sensor-temperature', nlabel => 'host.sensor.temperature.celsius', set => { key_values => [ { name => 'value' } ], output_template => 'temperature: %s C', perfdatas => [ { template => '%s', unit => 'C', min => 0, label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{sensors_fan} = [ { label => 'sensor-fan', nlabel => 'host.sensor.fan.speed.rpm', set => { key_values => [ { name => 'value' } ], output_template => 'fan speed: %s rpm', perfdatas => [ { template => '%s', unit => 'rpm', min => 0, label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{sensors_voltage} = [ { label => 'sensor-voltage', nlabel => 'host.sensor.voltage.volt', set => { key_values => [ { name => 'value' } ], output_template => 'voltage: %s V', perfdatas => [ { template => '%s', unit => 'V', min => 0, label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{sensors_power} = [ { label => 'sensor-power', nlabel => 'host.sensor.power.watt', set => { key_values => [ { name => 'value' } ], output_template => 'power: %s W', perfdatas => [ { template => '%s', unit => 'W', min => 0, label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'esx-hostname:s' => { name => 'esx_hostname' }, 'filter' => { name => 'filter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' }, 'scope-cluster:s' => { name => 'scope_cluster' }, 'storage-status' => { name => 'storage_status' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{global} = { total_problems => 0, total => 0 }; $self->{host} = {}; my $response = $options{custom}->execute( params => $self->{option_results}, command => 'healthhost' ); foreach my $host_id (keys %{$response->{data}}) { my $host_name = $response->{data}->{$host_id}->{name}; $self->{host}->{$host_name} = { display => $host_name, global_host => { state => $response->{data}->{$host_id}->{state}, }, global_summary => {}, global_problems => { ok => 0, total_problems => 0, red => 0, yellow => 0, total => 0 }, sensors_temp => {} }; my $i = 0; foreach (('memory_info', 'cpu_info', 'sensor_info', 'storage_info')) { if (defined($response->{data}->{$host_id}->{$_})) { foreach my $entry (@{$response->{data}->{$host_id}->{$_}}) { my $status = 'ok'; $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 { $self->{host}->{$host_name}->{global_summary}->{$i} = { type => defined($entry->{type}) ? $entry->{type} : '', name => $entry->{name}, summary => $entry->{summary} }; } } $i++; } } if (defined($response->{data}->{$host_id}->{sensor_info})) { foreach my $entry (@{$response->{data}->{$host_id}->{sensor_info}}) { next if ($entry->{current_reading} == 0); $entry->{current_reading} *= 10 ** $entry->{power10}; $entry->{name} =~ s/\s---\s.+//; if (lc($entry->{type}) eq 'temperature' && $entry->{unit} =~ /Degrees\s+C/i) { $self->{host}->{$host_name}->{sensors_temp}->{ $entry->{name} } = { value => $entry->{current_reading} }; } elsif (lc($entry->{type}) eq 'fan' && $entry->{unit} =~ /rpm/i) { $self->{host}->{$host_name}->{sensors_fan}->{ $entry->{name} } = { value => $entry->{current_reading} }; } elsif (lc($entry->{type}) eq 'voltage' && $entry->{unit} =~ /volts/i) { $self->{host}->{$host_name}->{sensors_voltage}->{ $entry->{name} } = { value => $entry->{current_reading} }; } elsif (lc($entry->{type}) eq 'power' && $entry->{unit} =~ /watts/i) { $self->{host}->{$host_name}->{sensors_power}->{ $entry->{name} } = { value => $entry->{current_reading} }; } } } $self->{global}->{total_problems} += $self->{host}->{$host_name}->{global_problems}->{red} + $self->{host}->{$host_name}->{global_problems}->{yellow}; $self->{global}->{total} += $self->{host}->{$host_name}->{global_problems}->{total}; } } 1; __END__ =head1 MODE Check health of ESX hosts. =over 8 =item B<--esx-hostname> ESX hostname to check. If not set, we check all ESX. =item B<--filter> ESX hostname is a regexp. =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =item B<--scope-cluster> Search in following cluster(s) (can be a regexp). =item B<--storage-status> Check storage(s) status. =item B<--unknown-status> Set warning threshold for status (Default: '%{status} !~ /^connected$/i'). Can used special variables like: %{status} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{status} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'total-problems', 'problems', 'problems-yellow', 'problems-red', 'sensor-temperature', 'sensor-fan', 'sensor-voltage', 'sensor-power'. =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/licenses.pm000066400000000000000000000332411417000230700245640ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::licenses; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; 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_expires_perfdata { my ($self, %options) = @_; $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_expires_threshold { my ($self, %options) = @_; 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_expires_output { my ($self, %options) = @_; my $msg; if ($self->{result_values}->{expires_seconds} == 0) { $msg = 'expired'; } else { $msg = 'expires in ' . $self->{result_values}->{expires_human}; } return $msg; } sub custom_usage_output { my ($self, %options) = @_; my $msg; if ($self->{result_values}->{total} <= 0) { $msg = sprintf('used: %s (unlimited)', $self->{result_values}->{used}); } else { $msg = sprintf( "total: %s used: %s (%.2f%%) free: %s (%.2f%%)", $self->{result_values}->{total}, $self->{result_values}->{used}, $self->{result_values}->{prct_used}, $self->{result_values}->{free}, $self->{result_values}->{prct_free} ); } return $msg; } sub custom_usage_calc { my ($self, %options) = @_; $self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_name'}; $self->{result_values}->{edition} = $options{new_datas}->{$self->{instance} . '_edition'}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_total'}; $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_used'}; if ($self->{result_values}->{total} == 0) { return -10 if ($options{extra_options}->{label} ne 'usage'); return 0; } $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}; $self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used}; return 0; } sub prefix_license_output { my ($self, %options) = @_; return sprintf( "License '%s' [edition: %s] ", $options{instance}, $options{instance_value}->{edition} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'licenses', type => 1, cb_prefix_output => 'prefix_license_output', message_multiple => 'All licenses are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'total-licenses', nlabel => 'licenses.total.count', set => { key_values => [ { name => 'total' } ], output_template => 'Number of licenses: %s', perfdatas => [ { template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{licenses} = [ { label => 'usage', nlabel => 'license.usage.count', set => { key_values => [ { name => 'edition' }, { name => 'name' }, { name => 'used' }, { name => 'total' } ], closure_custom_calc_extra_options => { label => 'usage' }, closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_output => $self->can('custom_usage_output'), closure_custom_threshold_check => sub { my ($self, %options) = @_; return $self->{perfdata}->threshold_check( value => $self->{result_values}->{used}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ] ); }, closure_custom_perfdata => sub { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel}, instances => $self->{result_values}->{name}, value => $self->{result_values}->{used}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}), min => 0, max => $self->{result_values}->{total} > 0 ? $self->{result_values}->{total} : undef ); } } }, { label => 'usage-free', nlabel => 'license.free.count', display_ok => 0, set => { key_values => [ { name => 'edition' }, { name => 'name' }, { name => 'used' }, { name => 'total' } ], closure_custom_calc_extra_options => { label => 'free' }, closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_output => $self->can('custom_usage_output'), closure_custom_threshold_check => sub { my ($self, %options) = @_; return $self->{perfdata}->threshold_check( value => $self->{result_values}->{free}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel}, exit_litteral => 'warning' } ] ); }, closure_custom_perfdata => sub { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel}, instances => $self->{result_values}->{name}, value => $self->{result_values}->{free}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}), min => 0, max => $self->{result_values}->{total} ); } } }, { label => 'usage-prct', nlabel => 'license.usage.percentage', display_ok => 0, set => { key_values => [ { name => 'edition' }, { name => 'name' }, { name => 'used' }, { name => 'total' } ], closure_custom_calc_extra_options => { label => 'prct' }, closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_output => $self->can('custom_usage_output'), closure_custom_threshold_check => sub { my ($self, %options) = @_; return $self->{perfdata}->threshold_check( value => $self->{result_values}->{prct_used}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel}, exit_litteral => 'warning' } ] ); }, closure_custom_perfdata => sub { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel}, unit => '%', instances => $self->{result_values}->{name}, value => $self->{result_values}->{prct_used}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}), min => 0, max => 100 ); } } }, { label => 'expires', nlabel => 'license.expires', set => { key_values => [ { name => 'expires_seconds' }, { name => 'expires_human' }, { name => 'name' } ], closure_custom_output => $self->can('custom_expires_output'), closure_custom_perfdata => $self->can('custom_expires_perfdata'), closure_custom_threshold_check => $self->can('custom_expires_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 => { 'filter-name:s' => { name => 'filter_name' }, 'exclude-name:s' => { name => 'exclude_name' }, 'filter-edition:s' => { name => 'filter_edition' }, 'exclude-edition:s' => { name => 'exclude_edition' }, 'unit:s' => { name => 'unit', default => 'd' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if ($self->{option_results}->{unit} eq '' || !defined($unitdiv->{$self->{option_results}->{unit}})) { $self->{option_results}->{unit} = 'd'; } } sub manage_selection { my ($self, %options) = @_; my $response = $options{custom}->execute( params => $self->{option_results}, command => 'licenses' ); $self->{global} = { total => 0 }; $self->{licenses} = {}; foreach my $name (keys %{$response->{data}}) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $name !~ /$self->{option_results}->{filter_name}/); next if (defined($self->{option_results}->{exclude_name}) && $self->{option_results}->{exclude_name} ne '' && $name =~ /$self->{option_results}->{exclude_name}/); next if (defined($self->{option_results}->{filter_edition}) && $self->{option_results}->{filter_edition} ne '' && $response->{data}->{$name}->{edition} !~ /$self->{option_results}->{filter_edition}/); next if (defined($self->{option_results}->{exclude_edition}) && $self->{option_results}->{exclude_edition} ne '' && $response->{data}->{$name}->{edition} =~ /$self->{option_results}->{exclude_edition}/); next if (!defined($response->{data}->{$name}->{used}) && !defined($response->{data}->{$name}->{expiration_minutes})); $self->{licenses}->{$name} = { name => $name, edition => $response->{data}->{$name}->{edition}, total => $response->{data}->{$name}->{total}, used => $response->{data}->{$name}->{used} }; if (defined($response->{data}->{$name}->{expiration_minutes})) { $self->{licenses}->{$name}->{expires_seconds} = $response->{data}->{$name}->{expiration_minutes} * 60; $self->{licenses}->{$name}->{expires_human} = centreon::plugins::misc::change_seconds( value => $self->{licenses}->{$name}->{expires_seconds} ); } $self->{global}->{total}++; } } 1; __END__ =head1 MODE Check licenses. =over 8 =item B<--filter-name> Filter licenses by name (can be a regexp). =item B<--exclude-name> Exclude licenses by name (can be a regexp). =item B<--filter-edition> Filter licenses by edition name (can be a regexp). =item B<--exclude-edition> Exclude licenses by edition name (can be a regexp). =item B<--unit> Select the unit for expires threshold. May be 's' for seconds, 'm' for minutes, 'h' for hours, 'd' for days, 'w' for weeks. Default is days. =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'total-licenses', 'usage', 'usage-free', 'usage-prct', 'expires'. =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/limitvm.pm000066400000000000000000000251261417000230700244430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::limitvm; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_limit_output { my ($self, %options) = @_; my $msg; if ($self->{result_values}->{limit} != -1) { $msg = sprintf("%s limit set", $self->{result_values}->{label}); } else { $msg = sprintf("no %s limit set", $self->{result_values}->{label}); } return $msg; } sub custom_limit_calc { my ($self, %options) = @_; $self->{result_values}->{limit} = $options{new_datas}->{$self->{instance} . '_'. $options{extra_options}->{label_ref} . '_limit'}; $self->{result_values}->{label} = $options{extra_options}->{label_ref}; $self->{result_values}->{connection_state} = $options{new_datas}->{$self->{instance} . '_connection_state'}; $self->{result_values}->{power_state} = $options{new_datas}->{$self->{instance} . '_power_state'}; $self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_name'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'cpu_alarms', type => 2, cb_long_output => 'cpu_long_output', message_multiple => '0 cpu limit problem(s) detected', format_output => '%s cpu limit problem(s) detected', display_counter_problem => { label => 'cpu_alerts', nlabel => 'vm.limit.cpu.alerts.count', min => 0 }, group => [ { name => 'cpu_alarm', cb_prefix_output => 'prefix_vm_output', skipped_code => { -11 => 1 } } ] }, { name => 'memory_alarms', type => 2,cb_long_output => 'memory_long_output', message_multiple => '0 memory limit problem(s) detected', format_output => '%s memory limit problem(s) detected', display_counter_problem => { label => 'memory_alerts', nlabel => 'vm.limit.memory.alerts.count', min => 0 }, group => [ { name => 'memory_alarm', cb_prefix_output => 'prefix_vm_output', skipped_code => { -11 => 1 } } ] }, { name => 'disk_alarms', type => 2, cb_long_output => 'disk_long_output', message_multiple => '0 disk limit problem(s) detected', format_output => '%s disk limit problem(s) detected', display_counter_problem => { label => 'disk_alerts', nlabel => 'vm.limit.disk.alerts.count', min => 0 }, group => [ { name => 'disk_alarm', cb_prefix_output => 'prefix_vm_output', skipped_code => { -11 => 1 } } ] } ]; $self->{maps_counters}->{cpu_alarm} = [ { label => 'cpu-status', type => 2, critical_default => '%{connection_state} !~ /^connected$/i || %{limit} != -1', set => { key_values => [ { name => 'name' }, { name => 'connection_state' }, { name => 'power_state' }, { name => 'cpu_limit' } ], closure_custom_calc => $self->can('custom_limit_calc'), closure_custom_calc_extra_options => { label_ref => 'cpu' }, closure_custom_output => $self->can('custom_limit_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{memory_alarm} = [ { label => 'memory-status', type => 2, critical_default => '%{connection_state} !~ /^connected$/i || %{limit} != -1', set => { key_values => [ { name => 'name' }, { name => 'connection_state' }, { name => 'power_state' }, { name => 'memory_limit' } ], closure_custom_calc => $self->can('custom_limit_calc'), closure_custom_calc_extra_options => { label_ref => 'memory' }, closure_custom_output => $self->can('custom_limit_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{disk_alarm} = [ { label => 'disk-status', type => 2, critical_default => '%{connection_state} !~ /^connected$/i || %{limit} != -1', set => { key_values => [ { name => 'name' }, { name => 'connection_state' }, { name => 'power_state' }, { name => 'disk_limit' } ], closure_custom_calc => $self->can('custom_limit_calc'), closure_custom_calc_extra_options => { label_ref => 'disk' }, closure_custom_output => $self->can('custom_limit_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub cpu_long_output { my ($self, %options) = @_; return "checking cpu limit"; } sub memory_long_output { my ($self, %options) = @_; return "checking memory limit"; } sub disk_long_output { my ($self, %options) = @_; return "checking disk limit"; } sub prefix_vm_output { my ($self, %options) = @_; my $msg = "Virtual machine '" . $options{instance_value}->{name} . "'"; if (defined($options{instance_value}->{config_annotation})) { $msg .= ' [annotation: ' . $options{instance_value}->{config_annotation} . ']'; } $msg .= ' : '; return $msg; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'vm-hostname:s' => { name => 'vm_hostname' }, 'filter' => { name => 'filter' }, 'filter-description:s' => { name => 'filter_description' }, 'filter-os:s' => { name => 'filter_os' }, 'filter-uuid:s' => { name => 'filter_uuid' }, 'display-description' => { name => 'display_description' }, 'check-disk-limit' => { name => 'check_disk_limit' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $response = $options{custom}->execute( params => $self->{option_results}, command => 'limitvm' ); my $i = 0; $self->{cpu_alarms}->{global} = { cpu_alarm => {} }; $self->{memory_alarms}->{global} = { memory_alarm => {} }; $self->{disk_alarms}->{global} = { disk_alarm => {} } if (defined($self->{option_results}->{check_disk_limit})); foreach my $vm_id (keys %{$response->{data}}) { my $vm_name = $response->{data}->{$vm_id}->{name}; $self->{cpu_alarms}->{global}->{cpu_alarm}->{$i} = { name => $vm_name, config_annotation => defined($self->{option_results}->{display_description}) ? $options{custom}->strip_cr(value => $response->{data}->{$vm_id}->{'config.annotation'}) : undef, connection_state => $response->{data}->{$vm_id}->{connection_state}, power_state => $response->{data}->{$vm_id}->{power_state}, cpu_limit => $response->{data}->{$vm_id}->{'config.cpuAllocation.limit'}, }; $self->{memory_alarms}->{global}->{memory_alarm}->{$i} = { name => $vm_name, config_annotation => defined($self->{option_results}->{display_description}) ? $options{custom}->strip_cr(value => $response->{data}->{$vm_id}->{'config.annotation'}) : undef, connection_state => $response->{data}->{$vm_id}->{connection_state}, power_state => $response->{data}->{$vm_id}->{power_state}, memory_limit => $response->{data}->{$vm_id}->{'config.memoryAllocation.limit'} }; if (defined($self->{option_results}->{check_disk_limit})) { $self->{disk_alarms}->{global}->{disk_alarm}->{$i} = { name => $vm_name, config_annotation => defined($self->{option_results}->{display_description}) ? $options{custom}->strip_cr(value => $response->{data}->{$vm_id}->{'config.annotation'}) : undef, connection_state => $response->{data}->{$vm_id}->{connection_state}, power_state => $response->{data}->{$vm_id}->{power_state}, disk_limit => -1 }; foreach (@{$response->{data}->{$vm_id}->{'config.storageIOAllocation.limit'}}) { if ($_->{limit} != -1) { $self->{disk_alarms}->{global}->{disk_alarm}->{$i}->{disk_limit} = 1; } } } $i++; } } 1; __END__ =head1 MODE Check virtual machine limits. =over 8 =item B<--vm-hostname> VM hostname to check. If not set, we check all VMs. =item B<--filter> VM hostname is a regexp. =item B<--filter-description> Filter also virtual machines description (can be a regexp). =item B<--filter-os> Filter also virtual machines OS name (can be a regexp). =item B<--display-description> Display virtual machine description. =item B<--check-disk-limit> Check disk limits (since vsphere 5.0). =item B<--warning-disk-status> Set warning threshold for status (Default: ''). Can used special variables like: %{connection_state}, %{power_state}, %{limit} =item B<--critical-disk-status> Set critical threshold for status (Default: '%{connection_state} !~ /^connected$/i || %{limit} != -1'). Can used special variables like: %{connection_state}, %{power_state}, %{limit} =item B<--warning-cpu-status> Set warning threshold for status (Default: ''). Can used special variables like: %{connection_state}, %{power_state}, %{limit} =item B<--critical-cpu-status> Set critical threshold for status (Default: '%{connection_state} !~ /^connected$/i || %{limit} != -1'). Can used special variables like: %{connection_state}, %{power_state}, %{limit} =item B<--warning-memory-status> Set warning threshold for status (Default: ''). Can used special variables like: %{connection_state}, %{power_state}, %{limit} =item B<--critical-memory-status> Set critical threshold for status (Default: '%{connection_state} !~ /^connected$/i || %{limit} != -1'). Can used special variables like: %{connection_state}, %{power_state}, %{limit} =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/listclusters.pm000066400000000000000000000045651417000230700255260ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::listclusters; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'cluster:s' => { name => 'cluster' }, 'filter' => { name => 'filter' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my $response = $options{custom}->execute(params => $self->{option_results}, command => 'listclusters'); foreach (keys %{$response->{data}}) { $self->{output}->output_add(long_msg => ' ' . $response->{data}->{$_}->{name}); } $self->{output}->output_add(severity => 'OK', short_msg => 'List cluster(s):'); $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) = @_; my $response = $options{custom}->execute(params => $self->{option_results}, command => 'listclusters'); foreach (keys %{$response->{data}}) { $self->{output}->add_disco_entry(name => $response->{data}->{$_}->{name}); } } 1; __END__ =head1 MODE List clusters. =over 8 =item B<--cluster> Cluster to check. If not set, we check all clusters. =item B<--filter> Cluster is a regexp. =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/listdatacenters.pm000066400000000000000000000047041417000230700261520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::listdatacenters; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'datacenter:s' => { name => 'datacenter' }, 'filter' => { name => 'filter' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my $response = $options{custom}->execute(params => $self->{option_results}, command => 'listdatacenters'); foreach (keys %{$response->{data}}) { $self->{output}->output_add(long_msg => ' ' . $response->{data}->{$_}->{name}); } $self->{output}->output_add(severity => 'OK', short_msg => 'List datacenter(s):'); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); $self->{connector} = $options{custom}; } sub disco_format { my ($self, %options) = @_; $self->{output}->add_disco_format(elements => ['name']); } sub disco_show { my ($self, %options) = @_; my $response = $options{custom}->execute(params => $self->{option_results}, command => 'listdatacenters'); foreach (keys %{$response->{data}}) { $self->{output}->add_disco_entry(name => $response->{data}->{$_}->{name}); } } 1; __END__ =head1 MODE List datacenters. =over 8 =item B<--datacenter> Datacenter to check. If not set, we check all datacenters. =item B<--filter> Datacenter is a regexp. =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/listdatastores.pm000066400000000000000000000056531417000230700260320ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::listdatastores; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'datastore-name:s' => { name => 'datastore_name' }, 'filter' => { name => 'filter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my $response = $options{custom}->execute(params => $self->{option_results}, command => 'listdatastores'); foreach (keys %{$response->{data}}) { $self->{output}->output_add(long_msg => sprintf(" %s [%s] [%s]", $response->{data}->{$_}->{name}, $response->{data}->{$_}->{accessible}, $response->{data}->{$_}->{type})); } $self->{output}->output_add(severity => 'OK', short_msg => 'List datastore(s):'); $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', 'accessible', 'type']); } sub disco_show { my ($self, %options) = @_; my $response = $options{custom}->execute(params => $self->{option_results}, command => 'listdatastores'); foreach (keys %{$response->{data}}) { $self->{output}->add_disco_entry(name => $response->{data}->{$_}->{name}, accessible => $response->{data}->{$_}->{accessible}, type => $response->{data}->{$_}->{type} ); } } 1; __END__ =head1 MODE List datastores. =over 8 =item B<--datastore-name> datastore name to list. =item B<--filter> Datastore name is a regexp. =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/listnichost.pm000066400000000000000000000056071417000230700253270ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::listnichost; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'esx-hostname:s' => { name => 'esx_hostname' }, 'filter' => { name => 'filter' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{esx_hostname}) || $self->{option_results}->{esx_hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Please set option --esx-hostname."); $self->{output}->option_exit(); } } sub run { my ($self, %options) = @_; my $response = $options{custom}->execute(params => $self->{option_results}, command => 'listnichost'); foreach (sort keys %{$response->{data}}) { $self->{output}->output_add(long_msg => sprintf('%s [status: %s] [vswitch: %s]', $response->{data}->{$_}->{name}, $response->{data}->{$_}->{status}, $response->{data}->{$_}->{vswitch}) ); } $self->{output}->output_add(severity => 'OK', short_msg => 'List nic host:'); $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', 'status', 'vswitch']); } sub disco_show { my ($self, %options) = @_; my $response = $options{custom}->execute(params => $self->{option_results}, command => 'listnichost'); foreach (sort keys %{$response->{data}}) { $self->{output}->add_disco_entry(name => $response->{data}->{$_}->{name}, status => $response->{data}->{$_}->{status}, vswitch => $response->{data}->{$_}->{vswitch} ); } } 1; __END__ =head1 MODE List ESX interfaces. =over 8 =item B<--esx-hostname> ESX hostname to check (required). =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/maintenancehost.pm000066400000000000000000000113331417000230700261350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::maintenancehost; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return 'status ' . $self->{result_values}->{status}; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_state'}; return 0; } sub custom_maintenance_output { my ($self, %options) = @_; return 'maintenance mode is ' . $self->{result_values}->{maintenance}; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'host', type => 1, cb_prefix_output => 'prefix_host_output', message_multiple => 'All ESX Hosts are ok' } ]; $self->{maps_counters}->{host} = [ { label => 'status', type => 2, unknown_default => '%{status} !~ /^connected$/i', set => { key_values => [ { name => 'state' } ], 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 => \&catalog_status_threshold_ng } }, { label => 'maintenance-status', type => 2, critical_default => '%{maintenance} !~ /false/', set => { key_values => [ { name => 'maintenance' } ], closure_custom_output => $self->can('custom_maintenance_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub prefix_host_output { my ($self, %options) = @_; return "Host '" . $options{instance_value}->{display} . "' : "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'esx-hostname:s' => { name => 'esx_hostname' }, 'filter' => { name => 'filter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' }, 'scope-cluster:s' => { name => 'scope_cluster' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{host} = {}; my $response = $options{custom}->execute( params => $self->{option_results}, command => 'maintenancehost' ); foreach my $host_id (keys %{$response->{data}}) { my $host_name = $response->{data}->{$host_id}->{name}; $self->{host}->{$host_name} = { display => $host_name, state => $response->{data}->{$host_id}->{state}, maintenance => $response->{data}->{$host_id}->{inMaintenanceMode} }; } } 1; __END__ =head1 MODE Check maintenance mode of ESX hosts. =over 8 =item B<--esx-hostname> ESX hostname to check. If not set, we check all ESX. =item B<--filter> ESX hostname is a regexp. =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =item B<--scope-cluster> Search in following cluster(s) (can be a regexp). =item B<--unknown-status> Set warning threshold for status (Default: '%{status} !~ /^connected$/i'). Can used special variables like: %{status} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{status} =item B<--warning-maintenance-status> Set warning threshold for status (Default: ''). Can used special variables like: %{maintenance} =item B<--critical-maintenance-status> Set critical threshold for status (Default: '%{maintenance} !~ /false/'). Can used special variables like: %{maintenance} =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/memoryhost.pm000066400000000000000000000243311417000230700251650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::memoryhost; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return 'status : ' . $self->{result_values}->{status}; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_state'}; return 0; } sub custom_usage_perfdata { my ($self, %options) = @_; my ($label, $nlabel) = ('used', $self->{nlabel}); my $value_perf = $self->{result_values}->{used}; if (defined($self->{instance_mode}->{option_results}->{free})) { ($label, $nlabel) = ('free', 'host.memory.free.bytes'); $value_perf = $self->{result_values}->{free}; } my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } $self->{output}->perfdata_add( label => $label, unit => 'B', instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, nlabel => $nlabel, 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} ); } sub custom_usage_threshold { my ($self, %options) = @_; my ($exit, $threshold_value); $threshold_value = $self->{result_values}->{used}; $threshold_value = $self->{result_values}->{free} if (defined($self->{instance_mode}->{option_results}->{free})); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; $threshold_value = $self->{result_values}->{prct_free} if (defined($self->{instance_mode}->{option_results}->{free})); } $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel}, 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( "Memory 'consumed' 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'}; if ($self->{result_values}->{total} <= 0) { $self->{error_msg} = 'size is 0'; return -20; } $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_consumed'}; $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 custom_overhead_output { my ($self, %options) = @_; my ($overhead_value, $overhead_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{overhead}); return sprintf( "Memory Overhead: %s", $overhead_value . " " . $overhead_unit ); } sub custom_memstate_output { my ($self, %options) = @_; return 'Memory state is ' . $self->{result_values}->{mem_state_str}; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'host', type => 1, cb_prefix_output => 'prefix_host_output', message_multiple => 'All hosts are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{host} = [ { label => 'status', type => 2, unknown_default => '%{status} !~ /^connected$/i', 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 => \&catalog_status_threshold_ng } }, { label => 'consumed-memory', nlabel => 'host.memory.usage.bytes', set => { key_values => [ { name => 'display' }, { name => 'consumed' }, { 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') } }, { label => 'overhead-memory', nlabel => 'host.memory.overhead.bytes', set => { key_values => [ { name => 'overhead' }, { name => 'display' } ], closure_custom_output => $self->can('custom_overhead_output'), perfdatas => [ { label => 'overhead', template => '%s', unit => 'B', min => 0, label_extra_instance => 1 } ] } }, { label => 'state-memory', nlabel => 'host.memory.state.count', set => { key_values => [ { name => 'mem_state' }, { name => 'mem_state_str' }, { name => 'display' } ], closure_custom_output => $self->can('custom_memstate_output'), perfdatas => [ { label => 'state', template => '%s', min => 0, max => 3, label_extra_instance => 1 } ] } } ]; } sub prefix_host_output { my ($self, %options) = @_; return "Host '" . $options{instance_value}->{display} . "' : "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'esx-hostname:s' => { name => 'esx_hostname' }, 'filter' => { name => 'filter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' }, 'scope-cluster:s' => { name => 'scope_cluster' }, 'units:s' => { name => 'units', default => '%' }, 'free' => { name => 'free' }, 'no-memory-state' => { name => 'no_memory_state' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{host} = {}; my $response = $options{custom}->execute( params => $self->{option_results}, command => 'memhost' ); foreach my $host_id (keys %{$response->{data}}) { my $host_name = $response->{data}->{$host_id}->{name}; $self->{host}->{$host_name} = { display => $host_name, state => $response->{data}->{$host_id}->{state}, consumed => $response->{data}->{$host_id}->{'mem.consumed.average'}, overhead => $response->{data}->{$host_id}->{'mem.overhead.average'}, mem_state => $response->{data}->{$host_id}->{mem_state}, mem_state_str => $response->{data}->{$host_id}->{mem_state_str}, total => $response->{data}->{$host_id}->{mem_size} }; } } 1; __END__ =head1 MODE Check ESX memory usage. =over 8 =item B<--esx-hostname> ESX hostname to check. If not set, we check all ESX. =item B<--filter> ESX hostname is a regexp. =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =item B<--scope-cluster> Search in following cluster(s) (can be a regexp). =item B<--units> Units of thresholds (Default: '%') ('%', 'B'). =item B<--free> Thresholds are on free space left. =item B<--unknown-status> Set warning threshold for status (Default: '%{status} !~ /^connected$/i'). Can used special variables like: %{status} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{status} =item B<--warning-consumed-memory> Threshold warning (can use unit option). =item B<--critical-consumed-memory> Threshold critical (can use unit option). =item B<--warning-overhead-memory> Threshold overhead. =item B<--critical-overhead-memory> Threshold critical. =item B<--warning-state-memory> Threshold warning. For state != 'high': --warning-state=0 =item B<--critical-state-memory> Threshold critical. For state != 'high': --warning-state=0 =item B<--no-memory-state> Don't check memory state. =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/memoryvm.pm000066400000000000000000000331651417000230700246370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::memoryvm; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return '[connection state ' . $self->{result_values}->{connection_state} . '][power state ' . $self->{result_values}->{power_state} . ']'; } sub custom_usage_perfdata { my ($self, %options) = @_; my ($label, $nlabel) = ('used', $self->{nlabel}); my $value_perf = $self->{result_values}->{used}; if (defined($self->{instance_mode}->{option_results}->{free})) { ($label, $nlabel) = ('free', 'vm.memory.' . $self->{result_values}->{label_ref} . '.free.bytes'); $value_perf = $self->{result_values}->{free}; } my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } $self->{output}->perfdata_add( label => $self->{result_values}->{label_ref} . '_' . $label, unit => 'B', instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{instance} : undef, nlabel => $nlabel, 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} ); } sub custom_usage_threshold { my ($self, %options) = @_; my ($exit, $threshold_value); $threshold_value = $self->{result_values}->{used}; $threshold_value = $self->{result_values}->{free} if (defined($self->{instance_mode}->{option_results}->{free})); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; $threshold_value = $self->{result_values}->{prct_free} if (defined($self->{instance_mode}->{option_results}->{free})); } $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel}, 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( 'Memory %s Usage Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)', $self->{result_values}->{label_ref}, $total_size_value . " " . $total_size_unit, $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}, $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free} ); } sub 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}->{label_ref} = $options{extra_options}->{label_ref}; if ($self->{result_values}->{total} <= 0) { $self->{error_msg} = 'size is 0'; return -20; } $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_' . $self->{result_values}->{label_ref}}; $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 custom_overhead_output { my ($self, %options) = @_; my ($value, $unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{overhead}); return sprintf('Memory overhead: %s %s', $value, $unit); } sub custom_ballooning_output { my ($self, %options) = @_; my ($value, $unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{vmmemctl}); return sprintf('Memory ballooning: %s %s', $value, $unit); } sub custom_shared_output { my ($self, %options) = @_; my ($value, $unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{shared}); return sprintf('Memory shared: %s %s', $value, $unit); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'vm', type => 3, cb_prefix_output => 'prefix_vm_output', cb_long_output => 'vm_long_output', indent_long_output => ' ', message_multiple => 'All virtual machines are ok', group => [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'global_consumed', type => 0, skipped_code => { -10 => 1 } }, { name => 'global_active', type => 0, skipped_code => { -10 => 1 } }, { name => 'global_overhead', type => 0, skipped_code => { -10 => 1 } }, { name => 'global_vmmemctl', type => 0, skipped_code => { -10 => 1 } }, { name => 'global_shared', type => 0, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'status', type => 2, unknown_default => '%{connection_state} !~ /^connected$/i or %{power_state} !~ /^poweredOn$/i', set => { key_values => [ { name => 'connection_state' }, { name => 'power_state' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{global_consumed} = [ { label => 'consumed', nlabel => 'vm.memory.consumed.usage.bytes', set => { key_values => [ { name => 'consumed' }, { name => 'total' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { label_ref => 'consumed' }, 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') } } ]; $self->{maps_counters}->{global_active} = [ { label => 'active', nlabel => 'vm.memory.active.usage.bytes', set => { key_values => [ { name => 'active' }, { name => 'total' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { label_ref => 'active' }, 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') } } ]; $self->{maps_counters}->{global_overhead} = [ { label => 'overhead', nlabel => 'vm.memory.overhead.bytes', set => { key_values => [ { name => 'overhead' } ], closure_custom_output => $self->can('custom_overhead_output'), perfdatas => [ { label => 'overhead', template => '%s', unit => 'B', min => 0, label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{global_vmmemctl} = [ { label => 'ballooning', nlabel => 'vm.memory.ballooning.bytes', set => { key_values => [ { name => 'vmmemctl' } ], closure_custom_output => $self->can('custom_ballooning_output'), perfdatas => [ { label => 'ballooning', template => '%s', unit => 'B', min => 0, label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{global_shared} = [ { label => 'shared', nlabel => 'vm.memory.shared.bytes', set => { key_values => [ { name => 'shared' } ], closure_custom_output => $self->can('custom_shared_output'), perfdatas => [ { label => 'shared', template => '%s', unit => 'B', min => 0, label_extra_instance => 1 } ] } } ]; } sub prefix_vm_output { my ($self, %options) = @_; my $msg = "Virtual machine '" . $options{instance_value}->{display} . "'"; if (defined($options{instance_value}->{config_annotation})) { $msg .= ' [annotation: ' . $options{instance_value}->{config_annotation} . ']'; } $msg .= ' : '; return $msg; } sub vm_long_output { my ($self, %options) = @_; my $msg = "checking virtual machine '" . $options{instance_value}->{display} . "'"; if (defined($options{instance_value}->{config_annotation})) { $msg .= ' [annotation: ' . $options{instance_value}->{config_annotation} . ']'; } return $msg; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'vm-hostname:s' => { name => 'vm_hostname' }, 'filter' => { name => 'filter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' }, 'scope-cluster:s' => { name => 'scope_cluster' }, 'scope-host:s' => { name => 'scope_host' }, 'filter-description:s' => { name => 'filter_description' }, 'filter-os:s' => { name => 'filter_os' }, 'filter-uuid:s' => { name => 'filter_uuid' }, 'display-description' => { name => 'display_description' }, 'units:s' => { name => 'units', default => '%' }, 'free' => { name => 'free' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{vm} = {}; my $response = $options{custom}->execute( params => $self->{option_results}, command => 'memvm' ); foreach my $vm_id (keys %{$response->{data}}) { my $vm_name = $response->{data}->{$vm_id}->{name}; $self->{vm}->{$vm_name} = { display => $vm_name, global => { connection_state => $response->{data}->{$vm_id}->{connection_state}, power_state => $response->{data}->{$vm_id}->{power_state} } }; foreach (('consumed', 'active', 'overhead', 'vmmemctl', 'shared')) { next if (!defined($response->{data}->{$vm_id}->{'mem.' . $_ . '.average'})); $self->{vm}->{$vm_name}->{'global_' . $_} = { $_ => $response->{data}->{$vm_id}->{'mem.' . $_ . '.average'}, total => $response->{data}->{$vm_id}->{memory_size} }; } if (defined($self->{option_results}->{display_description})) { $self->{vm}->{$vm_name}->{config_annotation} = $options{custom}->strip_cr(value => $response->{data}->{$vm_id}->{'config.annotation'}); } } } 1; __END__ =head1 MODE Check virtual machine memory. =over 8 =item B<--vm-hostname> VM hostname to check. If not set, we check all VMs. =item B<--filter> VM hostname is a regexp. =item B<--filter-description> Filter also virtual machines description (can be a regexp). =item B<--filter-os> Filter also virtual machines OS name (can be a regexp). =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =item B<--scope-cluster> Search in following cluster(s) (can be a regexp). =item B<--scope-host> Search in following host(s) (can be a regexp). =item B<--display-description> Display virtual machine description. =item B<--unknown-status> Set warning threshold for status (Default: '%{connection_state} !~ /^connected$/i or %{power_state} !~ /^poweredOn$/i'). Can used special variables like: %{connection_state}, %{power_state} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{connection_state}, %{power_state} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{connection_state}, %{power_state} =item B<--units> Units of thresholds (Default: '%') ('%', 'B'). =item B<--free> Thresholds are on free space left. =item B<--warning-*> Threshold warning. Can be: 'consumed', 'active', 'overhead', 'ballooning', 'shared'. =item B<--critical-*> Threshold critical. Can be: 'consumed', 'active', 'overhead', 'ballooning', 'shared'. =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/nethost.pm000066400000000000000000000434461417000230700244530ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::nethost; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return 'status ' . $self->{result_values}->{status}; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_state'}; return 0; } sub custom_linkstatus_output { my ($self, %options) = @_; return 'status ' . $self->{result_values}->{link_status}; } sub custom_linkstatus_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{link_status} = $options{new_datas}->{$self->{instance} . '_status'}; return 0; } sub custom_traffic_output { my ($self, %options) = @_; my ($value, $unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{traffic}, network => 1); return sprintf( "traffic %s: %s/s (%.2f %%)", $self->{result_values}->{label_ref}, $value . $unit, $self->{result_values}->{traffic_prct} ); } sub custom_traffic_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{speed} = $options{new_datas}->{$self->{instance} . '_speed'}; $self->{result_values}->{traffic} = $options{new_datas}->{$self->{instance} . '_traffic_' . $options{extra_options}->{label_ref}}; $self->{result_values}->{label_ref} = $options{extra_options}->{label_ref}; $self->{result_values}->{traffic_prct} = $self->{result_values}->{traffic} * 100 / $self->{result_values}->{speed}; return 0; } sub custom_dropped_output { my ($self, %options) = @_; return sprintf( 'packets %s dropped: %.2f %% (%d/%d packets)', $self->{result_values}->{label_ref}, $self->{result_values}->{dropped_prct}, $self->{result_values}->{dropped}, $self->{result_values}->{packets} ); } sub custom_dropped_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{dropped} = $options{new_datas}->{$self->{instance} . '_dropped_' . $options{extra_options}->{label_ref}}; $self->{result_values}->{packets} = $options{new_datas}->{$self->{instance} . '_packets_' . $options{extra_options}->{label_ref}}; $self->{result_values}->{label_ref} = $options{extra_options}->{label_ref}; $self->{result_values}->{dropped_prct} = 0; if ($self->{result_values}->{packets} > 0) { $self->{result_values}->{dropped_prct} = $self->{result_values}->{dropped} * 100 / $self->{result_values}->{packets}; } return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'host', type => 3, cb_prefix_output => 'prefix_host_output', cb_long_output => 'host_long_output', indent_long_output => ' ', message_multiple => 'All ESX hosts are ok', group => [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'global_host', type => 0, skipped_code => { -10 => 1 } }, { name => 'pnic', cb_prefix_output => 'prefix_pnic_output', message_multiple => 'All physical interfaces are ok', type => 1, skipped_code => { -10 => 1 } }, { name => 'vswitch', cb_prefix_output => 'prefix_vswitch_output', message_multiple => 'All vswitchs are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'status', type => 2, unknown_default => '%{status} !~ /^connected$/i', set => { key_values => [ { name => 'state' } ], 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 => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{global_host} = [ { label => 'host-traffic-in', nlabel => 'host.traffic.in.bitsperseconds', set => { key_values => [ { name => 'traffic_in' } ], output_template => 'host traffic in: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'host_traffic_in', template => '%s', unit => 'b/s', min => 0, label_extra_instance => 1 } ] } }, { label => 'host-traffic-out', nlabel => 'host.traffic.out.bitsperseconds', set => { key_values => [ { name => 'traffic_out' } ], output_template => 'host traffic out: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'host_traffic_out', template => '%s', unit => 'b/s', min => 0, label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{vswitch} = [ { label => 'vswitch-traffic-in', nlabel => 'host.vswitch.traffic.in.bitsperseconds', set => { key_values => [ { name => 'traffic_in' } ], output_template => 'traffic in: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'vswitch_traffic_in', template => '%s', unit => 'b/s', min => 0, label_extra_instance => 1 } ] } }, { label => 'vswitch-traffic-out', nlabel => 'host.vswitch.traffic.out.bitsperseconds', set => { key_values => [ { name => 'traffic_out' } ], output_template => 'traffic out: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'vswitch_traffic_out', template => '%s', unit => 'b/s', min => 0, label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{pnic} = [ { label => 'link-status', type => 2, critical_default => '%{link_status} !~ /up/', set => { key_values => [ { name => 'status' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_linkstatus_calc'), closure_custom_output => $self->can('custom_linkstatus_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'link-traffic-in', nlabel => 'host.traffic.in.bitsperseconds', set => { key_values => [ { name => 'display' }, { name => 'traffic_in' }, { name => 'speed' } ], closure_custom_calc => $self->can('custom_traffic_calc'), closure_custom_calc_extra_options => { label_ref => 'in' }, closure_custom_output => $self->can('custom_traffic_output'), threshold_use => 'traffic_prct', perfdatas => [ { label => 'traffic_in', value => 'traffic', template => '%s', unit => 'b/s', min => 0, max => 'speed', threshold_total => 'speed', cast_int => 1, label_extra_instance => 1 } ] } }, { label => 'link-traffic-out', nlabel => 'host.traffic.out.bitsperseconds', set => { key_values => [ { name => 'display' }, { name => 'traffic_out' }, { name => 'speed' } ], closure_custom_calc => $self->can('custom_traffic_calc'), closure_custom_calc_extra_options => { label_ref => 'out' }, closure_custom_output => $self->can('custom_traffic_output'), threshold_use => 'traffic_prct', perfdatas => [ { label => 'traffic_out', value => 'traffic', template => '%s', unit => 'b/s', min => 0, max => 'speed', threshold_total => 'speed', cast_int => 1, label_extra_instance => 1 } ] } }, { label => 'link-dropped-in', nlabel => 'host.packets.in.dropped.percentage', set => { key_values => [ { name => 'display' }, { name => 'packets_in' }, { name => 'dropped_in' } ], closure_custom_calc => $self->can('custom_dropped_calc'), closure_custom_calc_extra_options => { label_ref => 'in' }, closure_custom_output => $self->can('custom_dropped_output'), threshold_use => 'dropped_prct', perfdatas => [ { label => 'packets_dropped_in', value => 'dropped_prct', template => '%s', unit => '%', min => 0, max => 100, label_extra_instance => 1 } ] } }, { label => 'link-dropped-out', nlabel => 'host.packets.out.dropped.percentage', set => { key_values => [ { name => 'display' }, { name => 'packets_out' }, { name => 'dropped_out' } ], closure_custom_calc => $self->can('custom_dropped_calc'), closure_custom_calc_extra_options => { label_ref => 'out' }, closure_custom_output => $self->can('custom_dropped_output'), threshold_use => 'dropped_prct', perfdatas => [ { label => 'packets_dropped_out', value => 'dropped_prct', template => '%s', unit => '%', min => 0, max => 100, label_extra_instance => 1 } ] } } ]; } sub prefix_host_output { my ($self, %options) = @_; return "Host '" . $options{instance_value}->{display} . "' : "; } sub host_long_output { my ($self, %options) = @_; return "checking host '" . $options{instance_value}->{display} . "'"; } sub prefix_pnic_output { my ($self, %options) = @_; return "physical interface '" . $options{instance_value}->{display} . "' "; } sub prefix_vswitch_output { my ($self, %options) = @_; return "vswitch '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'esx-hostname:s' => { name => 'esx_hostname' }, 'nic-name:s' => { name => 'nic_name' }, 'filter' => { name => 'filter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' }, 'scope-cluster:s' => { name => 'scope_cluster' }, 'no-proxyswitch' => { name => 'no_proxyswitch' }, 'filter-vswitch-name:s' => { name => 'filter_vswitch_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{host} = {}; my $response = $options{custom}->execute( params => $self->{option_results}, command => 'nethost' ); foreach my $host_id (keys %{$response->{data}}) { my $host_name = $response->{data}->{$host_id}->{name}; $self->{host}->{$host_name} = { display => $host_name, global => { state => $response->{data}->{$host_id}->{state} }, global_host => { traffic_in => 0, traffic_out => 0 } }; foreach my $pnic_name (sort keys %{$response->{data}->{$host_id}->{pnic}}) { $self->{host}->{$host_name}->{pnic} = {} if (!defined($self->{host}->{$host_name}->{pnic})); next if (defined($self->{option_results}->{nic_name}) && $self->{option_results}->{nic_name} ne '' && $pnic_name !~ /$self->{option_results}->{nic_name}/); my $filtered = 1; if (defined($self->{option_results}->{filter_vswitch_name}) && $self->{option_results}->{filter_vswitch_name} ne '') { $filtered = 0; foreach my $vswitch_name (keys %{$response->{data}->{$host_id}->{vswitch}}) { next if (!defined($response->{data}->{$host_id}->{vswitch}->{$vswitch_name}->{pnic})); next if ($vswitch_name !~ /$self->{option_results}->{filter_vswitch_name}/); foreach (@{$response->{data}->{$host_id}->{vswitch}->{$vswitch_name}->{pnic}}) { $filtered = 1 if ($_ eq $response->{data}->{$host_id}->{pnic}->{$pnic_name}->{key}); } } } next if ($filtered == 0); $self->{host}->{$host_name}->{pnic}->{$pnic_name} = { display => $pnic_name, status => $response->{data}->{$host_id}->{pnic}->{$pnic_name}->{status} , traffic_in => $response->{data}->{$host_id}->{pnic}->{$pnic_name}->{'net.received.average'}, traffic_out => $response->{data}->{$host_id}->{pnic}->{$pnic_name}->{'net.transmitted.average'}, speed => defined($response->{data}->{$host_id}->{pnic}->{$pnic_name}->{speed}) ? $response->{data}->{$host_id}->{pnic}->{$pnic_name}->{speed} * 1024 * 1024 : undef, , packets_in => $response->{data}->{$host_id}->{pnic}->{$pnic_name}->{'net.packetsRx.summation'}, packets_out => $response->{data}->{$host_id}->{pnic}->{$pnic_name}->{'net.packetsTx.summation'}, dropped_in => $response->{data}->{$host_id}->{pnic}->{$pnic_name}->{'net.droppedRx.summation'}, dropped_out => $response->{data}->{$host_id}->{pnic}->{$pnic_name}->{'net.droppedTx.summation'} }; next if (!defined($response->{data}->{$host_id}->{pnic}->{$pnic_name}->{speed})); foreach my $vswitch_name (keys %{$response->{data}->{$host_id}->{vswitch}}) { next if (!defined($response->{data}->{$host_id}->{vswitch}->{$vswitch_name}->{pnic})); foreach (@{$response->{data}->{$host_id}->{vswitch}->{$vswitch_name}->{pnic}}) { if ($_ eq $response->{data}->{$host_id}->{pnic}->{$pnic_name}->{key}) { $self->{host}->{$host_name}->{vswitch} = {} if (!defined($self->{host}->{$host_name}->{vswitch})); $self->{host}->{$host_name}->{vswitch}->{$vswitch_name} = { display => $vswitch_name, traffic_in => 0, traffic_out => 0 } if (!defined($self->{host}->{$host_name}->{vswitch}->{$vswitch_name})); $self->{host}->{$host_name}->{vswitch}->{$vswitch_name}->{traffic_in} += $response->{data}->{$host_id}->{pnic}->{$pnic_name}->{'net.received.average'}; $self->{host}->{$host_name}->{vswitch}->{$vswitch_name}->{traffic_out} += $response->{data}->{$host_id}->{pnic}->{$pnic_name}->{'net.transmitted.average'}; } } } $self->{host}->{$host_name}->{global_host}->{traffic_in} += $response->{data}->{$host_id}->{pnic}->{$pnic_name}->{'net.received.average'} if (defined($response->{data}->{$host_id}->{pnic}->{$pnic_name}->{'net.received.average'})); $self->{host}->{$host_name}->{global_host}->{traffic_out} += $response->{data}->{$host_id}->{pnic}->{$pnic_name}->{'net.transmitted.average'} if (defined($response->{data}->{$host_id}->{pnic}->{$pnic_name}->{'net.transmitted.average'})); } } } 1; __END__ =head1 MODE Check ESX net usage. =over 8 =item B<--esx-hostname> ESX hostname to check. If not set, we check all ESX. =item B<--filter> ESX hostname is a regexp. =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =item B<--scope-cluster> Search in following cluster(s) (can be a regexp). =item B<--nic-name> ESX nic to check. If not set, we check all nics. =item B<--filter-vswitch-name> Filter vswitch by name. It monitors only ESX nic that belongs to the filtered vswitches. =item B<--unknown-status> Set warning threshold for status (Default: '%{status} !~ /^connected$/i'). Can used special variables like: %{status} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{status} =item B<--unknown-link-status> Set warning threshold for status. Can used special variables like: %{link_status}, %{display} =item B<--warning-link-status> Set warning threshold for status. Can used special variables like: %{link_status}, %{display} =item B<--critical-link-status> Set critical threshold for status (Default: '%{link_status} !~ /up/'). Can used special variables like: %{link_status}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'host-traffic-in' (b/s), 'host-traffic-out' (b/s), 'vswitch-traffic-in' (b/s), 'vswitch-traffic-out' (b/s), 'link-traffic-in' (%), 'link-traffic-out' (%), 'link-dropped-in', 'link-dropped-out'. =item B<--no-proxyswitch> Use the following option if you are checking an ESX 3.x version (it's mandatory). =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/netvm.pm000066400000000000000000000337471417000230700241230ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::netvm; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return '[connection state ' . $self->{result_values}->{connection_state} . '][power state ' . $self->{result_values}->{power_state} . ']'; } sub custom_traffic_perfdata { my ($self, %options) = @_; my ($warning, $critical); if ($self->{instance_mode}->{option_results}->{units_traffic} eq '%' && defined($self->{result_values}->{speed})) { $warning = $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, total => $self->{result_values}->{speed}, cast_int => 1); $critical = $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, total => $self->{result_values}->{speed}, cast_int => 1); } elsif ($self->{instance_mode}->{option_results}->{units_traffic} eq 'b/s') { $warning = $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}); $critical = $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}); } $self->{output}->perfdata_add( unit => 'b/s', nlabel => $self->{nlabel}, instances => $self->{instance}, value => sprintf("%.2f", $self->{result_values}->{traffic}), warning => $warning, critical => $critical, min => 0, max => $self->{result_values}->{speed} ); } sub custom_traffic_threshold { my ($self, %options) = @_; my $exit = 'ok'; if ($self->{instance_mode}->{option_results}->{units_traffic} eq '%' && defined($self->{result_values}->{speed})) { $exit = $self->{perfdata}->threshold_check( value => $self->{result_values}->{traffic_prct}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' }, { label => 'unknown-' . $self->{thlabel}, exit_litteral => 'unknown' } ] ); } elsif ($self->{instance_mode}->{option_results}->{units_traffic} eq 'b/s') { $exit = $self->{perfdata}->threshold_check( value => $self->{result_values}->{traffic}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' }, { label => 'unknown-' . $self->{thlabel}, exit_litteral => 'unknown' } ] ); } return $exit; } sub custom_traffic_output { my ($self, %options) = @_; my ($traffic_value, $traffic_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{traffic}, network => 1); my ($total_value, $total_unit); if (defined($self->{result_values}->{speed}) && $self->{result_values}->{speed} =~ /[0-9]/) { ($total_value, $total_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{speed}, network => 1); } return sprintf( 'traffic %s : %s/s (%s on %s)', $self->{result_values}->{label}, $traffic_value . $traffic_unit, defined($self->{result_values}->{traffic_prct}) ? sprintf("%.2f%%", $self->{result_values}->{traffic_prct}) : '-', defined($total_value) ? $total_value . $total_unit : '-' ); } sub custom_traffic_calc { my ($self, %options) = @_; $self->{result_values}->{label} = $options{extra_options}->{label_ref}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{traffic} = $options{new_datas}->{$self->{instance} . '_traffic_' . $self->{result_values}->{label}}; if (defined($self->{instance_mode}->{option_results}->{ 'speed_' . $self->{result_values}->{label} }) && $self->{instance_mode}->{option_results}->{ 'speed_' . $self->{result_values}->{label} } =~ /[0-9]/) { $self->{result_values}->{traffic_prct} = $self->{result_values}->{traffic} * 100 / ($self->{instance_mode}->{option_results}->{'speed_' . $self->{result_values}->{label}} * 1000 * 1000); $self->{result_values}->{speed} = $self->{instance_mode}->{option_results}->{ 'speed_' . $self->{result_values}->{label} } * 1000 * 1000; } return 0; } sub vm_long_output { my ($self, %options) = @_; return "checking virtual machine '" . $options{instance_value}->{display} . "'"; } sub prefix_vm_output { my ($self, %options) = @_; my $msg = "Virtual machine '" . $options{instance_value}->{display} . "'"; if (defined($options{instance_value}->{config_annotation})) { $msg .= ' [annotation: ' . $options{instance_value}->{config_annotation} . ']'; } $msg .= ': '; return $msg; } sub prefix_interface_output { my ($self, %options) = @_; return "interface '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'vm', type => 3, cb_prefix_output => 'prefix_vm_output', cb_long_output => 'vm_long_output', indent_long_output => ' ', message_multiple => 'All virtual machines are ok', group => [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'global_vm', type => 0, skipped_code => { -10 => 1 } }, { name => 'interfaces', cb_prefix_output => 'prefix_interface_output', message_multiple => 'All interfaces are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'status', type => 2, unknown_default => '%{connection_state} !~ /^connected$/i or %{power_state} !~ /^poweredOn$/i', set => { key_values => [ { name => 'connection_state' }, { name => 'power_state' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{global_vm} = [ { label => 'vm-traffic-in', nlabel => 'vm.traffic.in.bitsperseconds', set => { key_values => [ { name => 'traffic_in' } ], output_template => 'traffic in: %s %s/s', output_change_bytes => 2, perfdatas => [ { template => '%s', unit => 'b/s', min => 0, label_extra_instance => 1 } ] } }, { label => 'vm-traffic-out', nlabel => 'vm.traffic.out.bitsperseconds', set => { key_values => [ { name => 'traffic_out' } ], output_template => 'traffic out: %s %s/s', output_change_bytes => 2, perfdatas => [ { template => '%s', unit => 'b/s', min => 0, label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{interfaces} = [ { label => 'interface-traffic-in', nlabel => 'vm.interface.traffic.in.bitsperseconds', set => { key_values => [ { name => 'display' }, { name => 'traffic_in' }, { name => 'speed_in' } ], closure_custom_calc => $self->can('custom_traffic_calc'), closure_custom_calc_extra_options => { label_ref => 'in' }, closure_custom_output => $self->can('custom_traffic_output'), closure_custom_perfdata => $self->can('custom_traffic_perfdata'), closure_custom_threshold_check => $self->can('custom_traffic_threshold') } }, { label => 'interface-traffic-out', nlabel => 'vm.interface.traffic.out.bitsperseconds', set => { key_values => [ { name => 'display' }, { name => 'traffic_out' }, { name => 'speed_out' } ], closure_custom_calc => $self->can('custom_traffic_calc'), closure_custom_calc_extra_options => { label_ref => 'out' }, closure_custom_output => $self->can('custom_traffic_output'), closure_custom_perfdata => $self->can('custom_traffic_perfdata'), closure_custom_threshold_check => $self->can('custom_traffic_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 => { 'vm-hostname:s' => { name => 'vm_hostname' }, 'filter' => { name => 'filter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' }, 'scope-cluster:s' => { name => 'scope_cluster' }, 'scope-host:s' => { name => 'scope_host' }, 'filter-description:s' => { name => 'filter_description' }, 'filter-os:s' => { name => 'filter_os' }, 'filter-uuid:s' => { name => 'filter_uuid' }, 'display-description' => { name => 'display_description' },, 'filter-interface-name:s' => { name => 'filter_interface_name' }, 'speed-in:s' => { name => 'speed_in' }, 'speed-out:s' => { name => 'speed_out' }, 'units-traffic:s' => { name => 'units_traffic', default => '%' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $response = $options{custom}->execute( params => $self->{option_results}, command => 'netvm' ); $self->{vm} = {}; foreach my $vm_id (keys %{$response->{data}}) { my $vm_name = $response->{data}->{$vm_id}->{name}; $self->{vm}->{$vm_name} = { display => $vm_name, global => { connection_state => $response->{data}->{$vm_id}->{connection_state}, power_state => $response->{data}->{$vm_id}->{power_state}, }, global_vm => { traffic_in => 0, traffic_out => 0 } }; if (defined($self->{option_results}->{display_description})) { $self->{vm}->{$vm_name}->{config_annotation} = $options{custom}->strip_cr(value => $response->{data}->{$vm_id}->{'config.annotation'}); } foreach my $interface_name (sort keys %{$response->{data}->{$vm_id}->{interfaces}}) { next if (defined($self->{option_results}->{filter_interface_name}) && $self->{option_results}->{filter_interface_name} ne '' && $interface_name !~ /$self->{option_results}->{filter_interface_name}/); $self->{vm}->{$vm_name}->{interfaces} = {} if (!defined($self->{vm}->{$vm_name}->{interfaces})); $self->{vm}->{$vm_name}->{interfaces}->{$interface_name} = { display => $interface_name, traffic_in => $response->{data}->{$vm_id}->{interfaces}->{$interface_name}->{'net.received.average'}, traffic_out => $response->{data}->{$vm_id}->{interfaces}->{$interface_name}->{'net.transmitted.average'}, speed_in => defined($self->{option_results}->{speed_in}) ? $self->{option_results}->{speed_in} : '', speed_out => defined($self->{option_results}->{speed_in}) ? $self->{option_results}->{speed_out} : '' }; $self->{vm}->{$vm_name}->{global_vm}->{traffic_in} += $response->{data}->{$vm_id}->{interfaces}->{$interface_name}->{'net.received.average'}; $self->{vm}->{$vm_name}->{global_vm}->{traffic_out} += $response->{data}->{$vm_id}->{interfaces}->{$interface_name}->{'net.transmitted.average'}; } } } 1; __END__ =head1 MODE Check virtual machine interfaces. =over 8 =item B<--vm-hostname> VM hostname to check. If not set, we check all VMs. =item B<--filter> VM hostname is a regexp. =item B<--filter-description> Filter also virtual machines description (can be a regexp). =item B<--filter-os> Filter also virtual machines OS name (can be a regexp). =item B<--filter-interface-name> Virtual machine interface to check. =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =item B<--scope-cluster> Search in following cluster(s) (can be a regexp). =item B<--scope-host> Search in following host(s) (can be a regexp). =item B<--display-description> Display virtual machine description. =item B<--unknown-status> Set warning threshold for status (Default: '%{connection_state} !~ /^connected$/i or %{power_state} !~ /^poweredOn$/i'). Can used special variables like: %{connection_state}, %{power_state} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{connection_state}, %{power_state} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{connection_state}, %{power_state} =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<--units-traffic> Units of thresholds for the traffic (Default: '%') ('%', 'b/s'). =item B<--warning-*> Threshold warning. Can be: 'swap-in', 'swap-out'. =item B<--critical-*> Threshold critical. Can be: 'swap-in', 'swap-out'. =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/servicehost.pm000066400000000000000000000147541417000230700253250ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::servicehost; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return 'status ' . $self->{result_values}->{status} . ', maintenance mode is ' . $self->{result_values}->{maintenance}; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_state'}; $self->{result_values}->{maintenance} = $options{new_datas}->{$self->{instance} . '_maintenance'}; return 0; } sub custom_service_output { my ($self, %options) = @_; return '[policy ' . $self->{result_values}->{policy} . '][running ' . $self->{result_values}->{running} . ']'; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'host', type => 3, cb_prefix_output => 'prefix_host_output', cb_long_output => 'host_long_output', indent_long_output => ' ', message_multiple => 'All ESX hosts are ok', group => [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'service', cb_prefix_output => 'prefix_service_output', message_multiple => 'All services are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'status', type => 2, unknown_default => '%{status} !~ /^connected$/i && %{maintenance} =~ /false/i', set => { key_values => [ { name => 'state' }, { name => 'maintenance' } ], 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 => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{service} = [ { label => 'service-status', type => 2, critical_default => '%{policy} =~ /^on|automatic/i && !%{running}', set => { key_values => [ { name => 'display' }, { name => 'policy' }, { name => 'running' }, { name => 'key' } ], closure_custom_output => $self->can('custom_service_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub prefix_host_output { my ($self, %options) = @_; return "Host '" . $options{instance_value}->{display} . "' : "; } sub host_long_output { my ($self, %options) = @_; return "checking host '" . $options{instance_value}->{display} . "'"; } sub prefix_service_output { my ($self, %options) = @_; return "service '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'esx-hostname:s' => { name => 'esx_hostname' }, 'filter' => { name => 'filter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' }, 'scope-cluster:s' => { name => 'scope_cluster' }, 'filter-services:s' => { name => 'filter_services' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{host} = {}; my $response = $options{custom}->execute( params => $self->{option_results}, command => 'servicehost' ); foreach my $host_id (keys %{$response->{data}}) { my $host_name = $response->{data}->{$host_id}->{name}; $self->{host}->{$host_name} = { display => $host_name, global => { state => $response->{data}->{$host_id}->{state}, maintenance => $response->{data}->{$host_id}->{inMaintenanceMode} } }; foreach (@{$response->{data}->{$host_id}->{services}}) { next if (defined($self->{option_results}->{filter_services}) && $self->{option_results}->{filter_services} ne '' && $_->{key} !~ /$self->{option_results}->{filter_services}/); $self->{host}->{$host_name}->{service} = {} if (!defined($self->{host}->{$host_name}->{service})); $self->{host}->{$host_name}->{service}->{$_->{label}} = { display => $_->{label}, policy => $_->{policy}, running => $_->{running}, key => $_->{key} }; } } } 1; __END__ =head1 MODE Check ESX services. =over 8 =item B<--esx-hostname> ESX hostname to check. If not set, we check all ESX. =item B<--filter> ESX hostname is a regexp. =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =item B<--scope-cluster> Search in following cluster(s) (can be a regexp). =item B<--filter-services> Filter services you want to check (can be a regexp). =item B<--unknown-status> Set warning threshold for status (Default: '%{status} !~ /^connected$/i && %{maintenance} =~ /false/i'). Can used special variables like: %{status} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{status} =item B<--warning-service-status> Set warning threshold for status (Default: ''). Can used special variables like: %{running}, %{label}, %{policy} =item B<--critical-service-status> Set critical threshold for status (Default: '%{policy} =~ /^on|automatic/i && !%{running}'). Can used special variables like: %{running}, %{label}, %{policy} =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/snapshotvm.pm000066400000000000000000000230601417000230700251570ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::snapshotvm; use base qw(centreon::plugins::mode); use strict; use warnings; use Date::Parse; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'vm-hostname:s' => { name => 'vm_hostname' }, 'filter' => { name => 'filter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' }, 'scope-cluster:s' => { name => 'scope_cluster' }, 'scope-host:s' => { name => 'scope_host' }, 'filter-description:s' => { name => 'filter_description' }, 'filter-os:s' => { name => 'filter_os' }, 'filter-uuid:s' => { name => 'filter_uuid' }, 'display-description' => { name => 'display_description' }, 'check-consolidation' => { name => 'check_consolidation' }, 'nopoweredon-skip' => { name => 'nopoweredon_skip' }, 'empty-continue' => { name => 'empty_continue' }, 'warning:s' => { name => 'warning' }, 'critical:s' => { name => 'critical' }, 'disconnect-status:s' => { name => 'disconnect_status', default => 'unknown' }, 'unit:s' => { name => 'unit', default => 's' } }); return $self; } my $unitdiv = { s => ['seconds', 1], w => ['weeks', 604800], d => ['days', 86400], h => ['hours', 3600], m => ['minutes', 60] }; sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); foreach my $label (('warning', 'critical')) { if (($self->{perfdata}->threshold_validate(label => $label, value => $self->{option_results}->{$label})) == 0) { my ($label_opt) = $label; $label_opt =~ tr/_/-/; $self->{output}->add_option_msg(short_msg => "Wrong " . $label_opt . " threshold '" . $self->{option_results}->{$label} . "'."); $self->{output}->option_exit(); } } if ($self->{output}->is_litteral_status(status => $self->{option_results}->{disconnect_status}) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong disconnect-status option '" . $self->{option_results}->{disconnect_status} . "'."); $self->{output}->option_exit(); } if ($self->{option_results}->{unit} eq '' || !defined($unitdiv->{$self->{option_results}->{unit}})) { $self->{option_results}->{unit} = 's'; } } sub run { my ($self, %options) = @_; my $response = $options{custom}->execute( params => $self->{option_results}, command => 'snapshotvm' ); my $multiple = 0; my %vm_consolidate = (); my %vm_errors = (warning => {}, critical => {}); if (scalar(keys %{$response->{data}}) > 1) { $multiple = 1; } if ($multiple == 1) { $self->{output}->output_add( severity => 'OK', short_msg => sprintf("All snapshots are ok") ); } else { $self->{output}->output_add( severity => 'OK', short_msg => sprintf("Snapshot(s) OK") ); } foreach my $vm_id (sort keys %{$response->{data}}) { my $vm_name = $response->{data}->{$vm_id}->{name}; if ($options{custom}->entity_is_connected(state => $response->{data}->{$vm_id}->{connection_state}) == 0) { my $output = "VM '" . $vm_name . "' not connected. Current Connection State: '$response->{data}->{$vm_id}->{connection_state}'."; if ($multiple == 0 || !$self->{output}->is_status(value => $self->{option_results}->{disconnect_status}, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $self->{option_results}->{disconnect_status}, short_msg => $output ); } next; } next if (defined($self->{option_results}->{nopoweredon_skip}) && $options{custom}->vm_is_running(power => $response->{data}->{$vm_id}->{power_state}) == 0); if (defined($self->{check_consolidation}) && defined($response->{data}->{$vm_id}->{consolidation_needed}) && $response->{data}->{$vm_id}->{consolidation_needed} == 1) { $vm_consolidate{$response->{data}->{$vm_id}->{name}} = 1; } foreach (@{$response->{data}->{$vm_id}->{snapshosts}}) { my $create_time = Date::Parse::str2time($_->{create_time}); if (!defined($create_time)) { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => "Can't Parse date '" . $_->{create_time} . "' for vm '" . $vm_name . "'" ); next; } my $diff_time = time() - $create_time; my $days = int($diff_time / 60 / 60 / 24); my $exit = $self->{perfdata}->threshold_check(value => ($diff_time / $unitdiv->{$self->{option_results}->{unit}}->[1]), threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); my $prefix_msg = "'$vm_name'"; if (defined($self->{display_description}) && defined($response->{data}->{$vm_id}->{'config.annotation'}) && $response->{data}->{$vm_id}->{'config.annotation'} ne '') { $prefix_msg .= ' [' . $options{custom}->strip_cr(value => $response->{data}->{$vm_id}->{'config.annotation'}) . ']'; } my $suffix_msg = ''; if (defined($_->{description}) && $_->{description} ne '') { $suffix_msg = ' [' . $options{custom}->strip_cr(value => $_->{description}) . ']'; } if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $vm_errors{$exit}->{$vm_name} = 1; $self->{output}->output_add(long_msg => "$prefix_msg snapshot create time: " . $_->{create_time} . $suffix_msg); } } } $self->{output}->perfdata_add( label => 'num_warning', nlabel => 'vm.snapshots.warning.current.count', value => scalar(keys %{$vm_errors{warning}}), min => 0 ); $self->{output}->perfdata_add( label => 'num_critical', nlabel => 'vm.snapshots.critical.current.count', value => scalar(keys %{$vm_errors{critical}}), min => 0 ); if (scalar(keys %{$vm_errors{warning}}) > 0) { $self->{output}->output_add( severity => 'WARNING', short_msg => sprintf( 'Snapshots for VM older than %d %s: [%s]', $self->{option_results}->{warning}, $unitdiv->{$self->{option_results}->{unit}}->[0], join('] [', sort keys %{$vm_errors{warning}}) ) ); } if (scalar(keys %{$vm_errors{critical}}) > 0) { $self->{output}->output_add( severity => 'CRITICAL', short_msg => sprintf( 'Snapshots for VM older than %d %s: [%s]', $self->{option_results}->{critical}, $unitdiv->{$self->{option_results}->{unit}}->[0], join('] [', sort keys %{$vm_errors{critical}}) ) ); } if (scalar(keys %vm_consolidate) > 0) { $self->{output}->output_add( severity => 'CRITICAL', short_msg => sprintf( 'VMs need consolidation: [%s]', join('] [', sort keys %vm_consolidate) ) ); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check virtual machine snapshots. =over 8 =item B<--vm-hostname> VM hostname to check. If not set, we check all VMs. =item B<--filter> VM hostname is a regexp. =item B<--filter-description> Filter also virtual machines description (can be a regexp). =item B<--filter-os> Filter also virtual machines OS name (can be a regexp). =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =item B<--scope-cluster> Search in following cluster(s) (can be a regexp). =item B<--scope-host> Search in following host(s) (can be a regexp). =item B<--display-description> Display virtual machine description. =item B<--check-consolidation> Check if VM needs consolidation (since vsphere 5.0). =item B<--disconnect-status> Status if VM disconnected (default: 'unknown'). =item B<--nopoweredon-skip> Skip check if VM is not poweredOn. =item B<--empty-continue> Ask to the connector that an empty response is ok. =item B<--unit> Select the unit for performance data and thresholds. May be 's' for seconds, 'm' for minutes, 'h' for hours, 'd' for days, 'w' for weeks. Default is seconds =item B<--warning> Warning threshold for snapshot's age. =item B<--critical> Critical threshold for snapshot's age. =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/statconnectors.pm000066400000000000000000000070011417000230700260230ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::statconnectors; 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 => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'container', type => 1, cb_prefix_output => 'prefix_container_output', message_multiple => 'All containers are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'total-requests', nlabel => 'connector.requests.total.count', set => { key_values => [ { name => 'requests', diff => 1 } ], output_template => 'Total %s requests', perfdatas => [ { label => 'requests', template => '%s', min => 0, label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{container} = [ { label => 'requests', nlabel => 'connector.requests.total.count', set => { key_values => [ { name => 'requests', diff => 1 } ], output_template => '%s requests', perfdatas => [ { label => 'requests', template => '%s', min => 0, label_extra_instance => 1 } ] } } ]; } sub prefix_container_output { my ($self, %options) = @_; return "Container '" . $options{instance_value}->{display} . "' : "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{global} = { requests => 0 }; $self->{container} = {}; my $response = $options{custom}->execute( params => $self->{option_results}, command => 'stats' ); foreach my $container_name (keys %{$response->{data}}) { $self->{container}->{$container_name} = { display => $container_name, requests => $response->{data}->{$container_name}->{requests} }; $self->{global}->{requests} += $response->{data}->{$container_name}->{requests}; } $self->{cache_name} = "cache_vmware_" . $options{custom}->get_id() . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Get number of requests for each connectors (information from daemon. Not VMWare). =over 8 =item B<--warning-*> Threshold warning. Can be: 'total-requests', 'requests'. =item B<--critical-*> Threshold critical. Can be: 'total-requests', 'requests'. =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/statuscluster.pm000066400000000000000000000120331417000230700257000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::statuscluster; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; my $msg = 'status is ' . $self->{result_values}->{overall_status}; $msg .= ' [vsan status: ' . $self->{result_values}->{vsan_status} . ']' if ($self->{result_values}->{vsan_status} ne ''); $msg .= ' [ha enabled: ' . $self->{result_values}->{ha_enabled} . ']' if ($self->{result_values}->{ha_enabled} ne ''); $msg .= ' [drs enabled: ' . $self->{result_values}->{drs_enabled} . ']' if ($self->{result_values}->{drs_enabled} ne ''); return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'cluster', type => 1, cb_prefix_output => 'prefix_cluster_output', message_multiple => 'All clusters are ok' } ]; $self->{maps_counters}->{cluster} = [ { label => 'status', type => 2, unknown_default => '%{overall_status} =~ /gray/i || %{vsan_status} =~ /gray/i', warning_default => '%{overall_status} =~ /yellow/i || %{vsan_status} =~ /yellow/i', critical_default => '%{overall_status} =~ /red/i || %{vsan_status} =~ /red/i', set => { key_values => [ { name => 'overall_status' }, { name => 'vsan_status' }, { name => 'ha_enabled' }, { name => 'drs_enabled' }, { name => 'display' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub prefix_cluster_output { my ($self, %options) = @_; return "Cluster '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'cluster-name:s' => { name => 'cluster_name' }, 'filter' => { name => 'filter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $response = $options{custom}->execute( params => $self->{option_results}, command => 'statuscluster' ); $self->{cluster} = {}; foreach my $cluster_id (keys %{$response->{data}}) { my $cluster_name = $response->{data}->{$cluster_id}->{name}; $self->{cluster}->{$cluster_name} = { display => $cluster_name, overall_status => $response->{data}->{$cluster_id}->{overall_status}, vsan_status => defined($response->{data}->{$cluster_id}->{vsan_cluster_status}) ? $response->{data}->{$cluster_id}->{vsan_cluster_status} : '', ha_enabled => defined($response->{data}->{$cluster_id}->{ha_enabled}) ? $response->{data}->{$cluster_id}->{ha_enabled} : '', drs_enabled => defined($response->{data}->{$cluster_id}->{drs_enabled}) ? $response->{data}->{$cluster_id}->{drs_enabled} : '' }; } } 1; __END__ =head1 MODE Check cluster status (also vsan status). =over 8 =item B<--cluster-name> cluster to check. If not set, we check all clusters. =item B<--filter> Cluster name is a regexp. =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =item B<--unknown-status> Set warning threshold for status (Default: '%{overall_status} =~ /gray/i || %{vsan_status} =~ /gray/i'). Can used special variables like: %{overall_status}, %{vsan_status}, %{drs_enabled}, %{ha_enabled} =item B<--warning-status> Set warning threshold for status (Default: '%{overall_status} =~ /yellow/i || %{vsan_status} =~ /yellow/i'). Can used special variables like: %{overall_status}, %{vsan_status}, %{drs_enabled}, %{ha_enabled} =item B<--critical-status> Set critical threshold for status (Default: '%{overall_status} =~ /red/i || %{vsan_status} =~ /red/i'). Can used special variables like: %{overall_status}, %{vsan_status}, %{drs_enabled}, %{ha_enabled} =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/statushost.pm000066400000000000000000000120241417000230700251740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::statushost; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return 'status ' . $self->{result_values}->{status}; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_state'}; return 0; } sub custom_overall_output { my ($self, %options) = @_; return 'overall status is ' . $self->{result_values}->{overall_status}; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'host', type => 1, cb_prefix_output => 'prefix_host_output', message_multiple => 'All ESX Hosts are ok' } ]; $self->{maps_counters}->{host} = [ { label => 'status', type => 2, unknown_default => '%{status} !~ /^connected$/i', set => { key_values => [ { name => 'state' } ], 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 => \&catalog_status_threshold_ng } }, { label => 'overall-status', type => 2, unknown_default => '%{overall_status} =~ /gray/i', warning_default => '%{overall_status} =~ /yellow/i', critical_default => '%{overall_status} =~ /red/i', set => { key_values => [ { name => 'overall_status' } ], closure_custom_output => $self->can('custom_overall_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub prefix_host_output { my ($self, %options) = @_; return "Host '" . $options{instance_value}->{display} . "' : "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'esx-hostname:s' => { name => 'esx_hostname' }, 'filter' => { name => 'filter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' }, 'scope-cluster:s' => { name => 'scope_cluster' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{host} = {}; my $response = $options{custom}->execute( params => $self->{option_results}, command => 'statushost' ); foreach my $host_id (keys %{$response->{data}}) { my $host_name = $response->{data}->{$host_id}->{name}; $self->{host}->{$host_name} = { display => $host_name, state => $response->{data}->{$host_id}->{state}, overall_status => $response->{data}->{$host_id}->{overall_status} }; } } 1; __END__ =head1 MODE Check ESX global status. =over 8 =item B<--esx-hostname> ESX hostname to check. If not set, we check all ESX. =item B<--filter> ESX hostname is a regexp. =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =item B<--scope-cluster> Search in following cluster(s) (can be a regexp). =item B<--unknown-status> Set warning threshold for status (Default: '%{status} !~ /^connected$/i'). Can used special variables like: %{status} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{status} =item B<--unknown-overall-status> Set warning threshold for status (Default: '%{overall_status} =~ /gray/i'). Can used special variables like: %{overall_status} =item B<--warning-overall-status> Set warning threshold for status (Default: '%{overall_status} =~ /yellow/i'). Can used special variables like: %{overall_status} =item B<--critical-overall-status> Set critical threshold for status (Default: '%{overall_status} =~ /red/i'). Can used special variables like: %{overall_status} =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/statusvm.pm000066400000000000000000000137731417000230700246550ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::statusvm; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return 'status ' . $self->{result_values}->{connection_state} . ' [' . $self->{result_values}->{power_state} . ']'; } sub custom_overall_output { my ($self, %options) = @_; return 'overall status is ' . $self->{result_values}->{overall_status}; } 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' } ]; $self->{maps_counters}->{vm} = [ { label => 'status', type => 2, unknown_default => '%{connection_state} !~ /^connected$/i', set => { key_values => [ { name => 'connection_state' }, { name => 'power_state' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'overall-status', type => 2, unknown_default => '%{overall_status} =~ /gray/i', warning_default => '%{overall_status} =~ /yellow/i', critical_default => '%{overall_status} =~ /red/i', set => { key_values => [ { name => 'overall_status' } ], closure_custom_output => $self->can('custom_overall_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub prefix_vm_output { my ($self, %options) = @_; my $msg = "Virtual machine '" . $options{instance_value}->{display} . "'"; if (defined($options{instance_value}->{config_annotation})) { $msg .= ' [annotation: ' . $options{instance_value}->{config_annotation} . ']'; } $msg .= ': '; return $msg; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'vm-hostname:s' => { name => 'vm_hostname' }, 'filter' => { name => 'filter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' }, 'scope-cluster:s' => { name => 'scope_cluster' }, 'scope-host:s' => { name => 'scope_host' }, 'filter-description:s' => { name => 'filter_description' }, 'filter-os:s' => { name => 'filter_os' }, 'filter-uuid:s' => { name => 'filter_uuid' }, 'display-description' => { name => 'display_description' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{vm} = {}; my $response = $options{custom}->execute( params => $self->{option_results}, command => 'statusvm' ); foreach my $vm_id (keys %{$response->{data}}) { my $vm_name = $response->{data}->{$vm_id}->{name}; $self->{vm}->{$vm_name} = { display => $vm_name, connection_state => $response->{data}->{$vm_id}->{connection_state}, power_state => $response->{data}->{$vm_id}->{power_state}, overall_status => $response->{data}->{$vm_id}->{overall_status} }; if (defined($self->{option_results}->{display_description})) { $self->{vm}->{$vm_name}->{config_annotation} = $options{custom}->strip_cr(value => $response->{data}->{$vm_id}->{'config.annotation'}); } } } 1; __END__ =head1 MODE Check virtual machine global status. =over 8 =item B<--vm-hostname> VM hostname to check. If not set, we check all VMs. =item B<--filter> VM hostname is a regexp. =item B<--filter-description> Filter also virtual machines description (can be a regexp). =item B<--filter-os> Filter also virtual machines OS name (can be a regexp). =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =item B<--scope-cluster> Search in following cluster(s) (can be a regexp). =item B<--scope-host> Search in following host(s) (can be a regexp). =item B<--unknown-status> Set unknown threshold for status (Default: '%{connection_state} !~ /^connected$/i'). Can used special variables like: %{connection_state}, %{power_state} =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{connection_state} =item B<--critical-status> Set critical threshold for status. Can used special variables like: %{connection_state}, %{power_state} =item B<--unknown-overall-status> Set unknown threshold for status (Default: '%{overall_status} =~ /gray/i'). Can used special variables like: %{overall_status} =item B<--warning-overall-status> Set warning threshold for status (Default: '%{overall_status} =~ /yellow/i'). Can used special variables like: %{overall_status} =item B<--critical-overall-status> Set critical threshold for status (Default: '%{overall_status} =~ /red/i'). Can used special variables like: %{overall_status} =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/storagehost.pm000066400000000000000000000345651417000230700253330ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::storagehost; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return 'status ' . $self->{result_values}->{status} . ', maintenance mode is ' . $self->{result_values}->{maintenance}; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_state'}; $self->{result_values}->{maintenance} = $options{new_datas}->{$self->{instance} . '_maintenance'}; return 0; } sub custom_adapter_output { my ($self, %options) = @_; return sprintf( 'status: %s', $self->{result_values}->{status} ); } sub prefix_host_output { my ($self, %options) = @_; return "Host '" . $options{instance} . "' : "; } sub host_long_output { my ($self, %options) = @_; return "checking host '" . $options{instance} . "'"; } sub prefix_adapters_output { my ($self, %options) = @_; return 'adapters '; } sub prefix_adapter_output { my ($self, %options) = @_; return "adapter '" . $options{instance_value}->{name} . "' "; } sub prefix_luns_output { my ($self, %options) = @_; return 'luns '; } sub prefix_lun_output { my ($self, %options) = @_; return "lun '" . $options{instance_value}->{name} . "' "; } sub prefix_paths_output { my ($self, %options) = @_; return 'paths '; } sub prefix_path_output { my ($self, %options) = @_; return "path '" . $options{instance_value}->{name} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'host', type => 3, cb_prefix_output => 'prefix_host_output', cb_long_output => 'host_long_output', indent_long_output => ' ', message_multiple => 'All ESX hosts are ok', group => [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'adapters_global', type => 0, cb_prefix_output => 'prefix_adapters_output', skipped_code => { -10 => 1 } }, { name => 'luns_global', type => 0, cb_prefix_output => 'prefix_luns_output', skipped_code => { -10 => 1 } }, { name => 'paths_global', type => 0, cb_prefix_output => 'prefix_paths_output', skipped_code => { -10 => 1 } }, { name => 'adapters', type => 1, display_long => 1, cb_prefix_output => 'prefix_adapter_output', message_multiple => 'All adapters are ok', skipped_code => { -10 => 1 } }, { name => 'luns', type => 1, display_long => 1, cb_prefix_output => 'prefix_lun_output', message_multiple => 'All luns are ok', skipped_code => { -10 => 1 } }, { name => 'paths', type => 1, display_long => 1, cb_prefix_output => 'prefix_path_output', message_multiple => 'All paths are ok', skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'status', type => 2, unknown_default => '%{status} !~ /^connected$/i && %{maintenance} =~ /false/i', set => { key_values => [ { name => 'state' }, { name => 'maintenance' } ], 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 => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{adapters_global} = []; foreach ('total', 'online', 'offline', 'fault', 'unknown') { push @{$self->{maps_counters}->{adapters_global}}, { label => 'adapters-' . $_, nlabel => 'host.adapters.' . $_ . '.count', set => { key_values => [ { name => $_ } ], output_template => $_ . ': %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } }; } $self->{maps_counters}->{luns_global} = []; foreach ('total', 'ok', 'error', 'off', 'unknown', 'quiesced', 'degraded') { push @{$self->{maps_counters}->{luns_global}}, { label => 'luns-' . $_, nlabel => 'host.luns.' . $_ . '.count', set => { key_values => [ { name => $_ } ], output_template => $_ . ': %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } }; } $self->{maps_counters}->{paths_global} = []; foreach ('total', 'active', 'disabled', 'standby', 'dead', 'unknown') { push @{$self->{maps_counters}->{paths_global}}, { label => 'paths-' . $_, nlabel => 'host.paths.' . $_ . '.count', set => { key_values => [ { name => $_ } ], output_template => $_ . ': %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } }; } $self->{maps_counters}->{adapters} = [ { label => 'adapter-status', type => 2, critical_default => '%{status} =~ /fault/', set => { key_values => [ { name => 'name' }, { name => 'status' }, { name => 'host' } ], closure_custom_output => $self->can('custom_adapter_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{luns} = [ { label => 'lun-status', type => 2, warning_default => '%{status} =~ /degraded|quiesced/', critical_default => '%{status} =~ /lostcommunication|error/', set => { key_values => [ { name => 'name' }, { name => 'status' }, { name => 'host' } ], closure_custom_output => $self->can('custom_adapter_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{paths} = [ { label => 'path-status', type => 2, critical_default => '%{status} =~ /dead/', set => { key_values => [ { name => 'name' }, { name => 'status' }, { name => 'host' } ], closure_custom_output => $self->can('custom_adapter_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'esx-hostname:s' => { name => 'esx_hostname' }, 'filter' => { name => 'filter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' }, 'scope-cluster:s' => { name => 'scope_cluster' }, 'filter-adapter-name:s' => { name => 'filter_adapter_name' }, 'filter-lun-name:s' => { name => 'filter_lun_name' }, 'filter-path-name:s' => { name => 'filter_path_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{host} = {}; my $response = $options{custom}->execute( params => $self->{option_results}, command => 'storagehost' ); foreach my $host_id (keys %{$response->{data}}) { my $host_name = $response->{data}->{$host_id}->{name}; $self->{host}->{$host_name} = { global => { state => $response->{data}->{$host_id}->{state}, maintenance => $response->{data}->{$host_id}->{inMaintenanceMode} } }; if (defined($response->{data}->{$host_id}->{adapters})) { $self->{host}->{$host_name}->{adapters} = {}; $self->{host}->{$host_name}->{adapters_global} = { online => 0, offline => 0, fault => 0, unknown => 0, total => 0 }; foreach (@{$response->{data}->{$host_id}->{adapters}}) { next if (defined($self->{option_results}->{filter_adapter_name}) && $self->{option_results}->{filter_adapter_name} ne '' && $_->{name} !~ /$self->{option_results}->{filter_adapter_name}/); $self->{host}->{$host_name}->{adapters_global}->{total}++; if (defined($self->{host}->{$host_name}->{adapters_global}->{ $_->{status} })) { $self->{host}->{$host_name}->{adapters_global}->{ $_->{status} }++; } else { $self->{host}->{$host_name}->{adapters_global}->{unknown}++; } $self->{host}->{$host_name}->{adapters}->{ $_->{name} } = { name => $_->{name}, host => $host_name, status => $_->{status} }; } } if (defined($response->{data}->{$host_id}->{luns})) { $self->{host}->{$host_name}->{luns} = {}; $self->{host}->{$host_name}->{luns_global} = { ok => 0, error => 0, off => 0, unknown => 0, quiesced => 0, degraded => 0, total => 0 }; foreach (@{$response->{data}->{$host_id}->{luns}}) { next if (defined($self->{option_results}->{filter_lun_name}) && $self->{option_results}->{filter_lun_name} ne '' && $_->{name} !~ /$self->{option_results}->{filter_lun_name}/); $self->{host}->{$host_name}->{luns_global}->{total}++; foreach my $state (@{$_->{operational_states}}) { if (defined($self->{host}->{$host_name}->{luns_global}->{$state})) { $self->{host}->{$host_name}->{luns_global}->{$state}++; } else { $self->{host}->{$host_name}->{luns_global}->{unknown}++; } } $self->{host}->{$host_name}->{luns}->{ $_->{name} } = { name => $_->{name}, host => $host_name, status => join(',', @{$_->{operational_states}}) }; } } if (defined($response->{data}->{$host_id}->{paths})) { $self->{host}->{$host_name}->{paths} = {}; $self->{host}->{$host_name}->{paths_global} = { active => 0, disabled => 0, standby => 0, dead => 0, unknown => 0 }; foreach (@{$response->{data}->{$host_id}->{paths}}) { next if (defined($self->{option_results}->{filter_path_name}) && $self->{option_results}->{filter_path_name} ne '' && $_->{name} !~ /$self->{option_results}->{filter_path_name}/); $self->{host}->{$host_name}->{paths_global}->{total}++; if (defined($self->{host}->{$host_name}->{paths_global}->{ $_->{state} })) { $self->{host}->{$host_name}->{paths_global}->{ $_->{state} }++; } else { $self->{host}->{$host_name}->{paths_global}->{unknown}++; } $self->{host}->{$host_name}->{paths}->{ $_->{name} } = { name => $_->{name}, host => $host_name, status => $_->{state} }; } } } } 1; __END__ =head1 MODE Check ESX storage infos. =over 8 =item B<--esx-hostname> ESX hostname to check. If not set, we check all ESX. =item B<--filter> ESX hostname is a regexp. =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =item B<--scope-cluster> Search in following cluster(s) (can be a regexp). =item B<--filter-adapter-name> Filter adapters by name (can be a regexp). =item B<--filter-lun-name> Filter luns by name (can be a regexp). =item B<--filter-path-name> Filter paths by name (can be a regexp). =item B<--unknown-status> Set warning threshold for status (Default: '%{status} !~ /^connected$/i && %{maintenance} =~ /false/i'). Can used special variables like: %{status}, %{maintenance} =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{status}, %{maintenance} =item B<--critical-status> Set critical threshold for status. Can used special variables like: %{status}, %{maintenance} =item B<--warning-adapter-status> Set warning threshold for adapter status. Can used special variables like: %{name}, %{host}, %{status} =item B<--critical-adapter-status> Set critical threshold for adapter status (Default: '%{status} =~ /fault/'). Can used special variables like: %{name}, %{host}, %{status} =item B<--warning-lun-status> Set warning threshold for lun status (Default: '%{status} =~ /degraded|quiesced/'). Can used special variables like: %{name}, %{host}, %{status} =item B<--critical-lun-status> Set critical threshold for lun status (Default: '%{status} =~ /lostcommunication|error/'). Can used special variables like: %{name}, %{host}, %{status} =item B<--warning-path-status> Set warning threshold for path status. Can used special variables like: %{name}, %{host}, %{status} =item B<--critical-path-status> Set critical threshold for path status (Default: '%{status} =~ /dead/'). Can used special variables like: %{name}, %{host}, %{status} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'adapters-total', 'adapters-online', 'adapters-offline', 'adapters-fault', 'adapters-unknown', =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/swaphost.pm000066400000000000000000000120511417000230700246230ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::swaphost; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return 'status : ' . $self->{result_values}->{status}; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_state'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'host', type => 1, cb_prefix_output => 'prefix_host_output', message_multiple => 'All hosts are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{host} = [ { label => 'status', type => 2, unknown_default => '%{status} !~ /^connected$/i', 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 => \&catalog_status_threshold_ng } }, { label => 'swap-in', nlabel => 'host.swap.in.usage.bytespersecond', set => { key_values => [ { name => 'swap_in' }, { name => 'display' } ], output_template => 'Swap In: %s %s/s', output_change_bytes => 1, perfdatas => [ { label => 'swap_in', template => '%s', unit => 'B/s', min => 0, label_extra_instance => 1 } ] } }, { label => 'swap-out', nlabel => 'host.swap.out.usage.bytespersecond', set => { key_values => [ { name => 'swap_out' }, { name => 'display' } ], output_template => 'Swap Out: %s %s/s', output_change_bytes => 1, perfdatas => [ { label => 'swap_out', template => '%s', unit => 'B/s', min => 0, label_extra_instance => 1 } ] } } ]; } sub prefix_host_output { my ($self, %options) = @_; return "Host '" . $options{instance_value}->{display} . "' : "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'esx-hostname:s' => { name => 'esx_hostname' }, 'filter' => { name => 'filter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' }, 'scope-cluster:s' => { name => 'scope_cluster' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{host} = {}; my $response = $options{custom}->execute( params => $self->{option_results}, command => 'swaphost' ); foreach my $host_id (keys %{$response->{data}}) { my $host_name = $response->{data}->{$host_id}->{name}; $self->{host}->{$host_name} = { display => $host_name, state => $response->{data}->{$host_id}->{state}, swap_in => $response->{data}->{$host_id}->{'mem.swapinRate.average'}, swap_out => $response->{data}->{$host_id}->{'mem.swapoutRate.average'} }; } } 1; __END__ =head1 MODE Check ESX swap rate usage. =over 8 =item B<--esx-hostname> ESX hostname to check. If not set, we check all ESX. =item B<--filter> ESX hostname is a regexp. =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =item B<--scope-cluster> Search in following cluster(s) (can be a regexp). =item B<--unknown-status> Set warning threshold for status (Default: '%{status} !~ /^connected$/i'). Can used special variables like: %{status} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{status} =item B<--warning-*> Threshold warning. Can be: 'swap-in', 'swap-out'. =item B<--critical-*> Threshold critical. Can be: 'swap-in', 'swap-out'. =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/swapvm.pm000066400000000000000000000143121417000230700242720ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::swapvm; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return '[connection state ' . $self->{result_values}->{connection_state} . '][power state ' . $self->{result_values}->{power_state} . ']'; } 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 => 'status', type => 2, unknown_default => '%{connection_state} !~ /^connected$/i or %{power_state} !~ /^poweredOn$/i', set => { key_values => [ { name => 'connection_state' }, { name => 'power_state' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'swap-in', nlabel => 'vm.swap.in.usage.bytespersecond', set => { key_values => [ { name => 'swap_in' }, { name => 'display' } ], output_template => 'Swap In: %s %s/s', output_change_bytes => 1, perfdatas => [ { label => 'swap_in', template => '%s', unit => 'B/s', min => 0, label_extra_instance => 1 } ], } }, { label => 'swap-out', nlabel => 'vm.swap.out.usage.bytespersecond', set => { key_values => [ { name => 'swap_out' }, { name => 'display' } ], output_template => 'Swap Out: %s %s/s', output_change_bytes => 1, perfdatas => [ { label => 'swap_out', template => '%s', unit => 'B/s', min => 0, label_extra_instance => 1 } ] } } ]; } sub prefix_vm_output { my ($self, %options) = @_; my $msg = "Virtual machine '" . $options{instance_value}->{display} . "'"; if (defined($options{instance_value}->{config_annotation})) { $msg .= ' [annotation: ' . $options{instance_value}->{config_annotation} . ']'; } $msg .= ' : '; return $msg; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'vm-hostname:s' => { name => 'vm_hostname' }, 'filter' => { name => 'filter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' }, 'scope-cluster:s' => { name => 'scope_cluster' }, 'scope-host:s' => { name => 'scope_host' }, 'filter-description:s' => { name => 'filter_description' }, 'filter-os:s' => { name => 'filter_os' }, 'filter-uuid:s' => { name => 'filter_uuid' }, 'display-description' => { name => 'display_description' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{vm} = {}; my $response = $options{custom}->execute( params => $self->{option_results}, command => 'swapvm' ); foreach my $vm_id (keys %{$response->{data}}) { my $vm_name = $response->{data}->{$vm_id}->{name}; $self->{vm}->{$vm_name} = { display => $vm_name, connection_state => $response->{data}->{$vm_id}->{connection_state}, power_state => $response->{data}->{$vm_id}->{power_state}, swap_in => $response->{data}->{$vm_id}->{'mem.swapinRate.average'}, swap_out => $response->{data}->{$vm_id}->{'mem.swapoutRate.average'} }; if (defined($self->{option_results}->{display_description})) { $self->{vm}->{$vm_name}->{config_annotation} = $options{custom}->strip_cr(value => $response->{data}->{$vm_id}->{'config.annotation'}); } } } 1; __END__ =head1 MODE Check virtual machine swap rate usage. =over 8 =item B<--vm-hostname> VM hostname to check. If not set, we check all VMs. =item B<--filter> VM hostname is a regexp. =item B<--filter-description> Filter also virtual machines description (can be a regexp). =item B<--filter-os> Filter also virtual machines OS name (can be a regexp). =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =item B<--scope-cluster> Search in following cluster(s) (can be a regexp). =item B<--scope-host> Search in following host(s) (can be a regexp). =item B<--display-description> Display virtual machine description. =item B<--unknown-status> Set warning threshold for status (Default: '%{connection_state} !~ /^connected$/i or %{power_state} !~ /^poweredOn$/i'). Can used special variables like: %{connection_state}, %{power_state} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{connection_state}, %{power_state} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{connection_state}, %{power_state} =item B<--warning-*> Threshold warning. Can be: 'swap-in', 'swap-out'. =item B<--critical-*> Threshold critical. Can be: 'swap-in', 'swap-out'. =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/thinprovisioningvm.pm000066400000000000000000000164461417000230700267430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::thinprovisioningvm; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "vm-hostname:s" => { name => 'vm_hostname' }, "filter" => { name => 'filter' }, "scope-datacenter:s" => { name => 'scope_datacenter' }, "scope-cluster:s" => { name => 'scope_cluster' }, "scope-host:s" => { name => 'scope_host' }, "filter-description:s" => { name => 'filter_description' }, "filter-os:s" => { name => 'filter_os' }, "filter-uuid:s" => { name => 'filter_uuid' }, "disconnect-status:s" => { name => 'disconnect_status', default => 'unknown' }, "nopoweredon-skip" => { name => 'nopoweredon_skip' }, "display-description" => { name => 'display_description' }, "thinprovisioning-status:s" => { name => 'thinprovisioning_status' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if ($self->{output}->is_litteral_status(status => $self->{option_results}->{disconnect_status}) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong disconnect-status option '" . $self->{option_results}->{disconnect_status} . "'."); $self->{output}->option_exit(); } if (defined($self->{option_results}->{thinprovisioning_status}) && $self->{option_results}->{thinprovisioning_status} ne '') { ($self->{thin_entry}, $self->{thin_status}) = split /,/, $self->{option_results}->{thinprovisioning_status}; if ($self->{thin_entry} !~ /^(notactive|active)$/) { $self->{output}->add_option_msg(short_msg => "Wrong thinprovisioning-status option. Can only be 'active' or 'noactive'. Not: '" . $self->{thin_entry} . "'."); $self->{output}->option_exit(); } if ($self->{output}->is_litteral_status(status => $self->{thin_status}) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong thinprovisioning-status option. Not a good status: '" . $self->{thin_status} . "'."); $self->{output}->option_exit(); } } } sub display_verbose { my ($self, %options) = @_; foreach my $vm (sort keys %{$options{vms}}) { my $prefix = $vm; if (defined($options{vms}->{$vm}->{description}) && $options{vms}->{$vm}->{description} ne '') { $prefix .= ' [' . $options{vms}->{$vm}->{description} . ']'; } $self->{output}->output_add(long_msg => $prefix); foreach my $disk (sort keys %{$options{vms}->{$vm}->{disks}}) { $self->{output}->output_add(long_msg => ' ' . $disk); } } } sub run { my ($self, %options) = @_; my $response = $options{custom}->execute(params => $self->{option_results}, command => 'thinprovisioningvm'); my $multiple = 0; if (scalar(keys %{$response->{data}}) > 1) { $multiple = 1; } if ($multiple == 1) { $self->{output}->output_add(severity => 'OK', short_msg => 'All thinprovisoning virtualdisks are ok.'); } else { $self->{output}->output_add(severity => 'OK', short_msg => 'Thinprovisoning virtualdisks are ok.'); } my $disks_vm = {}; my %maps_match = ('active' => { regexp => '^1$', output => 'VirtualDisks thinprovisioning actived' }, 'notactive' => { regexp => '^(?!(1)$)', output => 'VirtualDisks thinprovisioning not actived' }); my $num = 0; foreach my $vm_id (sort keys %{$response->{data}}) { my $vm_name = $response->{data}->{$vm_id}->{name}; if ($options{custom}->entity_is_connected(state => $response->{data}->{$vm_id}->{connection_state}) == 0) { my $output = "VM '" . $vm_name . "' not connected. Current Connection State: '$response->{data}->{$vm_id}->{connection_state}'."; if ($multiple == 0 || !$self->{output}->is_status(value => $self->{option_results}->{disconnect_status}, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $self->{option_results}->{disconnect_status}, short_msg => $output); } next; } next if (defined($self->{option_results}->{nopoweredon_skip}) && $options{custom}->vm_is_running(power => $response->{data}->{$vm_id}->{power_state}) == 0); foreach (@{$response->{data}->{$vm_id}->{disks}}) { if (defined($self->{thin_entry}) && $_->{thin_provisioned} =~ /$maps_match{$self->{thin_entry}}->{regexp}/) { $num++; if (!defined($disks_vm->{$vm_name})) { $disks_vm->{$vm_name} = { disks => {}, description => (defined($self->{option_results}->{display_description}) ? $options{custom}->strip_cr(value => $response->{data}->{$vm_id}->{'config.annotation'}) : undef) }; } $disks_vm->{$vm_name}->{disks}->{$_->{name}} = 1; } } } if ($num > 0) { $self->{output}->output_add(severity => $self->{thin_status}, short_msg => sprintf('%d %s', $num, $maps_match{$self->{thin_entry}}->{output})); $self->display_verbose(vms => $disks_vm); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check virtual machine thin provisioning option. =over 8 =item B<--vm-hostname> VM hostname to check. If not set, we check all VMs. =item B<--filter> VM hostname is a regexp. =item B<--filter-description> Filter also virtual machines description (can be a regexp). =item B<--filter-os> Filter also virtual machines OS name (can be a regexp). =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =item B<--scope-cluster> Search in following cluster(s) (can be a regexp). =item B<--scope-host> Search in following host(s) (can be a regexp). =item B<--disconnect-status> Status if VM disconnected (default: 'unknown'). =item B<--nopoweredon-skip> Skip check if VM is not poweredOn. =item B<--display-description> Display virtual machine description. =item B<--thinprovisioning-status> Thinprovisioning status (default: none) Example: 'active,CRITICAL' or 'notactive,WARNING' =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/timehost.pm000066400000000000000000000116201417000230700246100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::timehost; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Date::Parse; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return 'status ' . $self->{result_values}->{status}; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_state'}; return 0; } sub custom_time_output { my ($self, %options) = @_; return sprintf( 'time offset %d second(s) : %s', $self->{result_values}->{offset}, $self->{result_values}->{date} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'host', type => 1, cb_prefix_output => 'prefix_host_output', message_multiple => 'All hosts are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{host} = [ { label => 'status', type => 2, unknown_default => '%{status} !~ /^connected$/i', 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 => \&catalog_status_threshold_ng } }, { label => 'time', nlabel => 'host.time.offset.seconds', set => { key_values => [ { name => 'offset' }, { name => 'date' }, { name => 'display' } ], closure_custom_output => $self->can('custom_time_output'), perfdatas => [ { label => 'offset', template => '%.2f', unit => 's', label_extra_instance => 1 } ] } } ]; } sub prefix_host_output { my ($self, %options) = @_; return "Host '" . $options{instance_value}->{display} . "' : "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'esx-hostname:s' => { name => 'esx_hostname' }, 'filter' => { name => 'filter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' }, 'scope-cluster:s' => { name => 'scope_cluster' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{host} = {}; my $response = $options{custom}->execute( params => $self->{option_results}, command => 'timehost' ); foreach my $host_id (keys %{$response->{data}}) { my $host_name = $response->{data}->{$host_id}->{name}; my $offset; if (defined($response->{data}->{$host_id}->{current_time})) { my $timestamp = Date::Parse::str2time($response->{data}->{$host_id}->{current_time}); $offset = time() - $timestamp; } $self->{host}->{$host_name} = { display => $host_name, state => $response->{data}->{$host_id}->{state}, offset => $offset, date => $response->{data}->{$host_id}->{current_time} }; } } 1; __END__ =head1 MODE Check ESX time. =over 8 =item B<--esx-hostname> ESX hostname to check. If not set, we check all ESX. =item B<--filter> ESX hostname is a regexp. =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =item B<--scope-cluster> Search in following cluster(s) (can be a regexp). =item B<--unknown-status> Set warning threshold for status (Default: '%{status} !~ /^connected$/i'). Can used special variables like: %{status} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{status} =item B<--warning-time> Threshold warning in seconds. =item B<--critical-time> Threshold critical in seconds. =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/toolsvm.pm000066400000000000000000000234661417000230700244720ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::toolsvm; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'vm-hostname:s' => { name => 'vm_hostname' }, 'filter' => { name => 'filter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' }, 'scope-cluster:s' => { name => 'scope_cluster' }, 'scope-host:s' => { name => 'scope_host' }, 'filter-description:s' => { name => 'filter_description' }, 'filter-os:s' => { name => 'filter_os' }, 'filter-uuid:s' => { name => 'filter_uuid' }, 'display-description' => { name => 'display_description' }, 'disconnect-status:s' => { name => 'disconnect_status', default => 'unknown' }, 'tools-notinstalled-status:s' => { name => 'tools_notinstalled_status', default => 'critical' }, 'tools-notrunning-status:s' => { name => 'tools_notrunning_status', default => 'critical' }, 'tools-notup2date-status:s' => { name => 'tools_notupd2date_status', default => 'warning' }, 'nopoweredon-skip' => { name => 'nopoweredon_skip' }, 'empty-continue' => { name => 'empty_continue' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if ($self->{output}->is_litteral_status(status => $self->{option_results}->{disconnect_status}) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong disconnect-status option '" . $self->{option_results}->{disconnect_status} . "'."); $self->{output}->option_exit(); } if ($self->{output}->is_litteral_status(status => $self->{option_results}->{tools_notinstalled_status}) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong tools-notinstalled-status option '" . $self->{option_results}->{tools_notinstalled_status} . "'."); $self->{output}->option_exit(); } if ($self->{output}->is_litteral_status(status => $self->{option_results}->{tools_notrunning_status}) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong tools-notrunning-status option '" . $self->{option_results}->{tools_notrunning_status} . "'."); $self->{output}->option_exit(); } if ($self->{output}->is_litteral_status(status => $self->{option_results}->{tools_notupd2date_status}) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong tools-notupd2date-status option '" . $self->{option_results}->{tools_notupd2date_status} . "'."); $self->{output}->option_exit(); } } sub display_verbose { my ($self, %options) = @_; $self->{output}->output_add(long_msg => $options{label}); foreach my $vm (sort keys %{$options{vms}}) { my $prefix = $vm; if ($options{vms}->{$vm} ne '') { $prefix .= ' [' . $options{custom}->strip_cr(value => $options{vms}->{$vm}) . ']'; } $self->{output}->output_add(long_msg => ' ' . $prefix); } } sub run { my ($self, %options) = @_; my $response = $options{custom}->execute( params => $self->{option_results}, command => 'toolsvm' ); my $multiple = 0; if (scalar(keys %{$response->{data}}) > 1) { $multiple = 1; } if ($multiple == 1) { $self->{output}->output_add( severity => 'OK', short_msg => 'All VMTools are OK' ); } else { $self->{output}->output_add( severity => 'OK', short_msg => 'VMTools are OK' ); } my %not_installed = (); my %not_running = (); my %not_up2date = (); foreach my $vm_id (sort keys %{$response->{data}}) { my $vm_name = $response->{data}->{$vm_id}->{name}; if ($options{custom}->entity_is_connected(state => $response->{data}->{$vm_id}->{connection_state}) == 0) { my $output = "VM '" . $vm_name . "' not connected. Current Connection State: '$response->{data}->{$vm_id}->{connection_state}'."; if ($multiple == 0 || !$self->{output}->is_status(value => $self->{option_results}->{disconnect_status}, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $self->{option_results}->{disconnect_status}, short_msg => $output ); } next; } next if (defined($self->{option_results}->{nopoweredon_skip}) && $options{custom}->vm_is_running(power => $response->{data}->{$vm_id}->{power_state}) == 0); next if (!defined($response->{data}->{$vm_id}->{tools_status})); my $tools_status = lc($response->{data}->{$vm_id}->{tools_status}); if ($tools_status eq 'toolsnotinstalled') { $not_installed{$vm_name} = defined($response->{data}->{$vm_id}->{'config.annotation'}) ? $response->{data}->{$vm_id}->{'config.annotation'} : ''; } elsif ($tools_status eq 'toolsnotrunning') { $not_running{$vm_name} = defined($response->{data}->{$vm_id}->{'config.annotation'}) ? $response->{data}->{$vm_id}->{'config.annotation'} : ''; } elsif ($tools_status eq 'toolsold') { $not_up2date{$vm_name} = defined($response->{data}->{$vm_id}->{'config.annotation'}) ? $response->{data}->{$vm_id}->{'config.annotation'} : ''; } } if (scalar(keys %not_up2date) > 0 && !$self->{output}->is_status(value => $self->{option_results}->{tools_notupd2date_status}, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $self->{option_results}->{tools_notupd2date_status}, short_msg => sprintf('%d VM with VMTools not up-to-date', scalar(keys %not_up2date)) ); $self->display_verbose(label => 'vmtools not up-to-date:', vms => \%not_up2date, custom => $options{custom}); } if (scalar(keys %not_running) > 0 && !$self->{output}->is_status(value => $self->{option_results}->{tools_notrunning_status}, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $self->{option_results}->{tools_notrunning_status}, short_msg => sprintf('%d VM with VMTools not running', scalar(keys %not_running)) ); $self->display_verbose(label => 'vmtools not running:', vms => \%not_running, custom => $options{custom}); } if (scalar(keys %not_installed) > 0 && !$self->{output}->is_status(value => $self->{option_results}->{tools_notinstalled_status}, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $self->{option_results}->{tools_notinstalled_status}, short_msg => sprintf('%d VM with VMTools not installed', scalar(keys %not_installed)) ); $self->display_verbose(label => 'vmtools not installed:', vms => \%not_installed, custom => $options{custom}); } if ($multiple == 1) { my $total = scalar(keys %not_up2date) + scalar(keys %not_running) + scalar(keys %not_installed); $self->{output}->perfdata_add( label => 'not_updated', nlabel => 'vm.tools.notupdated.current.count', value => scalar(keys %not_up2date), min => 0, max => $total ); $self->{output}->perfdata_add( label => 'not_running', nlabel => 'vm.tools.notrunning.current.count', value => scalar(keys %not_running), min => 0, max => $total ); $self->{output}->perfdata_add( label => 'not_installed', nlabel => 'vm.tools.notinstalled.current.count', value => scalar(keys %not_installed), min => 0, max => $total ); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check virtual machine tools. =over 8 =item B<--vm-hostname> VM hostname to check. If not set, we check all VMs. =item B<--filter> VM hostname is a regexp. =item B<--filter-description> Filter also virtual machines description (can be a regexp). =item B<--filter-os> Filter also virtual machines OS name (can be a regexp). =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =item B<--scope-cluster> Search in following cluster(s) (can be a regexp). =item B<--scope-host> Search in following host(s) (can be a regexp). =item B<--disconnect-status> Status if VM disconnected (default: 'unknown'). =item B<--nopoweredon-skip> Skip check if VM is not poweredOn. =item B<--empty-continue> Ask to the connector that an empty response is ok. =item B<--display-description> Display virtual machine description. =item B<--tools-notinstalled-status> Status if vmtools is not installed (default: critical). =item B<--tools-notrunning-status> Status if vmtools is not running (default: critical). =item B<--tools-notup2date-status> Status if vmtools is not upd2date (default: warning). =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/uptimehost.pm000066400000000000000000000115431417000230700251610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::uptimehost; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Date::Parse; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return 'status ' . $self->{result_values}->{status}; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_state'}; return 0; } sub custom_time_output { my ($self, %options) = @_; return sprintf( 'Uptime: %s day(s)', int($self->{result_values}->{offset} / 60 / 60 / 24) ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'host', type => 1, cb_prefix_output => 'prefix_host_output', message_multiple => 'All hosts are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{host} = [ { label => 'status', type => 2, unknown_default => '%{status} !~ /^connected$/i', 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 => \&catalog_status_threshold_ng } }, { label => 'time', nlabel => 'host.uptime.offset.seconds', set => { key_values => [ { name => 'offset' }, { name => 'date' }, { name => 'display' } ], closure_custom_output => $self->can('custom_time_output'), perfdatas => [ { label => 'uptime', template => '%.2f', unit => 's', label_extra_instance => 1 } ] } } ]; } sub prefix_host_output { my ($self, %options) = @_; return "Host '" . $options{instance_value}->{display} . "' : "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'esx-hostname:s' => { name => 'esx_hostname' }, 'filter' => { name => 'filter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' }, 'scope-cluster:s' => { name => 'scope_cluster' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{host} = {}; my $response = $options{custom}->execute( params => $self->{option_results}, command => 'uptimehost' ); foreach my $host_id (keys %{$response->{data}}) { my $host_name = $response->{data}->{$host_id}->{name}; my $offset; if (defined($response->{data}->{$host_id}->{boot_time})) { my $timestamp = Date::Parse::str2time($response->{data}->{$host_id}->{boot_time}); $offset = time() - $timestamp; } $self->{host}->{$host_name} = { display => $host_name, state => $response->{data}->{$host_id}->{state}, offset => $offset, date => $response->{data}->{$host_id}->{boot_time} }; } } 1; __END__ =head1 MODE Check ESX uptime. =over 8 =item B<--esx-hostname> ESX hostname to check. If not set, we check all ESX. =item B<--filter> ESX hostname is a regexp. =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =item B<--scope-cluster> Search in following cluster(s) (can be a regexp). =item B<--unknown-status> Set warning threshold for status (Default: '%{status} !~ /^connected$/i'). Can used special variables like: %{status} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{status} =item B<--warning-time> Threshold warning in seconds. =item B<--critical-time> Threshold critical in seconds. =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/vmoperationcluster.pm000066400000000000000000000107251417000230700267260ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::vmoperationcluster; 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 => 'cluster', type => 1, cb_prefix_output => 'prefix_cluster_output', message_multiple => 'All virtual machine operations are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{cluster} = [ { label => 'svmotion', nlabel => 'cluster.operations.svmotion.current.count', set => { key_values => [ { name => 'numSVMotion', diff => 1 }, { name => 'display' } ], output_template => 'SVMotion %s', perfdatas => [ { label => 'svmotion', template => '%s', min => 0, label_extra_instance => 1 } ] } }, { label => 'vmotion', nlabel => 'cluster.operations.vmotion.current.count', set => { key_values => [ { name => 'numVMotion', diff => 1 }, { name => 'display' } ], output_template => 'VMotion %s', perfdatas => [ { label => 'vmotion', template => '%s', min => 0, label_extra_instance => 1 } ] } }, { label => 'clone', nlabel => 'cluster.operations.clone.current.count', set => { key_values => [ { name => 'numClone', diff => 1 }, { name => 'display' } ], output_template => 'Clone %s', perfdatas => [ { label => 'clone', template => '%s', min => 0, label_extra_instance => 1 } ] } } ]; } sub prefix_cluster_output { my ($self, %options) = @_; return "Cluster '" . $options{instance_value}->{display} . "' vm operations: "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'cluster:s' => { name => 'cluster' }, 'filter' => { name => 'filter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{cluster} = {}; my $response = $options{custom}->execute( params => $self->{option_results}, command => 'vmoperationcluster' ); foreach my $cluster_id (keys %{$response->{data}}) { my $cluster_name = $response->{data}->{$cluster_id}->{name}; $self->{cluster}->{$cluster_name} = { display => $cluster_name, numVMotion => $response->{data}->{$cluster_id}->{'vmop.numVMotion.latest'}, numClone => $response->{data}->{$cluster_id}->{'vmop.numClone.latest'}, numSVMotion => $response->{data}->{$cluster_id}->{'vmop.numSVMotion.latest'} }; } $self->{cache_name} = "cache_vmware_" . $options{custom}->get_id() . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{cluster}) ? md5_hex($self->{option_results}->{cluster}) : md5_hex('all')); } 1; __END__ =head1 MODE Check virtual machines operations on cluster(s). =over 8 =item B<--cluster> Cluster to check. If not set, we check all clusters. =item B<--filter> Cluster is a regexp. =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =item B<--warning-*> Threshold warning. Can be: svmotion, vmotion, clone. =item B<--critical-*> Threshold critical. Can be: svmotion, vmotion, clone. =back =cut centreon-plugins-20220113/apps/vmware/connector/mode/vsanclusterusage.pm000066400000000000000000000133031417000230700263520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::mode::vsanclusterusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'cluster', type => 1, cb_prefix_output => 'prefix_cluster_output', message_multiple => 'All clusters are ok' } ]; $self->{maps_counters}->{cluster} = [ { label => 'backend-read-usage', nlabel => 'cluster.vsan.backend.read.usage.iops', set => { key_values => [ { name => 'iopsRead' } ], output_template => 'read IOPS: %s', perfdatas => [ { template => '%s', unit => 'iops', min => 0 } ] } }, { label => 'backend-write-usage', nlabel => 'cluster.vsan.backend.write.usage.iops', set => { key_values => [ { name => 'iopsWrite' } ], output_template => 'write IOPS: %s', perfdatas => [ { template => '%s', unit => 'iops', min => 0 } ] } }, { label => 'backend-congestions', nlabel => 'cluster.vsan.backend.congestions.count', set => { key_values => [ { name => 'congestion' } ], output_template => 'congestions: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'backend-outstanding-io', nlabel => 'cluster.vsan.backend.outstanding.io.count', set => { key_values => [ { name => 'oio' } ], output_template => 'outstanding IO: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'backend-throughput-read', nlabel => 'cluster.vsan.backend.throughput.read.bytespersecond', display_ok => 0, set => { key_values => [ { name => 'throughputRead' } ], output_template => 'read throughput: %s %s/s', output_change_bytes => 1, perfdatas => [ { template => '%s', unit => 'B/s', min => 0 } ] } }, { label => 'backend-throughput-write', nlabel => 'cluster.vsan.backend.throughput.write.bytespersecond', display_ok => 0, set => { key_values => [ { name => 'throughputWrite' } ], output_template => 'write throughput: %s %s/s', output_change_bytes => 1, perfdatas => [ { template => '%s', unit => 'B/s', min => 0 } ] } }, { label => 'backend-latency-read', nlabel => 'cluster.vsan.backend.latency.read.milliseconds', display_ok => 0, set => { key_values => [ { name => 'latencyAvgRead' } ], output_template => 'read latency: %s ms', perfdatas => [ { template => '%s', unit => 'ms', min => 0 } ] } }, { label => 'backend-latency-write', nlabel => 'cluster.vsan.backend.latency.write.milliseconds', display_ok => 0, set => { key_values => [ { name => 'latencyAvgWrite' } ], output_template => 'write latency: %s ms', perfdatas => [ { template => '%s', unit => 'ms', min => 0 } ] } } ]; } sub prefix_cluster_output { my ($self, %options) = @_; return "Cluster '" . $options{instance_value}->{display} . "' vsan backend "; } 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 => { 'cluster-name:s' => { name => 'cluster_name' }, 'filter' => { name => 'filter' }, 'scope-datacenter:s' => { name => 'scope_datacenter' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{cluster} = {}; my $response = $options{custom}->execute( params => $self->{option_results}, command => 'vsanclusterusage' ); foreach my $cluster_id (keys %{$response->{data}}) { my $cluster_name = $response->{data}->{$cluster_id}->{name}; $self->{cluster}->{$cluster_name} = { display => $cluster_name, %{$response->{data}->{$cluster_id}->{cluster_domcompmgr}}, }; } } 1; __END__ =head1 MODE Check Vsan cluster usage =over 8 =item B<--cluster-name> cluster to check. If not set, we check all clusters. =item B<--filter> Cluster name is a regexp. =item B<--scope-datacenter> Search in following datacenter(s) (can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'backend-write-usage', 'backend-read-usage', 'backend-outstanding-io', 'backend-congestions', 'backend-throughput-read', 'backend-throughput-write' . =back =cut centreon-plugins-20220113/apps/vmware/connector/plugin.pm000066400000000000000000000111431417000230700233260ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::connector::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} = { 'alarm-datacenter' => 'apps::vmware::connector::mode::alarmdatacenter', 'alarm-host' => 'apps::vmware::connector::mode::alarmhost', 'countvm-host' => 'apps::vmware::connector::mode::countvmhost', 'cpu-cluster' => 'apps::vmware::connector::mode::cpucluster', 'cpu-host' => 'apps::vmware::connector::mode::cpuhost', 'cpu-vm' => 'apps::vmware::connector::mode::cpuvm', 'datastore-countvm' => 'apps::vmware::connector::mode::datastorecountvm', 'datastore-host' => 'apps::vmware::connector::mode::datastorehost', 'datastore-io' => 'apps::vmware::connector::mode::datastoreio', 'datastore-iops' => 'apps::vmware::connector::mode::datastoreiops', 'datastore-snapshot' => 'apps::vmware::connector::mode::datastoresnapshot', 'datastore-usage' => 'apps::vmware::connector::mode::datastoreusage', 'datastore-vm' => 'apps::vmware::connector::mode::datastorevm', 'device-vm' => 'apps::vmware::connector::mode::devicevm', 'discovery' => 'apps::vmware::connector::mode::discovery', 'getmap' => 'apps::vmware::connector::mode::getmap', 'health-host' => 'apps::vmware::connector::mode::healthhost', 'licenses' => 'apps::vmware::connector::mode::licenses', 'limit-vm' => 'apps::vmware::connector::mode::limitvm', 'list-clusters' => 'apps::vmware::connector::mode::listclusters', 'list-datacenters' => 'apps::vmware::connector::mode::listdatacenters', 'list-datastores' => 'apps::vmware::connector::mode::listdatastores', 'list-nichost' => 'apps::vmware::connector::mode::listnichost', 'maintenance-host' => 'apps::vmware::connector::mode::maintenancehost', 'memory-host' => 'apps::vmware::connector::mode::memoryhost', 'memory-vm' => 'apps::vmware::connector::mode::memoryvm', 'net-host' => 'apps::vmware::connector::mode::nethost', 'net-vm' => 'apps::vmware::connector::mode::netvm', 'service-host' => 'apps::vmware::connector::mode::servicehost', 'snapshot-vm' => 'apps::vmware::connector::mode::snapshotvm', 'stat-connectors' => 'apps::vmware::connector::mode::statconnectors', 'status-cluster' => 'apps::vmware::connector::mode::statuscluster', 'status-host' => 'apps::vmware::connector::mode::statushost', 'status-vm' => 'apps::vmware::connector::mode::statusvm', 'storage-host' => 'apps::vmware::connector::mode::storagehost', 'swap-host' => 'apps::vmware::connector::mode::swaphost', 'swap-vm' => 'apps::vmware::connector::mode::swapvm', 'thinprovisioning-vm' => 'apps::vmware::connector::mode::thinprovisioningvm', 'time-host' => 'apps::vmware::connector::mode::timehost', 'tools-vm' => 'apps::vmware::connector::mode::toolsvm', 'uptime-host' => 'apps::vmware::connector::mode::uptimehost', 'vmoperation-cluster' => 'apps::vmware::connector::mode::vmoperationcluster', 'vsan-cluster-usage' => 'apps::vmware::connector::mode::vsanclusterusage', }; $self->{custom_modes}->{connector} = 'apps::vmware::connector::custom::connector'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check VMWare with centreon-vmware connector. =cut centreon-plugins-20220113/apps/vmware/vcsa/000077500000000000000000000000001417000230700204345ustar00rootroot00000000000000centreon-plugins-20220113/apps/vmware/vcsa/restapi/000077500000000000000000000000001417000230700221035ustar00rootroot00000000000000centreon-plugins-20220113/apps/vmware/vcsa/restapi/custom/000077500000000000000000000000001417000230700234155ustar00rootroot00000000000000centreon-plugins-20220113/apps/vmware/vcsa/restapi/custom/api.pm000066400000000000000000000201411417000230700245220ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::vcsa::restapi::custom::api; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::http; use centreon::plugins::statefile; use JSON::XS; use Digest::MD5 qw(md5_hex); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port'}, 'proto:s' => { name => 'proto' }, 'api-username:s' => { name => 'api_username' }, 'api-password:s' => { name => 'api_password' }, 'timeout:s' => { name => 'timeout', default => 30 } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); $self->{cache} = centreon::plugins::statefile->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : undef; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 30; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : undef; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : undef; if (!defined($self->{hostname}) || $self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } if (!defined($self->{api_username}) || $self->{api_username} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-username option."); $self->{output}->option_exit(); } if (!defined($self->{api_password}) || $self->{api_password} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-password option."); $self->{output}->option_exit(); } $self->{cache}->check_options(option_results => $self->{option_results}); return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Content-Type', value => 'application/json;charset=UTF-8'); $self->{http}->add_header(key => 'Accept', value => 'application/json;charset=UTF-8'); $self->{http}->set_options(%{$self->{option_results}}); } sub json_decode { my ($self, %options) = @_; my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($options{content}); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } return $decoded; } sub clean_session_id { my ($self, %options) = @_; my $datas = { last_timestamp => time() }; $options{statefile}->write(data => $datas); $self->{session_id} = undef; $self->{http}->add_header(key => 'vmware-api-session-id', value => undef); } sub authenticate { my ($self, %options) = @_; my $has_cache_file = $options{statefile}->read(statefile => 'vcsa_api_' . md5_hex($self->{option_results}->{hostname}) . '_' . md5_hex($self->{option_results}->{api_username})); my $session_id = $options{statefile}->get(name => 'session_id'); if ($has_cache_file == 0 || !defined($session_id)) { my $content = $self->{http}->request( method => 'POST', query_form_post => '', url_path => '/rest/com/vmware/cis/session', credentials => 1, basic => 1, username => $self->{api_username}, password => $self->{api_password}, warning_status => '', unknown_status => '', critical_status => '' ); if ($self->{http}->get_code() != 200) { $self->{output}->add_option_msg(short_msg => "Login error [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded = $self->json_decode(content => $content); if (defined($decoded) && defined($decoded->{value})) { $session_id = $decoded->{value}; } else { $self->{output}->add_option_msg(short_msg => "Error retrieving session_id"); $self->{output}->option_exit(); } my $datas = { last_timestamp => time(), session_id => $session_id }; $options{statefile}->write(data => $datas); } $self->{session_id} = $session_id; $self->{http}->add_header(key => 'vmware-api-session-id', value => $self->{session_id}); } sub request_api { my ($self, %options) = @_; $self->settings(); if (!defined($self->{session_id})) { $self->authenticate(statefile => $self->{cache}); } my $content = $self->{http}->request(%options, warning_status => '', unknown_status => '', critical_status => '' ); # Maybe there is an issue with the session_id. So we retry. if ($self->{http}->get_code() != 200) { $self->clean_session_id(statefile => $self->{cache}); $self->authenticate(statefile => $self->{cache}); $content = $self->{http}->request(%options, warning_status => '', unknown_status => '', critical_status => '' ); } my $decoded = $self->json_decode(content => $content); if (!defined($decoded)) { $self->{output}->add_option_msg(short_msg => "Error while retrieving data (add --debug option for detailed message)"); $self->{output}->option_exit(); } if ($self->{http}->get_code() != 200) { $self->{output}->add_option_msg(short_msg => 'api request error: ' . (defined($decoded->{type}) ? $decoded->{type} : 'unknown')); $self->{output}->option_exit(); } return $decoded; } 1; __END__ =head1 NAME VCSA Rest API =head1 REST API OPTIONS =over 8 =item B<--hostname> Set hostname or IP of vsca. =item B<--port> Set port (Default: '443'). =item B<--proto> Specify https if needed (Default: 'https'). =item B<--api-username> Set username. =item B<--api-password> Set password. =item B<--timeout> Threshold for HTTP timeout (Default: '30'). =back =cut centreon-plugins-20220113/apps/vmware/vcsa/restapi/mode/000077500000000000000000000000001417000230700230275ustar00rootroot00000000000000centreon-plugins-20220113/apps/vmware/vcsa/restapi/mode/health.pm000066400000000000000000000100271417000230700246320ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::vcsa::restapi::mode::health; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); sub custom_status_output { my ($self, %options) = @_; my $msg .= 'health is ' . $self->{result_values}->{health}; return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'service', type => 1, cb_prefix_output => 'prefix_service_output', message_multiple => 'All services are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{service} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'health' }, { name => 'display' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold, } }, ]; } sub prefix_service_output { my ($self, %options) = @_; return "Service '" . $options{instance_value}->{display} ."' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $self->{version} = '1.0'; $options{options}->add_options(arguments => { 'filter-service:s' => { name => 'filter_service' }, 'unknown-status:s' => { name => 'unknown_status', default => '' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{health} !~ /green/' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => [ 'warning_status', 'critical_status', 'unknown_status', ]); } sub manage_selection { my ($self, %options) = @_; my $endpoint = '/rest/appliance/health/'; my @services = ('applmgmt', 'database-storage', 'load', 'mem', 'software-packages', 'storage', 'swap', 'system'); $self->{service} = {}; foreach (@services) { if (defined($self->{option_results}->{filter_service}) && $self->{option_results}->{filter_service} ne '' && $_ !~ /$self->{option_results}->{filter_service}/) { $self->{output}->output_add(long_msg => "skipping '" . $_ . "': no matching filter.", debug => 1); next; } my $result = $options{custom}->request_api(url_path => $endpoint . $_); $self->{service}->{$_} = { display => $_, health => $result->{value}, }; } } 1; __END__ =head1 MODE Check service health. =over 8 =item B<--filter-service> Filter service (can be a regexp). =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{health}, %{display} =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{health}, %{display} =item B<--critical-status> Set critical threshold for status (Default: '%{health} !~ /green/'). Can used special variables like: %{health}, %{display} =back =cut centreon-plugins-20220113/apps/vmware/vcsa/restapi/plugin.pm000066400000000000000000000025331417000230700237420ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::vcsa::restapi::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} = '1.0'; %{$self->{modes}} = ( 'health' => 'apps::vmware::vcsa::restapi::mode::health', ); $self->{custom_modes}{api} = 'apps::vmware::vcsa::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check vCenter Server Appliance (VCSA) through HTTP/REST API. =over 8 =back =cut centreon-plugins-20220113/apps/vmware/wsman/000077500000000000000000000000001417000230700206255ustar00rootroot00000000000000centreon-plugins-20220113/apps/vmware/wsman/mode/000077500000000000000000000000001417000230700215515ustar00rootroot00000000000000centreon-plugins-20220113/apps/vmware/wsman/mode/components/000077500000000000000000000000001417000230700237365ustar00rootroot00000000000000centreon-plugins-20220113/apps/vmware/wsman/mode/components/cim_card.pm000066400000000000000000000046621417000230700260450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::wsman::mode::components::cim_card; use strict; use warnings; sub load {} sub check { my ($self) = @_; my $result = $self->{wsman}->request(uri => 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_Card', dont_quit => 1); $self->{output}->output_add(long_msg => "Checking cim cards"); $self->{components}->{cim_card} = {name => 'cards', total => 0, skip => 0}; return if ($self->check_filter(section => 'cim_card') || !defined($result)); foreach (@{$result}) { my $instance = defined($_->{Name}) && $_->{Name} ne '' ? $_->{Name} : $_->{ElementName}; next if ($self->check_filter(section => 'cim_card', instance => $instance)); my $status = $self->get_status(entry => $_); if (!defined($status)) { $self->{output}->output_add(long_msg => sprintf("skipping card '%s' : no status", $_->{ElementName}), debug => 1); next; } $self->{components}->{cim_card}->{total}++; $self->{output}->output_add(long_msg => sprintf("Card '%s' status is '%s' [instance: %s].", $_->{ElementName}, $status, $instance )); my $exit = $self->get_severity(section => 'cim_card', label => 'default', value => $status); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Card '%s' status is '%s'", $_->{ElementName}, $status)); } } } 1; centreon-plugins-20220113/apps/vmware/wsman/mode/components/cim_computersystem.pm000066400000000000000000000050571417000230700302360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::wsman::mode::components::cim_computersystem; use strict; use warnings; sub load {} sub check { my ($self) = @_; my $result = $self->{wsman}->request(uri => 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ComputerSystem', dont_quit => 1); $self->{output}->output_add(long_msg => "Checking cim computer systems"); $self->{components}->{cim_computersystem} = {name => 'computer systems', total => 0, skip => 0}; return if ($self->check_filter(section => 'cim_computersystem') || !defined($result)); foreach (@{$result}) { my $instance = defined($_->{Name}) && $_->{Name} ne '' ? $_->{Name} : $_->{ElementName}; next if ($self->check_filter(section => 'cim_computersystem', instance => $instance)); my $status = $self->get_status(entry => $_); if (!defined($status)) { $self->{output}->output_add(long_msg => sprintf("skipping computer system '%s' : no status", $_->{ElementName}), debug => 1); next; } $self->{components}->{cim_computersystem}->{total}++; $self->{output}->output_add(long_msg => sprintf("Computer system '%s' status is '%s' [instance: %s].", $_->{ElementName}, $status, $instance )); my $exit = $self->get_severity(section => 'cim_computersystem', label => 'default', value => $status); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Computer system '%s' status is '%s'", $_->{ElementName}, $status)); } } } 1; centreon-plugins-20220113/apps/vmware/wsman/mode/components/cim_memory.pm000066400000000000000000000047141417000230700264420ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::wsman::mode::components::cim_memory; use strict; use warnings; sub load {} sub check { my ($self) = @_; my $result = $self->{wsman}->request(uri => 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_Memory', dont_quit => 1); $self->{output}->output_add(long_msg => "Checking cim memories"); $self->{components}->{cim_memory} = {name => 'memories', total => 0, skip => 0}; return if ($self->check_filter(section => 'cim_memory') || !defined($result)); foreach (@{$result}) { my $instance = defined($_->{Name}) && $_->{Name} ne '' ? $_->{Name} : $_->{ElementName}; next if ($self->check_filter(section => 'cim_memory', instance => $instance)); my $status = $self->get_status(entry => $_); if (!defined($status)) { $self->{output}->output_add(long_msg => sprintf("skipping memory '%s' : no status", $_->{ElementName}), debug => 1); next; } $self->{components}->{cim_memory}->{total}++; $self->{output}->output_add(long_msg => sprintf("Memory '%s' status is '%s' [instance: %s].", $_->{ElementName}, $status, $instance )); my $exit = $self->get_severity(section => 'cim_memory', label => 'default', value => $status); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Memory '%s' status is '%s'", $_->{ElementName}, $status)); } } } 1; centreon-plugins-20220113/apps/vmware/wsman/mode/components/cim_numericsensor.pm000066400000000000000000000143071417000230700300250ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::wsman::mode::components::cim_numericsensor; use strict; use warnings; use apps::vmware::wsman::mode::components::resources qw($mapping_units $mapping_sensortype); sub load {} sub check { my ($self) = @_; my $result = $self->{wsman}->request(uri => 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_NumericSensor', dont_quit => 1); $self->{output}->output_add(long_msg => "Checking cim numeric sensors"); $self->{components}->{cim_numericsensor} = {name => 'numeric sensors', total => 0, skip => 0}; return if ($self->check_filter(section => 'cim_numericsensor') || !defined($result)); foreach (@{$result}) { my $sensor_type = defined($mapping_sensortype->{$_->{SensorType}}) ? $mapping_sensortype->{$_->{SensorType}} : 'unknown'; my $name = defined($_->{Name}) && $_->{Name} ne '' ? $_->{Name} : $_->{ElementName}; my $instance = $sensor_type . '_' . $name; next if ($self->check_filter(section => 'cim_numericsensor', instance => $instance)); my $status = $self->get_status(entry => $_); if (!defined($status)) { $self->{output}->output_add(long_msg => sprintf("skipping numeric sensor '%s' : no status", $name), debug => 1); next; } $self->{components}->{cim_numericsensor}->{total}++; my $value = $_->{CurrentReading}; $value = $value * 10 ** int($_->{UnitModifier}) if (defined($value) && $value =~ /\d/); $self->{output}->output_add(long_msg => sprintf("Numeric sensor '%s' status is '%s' [instance: %s, current value: %s].", $name, $status, $instance, defined($value) ? $value : '-' )); my $exit = $self->get_severity(section => 'cim_numericsensor', label => 'default', value => $status); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Numeric sensor '%s' status is '%s'", $name, $status)); } next if (!defined($value) || $value !~ /\d/); my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'cim_numericsensor', instance => $instance, value => $value); if ($checked == 0) { my ($warn_th, $crit_th); $warn_th = $_->{LowerThresholdNonCritical} * 10 ** int($_->{UnitModifier}) . ':' if (defined($_->{LowerThresholdNonCritical}) && $_->{LowerThresholdNonCritical} =~ /\d/); if (defined($warn_th)) { $warn_th .= ($_->{UpperThresholdNonCritical} * 10 ** int($_->{UnitModifier})) if (defined($_->{UpperThresholdNonCritical}) && $_->{UpperThresholdNonCritical} =~ /\d/); } else { $warn_th = '~:' . ($_->{UpperThresholdNonCritical} * 10 ** int($_->{UnitModifier})) if (defined($_->{UpperThresholdNonCritical}) && $_->{UpperThresholdNonCritical} =~ /\d/); } $crit_th = $_->{LowerThresholdCritical} * 10 ** int($_->{UnitModifier}) . ':' if (defined($_->{LowerThresholdCritical}) && $_->{LowerThresholdCritical} =~ /\d/); if (defined($crit_th)) { $crit_th .= ($_->{UpperThresholdCritical} * 10 ** int($_->{UnitModifier})) if (defined($_->{UpperThresholdCritical}) && $_->{UpperThresholdCritical} =~ /\d/); } else { $crit_th = '~:' . ($_->{UpperThresholdCritical} * 10 ** int($_->{UnitModifier})) if (defined($_->{UpperThresholdCritical}) && $_->{UpperThresholdCritical} =~ /\d/); } $self->{perfdata}->threshold_validate(label => 'warning-cim_numericsensor-instance-' . $instance, value => $warn_th); $self->{perfdata}->threshold_validate(label => 'critical-cim_numericsensor-instance-' . $instance, value => $crit_th); $warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-cim_numericsensor-instance-' . $instance); $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-cim_numericsensor-instance-' . $instance); } if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit2, short_msg => sprintf("Numeric sensor '%s' value is %s %s", $name, $value, defined($mapping_units->{$_->{BaseUnits}}) ? $mapping_units->{$_->{BaseUnits}} : '-')); } my $min = defined($_->{MinReadable}) && $_->{MinReadable} =~ /\d/ ? $_->{MinReadable} * 10 ** int($_->{UnitModifier}) : undef; my $max = defined($_->{MaxReadable}) && $_->{MaxReadable} =~ /\d/ ? $_->{MaxReadable} * 10 ** int($_->{UnitModifier}) : undef; $self->{output}->perfdata_add( label => $sensor_type, unit => $mapping_units->{$_->{BaseUnits}}, nlabel => 'hardware.sensor.' . lc($sensor_type) . '.' . lc($mapping_units->{$_->{BaseUnits}}), instances => $name, value => $value, warning => $warn, critical => $crit, min => $min, max => $max ); } } 1; centreon-plugins-20220113/apps/vmware/wsman/mode/components/cim_processor.pm000066400000000000000000000052321417000230700271450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::wsman::mode::components::cim_processor; use strict; use warnings; sub load {} sub check { my ($self) = @_; my $result = $self->{wsman}->request(uri => 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_Processor', dont_quit => 1); $self->{output}->output_add(long_msg => "Checking cim processors"); $self->{components}->{cim_processor} = {name => 'processors', total => 0, skip => 0}; return if ($self->check_filter(section => 'cim_processor') || !defined($result)); foreach (@{$result}) { my $instance = defined($_->{Name}) && $_->{Name} ne '' ? $_->{Name} : $_->{ElementName}; next if ($self->check_filter(section => 'cim_processor', instance => $instance)); my $status = $self->get_status(entry => $_); if (!defined($status)) { $self->{output}->output_add(long_msg => sprintf("skipping processor '%s' : no status", $_->{ElementName}), debug => 1); next; } $self->{components}->{cim_processor}->{total}++; my $model_name = defined($_->{ModelName}) && $_->{ModelName} ne '' ? $_->{ModelName} : 'unknown'; $model_name =~ s/\s+/ /g; $self->{output}->output_add(long_msg => sprintf("Processor '%s' status is '%s' [instance: %s, Model: %s].", $_->{ElementName}, $status, $instance, $model_name )); my $exit = $self->get_severity(section => 'cim_processor', label => 'default', value => $status); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Processor '%s' status is '%s'", $_->{ElementName}, $status)); } } } 1; centreon-plugins-20220113/apps/vmware/wsman/mode/components/cim_recordlog.pm000066400000000000000000000047671417000230700271220ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::wsman::mode::components::cim_recordlog; use strict; use warnings; sub load {} sub check { my ($self) = @_; my $result = $self->{wsman}->request(uri => 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_RecordLog', dont_quit => 1); $self->{output}->output_add(long_msg => "Checking cim recordlog"); $self->{components}->{cim_recordlog} = {name => 'recordlog', total => 0, skip => 0}; return if ($self->check_filter(section => 'cim_recordlog') || !defined($result)); foreach (@{$result}) { my $instance = defined($_->{Name}) && $_->{Name} ne '' ? $_->{Name} : $_->{ElementName}; next if ($self->check_filter(section => 'cim_recordlog', instance => $instance)); my $status = $self->get_status(entry => $_); if (!defined($status)) { $self->{output}->output_add(long_msg => sprintf("skipping record log '%s' : no status", $_->{ElementName}), debug => 1); next; } $self->{components}->{cim_recordlog}->{total}++; $self->{output}->output_add(long_msg => sprintf("Record log '%s' status is '%s' [instance: %s].", $_->{ElementName}, $status, $instance )); my $exit = $self->get_severity(section => 'cim_recordlog', label => 'default', value => $status); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Record log '%s' status is '%s'", $_->{ElementName}, $status)); } } } 1; centreon-plugins-20220113/apps/vmware/wsman/mode/components/omc_discretesensor.pm000066400000000000000000000055251417000230700301750ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::wsman::mode::components::omc_discretesensor; use strict; use warnings; use apps::vmware::wsman::mode::components::resources qw($mapping_EnableState); sub load {} sub check { my ($self) = @_; my $result = $self->{wsman}->request(uri => 'http://schema.omc-project.org/wbem/wscim/1/cim-schema/2/OMC_DiscreteSensor', dont_quit => 1); $self->{output}->output_add(long_msg => "Checking OMC discrete sensors"); $self->{components}->{omc_discretesensor} = {name => 'omc discrete sensors', total => 0, skip => 0}; return if ($self->check_filter(section => 'omc_discretesensor') || !defined($result)); foreach (@{$result}) { my $instance = $_->{Name}; next if ($self->check_filter(section => 'omc_discretesensor', instance => $instance)); if (defined($mapping_EnableState->{$_->{EnabledState}}) && $mapping_EnableState->{$_->{EnabledState}} !~ /enabled/i) { $self->{output}->output_add(long_msg => sprintf("skipping discrete sensor '%s' : not enabled", $_->{Name}), debug => 1); next; } my $status = $self->get_status(entry => $_); if (!defined($status)) { $self->{output}->output_add(long_msg => sprintf("skipping discrete sensor '%s' : no status", $_->{Name}), debug => 1); next; } $self->{components}->{omc_discretesensor}->{total}++; $self->{output}->output_add(long_msg => sprintf("Discrete sensor '%s' status is '%s' [instance: %s].", $_->{Name}, $status, $instance )); my $exit = $self->get_severity(section => 'omc_discretesensor', label => 'default', value => $status); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Discrete sensor '%s' status is '%s'", $_->{Name}, $status)); } } } 1; centreon-plugins-20220113/apps/vmware/wsman/mode/components/omc_fan.pm000066400000000000000000000045351417000230700257050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::wsman::mode::components::omc_fan; use strict; use warnings; sub load {} sub check { my ($self) = @_; my $result = $self->{wsman}->request(uri => 'http://schema.omc-project.org/wbem/wscim/1/cim-schema/2/OMC_Fan', dont_quit => 1); $self->{output}->output_add(long_msg => "Checking OMC fans"); $self->{components}->{omc_fan} = {name => 'omc fans', total => 0, skip => 0}; return if ($self->check_filter(section => 'omc_fan') || !defined($result)); foreach (@{$result}) { my $instance = $_->{Name}; next if ($self->check_filter(section => 'omc_fan', instance => $instance)); my $status = $self->get_status(entry => $_); if (!defined($status)) { $self->{output}->output_add(long_msg => sprintf("skipping fan '%s' : no status", $_->{Name}), debug => 1); next; } $self->{components}->{omc_fan}->{total}++; $self->{output}->output_add(long_msg => sprintf("Fan '%s' status is '%s' [instance: %s].", $_->{Name}, $status, $instance )); my $exit = $self->get_severity(section => 'omc_fan', label => 'default', value => $status); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Fan '%s' status is '%s'", $_->{Name}, $status)); } } } 1; centreon-plugins-20220113/apps/vmware/wsman/mode/components/omc_psu.pm000066400000000000000000000046121417000230700257440ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::wsman::mode::components::omc_psu; use strict; use warnings; sub load {} sub check { my ($self) = @_; my $result = $self->{wsman}->request(uri => 'http://schema.omc-project.org/wbem/wscim/1/cim-schema/2/OMC_PowerSupply', dont_quit => 1); $self->{output}->output_add(long_msg => "Checking OMC power supplies"); $self->{components}->{omc_psu} = {name => 'omc psus', total => 0, skip => 0}; return if ($self->check_filter(section => 'omc_psu') || !defined($result)); foreach (@{$result}) { my $instance = $_->{Name}; next if ($self->check_filter(section => 'omc_psu', instance => $instance)); my $status = $self->get_status(entry => $_); if (!defined($status)) { $self->{output}->output_add(long_msg => sprintf("skipping power supply '%s' : no status", $_->{Name}), debug => 1); next; } $self->{components}->{omc_psu}->{total}++; $self->{output}->output_add(long_msg => sprintf("Power supply '%s' status is '%s' [instance: %s].", $_->{Name}, $status, $instance )); my $exit = $self->get_severity(section => 'omc_psu', label => 'default', value => $status); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Power supply '%s' status is '%s'", $_->{Name}, $status)); } } } 1; centreon-plugins-20220113/apps/vmware/wsman/mode/components/resources.pm000066400000000000000000000101461417000230700263100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::wsman::mode::components::resources; use strict; use warnings; use Exporter; our $mapping_HealthState; our $mapping_OperationalStatus; our $mapping_EnableState; our $mapping_units; our $mapping_sensortype; our @ISA = qw(Exporter); our @EXPORT_OK = qw($mapping_HealthState $mapping_OperationalStatus $mapping_EnableState $mapping_units $mapping_sensortype); $mapping_EnableState = { 0 => 'Unknown', 1 => 'Other', 2 => 'Enabled', 3 => 'Disabled', 4 => 'Shutting Down', 5 => 'Not Applicable', 6 => 'Enabled but Offline', 7 => 'In Test', 8 => 'Deferred', 9 => 'Quiesce', 10 => 'Starting', }; $mapping_HealthState = { 0 => 'Unknown', 5 => 'OK', 10 => 'Degraded', 15 => 'Minor failure', 20 => 'Major failure', 25 => 'Critical failure', 30 => 'Non-recoverable error', }; $mapping_OperationalStatus = { 0 => 'Unknown', 1 => 'Other', 2 => 'OK', 3 => 'Degraded', 4 => 'Stressed', 5 => 'Predictive Failure', 6 => 'Error', 7 => 'Non-Recoverable Error', 8 => 'Starting', 9 => 'Stopping', 10 => 'Stopped', 11 => 'In Service', 12 => 'No Contact', 13 => 'Lost Communication', 14 => 'Aborted', 15 => 'Dormant', 16 => 'Supporting Entity in Error', 17 => 'Completed', 18 => 'Power Mode', 19 => 'Relocating', }; $mapping_sensortype = { 0 => 'unknown', 1 => 'other', 2 => 'temperature', # Temperature 3 => 'voltage', # Voltage 4 => 'current', # Current 5 => 'tachometer', 6 => 'counter', 7 => 'switch', 8 => 'lock', 9 => 'humidity', # Humidity 10 => 'smokeDetection', # Smoke Detection 11 => 'presence', 12 => 'airFlow', # Air Flow 13 => 'powerConsumption', # Power Consumption 14 => 'powerProduction', # Power Production 15 => 'pressureIntrusion', # PressureIntrusion 16 => 'intrusion', }; $mapping_units = { 0 => 'unknown', 1 => 'unknown', 2 => 'celsius', # Degrees C 3 => 'fahrenheit', # Degrees F 4 => 'kelvin', # Degrees K 5 => 'volt', # Volts 6 => 'ampere', # Amps, 7 => 'watt', # Watts 8 => 'Joules', 9 => 'Coulombs', 10 => 'VA', 11 => 'Nits', 12 => 'Lumens', 13 => 'Lux', 14 => 'Candelas', 15 => 'kPa', 16 => 'PSI', 17 => 'Newtons', 18 => 'CFM', 19 => 'rpm', 20 => 'Hz', # Hertz 21 => 'Seconds', 22 => 'Minutes', 23 => 'Hours', 24 => 'Days', 25 => 'Weeks', 26 => 'Mils', 27 => 'Inches', 28 => 'Feet', 29 => 'CubicInches', 30 => 'CubicFeet', 31 => 'Meters', 32 => 'CubicCentimeters', 33 => 'CubicMeters', 34 => 'Liters', 35 => 'Fluid_Ounces', 36 => 'Radians', 37 => 'Steradians', 38 => 'Revolutions', 39 => 'Cycles', 40 => 'Gravities', 41 => 'Ounces', 42 => 'Pounds', 43 => 'FootPounds', 44 => 'OunceInches', 45 => 'Gauss', 46 => 'Gilberts', 47 => 'Henries', 48 => 'Farads', 49 => 'Ohms', 50 => 'Siemens', 51 => 'Moles', 52 => 'Becquerels', 53 => 'PPM', 54 => 'Decibels', 55 => 'DbA', 56 => 'DbC', 57 => 'Grays', 58 => 'Sieverts', 59 => 'ColorTemperatureDegreesKelvin', 60 => 'bits', # bits 61 => 'bytes', # Bytes 62 => 'Words', 63 => 'DoubleWords', 64 => 'QuadWords', 65 => 'percentage', # Percentage, 66 => 'Pascals', }; 1; centreon-plugins-20220113/apps/vmware/wsman/mode/components/vmware_battery.pm000066400000000000000000000047621417000230700273400ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::wsman::mode::components::vmware_battery; use strict; use warnings; sub load {} sub check { my ($self) = @_; my $result = $self->{wsman}->request(uri => 'http://schemas.vmware.com/wbem/wscim/1/cim-schema/2/VMware_Battery', dont_quit => 1); $self->{output}->output_add(long_msg => "Checking vmware batteries"); $self->{components}->{vmware_battery} = {name => 'batteries', total => 0, skip => 0}; return if ($self->check_filter(section => 'vmware_battery') || !defined($result)); foreach (@{$result}) { my $instance = defined($_->{Name}) && $_->{Name} ne '' ? $_->{Name} : $_->{ElementName}; next if ($self->check_filter(section => 'vmware_battery', instance => $instance)); my $status = $self->get_status(entry => $_); if (!defined($status)) { $self->{output}->output_add(long_msg => sprintf("skipping battery '%s' : no status", $_->{ElementName}), debug => 1); next; } $self->{components}->{vmware_battery}->{total}++; $self->{output}->output_add(long_msg => sprintf("Battery '%s' status is '%s' [instance: %s].", $_->{ElementName}, $status, $instance )); my $exit = $self->get_severity(section => 'vmware_battery', label => 'default', value => $status); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Battery '%s' status is '%s'", $_->{ElementName}, $status)); } } } 1; centreon-plugins-20220113/apps/vmware/wsman/mode/components/vmware_controller.pm000066400000000000000000000050221417000230700300370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::wsman::mode::components::vmware_controller; use strict; use warnings; sub load {} sub check { my ($self) = @_; my $result = $self->{wsman}->request(uri => 'http://schemas.vmware.com/wbem/wscim/1/cim-schema/2/VMware_Controller', dont_quit => 1); $self->{output}->output_add(long_msg => "Checking vmware controller"); $self->{components}->{vmware_controller} = {name => 'controller', total => 0, skip => 0}; return if ($self->check_filter(section => 'vmware_controller') || !defined($result)); foreach (@{$result}) { my $instance = defined($_->{Name}) && $_->{Name} ne '' ? $_->{Name} : $_->{ElementName}; next if ($self->check_filter(section => 'vmware_controller', instance => $instance)); my $status = $self->get_status(entry => $_); if (!defined($status)) { $self->{output}->output_add(long_msg => sprintf("skipping controller '%s' : no status", $_->{ElementName}), debug => 1); next; } $self->{components}->{vmware_controller}->{total}++; $self->{output}->output_add(long_msg => sprintf("Controller '%s' status is '%s' [instance: %s].", $_->{ElementName}, $status, $instance )); my $exit = $self->get_severity(section => 'vmware_controller', label => 'default', value => $status); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Controller '%s' status is '%s'", $_->{ElementName}, $status)); } } } 1; centreon-plugins-20220113/apps/vmware/wsman/mode/components/vmware_sassataport.pm000066400000000000000000000050521417000230700302230ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::wsman::mode::components::vmware_sassataport; use strict; use warnings; sub load {} sub check { my ($self) = @_; my $result = $self->{wsman}->request(uri => 'http://schemas.vmware.com/wbem/wscim/1/cim-schema/2/VMware_SASSATAPort', dont_quit => 1); $self->{output}->output_add(long_msg => "Checking vmware sas/sata ports"); $self->{components}->{vmware_sassataport} = {name => 'sas/sata ports', total => 0, skip => 0}; return if ($self->check_filter(section => 'vmware_sassataport') || !defined($result)); foreach (@{$result}) { my $instance = defined($_->{Name}) && $_->{Name} ne '' ? $_->{Name} : $_->{ElementName}; next if ($self->check_filter(section => 'vmware_sassataport', instance => $instance)); my $status = $self->get_status(entry => $_); if (!defined($status)) { $self->{output}->output_add(long_msg => sprintf("skipping sas/sata port '%s' : no status", $_->{ElementName}), debug => 1); next; } $self->{components}->{vmware_sassataport}->{total}++; $self->{output}->output_add(long_msg => sprintf("Sas/Sata port '%s' status is '%s' [instance: %s].", $_->{ElementName}, $status, $instance )); my $exit = $self->get_severity(section => 'vmware_sassataport', label => 'default', value => $status); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Sas/Sata port '%s' status is '%s'", $_->{ElementName}, $status)); } } } 1; centreon-plugins-20220113/apps/vmware/wsman/mode/components/vmware_storageextent.pm000066400000000000000000000050731417000230700305560ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::wsman::mode::components::vmware_storageextent; use strict; use warnings; sub load {} sub check { my ($self) = @_; my $result = $self->{wsman}->request(uri => 'http://schemas.vmware.com/wbem/wscim/1/cim-schema/2/VMware_StorageExtent', dont_quit => 1); $self->{output}->output_add(long_msg => "Checking vmware storage extent"); $self->{components}->{vmware_storageextent} = {name => 'storage extent', total => 0, skip => 0}; return if ($self->check_filter(section => 'vmware_storageextent') || !defined($result)); foreach (@{$result}) { my $instance = defined($_->{Name}) && $_->{Name} ne '' ? $_->{Name} : $_->{ElementName}; next if ($self->check_filter(section => 'vmware_storageextent', instance => $instance)); my $status = $self->get_status(entry => $_); if (!defined($status)) { $self->{output}->output_add(long_msg => sprintf("skipping storage extent '%s' : no status", $_->{ElementName}), debug => 1); next; } $self->{components}->{vmware_storageextent}->{total}++; $self->{output}->output_add(long_msg => sprintf("Storage extent '%s' status is '%s' [instance: %s].", $_->{ElementName}, $status, $instance )); my $exit = $self->get_severity(section => 'vmware_storageextent', label => 'default', value => $status); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Storage extent '%s' status is '%s'", $_->{ElementName}, $status)); } } } 1; centreon-plugins-20220113/apps/vmware/wsman/mode/components/vmware_storagevolume.pm000066400000000000000000000050751417000230700305600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::wsman::mode::components::vmware_storagevolume; use strict; use warnings; sub load {} sub check { my ($self) = @_; my $result = $self->{wsman}->request(uri => 'http://schemas.vmware.com/wbem/wscim/1/cim-schema/2/VMware_StorageVolume', dont_quit => 1); $self->{output}->output_add(long_msg => "Checking vmware storage volumes"); $self->{components}->{vmware_storagevolume} = {name => 'storage volumes', total => 0, skip => 0}; return if ($self->check_filter(section => 'vmware_storagevolume') || !defined($result)); foreach (@{$result}) { my $instance = defined($_->{Name}) && $_->{Name} ne '' ? $_->{Name} : $_->{ElementName}; next if ($self->check_filter(section => 'vmware_storagevolume', instance => $instance)); my $status = $self->get_status(entry => $_); if (!defined($status)) { $self->{output}->output_add(long_msg => sprintf("skipping storage volume '%s' : no status", $_->{ElementName}), debug => 1); next; } $self->{components}->{vmware_storagevolume}->{total}++; $self->{output}->output_add(long_msg => sprintf("Storage volume '%s' status is '%s' [instance: %s].", $_->{ElementName}, $status, $instance )); my $exit = $self->get_severity(section => 'vmware_storagevolume', label => 'default', value => $status); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Storage volume '%s' status is '%s'", $_->{ElementName}, $status)); } } } 1; centreon-plugins-20220113/apps/vmware/wsman/mode/hardware.pm000066400000000000000000000130121417000230700237010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::wsman::mode::hardware; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; use apps::vmware::wsman::mode::components::resources qw($mapping_HealthState $mapping_OperationalStatus); sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^(cim_numericsensor)$'; $self->{cb_hook1} = 'get_type'; $self->{thresholds} = { default => [ ['Unknown', 'OK'], ['OK', 'OK'], ['Degraded', 'WARNING'], ['Minor failure', 'WARNING'], ['Major failure', 'CRITICAL'], ['Critical failure', 'CRITICAL'], ['Non-recoverable error', 'CRITICAL'], ['Other', 'UNKNOWN'], ['Stressed', 'WARNING'], ['Predictive Failure', 'WARNING'], ['Error', 'CRITICAL'], ['Starting', 'OK'], ['Stopping', 'WARNING'], ['In Service', 'OK'], ['No Contact', 'CRITICAL'], ['Lost Communication', 'CRITICAL'], ['Aborted', 'CRITICAL'], ['Dormant', 'OK'], ['Supporting Entity in Error', 'CRITICAL'], ['Completed', 'OK'], ['Power Mode', 'OK'], ['Relocating', 'WARNING'], ], }; $self->{components_path} = 'apps::vmware::wsman::mode::components'; $self->{components_module} = ['omc_discretesensor', 'omc_fan', 'omc_psu', 'vmware_storageextent', 'vmware_controller', 'vmware_storagevolume', 'vmware_battery', 'vmware_sassataport', 'cim_card', 'cim_computersystem', 'cim_numericsensor', 'cim_memory', 'cim_processor', 'cim_recordlog']; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub get_type { my ($self, %options) = @_; my $result = $options{wsman}->request(uri => 'http://schema.omc-project.org/wbem/wscim/1/cim-schema/2/OMC_SMASHFirmwareIdentity', dont_quit => 1); $result = pop(@$result) if (defined($result)); $self->{manufacturer} = 'unknown'; if (defined($result->{Manufacturer}) && $result->{Manufacturer} ne '') { $self->{manufacturer} = $result->{Manufacturer}; } $result = $options{wsman}->request(uri => 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_Chassis'); $result = pop(@$result); my $model = defined($result->{Model}) && $result->{Model} ne '' ? $result->{Model} : 'unknown'; $self->{output}->output_add(long_msg => sprintf("Manufacturer : %s, Model : %s", $self->{manufacturer}, $model)); $self->{wsman} = $options{wsman}; } sub get_status { my ($self, %options) = @_; my $status; if ($self->{manufacturer} =~ /HP/i) { $status = $mapping_HealthState->{$options{entry}->{HealthState}} if (defined($options{entry}->{HealthState}) && defined($mapping_HealthState->{$options{entry}->{HealthState}})); } else { $status = $mapping_OperationalStatus->{$options{entry}->{OperationalStatus}} if (defined($options{entry}->{OperationalStatus}) && defined($mapping_OperationalStatus->{$options{entry}->{OperationalStatus}})); } return $status; } 1; __END__ =head1 MODE Check ESXi Hardware. Example: centreon_plugins.pl --plugin=apps::vmware::wsman::plugin --mode=hardware --hostname='XXX.XXX.XXX.XXX' --wsman-username='XXXX' --wsman-password='XXXX' --wsman-scheme=https --wsman-port=443 --verbose =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'omc_discretesensor', 'omc_fan', 'omc_psu', 'vmware_storageextent', 'vmware_controller', 'vmware_storagevolume', 'vmware_battery', 'vmware_sassataport', 'cim_card', 'cim_computersystem', 'cim_numericsensor', 'cim_memory', 'cim_processor', 'cim_recordlog'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=cim_card --filter=cim_recordlog) Can also exclude specific instance: --filter='omc_psu,Power Supply 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='cim_card,CRITICAL,^(?!(OK)$)' =item B<--warning> Set warning threshold for temperatures (syntax: type,instance,threshold) Example: --warning='cim_numericsensor,.*,30' =item B<--critical> Set critical threshold for temperatures (syntax: type,instance,threshold) Example: --critical='cim_numericsensor,.*,40' =back =cut centreon-plugins-20220113/apps/vmware/wsman/plugin.pm000066400000000000000000000023451417000230700224650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vmware::wsman::plugin; use strict; use warnings; use base qw(centreon::plugins::script_wsman); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $self->{version} = '0.1'; %{$self->{modes}} = ( 'hardware' => 'apps::vmware::wsman::mode::hardware', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check VMWare ESXi Hardware (ws-management protocol). =cut centreon-plugins-20220113/apps/voip/000077500000000000000000000000001417000230700171545ustar00rootroot00000000000000centreon-plugins-20220113/apps/voip/3cx/000077500000000000000000000000001417000230700176515ustar00rootroot00000000000000centreon-plugins-20220113/apps/voip/3cx/restapi/000077500000000000000000000000001417000230700213205ustar00rootroot00000000000000centreon-plugins-20220113/apps/voip/3cx/restapi/custom/000077500000000000000000000000001417000230700226325ustar00rootroot00000000000000centreon-plugins-20220113/apps/voip/3cx/restapi/custom/api.pm000066400000000000000000000256321417000230700237510ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::voip::3cx::restapi::custom::api; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::http; use centreon::plugins::statefile; use JSON::XS; use Digest::MD5 qw(md5_hex); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port'}, 'proto:s' => { name => 'proto' }, 'api-username:s' => { name => 'api_username' }, 'api-password:s' => { name => 'api_password' }, 'timeout:s' => { name => 'timeout', default => 30 }, 'unknown-http-status:s' => { name => 'unknown_http_status' }, 'warning-http-status:s' => { name => 'warning_http_status' }, 'critical-http-status:s' => { name => 'critical_http_status' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); $self->{cache} = centreon::plugins::statefile->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 30; $self->{ssl_opt} = (defined($self->{option_results}->{ssl_opt})) ? $self->{option_results}->{ssl_opt} : undef; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : ''; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : ''; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300' ; $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --hostname option.'); $self->{output}->option_exit(); } if ($self->{api_username} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --api-username option.'); $self->{output}->option_exit(); } if ($self->{api_password} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --api-password option.'); $self->{output}->option_exit(); } $self->{cache}->check_options(option_results => $self->{option_results}); return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{ssl_opt} = $self->{ssl_opt}; $self->{option_results}->{timeout} = $self->{timeout}; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Content-Type', value => 'application/json;charset=UTF-8'); if (defined($self->{cookie})) { $self->{http}->add_header(key => 'Cookie', value => $self->{cookie}); if (defined($self->{xsrf})) { $self->{http}->add_header(key => 'X-XSRF-TOKEN', value => $self->{xsrf}); } } $self->{http}->set_options(%{$self->{option_results}}); } sub authenticate { my ($self, %options) = @_; my $has_cache_file = $options{statefile}->read(statefile => '3cx_api_' . md5_hex($self->{option_results}->{hostname}) . '_' . md5_hex($self->{option_results}->{api_username})); my $cookie = $options{statefile}->get(name => 'cookie'); my $xsrf = $options{statefile}->get(name => 'xsrf'); my $expires_on = $options{statefile}->get(name => 'expires_on'); if ($has_cache_file == 0 || !defined($cookie) || !defined($xsrf) || (($expires_on - time()) < 10)) { my $post_data = '{"Username":"' . $self->{api_username} . '",' . '"Password":"' . $self->{api_password} . '"}'; $self->settings(); my $content = $self->{http}->request( method => 'POST', query_form_post => $post_data, url_path => '/api/login', unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status} ); my $header = $self->{http}->get_header(name => 'Set-Cookie'); # 3CX v16 cookie name is .AspNetCore.Cookies # 3CX v18 cookie name is .AspNetCore.CookiesA if (defined ($header) && $header =~ /(?:^| )(.AspNetCore.Cookies[A]?=[^;]+);.*/) { $cookie = $1; } else { $self->{output}->add_option_msg(short_msg => "Error retrieving cookie"); $self->{output}->option_exit(); } # 3CX 16.0.5.611 does not use XSRF-TOKEN anymore if (defined ($header) && $header =~ /(?:^| )XSRF-TOKEN=([^;]+);.*/) { $xsrf = $1; } my $datas = { last_timestamp => time(), cookie => $cookie, xsrf => $xsrf, expires_on => time() + (3600 * 24) }; $options{statefile}->write(data => $datas); } $self->{cookie} = $cookie; $self->{xsrf} = $xsrf; } sub request_api { my ($self, %options) = @_; if (!defined($self->{cookie})) { $self->authenticate(statefile => $self->{cache}); } $self->settings(); my $content = $self->{http}->request( %options, unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status} ); # Some content may be strangely returned, for example : # 3CX < 16.0.2.910 : "[{\"Category\":\"provider\",\"Count\":1}]" # 3CX >= 16.0.2.910 : {"tcxUpdate":"[{\"Category\":\"provider\",\"Count\":5},{\"Category\":\"sp150\",\"Count\":1}]","perPage":"[]"} if (defined($options{eval_content}) && $options{eval_content} == 1) { if (my $evcontent = eval "$content") { $content = $evcontent; } } my $decoded; eval { $decoded = JSON::XS->new->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } if (!defined($decoded)) { $self->{output}->add_option_msg(short_msg => "Error while retrieving data (add --debug option for detailed message)"); $self->{output}->option_exit(); } return $decoded; } sub internal_activecalls { my ($self, %options) = @_; my $status = $self->request_api(method => 'GET', url_path =>'/api/activeCalls'); return $status; } sub api_activecalls { my ($self, %options) = @_; my $status = $self->internal_activecalls(); return $status->{list}; } sub internal_extension_list { my ($self, %options) = @_; my $status = $self->request_api(method => 'GET', url_path =>'/api/ExtensionList'); return $status; } sub api_extension_list { my ($self, %options) = @_; my $status = $self->internal_extension_list(); return $status->{list}; } sub internal_single_status { my ($self, %options) = @_; my $status = $self->request_api(method => 'GET', url_path =>'/api/SystemStatus/GetSingleStatus'); return $status; } sub api_single_status { my ($self, %options) = @_; my $status = $self->internal_single_status(); return $status->{Health}; } sub internal_system_status { my ($self, %options) = @_; my $status = $self->request_api(method => 'GET', url_path =>'/api/SystemStatus'); return $status; } sub api_system_status { my ($self, %options) = @_; my $status = $self->internal_system_status(); return $status; } sub internal_update_checker { my ($self, %options) = @_; my $status = $self->request_api(method => 'GET', url_path =>'/api/UpdateChecker/GetFromParams', eval_content => 1); if (ref($status) eq 'HASH') { $status = $status->{tcxUpdate}; if (ref($status) ne 'ARRAY') { # See above note about strange content $status = JSON::XS->new->decode($status); } } return $status; } sub api_update_checker { my ($self, %options) = @_; my $status = $self->internal_update_checker(); return $status; } 1; __END__ =head1 NAME 3CX Rest API =head1 REST API OPTIONS =over 8 =item B<--hostname> Set hostname or IP of 3CX server. =item B<--port> Set 3CX Port (Default: '443'). =item B<--proto> Specify http if needed (Default: 'https'). =item B<--api-username> Set 3CX Username. =item B<--api-password> Set 3CX Password. =item B<--timeout> Threshold for HTTP timeout (Default: '30'). =item B<--unknown-http-status> Threshold unknown for http response code. (Default: '%{http_code} < 200 or %{http_code} >= 300') =item B<--warning-http-status> Threshold warning for http response code. =item B<--critical-http-status> Threshold critical for http response code. =back =cut centreon-plugins-20220113/apps/voip/3cx/restapi/mode/000077500000000000000000000000001417000230700222445ustar00rootroot00000000000000centreon-plugins-20220113/apps/voip/3cx/restapi/mode/extension.pm000066400000000000000000000140171417000230700246210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::voip::3cx::restapi::mode::extension; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); use Date::Parse; sub custom_status_output { my ($self, %options) = @_; my $msg = ''; if ($self->{result_values}->{registered} eq 'true') { $msg .= 'registered'; } else { $msg .= 'unregistered'; } if ($self->{result_values}->{dnd} eq 'true') { $msg .= ', in DND'; } else { $msg .= ', not in DND'; } $msg .= ', ' . $self->{result_values}->{profile}; if ($self->{result_values}->{status} ne '') { $msg .= ', ' . $self->{result_values}->{status}; $msg .= ' since ' . sprintf '%02dh %02dm %02ds', (gmtime($self->{result_values}->{duration}))[2,1,0]; } return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'extension', type => 1, cb_prefix_output => 'prefix_service_output', message_multiple => 'All extensions are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'count', nlabel => '3cx.extensions.count', display_ok => 0, set => { key_values => [ { name => 'count' } ], output_template => 'Extensions count : %d', perfdatas => [ { template => '%d', min => 0 } ] } } ]; $self->{maps_counters}->{extension} = [ { label => 'status', type => 2, set => { key_values => [ { name => 'extension' }, { name => 'registered' }, { name => 'dnd' }, { name => 'profile' }, { name => 'status' }, { name => 'duration' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } } ]; } sub prefix_service_output { my ($self, %options) = @_; return "Extension '" . $options{instance_value}->{extension} ."' "; } 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-extension:s' => { name => 'filter_extension' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my %status; my $activecalls = $options{custom}->api_activecalls(); foreach my $item (@$activecalls) { $status{$item->{Caller}} = { Status => $item->{Status}, Duration => $item->{Duration}, EstablishedAt => $item->{EstablishedAt}, }; $status{$item->{Callee}} = { Status => $item->{Status}, Duration => $item->{Duration}, EstablishedAt => $item->{EstablishedAt}, }; } my $extension = $options{custom}->api_extension_list(); $self->{extension} = {}; foreach my $item (@$extension) { if (!defined($item->{_str})) { # 3CX >= 16.0.6.641 $item->{_str} = $item->{Number} . (length($item->{FirstName}) ? ' ' . $item->{FirstName} : '') . (length($item->{LastName}) ? ' ' . $item->{LastName} : ''); } if (defined($self->{option_results}->{filter_extension}) && $self->{option_results}->{filter_extension} ne '' && $item->{_str} !~ /$self->{option_results}->{filter_extension}/) { $self->{output}->output_add(long_msg => "skipping extension '" . $item->{_str} . "': no matching filter.", debug => 1); next; } $self->{global}->{count}++; $self->{extension}->{$item->{_str}} = { extension => $item->{_str}, registered => $item->{IsRegistered} ? 'true' : 'false', dnd => $item->{DND} ? 'true' : 'false', profile => $item->{CurrentProfile}, status => $status{$item->{_str}}->{Status} ? $status{$item->{_str}}->{Status} : '', duration => 0 }; if (defined($status{$item->{_str}}->{EstablishedAt})) { # 3CX >= 16.0.6.641 (#2020-09-08T08:26:05+00:00) $self->{extension}->{$item->{_str}}->{duration} = time - Date::Parse::str2time($status{$item->{_str}}->{EstablishedAt}); } elsif (defined($status{$item->{_str}}->{Duration}) && $status{$item->{_str}}->{Duration} =~ /(\d\d):(\d\d):(\d\d).*/) { $self->{extension}->{$item->{_str}}->{duration} = $1 * 3600 + $2 * 60 + $3; } } } 1; __END__ =head1 MODE Check extentions status =over 8 =item B<--filter-extension> Filter extension. =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{extension}, %{registered}, %{dnd}, %{profile}, %{status}, %{duration} =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{extension}, %{registered}, %{dnd}, %{profile}, %{status}, %{duration} =item B<--critical-status> Set critical threshold for status. Can used special variables like: %{extension}, %{registered}, %{dnd}, %{profile}, %{status}, %{duration} =item B<--warning-*> B<--critical-*> Thresholds (Can be: 'count'). =back =cut centreon-plugins-20220113/apps/voip/3cx/restapi/mode/system.pm000066400000000000000000000167001417000230700241320ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::voip::3cx::restapi::mode::system; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; my $msg = ''; if ($self->{result_values}->{service} !~ /^Has[A-Z]/) { $msg .= 'error'; } $msg .= ': ' . $self->{result_values}->{error}; return $msg; } sub custom_calls_usage_output { my ($self, %options) = @_; return sprintf( 'active calls usage total: %s used: %s (%.2f%%) free: %s (%.2f%%)', $self->{result_values}->{calls_max}, $self->{result_values}->{calls_used}, $self->{result_values}->{calls_prct_used}, $self->{result_values}->{calls_free}, 100 - $self->{result_values}->{calls_prct_used} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'service', type => 1, cb_prefix_output => 'prefix_service_output', message_multiple => 'All services are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'calls-active-usage', nlabel => 'system.calls.active.usage.count', set => { key_values => [ { name => 'calls_used' }, { name => 'calls_free' }, { name => 'calls_prct_used' }, { name => 'calls_max' } ], closure_custom_output => $self->can('custom_calls_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'calls_max' } ] } }, { label => 'calls-active-free', nlabel => 'system.calls.active.free.count', display_ok => 0, set => { key_values => [ { name => 'calls_free' }, { name => 'calls_used' }, { name => 'calls_prct_used' }, { name => 'calls_max' } ], closure_custom_output => $self->can('custom_calls_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'calls_max' } ] } }, { label => 'calls-active-usage-prct', nlabel => 'system.calls.active.usage.percentage', display_ok => 0, set => { key_values => [ { name => 'calls_prct_used' }, { name => 'calls_free' }, { name => 'calls_used' }, { name => 'calls_max' } ], closure_custom_output => $self->can('custom_calls_usage_output'), perfdatas => [ { template => '%.2f', min => 0, max => 'calls_max' } ] } }, { label => 'extensions-registered', nlabel => 'system.extensions.registered.count', set => { key_values => [ { name => 'extensions_registered' }, { name => 'extensions_total' } ], output_template => 'extensions registered: %s', perfdatas => [ { label => 'extensions_registered', template => '%s', min => 0, max => 'extensions_total' } ] } } ]; $self->{maps_counters}->{service} = [ { label => 'status', type => 2, critical_default => '%{error} =~ /true/', set => { key_values => [ { name => 'error' }, { name => 'service' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub prefix_service_output { my ($self, %options) = @_; return "3CX '" . $options{instance_value}->{service} ."' "; } 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-category:s' => { name => 'filter_category' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $single = $options{custom}->api_single_status(); my $system = $options{custom}->api_system_status(); my $update = $options{custom}->api_update_checker(); $self->{service} = {}; foreach my $item (keys %$single) { # As of 3CX 15.5 / 16, we have Firewall, Phones, Trunks $self->{service}->{$item} = { service => $item, error => $single->{$item} ? 'false' : 'true', }; } # As per 3CX support, $single->{Trunks} does not trigger if TrunksRegistered != TrunksTotal, # but only if "trunk is unsupported", so let's workaround $self->{service}->{HasUnregisteredTrunks} = { service => 'HasUnregisteredTrunks', error => ($system->{TrunksRegistered} < $system->{TrunksTotal}) ? 'true' : 'false', }; $self->{service}->{HasNotRunningServices} = { service => 'HasNotRunningServices', error => $system->{HasNotRunningServices} ? 'true' : 'false', }; $self->{service}->{HasUnregisteredSystemExtensions} = { service => 'HasUnregisteredSystemExtensions', error => $system->{HasUnregisteredSystemExtensions} ? 'true' : 'false', }; my $updates = 0; foreach my $item (@$update) { if (defined($self->{option_results}->{filter_category}) && $self->{option_results}->{filter_category} ne '' && $item->{Category} !~ /$self->{option_results}->{filter_category}/) { $self->{output}->output_add(long_msg => "skipping update '" . $item->{Category} . "': no matching filter.", debug => 1); next; } $updates++; } $self->{service}->{HasUpdatesAvailable} = { service => 'HasUpdatesAvailable', error => $updates ? 'true' : 'false' }; $self->{global} = { calls_used => $system->{CallsActive}, calls_free => $system->{MaxSimCalls} - $system->{CallsActive}, calls_max => $system->{MaxSimCalls}, calls_prct_used => $system->{CallsActive} * 100 / $system->{MaxSimCalls}, extensions_registered => $system->{ExtensionsRegistered}, extensions_total => $system->{ExtensionsTotal} }; } 1; __END__ =head1 MODE Check system health =over 8 =item B<--filter-category> Filter updates' category. =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{error}, %{service} =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{error}, %{service} =item B<--critical-status> Set critical threshold for status (Default: '%{error} =~ /false/'). Can used special variables like: %{error}, %{service} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'calls-active-usage', 'calls-active-free', 'calls-active-usage-prct', 'extensions-registered'. =back =cut centreon-plugins-20220113/apps/voip/3cx/restapi/plugin.pm000066400000000000000000000026541417000230700231630ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::voip::3cx::restapi::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} = '1.0'; $self->{modes} = { 'extension' => 'apps::voip::3cx::restapi::mode::extension', 'system' => 'apps::voip::3cx::restapi::mode::system' }; $self->{custom_modes}->{api} = 'apps::voip::3cx::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check 3CX ressources through its HTTPS remote API. Requirements: at least 3CX 15.5. =over 8 =back =cut centreon-plugins-20220113/apps/voip/asterisk/000077500000000000000000000000001417000230700210015ustar00rootroot00000000000000centreon-plugins-20220113/apps/voip/asterisk/ami/000077500000000000000000000000001417000230700215475ustar00rootroot00000000000000centreon-plugins-20220113/apps/voip/asterisk/ami/custom/000077500000000000000000000000001417000230700230615ustar00rootroot00000000000000centreon-plugins-20220113/apps/voip/asterisk/ami/custom/api.pm000066400000000000000000000155471417000230700242040ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::voip::asterisk::ami::custom::api; use strict; use warnings; use IO::Socket::INET; use IO::Select; 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 => { 'ami-hostname:s@' => { name => 'ami_hostname' }, 'ami-port:s@' => { name => 'ami_port' }, 'ami-username:s@' => { name => 'ami_username' }, 'ami-password:s@' => { name => 'ami_password' }, 'timeout:s@' => { name => 'timeout' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'AMI API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{cnx_ami} = undef; return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{ami_hostname} = (defined($self->{option_results}->{ami_hostname})) ? shift(@{$self->{option_results}->{ami_hostname}}) : undef; $self->{ami_username} = (defined($self->{option_results}->{ami_username})) ? shift(@{$self->{option_results}->{ami_username}}) : undef; $self->{ami_password} = (defined($self->{option_results}->{ami_password})) ? shift(@{$self->{option_results}->{ami_password}}) : undef; $self->{ami_port} = (defined($self->{option_results}->{ami_port})) ? shift(@{$self->{option_results}->{ami_port}}) : 5038; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? shift(@{$self->{option_results}->{timeout}}) : 10; if (!defined($self->{ami_hostname})) { $self->{output}->add_option_msg(short_msg => "Need to specify --ami-hostname option."); $self->{output}->option_exit(); } if (!defined($self->{ami_username})) { $self->{output}->add_option_msg(short_msg => "Need to specify --ami-username option."); $self->{output}->option_exit(); } if (!defined($self->{ami_password})) { $self->{output}->add_option_msg(short_msg => "Need to specify --ami-password option."); $self->{output}->option_exit(); } if (!defined($self->{ami_hostname}) || scalar(@{$self->{option_results}->{ami_hostname}}) == 0) { return 0; } return 1; } sub get_connect_info { my ($self, %options) = @_; return $self->{ami_hostname} . '_' . $self->{ami_port}; } sub read_ami_protocol_end { my ($self, %options) = @_; if (defined($options{response})) { if ($options{response} eq 'Follows') { return 1 if ($options{message} =~ /^--END COMMAND--/ms); } else { if ($options{message} =~ /^Message:\s+Command\s+output\s+follows/i) { return 1 if ($options{message} =~ /\n\n/ms); } elsif ($options{message} =~ /^Message: (.*)(\n)/ms) { return 1; } } } return 0; } sub read_ami_protocol { my ($self, %options) = @_; my $select = IO::Select->new($self->{cnx_ami}); # Three types of message: # Response: Error # Message: Authentication failed # # Response: Follows # ... # --END COMMAND-- # # Response: Success # Message: Command output follows # output: xxxx # output: xxxx # ... # my ($response, $read_msg); my $message = ''; while (1) { if (!$select->can_read(10)) { $response = 'Timeout'; last; } my $status = $self->{cnx_ami}->recv($read_msg, 4096); $read_msg =~ s/\r//msg; if (!defined($response)) { next if ($read_msg !~ /^Response: (.*?)(?:\n)(.*)/ms); ($response, $message) = ($1, $2); } else { $message .= $read_msg; } last if ($self->read_ami_protocol_end(response => $response, message => $message)); } $message =~ s/^Output:\s+//mig; if ($response !~ /Success|Follows/) { $message =~ s/\n+$//msg; $message =~ s/\n/ -- /msg; $self->{output}->add_option_msg(short_msg => "Communication issue [" . $message . "]"); $self->{output}->option_exit(); } $self->{output}->output_add(long_msg => $message, debug => 1); return $message; } sub write_ami_protocol { my ($self, %options) = @_; $self->{cnx_ami}->send($options{cmd}); } sub login { my ($self, %options) = @_; $self->write_ami_protocol(cmd => "Action:login Username:$self->{ami_username} Secret:$self->{ami_password} Events: off "); # don't need to get it. If it comes, it's success :) $self->read_ami_protocol(); } sub connect { my ($self, %options) = @_; $self->{cnx_ami} = IO::Socket::INET->new( PeerAddr => $self->{ami_hostname}, PeerPort => $self->{ami_port}, Proto => 'tcp', Timeout => $self->{timeout}, ); if (!defined($self->{cnx_ami})) { $self->{output}->add_option_msg(short_msg => "Can't bind : $@"); $self->{output}->option_exit(); } $self->{cnx_ami}->autoflush(1); $self->login(); } sub command { my ($self, %options) = @_; if (!defined($self->{cnx_ami})) { $self->connect(); } $self->write_ami_protocol(cmd => "Action:command Command:$options{cmd} "); return $self->read_ami_protocol(); } sub DESTROY { my $self = shift; if (defined($self->{cnx_ami})) { $self->{cnx_ami}->close(); } } 1; __END__ =head1 NAME Asterisk AMI =head1 SYNOPSIS Asterisk AMI custom mode =head1 AMI API OPTIONS =over 8 =item B<--ami-hostname> AMI hostname (Required). =item B<--ami-port> AMI port (Default: 5038). =item B<--ami-username> AMI username. =item B<--ami-password> AMI password. =item B<--timeout> Set TCP timeout =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/voip/asterisk/ami/mode/000077500000000000000000000000001417000230700224735ustar00rootroot00000000000000centreon-plugins-20220113/apps/voip/asterisk/ami/mode/channelusage.pm000066400000000000000000000102171417000230700254670ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::voip::asterisk::ami::mode::channelusage; 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 => 'global', type => 0 }, ]; $self->{maps_counters}->{global} = [ { label => 'channels-active', nlabel => 'channels.active.count', set => { key_values => [ { name => 'channels_active' } ], output_template => 'channels active: %s', perfdatas => [ { label => 'channels_active', template => '%s', min => 0 } ] } }, { label => 'calls-active', nlabel => 'calls.active.count', set => { key_values => [ { name => 'calls_active' } ], output_template => 'calls active: %s', perfdatas => [ { label => 'calls_active', template => '%s', min => 0 } ] } }, { label => 'extcalls-active', nlabel => 'extcalls.active.count', set => { key_values => [ { name => 'extcalls_active' } ], output_template => 'external calls active: %s', perfdatas => [ { label => 'extcalls_active', template => '%s', min => 0 } ] } }, { label => 'calls-count', nlabel => 'calls.processed.count', set => { key_values => [ { name => 'calls_count', diff => 1 } ], output_template => 'calls count: %s', perfdatas => [ { label => 'calls_count', template => '%s', min => 0 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->command(cmd => 'core show channels'); $self->{global} = { channels_active => 0, calls_active => 0, calls_count => undef, extcalls_active => 0 }; $self->{global}->{channels_active} = $1 if ($result =~ /^(\d+)\s+active\s+channels/ms); $self->{global}->{calls_active} = $1 if ($result =~ /^(\d+)\s+active\s+calls/ms); $self->{global}->{calls_count} = $1 if ($result =~ /^(\d+)\s+calls\s+processed/ms); my $count = 0; $count++ while ($result =~ /Outgoing\s+Line/msig); $self->{global}->{extcalls_active} = $count; $self->{cache_name} = "asterisk_" . '_' . $self->{mode} . '_' . $options{custom}->get_connect_info() . '_' . (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 channel usage: active calls, external calls. =over 8 =item B<--warning-*> Threshold warning. Can be: 'channels-active', 'calls-active', 'extcalls-active', 'calls-count'. =item B<--critical-*> Threshold critical. Can be: 'channels-active', 'calls-active', 'extcalls-active', 'calls-count'. =back =cut centreon-plugins-20220113/apps/voip/asterisk/ami/mode/dahdistatus.pm000066400000000000000000000106211417000230700253460ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::voip::asterisk::ami::mode::dahdistatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf('status : %s', $self->{result_values}->{status}); } sub prefix_dahdi_output { my ($self, %options) = @_; return "Line '" . $options{instance_value}->{description} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'dahdi', type => 1, cb_prefix_output => 'prefix_dahdi_output', message_multiple => 'All dahdi lines are ok' }, ]; $self->{maps_counters}->{dahdi} = [ { label => 'status', type => 2, warning_default => '%{status} =~ /UNCONFIGURED|YEL|BLU/i', critical_default => '%{status} =~ /RED/i', set => { key_values => [ { name => 'description' }, { name => 'status' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-description:s" => { name => 'filter_description' } }); return $self; } sub manage_selection { my ($self, %options) = @_; # Status can be: OK, UNCONFIGURED, BLU, YEL, RED, REC (recover), NOP (notopen), UUU #Description Alarms IRQ bpviol CRC4 #Wildcard TDM410P Board 1 OK 0 0 0 #Wildcard TDM800P Board 2 OK 0 0 0 #Description Alarms IRQ bpviol CRC Fra Codi Options LBO #Wildcard TE131/TE133 Card 0 BLU/RED 0 0 0 CCS HDB3 0 db (CSU)/0-133 feet (DSX-1) my $result = $options{custom}->command(cmd => 'dahdi show status'); $self->{dahdi} = {}; foreach my $line (split /\n/, $result) { if ($line =~ /^(.*?)\s+((?:OK|UNCONFIGURED|BLU|YEL|RED|REC|NOP|UUU)[^\s]*)\s+/msg) { my ($description, $status) = ($1, $2); if (defined($self->{option_results}->{filter_description}) && $self->{option_results}->{filter_description} ne '' && $description !~ /$self->{option_results}->{filter_description}/) { $self->{output}->output_add(long_msg => "skipping '" . $description . "': no matching filter.", debug => 1); next; } $self->{dahdi}->{$description} = { description => $description, status => $status, }; } } if (scalar(keys %{$self->{dahdi}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No dahdi lines found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check status of dahdi lines. =over 8 =item B<--filter-description> Filter dahdi description (can be a regexp). =item B<--warning-status> Set warning threshold for status (Default: '%{status} =~ /UNCONFIGURED|YEL|BLU/i'). Can used special variables like: %{description}, %{status} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /RED/i'). Can used special variables like: %{description}, %{status} =back =cut centreon-plugins-20220113/apps/voip/asterisk/ami/mode/sippeersusage.pm000066400000000000000000000163271417000230700257210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::voip::asterisk::ami::mode::sippeersusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf('status : %s', $self->{result_values}->{status}); } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; $self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_name'}; return 0; } sub prefix_sip_output { my ($self, %options) = @_; return "Peer '" . $options{instance_value}->{name} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'sip', type => 1, cb_prefix_output => 'prefix_sip_output', message_multiple => 'All SIP peers are ok' }, ]; $self->{maps_counters}->{global} = [ { label => 'total-peers', nlabel => 'sip.peers.total.count', set => { key_values => [ { name => 'total_peers' } ], output_template => 'total peers: %s', perfdatas => [ { label => 'total_peers', template => '%s', min => 0 } ] } }, { label => 'monitor-online-peers', nlabel => 'sip.peers.monitor.online.count', set => { key_values => [ { name => 'monitor_online_peers' } ], output_template => 'monitor online peers: %s', perfdatas => [ { label => 'monitor_online_peers', template => '%s', min => 0 } ] } }, { label => 'monitor-offline-peers', nlabel => 'sip.peers.monitor.offline.count', set => { key_values => [ { name => 'monitor_offline_peers' } ], output_template => 'monitor offline peers: %s', perfdatas => [ { label => 'monitor_offline_peers', template => '%s', min => 0 } ] } }, { label => 'unmonitor-online-peers', nlabel => 'sip.peers.unmonitor.online.count', set => { key_values => [ { name => 'unmonitor_online_peers' } ], output_template => 'unmonitor online peers: %s', perfdatas => [ { label => 'unmonitor_online_peers', template => '%s', min => 0 } ] } }, { label => 'unmonitor-offline-peers', nlabel => 'sip.peers.unmonitor.offline.count', set => { key_values => [ { name => 'unmonitor_offline_peers' } ], output_template => 'unmonitor offline peers: %s', perfdatas => [ { label => 'unmonitor_offline_peers', template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{sip} = [ { label => 'status', type => 2, warning_default => '%{status} =~ /LAGGED|UNKNOWN/i', critical_default => '%{status} =~ /UNREACHABLE/i', set => { key_values => [ { name => 'name' }, { name => 'status' } ], 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 => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; # Status can be: UNREACHABLE, LAGGED (%d ms), OK (%d ms), UNKNOWN, Unmonitored #Name/username Host Dyn Forcerport Comedia ACL Port Status Description #02l44k/02l44k 10.9.0.61 D No No 5060 Unmonitored #0rafkw/0rafkw 10.9.0.28 D No No 5060 Unmonitored #... #55 sip peers [Monitored: 0 online, 0 offline Unmonitored: 43 online, 12 offline] my $result = $options{custom}->command(cmd => 'sip show peers'); $self->{sip} = {}; foreach my $line (split /\n/, $result) { if ($line =~ /^(.*?)\s+.*(UNREACHABLE|LAGGED|OK|UNKNOWN|Unmonitored)\s/msg) { my ($name, $status) = ($1, $2); 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->{sip}->{$name} = { name => $name, status => $status, }; } } $self->{global} = { total_peers => $1, monitor_online_peers => $2, monitor_offline_peers => $3, unmonitor_online_peers => $4, unmonitor_offline_peers => $5, } if ($result =~ /(\d+) sip peers \[Monitored: (\d+) online, (\d+) offline Unmonitored: (\d+) online, (\d+) offline]/msi); if (scalar(keys %{$self->{sip}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No sip peers found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check SIP peers usage. =over 8 =item B<--filter-name> Filter sip peer name (can be a regexp). =item B<--warning-status> Set warning threshold for status (Default: '%{status} =~ /LAGGED|UNKNOWN/i'). Can used special variables like: %{name}, %{status} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /UNREACHABLE/i'). Can used special variables like: %{name}, %{status} =item B<--warning-*> Threshold warning. Can be: 'total-peers', 'monitor-online-peers', 'monitor-offline-peers', 'unmonitor-online-peers', 'unmonitor-offline-peers'. =item B<--critical-*> Threshold critical. Can be: 'total-peers', 'monitor-online-peers', 'monitor-offline-peers', 'unmonitor-online-peers', 'unmonitor-offline-peers'. =back =cut centreon-plugins-20220113/apps/voip/asterisk/ami/plugin.pm000066400000000000000000000027211417000230700234050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::voip::asterisk::ami::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} = '1.0'; $self->{modes} = { 'channel-usage' => 'apps::voip::asterisk::ami::mode::channelusage', 'dahdi-status' => 'apps::voip::asterisk::ami::mode::dahdistatus', 'sip-peers-usage' => 'apps::voip::asterisk::ami::mode::sippeersusage' }; $self->{custom_modes}{api} = 'apps::voip::asterisk::ami::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Asterisk through AMI interface. =cut centreon-plugins-20220113/apps/voip/asterisk/snmp/000077500000000000000000000000001417000230700217565ustar00rootroot00000000000000centreon-plugins-20220113/apps/voip/asterisk/snmp/mode/000077500000000000000000000000001417000230700227025ustar00rootroot00000000000000centreon-plugins-20220113/apps/voip/asterisk/snmp/mode/channelusage.pm000066400000000000000000000072601417000230700257020ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::voip::asterisk::snmp::mode::channelusage; 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 => 'global', type => 0 }, ]; $self->{maps_counters}->{global} = [ { label => 'channels-active', nlabel => 'channels.active.count', set => { key_values => [ { name => 'channels_active' } ], output_template => 'channels active: %s', perfdatas => [ { label => 'channels_active', template => '%s', min => 0 } ] } }, { label => 'calls-active', nlabel => 'calls.active.count', set => { key_values => [ { name => 'calls_active' } ], output_template => 'calls active: %s', perfdatas => [ { label => 'calls_active', template => '%s', min => 0 } ] } }, { label => 'calls-count', nlabel => 'calls.processed.count', set => { key_values => [ { name => 'calls_count', diff => 1 } ], output_template => 'calls count: %s', perfdatas => [ { label => 'calls_count', template => '%s', min => 0 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $oid_astConfigCallsActive = '.1.3.6.1.4.1.22736.1.2.5.0'; my $oid_astConfigCallsProcessed = '.1.3.6.1.4.1.22736.1.2.6.0'; my $oid_astNumChannels = '.1.3.6.1.4.1.22736.1.5.1.0'; my $result = $options{snmp}->get_leef(oids => [$oid_astConfigCallsActive, $oid_astConfigCallsProcessed, $oid_astNumChannels], nothing_quit => 1); $self->{cache_name} = "asterisk_" . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); $self->{global} = { calls_active => $result->{$oid_astConfigCallsActive}, calls_count => $result->{$oid_astConfigCallsProcessed}, channels_active => $result->{$oid_astNumChannels}, }; } 1; __END__ =head1 MODE Check channel usage. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='calls-active' =item B<--warning-*> Threshold warning. Can be: 'channels-active', 'calls-active', 'calls-count'. =item B<--critical-*> Threshold critical. Can be: 'channels-active', 'calls-active', 'calls-count'. =back =cut centreon-plugins-20220113/apps/voip/asterisk/snmp/plugin.pm000066400000000000000000000023401417000230700236110ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::voip::asterisk::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} = { 'channel-usage' => 'apps::voip::asterisk::snmp::mode::channelusage' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Asterisk through SNMP =cut centreon-plugins-20220113/apps/voip/cisco/000077500000000000000000000000001417000230700202545ustar00rootroot00000000000000centreon-plugins-20220113/apps/voip/cisco/meetingplace/000077500000000000000000000000001417000230700227115ustar00rootroot00000000000000centreon-plugins-20220113/apps/voip/cisco/meetingplace/mode/000077500000000000000000000000001417000230700236355ustar00rootroot00000000000000centreon-plugins-20220113/apps/voip/cisco/meetingplace/mode/audiolicenses.pm000066400000000000000000000101171417000230700270220ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::voip::cisco::meetingplace::mode::audiolicenses; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning:s" => { name => 'warning', default => '60' }, "critical:s" => { name => 'critical', default => '70' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); $self->{warning} = $self->{option_results}->{warning}; $self->{critical} = $self->{option_results}->{critical}; if (($self->{perfdata}->threshold_validate(label => 'warning', value => $self->{warning})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning threshold '" . $self->{warning} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'critical', value => $self->{critical})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical threshold'" . $self->{critical} . "'."); $self->{output}->option_exit(); } } sub run { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; # Nombre de ports audio utilise my $oid_cmpAudioLicense = '.1.3.6.1.4.1.9.9.733.1.3.1.0'; # Nombre maximum de ports audio disponibles my $oid_cmpMaxAudioLicense = '.1.3.6.1.4.1.9.9.733.1.3.2.0'; my $result = $self->{snmp}->get_leef(oids => [$oid_cmpAudioLicense, $oid_cmpMaxAudioLicense], nothing_quit => 1); my $prct; if ($result->{$oid_cmpAudioLicense} > 0) { $prct = $result->{$oid_cmpAudioLicense} / $result->{$oid_cmpMaxAudioLicense} * 100; } else { $prct = 0; } my $abs_warning = $self->{option_results}->{warning} / 100 * $result->{$oid_cmpMaxAudioLicense}; my $abs_critical = $self->{option_results}->{critical} / 100 * $result->{$oid_cmpMaxAudioLicense}; my $exit = $self->{perfdata}->threshold_check(value => $prct, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ] ); $self->{output}->output_add(severity => $exit, short_msg => sprintf("%.2f%% of audio licenses are in use. (%d max)", $prct, $result->{$oid_cmpMaxAudioLicense})); $self->{output}->perfdata_add(label => "audio-licenses", unit => 'licenses', value => $result->{$oid_cmpAudioLicense}, warning => $abs_warning, critical => $abs_critical, min => 0, max => $result->{$oid_cmpMaxAudioLicense}); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check the percentage of audio licenses used on this cisco meeting place platform. =over 8 =item B<--warning> Threshold warning: Percentage value of audio licenses usage resulting in a warning state =item B<--critical> Threshold critical: Percentage value of audio licenses usage resulting in a critical state =back ==cut centreon-plugins-20220113/apps/voip/cisco/meetingplace/mode/audioports.pm000066400000000000000000000101721417000230700263650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::voip::cisco::meetingplace::mode::audioports; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning:s" => { name => 'warning', default => '60' }, "critical:s" => { name => 'critical', default => '70' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); $self->{warning} = $self->{option_results}->{warning}; $self->{critical} = $self->{option_results}->{critical}; if (($self->{perfdata}->threshold_validate(label => 'warning', value => $self->{warning})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning threshold '" . $self->{warning} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'critical', value => $self->{critical})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical threshold'" . $self->{critical} . "'."); $self->{output}->option_exit(); } } sub run { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; # Nombre de ports audio utilise my $oid_cmpAudioPortsUsage = '.1.3.6.1.4.1.9.9.733.1.4.3.0'; # Nombre maximum de ports audio disponibles my $oid_cmpMaxAudioPortsAvailable = '.1.3.6.1.4.1.9.9.733.1.4.4.0'; my $result = $self->{snmp}->get_leef(oids => [$oid_cmpAudioPortsUsage, $oid_cmpMaxAudioPortsAvailable], nothing_quit => 1); my $prct; if ($result->{$oid_cmpAudioPortsUsage} > 0) { $prct = $result->{$oid_cmpAudioPortsUsage} / $result->{$oid_cmpMaxAudioPortsAvailable} * 100; } else { $prct = 0; } my $abs_warning = $self->{option_results}->{warning} / 100 * $result->{$oid_cmpMaxAudioPortsAvailable}; my $abs_critical = $self->{option_results}->{critical} / 100 * $result->{$oid_cmpMaxAudioPortsAvailable}; my $exit = $self->{perfdata}->threshold_check(value => $prct, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ] ); $self->{output}->output_add(severity => $exit, short_msg => sprintf("%.2f%% of audio ports are in use. (%d max)", $prct, $result->{$oid_cmpMaxAudioPortsAvailable})); $self->{output}->perfdata_add(label => "audio-ports", unit => 'ports', value => $result->{$oid_cmpAudioPortsUsage}, warning => $abs_warning, critical => $abs_critical, min => 0, max => $result->{$oid_cmpMaxAudioPortsAvailable}); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check the percentage of audio ports used on this cisco meeting place platform. =over 8 =item B<--warning> Threshold warning: Percentage value of audio ports usage resulting in a warning state =item B<--critical> Threshold critical: Percentage value of audio ports usage resulting in a critical state =back ==cut centreon-plugins-20220113/apps/voip/cisco/meetingplace/mode/videolicenses.pm000066400000000000000000000101171417000230700270270ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::voip::cisco::meetingplace::mode::videolicenses; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning:s" => { name => 'warning', default => '60' }, "critical:s" => { name => 'critical', default => '70' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); $self->{warning} = $self->{option_results}->{warning}; $self->{critical} = $self->{option_results}->{critical}; if (($self->{perfdata}->threshold_validate(label => 'warning', value => $self->{warning})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning threshold '" . $self->{warning} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'critical', value => $self->{critical})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical threshold'" . $self->{critical} . "'."); $self->{output}->option_exit(); } } sub run { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; # Nombre de ports audio utilise my $oid_cmpVideoLicense = '.1.3.6.1.4.1.9.9.733.1.3.3.0'; # Nombre maximum de ports audio disponibles my $oid_cmpMaxVideoLicense = '.1.3.6.1.4.1.9.9.733.1.3.4.0'; my $result = $self->{snmp}->get_leef(oids => [$oid_cmpVideoLicense, $oid_cmpMaxVideoLicense], nothing_quit => 1); my $prct; if ($result->{$oid_cmpVideoLicense} > 0) { $prct = $result->{$oid_cmpVideoLicense} / $result->{$oid_cmpMaxVideoLicense} * 100; } else { $prct = 0; } my $abs_warning = $self->{option_results}->{warning} / 100 * $result->{$oid_cmpMaxVideoLicense}; my $abs_critical = $self->{option_results}->{critical} / 100 * $result->{$oid_cmpMaxVideoLicense}; my $exit = $self->{perfdata}->threshold_check(value => $prct, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ] ); $self->{output}->output_add(severity => $exit, short_msg => sprintf("%.2f%% of video licenses are in use. (%d max)", $prct, $result->{$oid_cmpMaxVideoLicense})); $self->{output}->perfdata_add(label => "video-licenses", unit => 'licenses', value => $result->{$oid_cmpVideoLicense}, warning => $abs_warning, critical => $abs_critical, min => 0, max => $result->{$oid_cmpMaxVideoLicense}); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check the percentage of video licenses used on this cisco meeting place platform. =over 8 =item B<--warning> Threshold warning: Percentage value of video licenses usage resulting in a warning state =item B<--critical> Threshold critical: Percentage value of video licenses usage resulting in a critical state =back ==cut centreon-plugins-20220113/apps/voip/cisco/meetingplace/mode/videoports.pm000066400000000000000000000100301417000230700263630ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::voip::cisco::meetingplace::mode::videoports; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning:s" => { name => 'warning', default => '60' }, "critical:s" => { name => 'critical', default => '70' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); $self->{warning} = $self->{option_results}->{warning}; $self->{critical} = $self->{option_results}->{critical}; if (($self->{perfdata}->threshold_validate(label => 'warning', value => $self->{warning})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning threshold '" . $self->{warning} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'critical', value => $self->{critical})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical threshold'" . $self->{critical} . "'."); $self->{output}->option_exit(); } } sub run { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; # Nombre de ports video utilise my $oid_cmpVideoPortsUsage = '.1.3.6.1.4.1.9.9.733.1.4.1.0'; # Nombre maximum de ports video disponibles my $oid_cmpMaxVideoPortsAvailable = '.1.3.6.1.4.1.9.9.733.1.4.2.0'; my $result = $self->{snmp}->get_leef(oids => [$oid_cmpVideoPortsUsage, $oid_cmpMaxVideoPortsAvailable], nothing_quit => 1); my $prct = $result->{$oid_cmpVideoPortsUsage} / $result->{$oid_cmpMaxVideoPortsAvailable} * 100; my $abs_warning = $self->{option_results}->{warning} / 100 * $result->{$oid_cmpMaxVideoPortsAvailable}; my $abs_critical = $self->{option_results}->{critical} / 100 * $result->{$oid_cmpMaxVideoPortsAvailable}; my $exit = $self->{perfdata}->threshold_check(value => $prct, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ] ); $self->{output}->output_add(severity => $exit, short_msg => sprintf("%.2f%% of video ports are in use. (%d max)", $prct, $result->{$oid_cmpMaxVideoPortsAvailable})); $self->{output}->perfdata_add(label => "video-ports", unit => 'ports', value => $result->{$oid_cmpVideoPortsUsage}, warning => $abs_warning, critical => $abs_critical, min => 0, max => $result->{$oid_cmpMaxVideoPortsAvailable}); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check the percentage of video ports used on this cisco meeting place platform. =over 8 =item B<--warning> Threshold warning: Percentage value of video ports usage resulting in a warning state =item B<--critical> Threshold critical: Percentage value of video ports usage resulting in a critical state =back ==cut centreon-plugins-20220113/apps/voip/cisco/meetingplace/plugin.pm000066400000000000000000000034261417000230700245520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::voip::cisco::meetingplace::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}} = ( 'cpu' => 'snmp_standard::mode::cpu', 'memory' => 'os::windows::snmp::mode::memory', 'storage' => 'snmp_standard::mode::storage', 'audio-ports' => 'apps::voip::cisco::meetingplace::mode::audioports', 'video-ports' => 'apps::voip::cisco::meetingplace::mode::videoports', 'audio-licenses' => 'apps::voip::cisco::meetingplace::mode::audiolicenses', 'video-licenses' => 'apps::voip::cisco::meetingplace::mode::videolicenses', 'interfaces' => 'snmp_standard::mode::interfaces', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Cisco Meeting place in SNMP. =cut centreon-plugins-20220113/apps/vtom/000077500000000000000000000000001417000230700171645ustar00rootroot00000000000000centreon-plugins-20220113/apps/vtom/restapi/000077500000000000000000000000001417000230700206335ustar00rootroot00000000000000centreon-plugins-20220113/apps/vtom/restapi/custom/000077500000000000000000000000001417000230700221455ustar00rootroot00000000000000centreon-plugins-20220113/apps/vtom/restapi/custom/api.pm000066400000000000000000000152241417000230700232600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vtom::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use JSON::XS; 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 => { 'hostname:s@' => { name => 'hostname' }, 'port:s@' => { name => 'port' }, 'proto:s@' => { name => 'proto' }, 'username:s@' => { name => 'username' }, 'password:s@' => { name => 'password' }, 'timeout:s@' => { name => 'timeout' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? shift(@{$self->{option_results}->{hostname}}) : undef; $self->{port} = (defined($self->{option_results}->{port})) ? shift(@{$self->{option_results}->{port}}) : 30080; $self->{proto} = (defined($self->{option_results}->{proto})) ? shift(@{$self->{option_results}->{proto}}) : 'http'; $self->{username} = (defined($self->{option_results}->{username})) ? shift(@{$self->{option_results}->{username}}) : ''; $self->{password} = (defined($self->{option_results}->{password})) ? shift(@{$self->{option_results}->{password}}) : ''; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? shift(@{$self->{option_results}->{timeout}}) : 10; if (!defined($self->{hostname})) { $self->{output}->add_option_msg(short_msg => "Need to specify hostname option."); $self->{output}->option_exit(); } if (!defined($self->{hostname}) || scalar(@{$self->{option_results}->{hostname}}) == 0) { return 0; } return 1; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{credentials} = 1; $self->{option_results}->{basic} = 1; $self->{option_results}->{username} = $self->{username}; $self->{option_results}->{password} = $self->{password}; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->set_options(%{$self->{option_results}}); } sub cache_environment { my ($self, %options) = @_; my $has_cache_file = $options{statefile}->read(statefile => 'cache_vtom_env_' . $self->{hostname} . '_' . $self->{port}); my $timestamp_cache = $options{statefile}->get(name => 'last_timestamp'); my $environments = $options{statefile}->get(name => 'environments'); if ($has_cache_file == 0 || !defined($timestamp_cache) || ((time() - $timestamp_cache) > (($options{reload_cache_time}) * 60))) { $environments = {}; my $datas = { last_timestamp => time(), environments => $environments }; my $result = $self->get(path => '/api/environment/list'); if (defined($result->{result}->{rows})) { foreach (@{$result->{result}->{rows}}) { $environments->{$_->{id}} = $_->{name}; } } $options{statefile}->write(data => $datas); } return $environments; } sub cache_application { my ($self, %options) = @_; my $has_cache_file = $options{statefile}->read(statefile => 'cache_vtom_app_' . $self->{hostname} . '_' . $self->{port}); my $timestamp_cache = $options{statefile}->get(name => 'last_timestamp'); my $applications = $options{statefile}->get(name => 'applications'); if ($has_cache_file == 0 || !defined($timestamp_cache) || ((time() - $timestamp_cache) > (($options{reload_cache_time}) * 60))) { $applications = {}; my $datas = { last_timestamp => time(), applications => $applications }; my $result = $self->get(path => '/api/application/list'); if (defined($result->{result}->{rows})) { foreach (@{$result->{result}->{rows}}) { $applications->{$_->{id}} = { name => $_->{name}, envSId => $_->{envSId} }; } } $options{statefile}->write(data => $datas); } return $applications; } sub get { my ($self, %options) = @_; $self->settings(); my $response = $self->{http}->request(url_path => $options{path}, critical_status => '', warning_status => ''); my $content; eval { $content = JSON::XS->new->utf8->decode($response); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } if (defined($content->{errmsg})) { $self->{output}->add_option_msg(short_msg => "Cannot get data: " . $content->{errmsg}); $self->{output}->option_exit(); } return $content; } 1; __END__ =head1 NAME VTOM REST API =head1 SYNOPSIS VTOM Rest API custom mode =head1 REST API OPTIONS =over 8 =item B<--hostname> VTOM hostname. =item B<--port> Port used (Default: 30080) =item B<--proto> Specify https if needed (Default: 'http') =item B<--username> VTOM username. =item B<--password> VTOM password. =item B<--timeout> Set HTTP timeout =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/vtom/restapi/mode/000077500000000000000000000000001417000230700215575ustar00rootroot00000000000000centreon-plugins-20220113/apps/vtom/restapi/mode/jobstatus.pm000066400000000000000000000321711417000230700241370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vtom::restapi::mode::jobstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::statefile; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; my $msg = 'status : ' . $self->{result_values}->{status}; if ($self->{result_values}->{information} ne '') { $msg .= ' [information: ' . $self->{result_values}->{information} . ']'; } return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; $self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_name'}; $self->{result_values}->{environment} = $options{new_datas}->{$self->{instance} . '_environment'}; $self->{result_values}->{application} = $options{new_datas}->{$self->{instance} . '_application'}; $self->{result_values}->{exit_code} = $options{new_datas}->{$self->{instance} . '_exit_code'}; $self->{result_values}->{family} = $options{new_datas}->{$self->{instance} . '_family'}; $self->{result_values}->{information} = $options{new_datas}->{$self->{instance} . '_information'}; return 0; } sub custom_long_output { my ($self, %options) = @_; my $msg = 'started since : ' . centreon::plugins::misc::change_seconds(value => $self->{result_values}->{elapsed}); return $msg; } sub custom_long_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; $self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_name'}; $self->{result_values}->{environment} = $options{new_datas}->{$self->{instance} . '_environment'}; $self->{result_values}->{application} = $options{new_datas}->{$self->{instance} . '_application'}; $self->{result_values}->{elapsed} = $options{new_datas}->{$self->{instance} . '_elapsed'}; $self->{result_values}->{family} = $options{new_datas}->{$self->{instance} . '_family'}; return -11 if ($self->{result_values}->{status} !~ /Running/i); return 0; } sub prefix_global_output { my ($self, %options) = @_; return "Total Job "; } sub prefix_job_output { my ($self, %options) = @_; return "job '" . $options{instance_value}->{environment} . '/' . $options{instance_value}->{application} . '/' . $options{instance_value}->{name} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', }, { name => 'job', type => 1, cb_prefix_output => 'prefix_job_output', message_multiple => 'All jobs are ok', , skipped_code => { -11 => 1 } }, ]; $self->{maps_counters}->{job} = [ { label => 'status', type => 2, critical_default => '%{status} =~ /Error/i', set => { key_values => [ { name => 'status' }, { name => 'name' }, { name => 'environment' }, { name => 'application' }, { name => 'exit_code' }, { name => 'family' }, { name => 'information' } ], 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 => \&catalog_status_threshold_ng, } }, { label => 'long', type => 2, set => { key_values => [ { name => 'status' }, { name => 'name' }, { name => 'environment' }, { name => 'application' }, { name => 'elapsed' }, { name => 'family' } ], closure_custom_calc => $self->can('custom_long_calc'), closure_custom_output => $self->can('custom_long_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng, } }, ]; $self->{maps_counters}->{global} = [ { label => 'total-error', nlabel => 'jobs.errors.total.count', set => { key_values => [ { name => 'error' }, { name => 'total' } ], output_template => 'error : %s', perfdatas => [ { label => 'total_error', template => '%s', min => 0, max => 'total' } ] } }, { label => 'total-running', nlabel => 'jobs.running.total.count', set => { key_values => [ { name => 'running' }, { name => 'total' } ], output_template => 'running : %s', perfdatas => [ { label => 'total_running', template => '%s', min => 0, max => 'total' } ] } }, { label => 'total-unplanned', nlabel => 'jobs.unplanned.total.count', set => { key_values => [ { name => 'unplanned' }, { name => 'total' } ], output_template => 'unplanned : %s', perfdatas => [ { label => 'total_unplanned', template => '%s', min => 0, max => 'total' } ] } }, { label => 'total-finished', nlabel => 'jobs.finished.total.count', set => { key_values => [ { name => 'finished' }, { name => 'total' } ], output_template => 'finished : %s', perfdatas => [ { label => 'total_finished', template => '%s', min => 0, max => 'total' } ] } }, { label => 'total-coming', nlabel => 'jobs.coming.total.count', set => { key_values => [ { name => 'coming' }, { name => 'total' } ], output_template => 'coming : %s', perfdatas => [ { label => 'total_coming', template => '%s', min => 0, max => 'total' }, ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-application:s" => { name => 'filter_application' }, "filter-environment:s" => { name => 'filter_environment' }, "filter-name:s" => { name => 'filter_name' }, "filter-family:s" => { name => 'filter_family' }, "reload-cache-time:s" => { name => 'reload_cache_time', default => 180 }, }); $self->{statefile_cache_app} = centreon::plugins::statefile->new(%options); $self->{statefile_cache_env} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{statefile_cache_app}->check_options(%options); $self->{statefile_cache_env}->check_options(%options); } my %mapping_job_status = ( R => 'Running', U => 'Unplanned', F => 'Finished', W => 'Coming', E => 'Error', ); sub manage_selection { my ($self, %options) = @_; my $environments = $options{custom}->cache_environment(statefile => $self->{statefile_cache_env}, reload_cache_time => $self->{option_results}->{reload_cache_time}); my $applications = $options{custom}->cache_application(statefile => $self->{statefile_cache_app}, reload_cache_time => $self->{option_results}->{reload_cache_time}); $self->{job} = {}; $self->{global} = { total => 0, running => 0, unplanned => 0, finished => 0, coming => 0, error => 0 }; my $path = '/api/job/getAll'; if (defined($self->{option_results}->{filter_application}) && $self->{option_results}->{filter_application} ne '') { $path = '/api/job/list?applicationName=' . $self->{option_results}->{filter_application}; } if (defined($self->{option_results}->{filter_environment}) && $self->{option_results}->{filter_environment} ne '') { $path = '/api/job/list?environmentName=' . $self->{option_results}->{filter_environment}; } my $result = $options{custom}->get(path => $path); my $entries = defined($result->{result}) && ref($result->{result}) eq 'ARRAY' ? $result->{result} : (defined($result->{result}->{rows}) ? $result->{result}->{rows} : []); my $current_time = time(); foreach my $entry (@{$entries}) { my $application_sid = defined($entry->{applicationSId}) ? $entry->{applicationSId} : (defined($entry->{appSId}) ? $entry->{appSId} : undef); my $application = defined($application_sid) && defined($applications->{$application_sid}) ? $applications->{$application_sid}->{name} : 'unknown'; my $environment = defined($application_sid) && defined($applications->{$application_sid}) && defined($environments->{$applications->{$application_sid}->{envSId}}) ? $environments->{$applications->{$application_sid}->{envSId}} : 'unknown'; my $display = $environment . '/' . $application . '/' . $entry->{name}; if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $display !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $display . "': no matching filter.", debug => 1); next; } my $family = defined($entry->{family}) ? $entry->{family} : '-'; if (defined($self->{option_results}->{filter_family}) && $self->{option_results}->{filter_family} ne '' && $family !~ /$self->{option_results}->{filter_family}/) { $self->{output}->output_add(long_msg => "skipping '" . $family . "': no matching filter.", debug => 1); next; } my $information = defined($entry->{information}) ? $entry->{information} : ''; $information =~ s/\|/-/msg; $self->{global}->{total} += 1; $self->{global}->{lc($mapping_job_status{$entry->{status}})} += 1; $self->{job}->{$entry->{id}} = { name => $entry->{name}, status => $mapping_job_status{$entry->{status}}, information => $information, exit_code => defined($entry->{retcode}) ? $entry->{retcode} : '-', family => $family, application => $application, environment => $environment, elapsed => defined($entry->{timeBegin}) ? ( $current_time - $entry->{timeBegin}) : undef, }; } if (scalar(keys %{$self->{job}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No job found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check job status. =over 8 =item B<--filter-environment> Filter environment name (cannot be a regexp). =item B<--filter-application> Filter application name (cannot be a regexp). =item B<--filter-name> Filter name (can be a regexp). =item B<--filter-family> Filter family (can be a regexp). =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^total-error$' =item B<--warning-*> Threshold warning. Can be: 'total-error', 'total-running', 'total-unplanned', 'total-finished', 'total-coming'. =item B<--critical-*> Threshold critical. Can be: 'total-error', 'total-running', 'total-unplanned', 'total-finished', 'total-coming'. =item B<--warning-status> Set warning threshold for status (Default: -) Can used special variables like: %{name}, %{status}, %{exit_code}, %{family}, %{information}, %{environment}, %{application} =item B<--critical-status> Set critical threshold for status (Default: '%{exit_code} =~ /Error/i'). Can used special variables like: %{name}, %{status}, %{exit_code}, %{family}, %{information}, %{environment}, %{application} =item B<--warning-long> Set warning threshold for long jobs (Default: none) Can used special variables like: %{name}, %{status}, %{elapsed}, %{family}, %{environment}, %{application} =item B<--critical-long> Set critical threshold for long jobs (Default: none). Can used special variables like: %{name}, %{status}, %{elapsed}, %{family}, %{environment}, %{application} =item B<--reload-cache-time> Time in seconds before reloading cache file (default: 180). =back =cut centreon-plugins-20220113/apps/vtom/restapi/plugin.pm000066400000000000000000000024401417000230700224670ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::vtom::restapi::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} = '1.0'; $self->{modes} = { 'job-status' => 'apps::vtom::restapi::mode::jobstatus' }; $self->{custom_modes}{api} = 'apps::vtom::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check VTOM software through HTTP/REST API. =cut centreon-plugins-20220113/apps/wallix/000077500000000000000000000000001417000230700174775ustar00rootroot00000000000000centreon-plugins-20220113/apps/wallix/bastion/000077500000000000000000000000001417000230700211365ustar00rootroot00000000000000centreon-plugins-20220113/apps/wallix/bastion/snmp/000077500000000000000000000000001417000230700221135ustar00rootroot00000000000000centreon-plugins-20220113/apps/wallix/bastion/snmp/mode/000077500000000000000000000000001417000230700230375ustar00rootroot00000000000000centreon-plugins-20220113/apps/wallix/bastion/snmp/mode/license.pm000066400000000000000000000264321417000230700250260ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::wallix::bastion::snmp::mode::license; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use JSON::XS; use DateTime; 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_expires_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel} . '.' . $unitdiv_long->{ $self->{instance_mode}->{option_results}->{unit} }, unit => $self->{instance_mode}->{option_results}->{unit}, 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_expires_threshold { my ($self, %options) = @_; 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_status_output { my ($self, %options) = @_; return 'status: ' . $self->{result_values}->{status}; } sub custom_license_output { my ($self, %options) = @_; my $msg; if ($self->{result_values}->{total} != -1) { $msg = sprintf( 'total: %s used: %s (%.2f%%) free: %s (%.2f%%)', $self->{result_values}->{total}, $self->{result_values}->{used}, $self->{result_values}->{prct_used}, $self->{result_values}->{free}, $self->{result_values}->{prct_free} ); } else { $msg = sprintf( 'used: %s', $self->{result_values}->{used} ); } return $msg; } sub custom_license_usage_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel}, instances => $self->{result_values}->{name}, value => $self->{result_values}->{used}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}), min => 0, max => $self->{result_values}->{total} != -1 ? $self->{result_values}->{total} : undef ); } sub custom_license_calc { my ($self, %options) = @_; return -10 if ($options{new_datas}->{$self->{instance} . '_total'} == -1); $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_total'}; $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_used'}; $self->{result_values}->{free} = $options{new_datas}->{$self->{instance} . '_free'}; $self->{result_values}->{prct_free} = $options{new_datas}->{$self->{instance} . '_prct_free'}; $self->{result_values}->{prct_used} = $options{new_datas}->{$self->{instance} . '_prct_used'}; return 0; } sub prefix_license_output { my ($self, %options) = @_; return sprintf( "License '%s' ", $options{instance_value}->{name}, ); } sub prefix_global_output { my ($self, %options) = @_; return 'License '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }, { name => 'licenses', type => 1, cb_prefix_output => 'prefix_license_output', message_multiple => 'All license usages are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'status', type => 2, critical_default => '%{status} eq "expired"', set => { key_values => [ { name => 'status' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'expires', nlabel => 'license.expires', set => { key_values => [ { name => 'expires_seconds' }, { name => 'expires_human' } ], output_template => 'expires in %s', output_use => 'expires_human', closure_custom_perfdata => $self->can('custom_expires_perfdata'), closure_custom_threshold_check => $self->can('custom_expires_threshold') } } ]; $self->{maps_counters}->{licenses} = [ { label => 'license-usage', nlabel => 'license.usage.count', set => { key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' }, { name => 'name' } ], closure_custom_output => $self->can('custom_license_output'), closure_custom_perfdata => $self->can('custom_license_usage_perfdata'), } }, { label => 'license-free', display_ok => 0, nlabel => 'license.free.count', set => { key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_calc => $self->can('custom_license_calc'), closure_custom_output => $self->can('custom_license_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', label_extra_instance => 1 } ] } }, { label => 'license-usage-prct', display_ok => 0, nlabel => 'license.usage.percentage', set => { key_values => [ { name => 'prct_used' }, { name => 'used' }, { name => 'free' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_calc => $self->can('custom_license_calc'), closure_custom_output => $self->can('custom_license_output'), perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'unit:s' => { name => 'unit', default => 's' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if ($self->{option_results}->{unit} eq '' || !defined($unitdiv->{$self->{option_results}->{unit}})) { $self->{option_results}->{unit} = 's'; } } sub add_license { my ($self, %options) = @_; $self->{licenses}->{ $options{name} } = { name => $options{name}, used => $options{used} }; if (defined($options{max}) && $options{max} > 0) { $self->{licenses}->{ $options{name} }->{total} = $options{max}; $self->{licenses}->{ $options{name} }->{free} = $options{max} - $options{used}; $self->{licenses}->{ $options{name} }->{prct_used} = $options{used} * 100 / $options{max}; $self->{licenses}->{ $options{name} }->{prct_free} = 100 - $self->{licenses}->{ $options{name} }->{prct_used}; } else { $self->{licenses}->{ $options{name} }->{total} = -1; $self->{licenses}->{ $options{name} }->{free} = -1; $self->{licenses}->{ $options{name} }->{prct_used} = -1; $self->{licenses}->{ $options{name} }->{prct_free} = -1; } } sub manage_selection { my ($self, %options) = @_; my $oid_licenseInfo = '.1.3.6.1.4.1.30373.1.5.0'; my $snmp_result = $options{snmp}->get_leef( oids => [ $oid_licenseInfo ], nothing_quit => 1 ); #{ # "resource_max": -1, # "primary": 7, # "waapm": 0, # "externvault_enabled": true, # "secondary_max": -1, # "siem_enabled": true, # "secondary": 6, # "evaluation": false, # "resource": 1063, # "session_manager": true, # "expiration_date": "2021-12-31", # "waapm_max": -1, # "primary_max": -1, # "password_manager": true, # "enterprise": false, # "is_expired": false #} my $decoded; eval { $snmp_result->{ $oid_licenseInfo } =~ s/\\//g; $decoded = JSON::XS->new->decode($snmp_result->{ $oid_licenseInfo }); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } $self->{global} = { status => $decoded->{is_expired} =~ /true|1/i ? 'expired' : 'ok' }; if (defined($decoded->{expiration_date}) && $decoded->{expiration_date} =~ /^(\d+)-(\d+)-(\d+)$/) { my $dt = DateTime->new( year => $1, month => $2, day => $3, hour => 0, minute => 0, second => 0 ); my $expiration = $dt->epoch(); $self->{global}->{expires_seconds} = $expiration - time(); $self->{global}->{expires_human} = centreon::plugins::misc::change_seconds( value => $self->{global}->{expires_seconds} ); } $self->{licenses} = {}; $self->add_license(name => 'primary', used => $decoded->{primary}, max => $decoded->{primary_max}); $self->add_license(name => 'secondary', used => $decoded->{secondary}, max => $decoded->{secondary_max}); $self->add_license(name => 'resource', used => $decoded->{resource}, max => $decoded->{resource_max}); } 1; __END__ =head1 MODE Check license. =over 8 =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{status} =item B<--critical-status> Set critical threshold for status (Default: '%{status} eq "expired"'). Can used special variables like: %{status} =item B<--unit> Select the unit for expires 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: 'total', 'expires', 'license-usage', 'license-free', 'license-usage-prct'. =back =cut centreon-plugins-20220113/apps/wallix/bastion/snmp/mode/system.pm000066400000000000000000000141311417000230700247210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::wallix::bastion::snmp::mode::system; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_services_status_output { my ($self, %options) = @_; return sprintf('services status: %s', $self->{result_values}->{status}); } sub system_long_output { my ($self, %options) = @_; return 'checking system'; } sub prefix_sessions_output { my ($self, %options) = @_; return 'sessions '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'system', type => 3, cb_long_output => 'system_long_output', indent_long_output => ' ', group => [ { name => 'services_status', type => 0, display_short => 0, skipped_code => { -10 => 1 } }, { name => 'sessions', type => 0, cb_prefix_output => 'prefix_sessions_output', message_separator => ' ', display_short => 0, skipped_code => { -10 => 1 } }, { name => 'requests', type => 0, display_short => 0, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{services_status} = [ { label => 'services-status', type => 2, critical_default => '%{status} eq "unreachable"', set => { key_values => [ { name => 'status' }, ], closure_custom_output => $self->can('custom_services_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{sessions} = [ { label => 'sessions-total', nlabel => 'sessions.total.count', set => { key_values => [ { name => 'total' } ], output_template => 'total: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'sessions-primary', nlabel => 'sessions.primary.count', set => { key_values => [ { name => 'primary' } ], output_template => 'primary: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'sessions-secondary', nlabel => 'sessions.secondary.count', set => { key_values => [ { name => 'secondary' } ], output_template => 'secondary: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'sessions-ghost', nlabel => 'sessions.ghost.count', set => { key_values => [ { name => 'ghost' } ], output_template => 'ghost: %s', perfdatas => [ { template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{requests} = [ { label => 'requests-pending', nlabel => 'requests.pending.count', set => { key_values => [ { name => 'pending' } ], output_template => 'requests pending: %s', perfdatas => [ { template => '%s', min => 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 => {}); return $self; } sub manage_selection { my ($self, %options) = @_; my $mapping_status = { 1 => 'running', 2 => 'unreachable' }; my $mapping = { total_session => { oid => '.1.3.6.1.4.1.30373.1.1.1' }, # totalSessionCount primary_session => { oid => '.1.3.6.1.4.1.30373.1.1.2' }, # primarySessionCount secondary_session => { oid => '.1.3.6.1.4.1.30373.1.1.3' }, # secondarySessionCount ghost_session => { oid => '.1.3.6.1.4.1.30373.1.1.4' }, # ghostSessionCount requests_pending => { oid => '.1.3.6.1.4.1.30373.1.1.7' }, # pendingApprovalCount services_status => { oid => '.1.3.6.1.4.1.30373.1.2.3', map => $mapping_status } # bastionStatus }; my $snmp_result = $options{snmp}->get_leef( oids => [ map($_->{oid} . '.0', values(%$mapping)) ], nothing_quit => 1 ); my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => 0); $self->{output}->output_add(short_msg => 'system is ok'); $self->{system} = { global => { services_status => { status => $result->{services_status} }, sessions => { total => $result->{total_session}, primary => $result->{primary_session}, secondary => $result->{secondary_session}, ghost => $result->{ghost_session} }, requests => { pending => $result->{requests_pending} } } }; } 1; __END__ =head1 MODE Check system usage. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='status' =item B<--warning-services-status> Set warning threshold for status. Can used special variables like: %{status} =item B<--critical-services-status> Set critical threshold for status (Default: ''). Can used special variables like: %{status} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'requests-pending', 'sessions-total', 'sessions-primary', 'sessions-secondary', 'sessions-ghost'. =back =cut centreon-plugins-20220113/apps/wallix/bastion/snmp/plugin.pm000066400000000000000000000024311417000230700237470ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::wallix::bastion::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} = { 'license' => 'apps::wallix::bastion::snmp::mode::license', 'system' => 'apps::wallix::bastion::snmp::mode::system' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check WALLIX Bastion in SNMP. =cut centreon-plugins-20220113/apps/wazuh/000077500000000000000000000000001417000230700173355ustar00rootroot00000000000000centreon-plugins-20220113/apps/wazuh/restapi/000077500000000000000000000000001417000230700210045ustar00rootroot00000000000000centreon-plugins-20220113/apps/wazuh/restapi/custom/000077500000000000000000000000001417000230700223165ustar00rootroot00000000000000centreon-plugins-20220113/apps/wazuh/restapi/custom/api.pm000066400000000000000000000132101417000230700234220ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::wazuh::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use JSON::XS; 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 => { 'hostname:s@' => { name => 'hostname' }, 'username:s@' => { name => 'username' }, 'password:s@' => { name => 'password' }, 'timeout:s@' => { name => 'timeout' }, 'port:s@' => { name => 'port' }, 'proto:s@' => { name => 'proto' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? shift(@{$self->{option_results}->{hostname}}) : undef; $self->{username} = (defined($self->{option_results}->{username})) ? shift(@{$self->{option_results}->{username}}) : ''; $self->{password} = (defined($self->{option_results}->{password})) ? shift(@{$self->{option_results}->{password}}) : ''; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? shift(@{$self->{option_results}->{timeout}}) : 10; $self->{port} = (defined($self->{option_results}->{port})) ? shift(@{$self->{option_results}->{port}}) : 55000; $self->{proto} = (defined($self->{option_results}->{proto})) ? shift(@{$self->{option_results}->{proto}}) : 'https'; if (!defined($self->{hostname})) { $self->{output}->add_option_msg(short_msg => 'Need to specify hostname option.'); $self->{output}->option_exit(); } if (!defined($self->{hostname}) || scalar(@{$self->{option_results}->{hostname}}) == 0) { return 0; } return 1; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub get_port { my ($self, %options) = @_; return $self->{port}; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{credentials} = 1; $self->{option_results}->{basic} = 1; $self->{option_results}->{username} = $self->{username}; $self->{option_results}->{password} = $self->{password}; if (!defined($self->{option_results}->{ssl_opt})) { $self->{option_results}->{ssl_opt} = ['SSL_verify_mode => SSL_VERIFY_NONE']; } if (!defined($self->{option_results}->{curl_opt})) { $self->{option_results}->{curl_opt} = ['CURLOPT_SSL_VERIFYPEER => 0', 'CURLOPT_SSL_VERIFYHOST => 0']; } } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->set_options(%{$self->{option_results}}); } sub request { my ($self, %options) = @_; $self->settings(); my $content = $self->{http}->request( url_path => $options{path}, unknown_status => '', warning_status => '', critical_status => '', ); if ($self->{http}->get_code() != 200) { $self->{output}->add_option_msg(short_msg => 'Connection issue : ' . $self->{http}->get_message() . ' (' . $self->{http}->get_code() . ')'); $self->{output}->option_exit(); } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => 'Cannot decode json response'); $self->{output}->option_exit(); } if ($decoded->{error} != 0) { $self->{output}->add_option_msg(short_msg => "api error $decoded->{error}: " . $decoded->{message}); $self->{output}->option_exit(); } return $decoded; } 1; __END__ =head1 NAME Wazuh REST API =head1 SYNOPSIS Wazuh Rest API custom mode =head1 REST API OPTIONS =over 8 =item B<--hostname> Wazuh hostname. =item B<--username> Wazuh username. =item B<--password> Wazuh password. =item B<--timeout> Set HTTP timeout in seconds (Default: '10'). =item B<--proto> Set protocol (default: 'https') =item B<--port> Set HTTP port (default: 55000) =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/wazuh/restapi/mode/000077500000000000000000000000001417000230700217305ustar00rootroot00000000000000centreon-plugins-20220113/apps/wazuh/restapi/mode/agents.pm000066400000000000000000000115311417000230700235500ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::wazuh::restapi::mode::agents; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf('status: %s [node name: %s]', $self->{result_values}->{status}, $self->{result_values}->{node_name} ); return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }, { name => 'agent', type => 1, cb_prefix_output => 'prefix_agent_output', message_multiple => 'All agents are ok' } ]; $self->{maps_counters}->{global} = []; foreach ('active', 'pending', 'neverconnected', 'disconnected') { push @{$self->{maps_counters}->{global}}, { label => $_, nlabel => 'agents.' . $_ . '.count', display_ok => 0, set => { key_values => [ { name => $_ } ], output_template => $_ . ': %s', perfdatas => [ { value => $_ , template => '%s', min => 0 }, ], } }; } $self->{maps_counters}->{agent} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'display' }, { name => 'node_name' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_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 => { '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); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub prefix_global_output { my ($self, %options) = @_; return "Total agents "; } sub prefix_agent_output { my ($self, %options) = @_; return "Agent '" . $options{instance_value}->{display} . "' "; } sub manage_selection { my ($self, %options) = @_; $self->{global} = { active => 0, pending => 0, neverconnected => 0, disconnected => 0 }; $self->{agent} = {}; my $result = $options{custom}->request(path => '/agents?select=name,status,node_name'); foreach (@{$result->{data}->{items}}) { 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 agent '" . $_->{name} . "': no matching filter.", debug => 1); next; } my $status = lc($_->{status}); $self->{agent}->{$_->{id}} = { display => $_->{name}, node_name => $_->{node_name}, status => $status, }; $self->{global}->{$status}++; } } 1; __END__ =head1 MODE Check wazuh agents. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^status$' =item B<--filter-name> Filter agent name (can be a regexp). =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{node_name}, %{display} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{status}, %{node_name}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'active', 'pending', 'neverconnected', 'disconnected'. =back =cut centreon-plugins-20220113/apps/wazuh/restapi/mode/manager.pm000066400000000000000000000153301417000230700237020ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::wazuh::restapi::mode::manager; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf('status: %s', $self->{result_values}->{status}, ); return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }, { name => 'process', type => 1, cb_prefix_output => 'prefix_process_output', message_multiple => 'All manager processes are ok' }, { name => 'log', type => 1, cb_prefix_output => 'prefix_log_output', message_multiple => 'All manager logs are ok' } ]; $self->{maps_counters}->{global} = []; foreach ('stopped', 'running') { push @{$self->{maps_counters}->{global}}, { label => 'processes-' . $_, nlabel => 'manager.processes.' . $_ . '.count', display_ok => 0, set => { key_values => [ { name => $_ } ], output_template => $_ . ': %s', perfdatas => [ { value => $_ , template => '%s', min => 0 }, ], } }; } $self->{maps_counters}->{process} = [ { label => 'process-status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'display' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold, } }, ]; $self->{maps_counters}->{log} = []; foreach ('error', 'critical', 'warning') { push @{$self->{maps_counters}->{log}}, { label => 'log-' . $_, nlabel => 'manager.log.' . $_ . '.count', set => { key_values => [ { name => $_, diff => 1 } ], output_template => $_ . ': %s', perfdatas => [ { value => $_ , template => '%s', min => 0 }, ], } }; } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, , statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-process:s' => { name => 'filter_process' }, 'filter-log:s' => { name => 'filter_log' }, 'warning-process-status:s' => { name => 'warning_process_status', default => '' }, 'critical-process-status:s' => { name => 'critical_process_status', default => '' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_process_status', 'critical_process_status']); } sub prefix_global_output { my ($self, %options) = @_; return "Total processes "; } sub prefix_process_output { my ($self, %options) = @_; return "Process '" . $options{instance_value}->{display} . "' "; } sub prefix_log_output { my ($self, %options) = @_; return "Log '" . $options{instance_value}->{display} . "' "; } sub manage_selection { my ($self, %options) = @_; $self->{global} = { running => 0, stopped => 0 }; $self->{process} = {}; my $result = $options{custom}->request(path => '/manager/status'); foreach (keys %{$result->{data}}) { if (defined($self->{option_results}->{filter_process}) && $self->{option_results}->{filter_process} ne '' && $_ !~ /$self->{option_results}->{filter_process}/) { $self->{output}->output_add(long_msg => "skipping process '" . $_ . "': no matching filter.", debug => 1); next; } my $status = lc($result->{data}->{$_}); $self->{process}->{$_} = { display => $_, status => $status, }; $self->{global}->{$status}++; } $self->{log} = {}; $result = $options{custom}->request(path => '/manager/logs/summary?'); foreach (keys %{$result->{data}}) { if (defined($self->{option_results}->{filter_log}) && $self->{option_results}->{filter_log} ne '' && $_ !~ /$self->{option_results}->{filter_log}/) { $self->{output}->output_add(long_msg => "skipping log '" . $_ . "': no matching filter.", debug => 1); next; } $self->{log}->{$_} = { display => $_, error => $result->{data}->{$_}->{error}, warning => $result->{data}->{$_}->{warning}, critical => $result->{data}->{$_}->{critical}, }; } $self->{cache_name} = 'wazuh_' . $options{custom}->get_hostname() . '_' . $options{custom}->get_port() . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_log}) ? md5_hex($self->{option_results}->{filter_log}) : md5_hex('all')); } 1; __END__ =head1 MODE Check wazuh manager processes and logs. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^status$' =item B<--filter-process> Filter process name (can be a regexp). =item B<--filter-log> Filter log name (can be a regexp). =item B<--warning-process-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{display} =item B<--critical-process-status> Set critical threshold for status (Default: ''). Can used special variables like: %{status}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'processes-running', 'processes-stopped', 'log-error', 'log-critical', 'log-warning'. =back =cut centreon-plugins-20220113/apps/wazuh/restapi/plugin.pm000066400000000000000000000025251417000230700226440ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::wazuh::restapi::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} = '1.0'; %{$self->{modes}} = ( 'agents' => 'apps::wazuh::restapi::mode::agents', 'manager' => 'apps::wazuh::restapi::mode::manager', ); $self->{custom_modes}{api} = 'apps::wazuh::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Wazuh through HTTP/REST API. =cut centreon-plugins-20220113/apps/zoom/000077500000000000000000000000001417000230700171635ustar00rootroot00000000000000centreon-plugins-20220113/apps/zoom/restapi/000077500000000000000000000000001417000230700206325ustar00rootroot00000000000000centreon-plugins-20220113/apps/zoom/restapi/custom/000077500000000000000000000000001417000230700221445ustar00rootroot00000000000000centreon-plugins-20220113/apps/zoom/restapi/custom/api.pm000066400000000000000000000146361417000230700232650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::zoom::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use centreon::plugins::statefile; use DateTime; use Digest::MD5 qw(md5_hex); use JSON::XS; use JSON::WebToken; 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 => { 'hostname:s' => { name => 'hostname' }, 'url-path:s' => { name => 'url_path' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'api-key:s' => { name => 'api_key' }, 'api-secret:s' => { name => 'api_secret' }, 'timeout:s' => { name => 'timeout' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); $self->{cache} = centreon::plugins::statefile->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : 'api.zoom.us'; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{url_path} = (defined($self->{option_results}->{url_path})) ? $self->{option_results}->{url_path} : '/v2'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{api_key} = (defined($self->{option_results}->{api_key})) ? $self->{option_results}->{api_key} : ''; $self->{api_secret} = (defined($self->{option_results}->{api_secret})) ? $self->{option_results}->{api_secret} : ''; if (!defined($self->{api_key}) || $self->{api_key} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-key option."); $self->{output}->option_exit(); } if (!defined($self->{api_secret}) || $self->{api_secret} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-secret option."); $self->{output}->option_exit(); } $self->{cache}->check_options(option_results => $self->{option_results}); return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{url_path} = $self->{url_path}; $self->{option_results}->{warning_status} = ''; $self->{option_results}->{critical_status} = ''; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); if (defined($self->{jwt_token})) { $self->{http}->add_header(key => 'Authorization', value => 'Bearer ' . $self->{jwt_token}); } $self->{http}->set_options(%{$self->{option_results}}); } sub get_jwt_token { my ($self, %options) = @_; my $has_cache_file = $options{statefile}->read(statefile => 'zoom_api_' . md5_hex($self->{api_key})); my $expires_on = $options{statefile}->get(name => 'expires_on'); my $jwt_token = $options{statefile}->get(name => 'jwt_token'); if ($has_cache_file == 0 || !defined($jwt_token) || (($expires_on - time()) < 10)) { my $exp = time() + 3600; $jwt_token = JSON::WebToken->encode({ alg => "HS256", typ => "JWT", iss => $self->{api_key}, exp => $exp, }, $self->{api_secret}, 'HS256'); my $datas = { last_timestamp => time(), jwt_token => $jwt_token, expires_on => $exp }; $options{statefile}->write(data => $datas); } return $jwt_token; } sub request_api { my ($self, %options) = @_; if (!defined($self->{jwt_token})) { $self->{jwt_token} = $self->get_jwt_token(statefile => $self->{cache}); } $self->settings; $self->{output}->output_add(long_msg => "Query URL: '" . $self->{proto} . "://" . $self->{hostname} . $self->{url_path} . $options{url_path} . "'", debug => 1); my $content = $self->{http}->request(url_path => $self->{url_path} . $options{url_path}); my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } return $decoded; } 1; __END__ =head1 NAME Zoom Rest API =head1 SYNOPSIS Zoom Rest API custom mode =head1 REST API OPTIONS Zoom Rest API =over 8 =item B<--hostname> Zoom API hostname (Default: 'api.zoom.us') =item B<--port> API port (Default: 443) =item B<--proto> Specify https if needed (Default: 'https') =item B<--url-path> API URL path (Default: '/v2') =item B<--api-key> JWT app API key. =item B<--api-secret> JWT app API secret. =item B<--timeout> Set HTTP timeout. =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/apps/zoom/restapi/mode/000077500000000000000000000000001417000230700215565ustar00rootroot00000000000000centreon-plugins-20220113/apps/zoom/restapi/mode/listusers.pm000066400000000000000000000064401417000230700241550ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::zoom::restapi::mode::listusers; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; my @users; my $page = 1; while (my $results = $options{custom}->request_api(url_path => '/users?page_size=30&page_number=' . $page)) { push @users, @{$results->{users}}; ($results->{page_number} < $results->{page_count}) ? $page++ : last; } foreach my $user (@users) { $self->{users}->{$user->{id}} = { first_name => $user->{first_name}, last_name => $user->{last_name}, email => $user->{email}, status => $user->{status}, id => $user->{id}, } } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $user (sort keys %{$self->{users}}) { $self->{output}->output_add( long_msg => sprintf("[id = %s] [first_name = %s] [last_name = %s] [email = %s] [status = %s]", $self->{users}->{$user}->{id}, $self->{users}->{$user}->{first_name}, $self->{users}->{$user}->{last_name}, $self->{users}->{$user}->{email}, $self->{users}->{$user}->{status}) ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List users:' ); $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 => ['id', 'first_name', 'last_name', 'email', 'status']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $user (sort keys %{$self->{users}}) { $self->{output}->add_disco_entry( id => $self->{users}->{$user}->{id}, first_name => $self->{users}->{$user}->{first_name}, last_name => $self->{users}->{$user}->{last_name}, email => $self->{users}->{$user}->{email}, status => $self->{users}->{$user}->{status}, ); } } 1; __END__ =head1 MODE List users. =over 8 =back =cut centreon-plugins-20220113/apps/zoom/restapi/plugin.pm000066400000000000000000000024101417000230700224630ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package apps::zoom::restapi::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}} = ( 'list-users' => 'apps::zoom::restapi::mode::listusers', ); $self->{custom_modes}{api} = 'apps::zoom::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Zoom. =cut centreon-plugins-20220113/blockchain/000077500000000000000000000000001417000230700173315ustar00rootroot00000000000000centreon-plugins-20220113/blockchain/hyperledger/000077500000000000000000000000001417000230700216435ustar00rootroot00000000000000centreon-plugins-20220113/blockchain/hyperledger/exporter/000077500000000000000000000000001417000230700235135ustar00rootroot00000000000000centreon-plugins-20220113/blockchain/hyperledger/exporter/mode/000077500000000000000000000000001417000230700244375ustar00rootroot00000000000000centreon-plugins-20220113/blockchain/hyperledger/exporter/mode/channels.pm000066400000000000000000000233161417000230700265750ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package blockchain::hyperledger::exporter::mode::channels; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::common::monitoring::openmetrics::scrape; use Digest::MD5 qw(md5_hex); sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'channel', type => 3, cb_prefix_output => 'prefix_channel_output', cb_long_output => 'channel_long_output', indent_long_output => ' ', message_multiple => 'All channels are ok', group => [ { name => 'channel_global', type => 0, message_separator => ' - ', skipped_code => { -10 => 1 } }, { name => 'channel_gscd', type => 0, cb_prefix_output => 'prefix_gscd_output', skipped_code => { -10 => 1 } }, { name => 'channel_gpvd', type => 0, cb_prefix_output => 'prefix_gpvd_output', skipped_code => { -10 => 1 } }, ] } ]; foreach (( ['gscd', 'gossip.state.commit', 'gossip_state_commit_duration'], ['gpvd', 'gossip.privdata.validation', 'gossip_privdata_validation_duration'] )) { $self->{maps_counters}->{'channel_' . $_->[0]} = [ { label => $_->[0] . '-total', nlabel => 'channel.' . $_->[1] . '.total.count', set => { key_values => [ { name => $_->[2] . '_count', diff => 1 } ], output_template => '%s (total)', perfdatas => [ { value => $_->[2] . '_count', template => '%s', min => 0, label_extra_instance => 1 }, ], } } ]; foreach my $label (('0.005', '0.01', '0.025', '0.05', '0.1', '0.25', '0.5', '1', '2.5', '5', '10', '+Inf')) { my $perf_label = $label; $perf_label =~ s/\+Inf/infinite/; push @{$self->{maps_counters}->{'channel_' . $_->[0]}}, { label => $_->[0] . '-time-le-' . $perf_label, nlabel => 'channel.' . $_->[1] . '.time.le.' . $perf_label . '.count', set => { key_values => [ { name => $_->[2] . '_bucket_' . $label, diff => 1 } ], output_template => '%s (<= ' . $perf_label . ' sec)', perfdatas => [ { value => $_->[2] . '_bucket_' . $label , template => '%s', min => 0, label_extra_instance => 1 }, ], } }; } } $self->{maps_counters}->{channel_global} = [ { label => 'ledger-transaction', nlabel => 'channel.ledger.transaction.count', set => { key_values => [ { name => 'ledger_transaction_count', diff => 1 } ], output_template => 'number of transactions processed: %s', perfdatas => [ { value => 'ledger_transaction_count', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, { label => 'gossip-membership-total-peers-known', nlabel => 'channel.gossip.membership.total.peers.known.count', set => { key_values => [ { name => 'gossip_membership_total_peers_known' } ], output_template => 'total known peers: %s', perfdatas => [ { value => 'gossip_membership_total_peers_known', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, { label => 'gossip-state-height', nlabel => 'channel.gossip.state.height.count', set => { key_values => [ { name => 'gossip_state_height' } ], output_template => 'current ledger height: %s', perfdatas => [ { value => 'gossip_state_height', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, { label => 'ledger-blockchain-height', nlabel => 'channel.ledger.blockchain.height.count', set => { key_values => [ { name => 'ledger_blockchain_height' } ], output_template => 'height of the chain in blocks: %s', perfdatas => [ { value => 'ledger_blockchain_height', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, ]; } sub channel_long_output { my ($self, %options) = @_; return "checking channel '" . $options{instance_value}->{display} . "'"; } sub prefix_channel_output { my ($self, %options) = @_; return "channel '" . $options{instance_value}->{display} . "' "; } sub prefix_gscd_output { my ($self, %options) = @_; return 'time it takes to commit a block: '; } sub prefix_gpvd_output { my ($self, %options) = @_; return 'time it takes to validate a block: '; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-channel:s' => { name => 'filter_channel' }, }); return $self; } sub change_macros { my ($self, %options) = @_; $options{template} =~ s/%\{(.*?)\}/$options{dimensions}->{$1}/g; if (defined($options{escape})) { $options{template} =~ s/([\Q$options{escape}\E])/\\$1/g; } return $options{template}; } sub search_metric { my ($self, %options) = @_; return if (!defined($options{metrics}->{$options{label}})); foreach (@{$options{metrics}->{$options{label}}->{data}}) { next if (!defined($_->{dimensions}->{$options{dimension}})); my $dimension = $_->{dimensions}->{$options{dimension}}; next if (defined($self->{option_results}->{filter_channel}) && $self->{option_results}->{filter_channel} ne '' && $dimension !~ /$self->{option_results}->{filter_channel}/); if (!defined($self->{channel}->{$dimension})) { $self->{channel}->{$dimension} = { display => $dimension }; } $self->{channel}->{$dimension}->{$options{store}} = {} if (!defined($self->{channel}->{$dimension}->{$options{store}})); my $key = $self->change_macros(template => $options{key}, dimensions => $_->{dimensions}); $self->{channel}->{$dimension}->{$options{store}}->{$key} = $_->{value}; } } sub manage_selection { my ($self, %options) = @_; my $metrics = centreon::common::monitoring::openmetrics::scrape::parse(%options, strip_chars => "[\"']"); $self->{channel} = {}; $self->search_metric( metrics => $metrics, label => 'gossip_state_commit_duration_bucket', dimension => 'channel', key => 'gossip_state_commit_duration_bucket_%{le}', store => 'channel_gscd' ); $self->search_metric( metrics => $metrics, label => 'gossip_state_commit_duration_count', dimension => 'channel', key => 'gossip_state_commit_duration_count', store => 'channel_gscd' ); $self->search_metric( metrics => $metrics, label => 'gossip_privdata_validation_duration_bucket', dimension => 'channel', key => 'gossip_privdata_validation_duration_bucket_%{le}', store => 'channel_gpvd' ); $self->search_metric( metrics => $metrics, label => 'gossip_privdata_validation_duration_count', dimension => 'channel', key => 'gossip_privdata_validation_duration_count', store => 'channel_gpvd' ); $self->search_metric( metrics => $metrics, label => 'ledger_transaction_count', dimension => 'channel', key => 'ledger_transaction_count', store => 'channel_global' ); $self->search_metric( metrics => $metrics, label => 'gossip_membership_total_peers_known', dimension => 'channel', key => 'gossip_membership_total_peers_known', store => 'channel_global' ); $self->search_metric( metrics => $metrics, label => 'gossip_state_height', dimension => 'channel', key => 'gossip_state_height', store => 'channel_global' ); $self->search_metric( metrics => $metrics, label => 'ledger_blockchain_height', dimension => 'channel', key => 'ledger_blockchain_height', store => 'channel_global' ); $self->{cache_name} = 'hyperledger_' . $options{custom}->get_uuid() . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_channel}) ? md5_hex($self->{option_results}->{filter_channel}) : md5_hex('all')); } 1; __END__ =head1 MODE Check blockchain system. =over 8 =item B<--filter-name> Filter channel channel (can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Use --list-counters to get available thresholds options. =back =cut centreon-plugins-20220113/blockchain/hyperledger/exporter/plugin.pm000066400000000000000000000026741417000230700253600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package blockchain::hyperledger::exporter::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}} = ( 'channels' => 'blockchain::hyperledger::exporter::mode::channels', ); $self->{custom_modes}{web} = 'centreon::common::monitoring::openmetrics::custom::web'; $self->{custom_modes}{file} = 'centreon::common::monitoring::openmetrics::custom::file'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Hyperledger blockchain with prometheus exporter. =cut centreon-plugins-20220113/blockchain/parity/000077500000000000000000000000001417000230700206415ustar00rootroot00000000000000centreon-plugins-20220113/blockchain/parity/ethpoller/000077500000000000000000000000001417000230700226375ustar00rootroot00000000000000centreon-plugins-20220113/blockchain/parity/ethpoller/custom/000077500000000000000000000000001417000230700241515ustar00rootroot00000000000000centreon-plugins-20220113/blockchain/parity/ethpoller/custom/api.pm000066400000000000000000000125731417000230700252700ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package blockchain::parity::ethpoller::custom::api; use strict; use warnings; use centreon::plugins::http; use DateTime; use JSON::XS; 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 => { "hostname:s" => { name => 'hostname' }, "port:s" => { name => 'port' }, "proto:s" => { name => 'proto' }, "url-path:s" => { name => 'url_path' }, "timeout:s" => { name => 'timeout' }, }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{mode} = $options{mode}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } 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->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : undef; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 8000; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'http'; $self->{url_path} = (defined($self->{option_results}->{url_path})) ? $self->{option_results}->{url_path} : ''; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; if (!defined($self->{hostname}) || $self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{url_path} = $self->{url_path}; $self->{option_results}->{warning_status} = ''; $self->{option_results}->{critical_status} = ''; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->set_options(%{$self->{option_results}}); } sub get_connection_info { my ($self, %options) = @_; return $self->{hostname} . ":" . $self->{port}; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub get_port { my ($self, %options) = @_; return $self->{port}; } sub request_api { my ($self, %options) = @_; $self->settings; $self->{output}->output_add(long_msg => "Query URL: '" . $self->{proto} . "://" . $self->{hostname} . $self->{url_path} . $options{url_path} . "'", debug => 1); my $content = $self->{http}->request(url_path => $self->{url_path} . $options{url_path}); my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } return $decoded; } 1; __END__ =head1 NAME Parity eth-poller Rest API =head1 SYNOPSIS Parity eth-poller Rest API custom mode =head1 REST API OPTIONS Parity eth-poller Rest API =over 8 =item B<--hostname> Parity eth-poller API hostname. =item B<--port> API port (Default: 8000) =item B<--proto> Specify https if needed (Default: 'http') =item B<--url-path> API URL path (Default: '') =item B<--timeout> Set HTTP timeout =back =head1 DESCRIPTION B. =cutcentreon-plugins-20220113/blockchain/parity/ethpoller/mode/000077500000000000000000000000001417000230700235635ustar00rootroot00000000000000centreon-plugins-20220113/blockchain/parity/ethpoller/mode/disk.pm000066400000000000000000000110411417000230700250500ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package blockchain::parity::ethpoller::mode::disk; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use bigint; use Digest::MD5 qw(md5_hex); sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', cb_prefix_output => 'prefix_module_output', type => 0 }, ]; $self->{maps_counters}->{global} = [ { label => 'disk-free', nlabel => 'eth.poller.disk.free', set => { key_values => [ { name => 'disk_free' } ], output_template => "Disk free: %d ", perfdatas => [ { label => 'disk_free', value => 'disk_free', unit => 'B', template => '%d', min => 0 } ], } }, { label => 'disk-available', nlabel => 'eth.poller.disk.available', set => { key_values => [ { name => 'disk_available' } ], output_template => "Disk available: %d ", perfdatas => [ { label => 'disk_available', value => 'disk_available', unit => 'B', template => '%d', min => 0 } ], } }, { label => 'disk-size', nlabel => 'eth.poller.disk.size', set => { key_values => [ { name => 'disk_size' } ], output_template => "Disk size: %d ", perfdatas => [ { label => 'disk_size', value => 'disk_size', template => '%d', unit => 'B', min => 0 } ], } }, { label => 'disk-used', nlabel => 'eth.poller.disk.used', set => { key_values => [ { name => 'disk_used' } ], output_template => "Disk used: %d ", perfdatas => [ { label => 'disk_used', value => 'disk_used', template => '%d', unit => 'B', min => 0 } ], } }, { label => 'disk-usage', nlabel => 'eth.poller.disk.usage', set => { key_values => [ { name => 'disk_usage' } ], output_template => "Disk usage: %d %%", perfdatas => [ { label => 'disk_usage', value => 'disk_usage', template => '%.2f', unit => '%', min => 0 } ], } }, { label => 'blockchain-dir', nlabel => 'eth.poller.blockchain.directory', set => { key_values => [ { name => 'blockchain_dir' } ], output_template => "Blockchain directory: %d", perfdatas => [ { label => 'blockchain_dir', value => 'blockchain_dir', unit => 'B', template => '%d', min => 0 } ], } } ]; } sub prefix_output { my ($self, %options) = @_; return "Disk '"; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, }); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->request_api(url_path => '/disk'); $self->{global} = { disk_free => $result->{free}, disk_available => $result->{available}, disk_size => $result->{size}, disk_used => $result->{used}, disk_usage => $result->{usage}, blockchain_dir => $result->{dir} }; $self->{output}->output_add(severity => 'OK', long_msg => 'Ledger: ' . $result->{dir} . ' (' . $result->{usage} . '%)'); } 1; __END__ =head1 MODE Check Parity eth-poller for disk monitoring =cut centreon-plugins-20220113/blockchain/parity/ethpoller/mode/stats.pm000066400000000000000000000147271417000230700252720ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package blockchain::parity::ethpoller::mode::stats; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use bigint; use Digest::MD5 qw(md5_hex); sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'block', cb_prefix_output => 'prefix_output_block', type => 0 }, { name => 'transaction', cb_prefix_output => 'prefix_output_transaction', type => 0 }, { name => 'fork', cb_prefix_output => 'prefix_output_fork', type => 0 } ]; $self->{maps_counters}->{block} = [ { label => 'block-frequency', nlabel => 'parity.stats.block.perminute', set => { key_values => [ { name => 'block_count', per_minute => 1 }, { name => 'last_block' }, { name => 'last_block_ts' } ], closure_custom_output => $self->can('custom_block_output'), perfdatas => [ { label => 'block', value => 'block_count', template => '%.2f' } ], } } ]; $self->{maps_counters}->{transaction} = [ { label => 'transaction-frequency', nlabel => 'parity.stats.transaction.perminute', set => { key_values => [ { name => 'transaction_count', per_minute => 1 }, { name => 'last_transaction' }, { name => 'last_transaction_ts' } ], closure_custom_output => $self->can('custom_transaction_output'), perfdatas => [ { label => 'transaction', value => 'transaction_count', template => '%.2f' } ], } } ]; $self->{maps_counters}->{fork} = [ { label => 'fork-frequency', nlabel => 'parity.stats.fork.perminute', set => { key_values => [ { name => 'fork_count', per_minute => 1 }, { name => 'last_fork' }, { name => 'last_fork_ts' } ], closure_custom_output => $self->can('custom_fork_output'), perfdatas => [ { label => 'fork', value => 'fork_count', template => '%.2f' } ], } } ]; } sub custom_block_output { my ($self, %options) = @_; if (0 eq $self->{result_values}->{block_count}) { return sprintf("No block yet..."); } else { return sprintf( "Block frequency: '%.2f/min', Last block (#%s)", $self->{result_values}->{block_count}, $self->{result_values}->{last_block} ); } } sub custom_transaction_output { my ($self, %options) = @_; if (0 eq $self->{result_values}->{transaction_count}) { return sprintf("No transaction yet..."); } else { return sprintf( "Transaction frequency: '%.2f/min', Last transaction (#%s)", $self->{result_values}->{transaction_count}, $self->{result_values}->{last_transaction} ); } } sub custom_fork_output { my ($self, %options) = @_; if (0 eq $self->{result_values}->{fork_count}) { return sprintf("No fork occurred yet..."); } else { return sprintf( "Fork frequency: '%.2f/min', Last fork (#%s)", $self->{result_values}->{fork_count}, $self->{result_values}->{last_fork} ); } } sub prefix_output_block { my ($self, %options) = @_; return "Block stats '"; } sub prefix_output_fork { my ($self, %options) = @_; return "Fork stats '"; } sub prefix_output_transaction { my ($self, %options) = @_; return "Transaction stats '"; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = "parity_ethpoller_" . $self->{mode} . '_' . (defined($self->{option_results}->{hostname}) ? $self->{option_results}->{hostname} : 'me') . '_' . (defined($self->{option_results}->{port}) ? $self->{option_results}->{port} : 'default') . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); my $result = $options{custom}->request_api(url_path => '/stats'); my $last_block_timestamp = (defined($result->{block}->{timestamp}) && $result->{block}->{timestamp} != 0) ? $result->{block}->{timestamp} : 'NONE'; my $last_transaction_timestamp = (defined($result->{transaction}->{timestamp}) && $result->{transaction}->{timestamp} != 0) ? $result->{transaction}->{timestamp} : 'NONE'; my $last_fork_timestamp = (defined($result->{fork}->{timestamp}) && $result->{fork}->{timestamp} != 0) ? $result->{fork}->{timestamp} : 'NONE'; $self->{block} = { block_count => $result->{block}->{count}, last_block => $result->{block}->{count}, last_block_ts => $last_block_timestamp }; $self->{transaction} = { transaction_count => $result->{transaction}->{count}, last_transaction => $result->{transaction}->{count}, last_transaction_ts => $last_transaction_timestamp }; $self->{fork} = { fork_count => $result->{fork}->{count}, last_fork => $result->{fork}->{count}, last_fork_ts => $last_fork_timestamp }; } 1; __END__ =head1 MODE Check Parity eth-poller for statsitics about blocks, transactions and forks =cut centreon-plugins-20220113/blockchain/parity/ethpoller/mode/tracking.pm000066400000000000000000000271611417000230700257320ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package blockchain::parity::ethpoller::mode::tracking; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use bigint; use Math::BigFloat; use Digest::MD5 qw(md5_hex); sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'events', cb_prefix_output => 'prefix_output_events', type => 1, message_multiple => 'Events metrics are ok' }, { name => 'mining', cb_prefix_output => 'prefix_output_mining', type => 1, message_multiple => 'Mining metrics are ok' }, { name => 'balance', cb_prefix_output => 'prefix_output_balances', type => 1, message_multiple => 'Balances metrics are ok' } ]; $self->{maps_counters}->{events} = [ { label => 'events-frequency', nlabel => 'parity.tracking.events.perminute', set => { key_values => [ { name => 'events_count', per_minute => 1 }, { name => 'display' }, { name => 'last_event' }, { name => 'last_event_block' }, { name => 'last_event_ts' } ], closure_custom_output => $self->can('custom_event_output'), perfdatas => [ { template => '%.2f', label_extra_instance => 1, instance_use => 'display' } ] } } ]; $self->{maps_counters}->{mining} = [ { label => 'mining-frequency', nlabel => 'parity.tracking.mined.block.perminute', set => { key_values => [ { name => 'mining_count', per_minute => 1 }, { name => 'display' }, , { name => 'last_mining' }, { name => 'last_mining_block' }, { name => 'last_mining_ts' } ], closure_custom_output => $self->can('custom_miner_output'), perfdatas => [ { template => '%.2f', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'mining-prct', nlabel => 'parity.tracking.mined.block.prct', display_ok => 0, set => { key_values => [], manual_keys => 1, closure_custom_calc => $self->can('custom_mining_prct_calc'), closure_custom_output => $self->can('custom_mining_prct_output'), threshold_use => 'mining_prct', perfdatas => [ { value => 'mining_prct', template => '%.2f', unit => '%', min => 0, label_extra_instance => 1, instance_use => 'display' } ], } } ]; $self->{maps_counters}->{balance} = [ # { label => 'balance-fluctuation-prct', nlabel => 'parity.tracking.balances.fluctuation', display_ok => 0, set => { # key_values => [], # manual_keys => 1, # closure_custom_calc => $self->can('custom_balance_prct_calc'), # closure_custom_output => $self->can('custom_balance_prct_output'), # threshold_use => 'balance_fluctuation_prct', # perfdatas => [ # { value => 'balance_fluctuation_prct', template => '%.2f', unit => '%', # min => 0, label_extra_instance => 1, instance_use => 'display' } # ], # } # } { label => 'balance-changes', nlabel => 'parity.tracking.balance.changes.perminute', set => { key_values => [ { name => 'balance_count', per_minute => 1 }, { name => 'display' }, { name => 'last_balance' } ], closure_custom_output => $self->can('custom_balance_output'), perfdatas => [ { template => '%.2f', label_extra_instance => 1, unit => 'wei', instance_use => 'display' } ] } }, ]; } sub prefix_output_balances { my ($self, %options) = @_; return "Balance '" . $options{instance_value}->{display} . "' "; } sub prefix_output_events { my ($self, %options) = @_; return "Event '" . $options{instance_value}->{display} . "' "; } sub prefix_output_mining { my ($self, %options) = @_; return "Miner '" . $options{instance_value}->{display} . "' "; } sub custom_mining_prct_output { my ($self, %options) = @_; return sprintf( "Mined: %d blocks, witch corresponds to %.2f %% of total validated block", $self->{result_values}->{mined_block_count}, $self->{result_values}->{mining_prct} ); } sub custom_mining_prct_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{mined_block_count} = Math::BigFloat->new($options{new_datas}->{$self->{instance} . '_mined_block_count'}); $self->{result_values}->{total_block} = Math::BigFloat->new($options{new_datas}->{$self->{instance} . '_total_block'}); $self->{result_values}->{mining_prct} = (defined($self->{result_values}->{total_block}) && $self->{result_values}->{total_block} != 0) ? $self->{result_values}->{mined_block_count} / $self->{result_values}->{total_block} * 100 : 0; return 0; } # sub custom_balance_prct_output { # my ($self, %options) = @_; # return sprintf( # "Balance: %s ether, Last fluctuation: %.2f ", # $self->{result_values}->{balance}, # $self->{result_values}->{balance_fluctuation_prct} # ); # } # sub custom_balance_prct_calc { # my ($self, %options) = @_; # $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; # $self->{result_values}->{balance} = Math::BigFloat->new($options{new_datas}->{$self->{instance} . '_balance'}); # $self->{result_values}->{balance_old} = Math::BigFloat->new($options{old_datas}->{$self->{instance} . '_balance'}); # $self->{result_values}->{balance_fluctuation_prct} = (defined($self->{result_values}->{balance_old}) && $self->{result_values}->{balance_old} != 0) ? # ($self->{result_values}->{balance} - $self->{result_values}->{balance_old}) / # $self->{result_values}->{balance_old} * 100 : 0; # return 0; # } sub custom_event_output { my ($self, %options) = @_; if (0 eq $self->{result_values}->{last_event}) { return sprintf("No event yet..."); } else { return sprintf( "Event frequency: %.2f/min, Last event (#%s) was in block #%s", $self->{result_values}->{event_count}, $self->{result_values}->{last_event}, $self->{result_values}->{last_event_block} ); } } sub custom_miner_output { my ($self, %options) = @_; if (0 eq $self->{result_values}->{last_mining}) { return sprintf("No validation yet..."); } else { return sprintf( "Mining frequency: %.2f/min, Last validation (#%s) ago for block #%s", $self->{result_values}->{mining_count}, $self->{result_values}->{last_mining}, $self->{result_values}->{last_mining_block} ); } } sub custom_balance_output { my ($self, %options) = @_; if (0 eq $self->{result_values}->{balance_count}) { return sprintf("No change in balance in last minute. Balance still %s wei", $self->{result_values}->{last_balance}); } else { return sprintf( "Balance changes: %.2f/min. New balance: %s", $self->{result_values}->{balance_count}, $self->{result_values}->{last_balance} ); } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = "parity_ethpoller_" . $self->{mode} . '_' . (defined($self->{option_results}->{hostname}) ? $self->{option_results}->{hostname} : 'me') . '_' . (defined($self->{option_results}->{port}) ? $self->{option_results}->{port} : 'default') . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); my $results = $options{custom}->request_api(url_path => '/tracking'); $self->{events} = {}; $self->{mining} = {}; $self->{balance} = {}; foreach my $event (@{$results->{events}}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $event->{id} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $event->{label} . "': no matching filter name.", debug => 1); next; } my $last_event_timestamp = (defined($event->{timestamp}) && $event->{timestamp} != 0) ? $event->{timestamp} : 'NONE'; $self->{events}->{lc($event->{label})} = { display => lc($event->{label}), events_count => $event->{count}, last_event => $event->{count}, last_event_block => $event->{block}, last_event_ts => $last_event_timestamp }; } foreach my $miner (@{$results->{miners}}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $miner->{id} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $miner->{label} . "': no matching filter name.", debug => 1); next; } my $last_mining_timestamp = (defined($miner->{timestamp}) && $miner->{timestamp} != 0) ? $miner->{timestamp} : 'NONE'; $self->{mining}->{lc($miner->{label})} = { display => lc($miner->{label}), mining_count => $miner->{count}, last_mining => $miner->{count}, last_mining_block => $miner->{block}, last_mining_ts => $last_mining_timestamp, total_block => $miner->{currentBlock}, mined_block_count => $miner->{count} }; } foreach my $balance (@{$results->{balances}}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $balance->{id} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $balance->{label} . "': no matching filter name.", debug => 1); next; } $self->{balance}->{lc($balance->{label})} = { display => lc($balance->{label}), balance_count => $balance->{balance}, last_balance => $balance->{balance} }; } } 1; __END__ =head1 MODE Check Parity eth-poller for events, miners and balances tracking =cutcentreon-plugins-20220113/blockchain/parity/ethpoller/plugin.pm000066400000000000000000000027721417000230700245030ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package blockchain::parity::ethpoller::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}} = ( 'stats' => 'blockchain::parity::ethpoller::mode::stats', 'disk' => 'blockchain::parity::ethpoller::mode::disk', 'tracking' => 'blockchain::parity::ethpoller::mode::tracking' ); $self->{custom_modes}{api} = 'blockchain::parity::ethpoller::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Parity blockchain accounts, contracts and forks from eth-poller with HTTP GET requests =cut centreon-plugins-20220113/blockchain/parity/restapi/000077500000000000000000000000001417000230700223105ustar00rootroot00000000000000centreon-plugins-20220113/blockchain/parity/restapi/custom/000077500000000000000000000000001417000230700236225ustar00rootroot00000000000000centreon-plugins-20220113/blockchain/parity/restapi/custom/api.pm000066400000000000000000000123611417000230700247340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package blockchain::parity::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use JSON; 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 => { "hostname:s" => { name => 'hostname' }, "port:s" => { name => 'port' }, "timeout:s" => { name => 'timeout' }, "api-path:s" => { name => 'api_path' }, }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{mode} = $options{mode}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } 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->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : undef; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 8545; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{api_path} = (defined($self->{option_results}->{api_path})) ? $self->{option_results}->{api_path} : '/'; if (!defined($self->{hostname})) { $self->{output}->add_option_msg(short_msg => "Need to specify hostname option."); $self->{output}->option_exit(); } return 0; } sub get_connection_infos { my ($self, %options) = @_; return $self->{hostname} . '_' . $self->{http}->get_port(); } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = 'http'; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->add_header(key => 'Content-Type', value => 'application/json'); $self->{http}->set_options(%{$self->{option_results}}); } sub request_api { my ($self, %options) = @_; $self->settings(); my $encoded; eval { $encoded = encode_json($options{query_form_post}); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot encode json request"); $self->{output}->option_exit(); } my $content = $self->{http}->request(method => $options{method}, url_path => '/', query_form_post => $encoded, critical_status => '', warning_status => '', unknown_status => ''); my $decoded; eval { $decoded = decode_json($content); }; if ($@) { $self->{output}->output_add(long_msg => $content, debug => 1); $self->{output}->add_option_msg(short_msg => "Cannot decode json response"); $self->{output}->option_exit(); } if ($self->{http}->get_code() != 200) { $self->{output}->add_option_msg(short_msg => "Connection issue: " . $decoded->{msg}); $self->{output}->option_exit(); } return $decoded; } 1; __END__ =head1 NAME Parity node JSON WEBRPC =head1 SYNOPSIS Parity node JSON RPC API custom mode =head1 REST API OPTIONS =over 8 =item B<--hostname> Parity node hostname or IP =item B<--timeout> Set HTTP timeout in seconds (Default: '10'). =item B<--api-path> API base url path (Default: '/'). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/blockchain/parity/restapi/mode/000077500000000000000000000000001417000230700232345ustar00rootroot00000000000000centreon-plugins-20220113/blockchain/parity/restapi/mode/eth.pm000066400000000000000000000206401417000230700243540ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package blockchain::parity::restapi::mode::eth; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use bigint; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); sub custom_status_output { my ($self, %options) = @_; return sprintf( 'Client mininig status: %s ', $self->{result_values}->{is_mining}, ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'gas', cb_prefix_output => 'prefix_module_output', type => 0 }, { name => 'block', cb_prefix_output => 'prefix_module_output', type => 0 }, { name => 'sync', cb_prefix_output => 'prefix_module_output', type => 0 }, ]; $self->{maps_counters}->{sync} = [ { label => 'sync-status', nlabel => 'parity.eth.sync.status', set => { key_values => [ { name => 'sync_status' } ], output_template => "Syncing: %d %% ", perfdatas => [ { label => 'sync_status', value => 'sync_status', template => '%d', min => 0 } ], } } ]; $self->{maps_counters}->{gas} = [ { label => 'gas-price', nlabel => 'parity.eth.gas.price', set => { key_values => [ { name => 'gas_price' } ], output_template => "The gas price is: %d wei ", perfdatas => [ { label => 'gas_price', value => 'gas_price', template => '%d', min => 0 } ], } }, { label => 'gas-used', nlabel => 'parity.eth.gas.used', set => { key_values => [ { name => 'gas_used' } ], output_template => "The gas used is: %d", perfdatas => [ { label => 'gas_used', value => 'gas_used', template => '%d', min => 0 } ], } }, { label => 'gas-limit', nlabel => 'parity.eth.gas.limit', set => { key_values => [ { name => 'gas_limit' } ], output_template => "The gas limit is: %d", perfdatas => [ { label => 'gas_limit', value => 'gas_limit', template => '%d', min => 0 } ], } } ]; $self->{maps_counters}->{block} = [ { label => 'block-size', nlabel => 'parity.eth.block.size', set => { key_values => [ { name => 'block_size' } ], output_template => "Block size: %d ", perfdatas => [ { label => 'block_size', value => 'block_size', template => '%d', min => 0 } ], } }, { label => 'block-usage', nlabel => 'parity.eth.block.usage', set => { key_values => [ { name => 'block_usage' } ], output_template => "Block usage: %.2f %%", perfdatas => [ { label => 'block_usage', value => 'block_usage', template => '%.2f', unit => '%', min => 0 } ], } }, { label => 'block-transactions', nlabel => 'parity.eth.block.transactions.number', set => { key_values => [ { name => 'block_transactions' } ], output_template => "Block transactions number: %d ", perfdatas => [ { label => 'block_transactions', value => 'block_transactions', template => '%d', min => 0 } ], } }, { label => 'block-gas', nlabel => 'parity.eth.block.gas', set => { key_values => [ { name => 'block_gas' } ], output_template => "Block gas: %d ", perfdatas => [ { label => 'block_gas', value => 'block_gas', template => '%d', min => 0 } ], } }, { label => 'block-uncles', nlabel => 'parity.eth.block.uncles', set => { key_values => [ { name => 'block_uncles' } ], output_template => "Block uncles: %d ", perfdatas => [ { label => 'block_uncles', value => 'block_uncles', template => '%d', min => 0 } ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'unknown-status:s' => { name => 'unknown_status', default => '' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{listening} !~ /true/' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['unknown_status', 'warning_status', 'critical_status']); } sub prefix_module_output { my ($self, %options) = @_; return "Parity Eth module: "; } sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = "parity_restapi_" . $self->{mode} . '_' . (defined($self->{option_results}->{hostname}) ? $self->{option_results}->{hostname} : 'me') . '_' . (defined($self->{option_results}->{port}) ? $self->{option_results}->{port} : 'default') . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); my $query_form_post = [ { method => 'eth_mining', params => [], id => "1", jsonrpc => "2.0" }, { method => 'eth_coinbase', params => [], id => "2", jsonrpc => "2.0" }, { method => 'eth_gasPrice', params => [], id => "3", jsonrpc => "2.0" } , { method => 'eth_hashrate', params => [], id => "4", jsonrpc => "2.0" } , { method => 'eth_blockNumber', params => [], id => "5", jsonrpc => "2.0" }, { method => 'eth_getBlockByNumber', params => ["latest",\0], id => "6", jsonrpc => "2.0" }, { method => 'eth_syncing', params => [], id => "7", jsonrpc => "2.0" } ]; my $result = $options{custom}->request_api(method => 'POST', query_form_post => $query_form_post); my $gas_price = hex(@{$result}[2]->{result}); my $res_block_time = @{$result}[5]->{result}->{timestamp} == 0 ? '': localtime(hex(@{$result}[5]->{result}->{timestamp})); my $res_sync = 100; if (@{$result}[6]->{result}) { my $res_sync = hex(@{$result}[6]->{result}->{highestBlock}) != 0 ? (hex(@{$result}[6]->{result}->{currentBlock}) * 100) / hex(@{$result}[6]->{result}->{highestBlock}) : 'none'; } $self->{sync} = { sync_status => $res_sync }; $self->{gas} = { gas_price => $gas_price, gas_used => hex(@{$result}[5]->{result}->{gasUsed}), gas_limit => hex(@{$result}[5]->{result}->{gasLimit}) }; my $calculated_block_usage = hex(@{$result}[5]->{result}->{gasUsed}) / hex(@{$result}[5]->{result}->{gasLimit}) * 100; $self->{block} = { block_size => hex(@{$result}[5]->{result}->{size}), block_gas => hex(@{$result}[5]->{result}->{gasUsed}), block_usage => $calculated_block_usage, block_uncles => scalar(@{$$result[5]->{result}->{uncles}}), block_transactions => scalar(@{$$result[5]->{result}->{transactions}})}; } 1; __END__ =head1 MODE Check eth module metrics parity (Gas, blocks and syncing status)centreon-plugins-20220113/blockchain/parity/restapi/mode/infos.pm000066400000000000000000000065331417000230700247170ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package blockchain::parity::restapi::mode::infos; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'unknown-status:s' => { name => 'unknown_status', default => '' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{listening} !~ /true/' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['unknown_status', 'warning_status', 'critical_status']); } sub prefix_module_output { my ($self, %options) = @_; return "Parity network module: "; } sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = "parity_restapi_" . $self->{mode} . '_' . (defined($self->{option_results}->{hostname}) ? $self->{option_results}->{hostname} : 'me') . '_' . (defined($self->{option_results}->{port}) ? $self->{option_results}->{port} : 'default') . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); my $query_form_post = [ { method => 'parity_versionInfo', params => [], id => "1", jsonrpc => "2.0" }, { method => 'parity_chain', params => [], id => "2", jsonrpc => "2.0" }, { method => 'eth_mining', params => [], id => "3", jsonrpc => "2.0" }, { method => 'parity_nodeName', params => [], id => "4", jsonrpc => "2.0" }, ]; my $result = $options{custom}->request_api(method => 'POST', query_form_post => $query_form_post); my $res_parity_version = @{$result}[0]->{result}->{version}->{major} . '.' . @{$result}[0]->{result}->{version}->{minor} . '.' . @{$result}[0]->{result}->{version}->{patch}; $self->{output}->output_add(short_msg => "Parity version: '" . $res_parity_version . "'. Chain name: '" . @{$result}[1]->{result} . "'. Node name: '" . @{$result}[3]->{result} . "'. is_validator: '" . @{$result}[2]->{result} . "'.", severity => 'OK'); } 1; __END__ =head1 MODE Check parity network cross module metrics (Parity version, chain name and node name and type) centreon-plugins-20220113/blockchain/parity/restapi/mode/net.pm000066400000000000000000000070271417000230700243660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package blockchain::parity::restapi::mode::net; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); sub custom_status_output { my ($self, %options) = @_; return sprintf( 'Listening status: %s ', $self->{result_values}->{listening}, ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'network', cb_prefix_output => 'prefix_module_output', type => 0 }, ]; $self->{maps_counters}->{network} = [ { label => 'peers', nlabel => 'parity.network.peers.count', set => { key_values => [ { name => 'peers' } ], output_template => "connected peers: %s ", perfdatas => [ { label => 'peer_count', value => 'peers', template => '%d', min => 0 } ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'unknown-status:s' => { name => 'unknown_status', default => '' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{listening} !~ /true/' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['unknown_status', 'warning_status', 'critical_status']); } sub prefix_module_output { my ($self, %options) = @_; return "Parity network module: "; } sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = "parity_restapi_" . $self->{mode} . '_' . (defined($self->{option_results}->{hostname}) ? $self->{option_results}->{hostname} : 'me') . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); my $query_form_post = [ { method => 'net_listening', params => [], id => "1", jsonrpc => "2.0" }, { method => 'net_peerCount', params => [], id => "2", jsonrpc => "2.0" } ]; my $result = $options{custom}->request_api(method => 'POST', query_form_post => $query_form_post); my $peer_count = hex(@{$result}[1]->{result}); $self->{network} = { peers => hex(@{$result}[1]->{result}) }; $self->{output}->output_add(long_msg => "Node status: [is_listening: " . @{$result}[0]->{result} . ']', severity => 'OK'); } 1; __END__ =head1 MODE Check network module metrics parity (net_isListening, net_peerCount)centreon-plugins-20220113/blockchain/parity/restapi/mode/parity.pm000066400000000000000000000156501417000230700251110ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package blockchain::parity::restapi::mode::parity; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'mempool', cb_prefix_output => 'prefix_module_output', type => 0 }, { name => 'peers', cb_prefix_output => 'prefix_module_output', type => 0 } ]; $self->{maps_counters}->{mempool} = [ { label => 'mempool-tx-pending', nlabel => 'parity.pending.transactions', set => { key_values => [ { name => 'tx_pending' } ], output_template => "Pending transactions: %d", perfdatas => [ { label => 'tx_pending', value => 'tx_pending', template => '%d', min => 0 } ], } }, { label => 'mempool-size', nlabel => 'parity.mempol.size', set => { key_values => [ { name => 'mempool_size' } ], output_template => "Mempool size: %d", perfdatas => [ { label => 'mempool_size', value => 'mempool_size', template => '%d', min => 0 } ], } }, { label => 'mempool-usage', nlabel => 'parity.mempol.usage', set => { key_values => [ { name => 'mempool_usage' } ], output_template => "Mempool usage: %d %% ", perfdatas => [ { label => 'mempool_usage', value => 'mempool_usage', template => '%.2f', unit => '%', min => 0 } ], } }, ]; $self->{maps_counters}->{peers} = [ { label => 'peers-connected', nlabel => 'parity.peers.connected', set => { key_values => [ { name => 'peers_connected' } ], output_template => "Connected peers: %d", perfdatas => [ { label => 'peers_connected', value => 'peers_connected', template => '%d', min => 0 } ], } }, { label => 'peers-max', nlabel => 'parity.peers.max', set => { key_values => [ { name => 'peers_max' } ], output_template => "Peers max: %d", perfdatas => [ { label => 'peers_max', value => 'peers_max', template => '%d', min => 0 } ], } }, { label => 'peers-usage', nlabel => 'parity.peers.usage', set => { key_values => [ { name => 'peers_usage' } ], output_template => "Peers usage: %d %% ", perfdatas => [ { label => 'peers_usage', value => 'peers_usage', template => '%.2f', unit => '%', min => 0 } ], } }, ]; } sub custom_peers_output { my ($self, %options) = @_; return sprintf( "Connected peers: %d / %d", $self->{result_values}->{peers_connected}, $self->{result_values}->{peers_limit} ); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'unknown-status:s' => { name => 'unknown_status', default => '' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{listening} !~ /true/' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['unknown_status', 'warning_status', 'critical_status']); } sub prefix_module_output { my ($self, %options) = @_; return "Parity module: "; } sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = "parity_restapi_" . $self->{mode} . '_' . (defined($self->{option_results}->{hostname}) ? $self->{option_results}->{hostname} : 'me') . '_' . (defined($self->{option_results}->{port}) ? $self->{option_results}->{port} : 'default') . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); my $query_form_post = [ { method => 'parity_versionInfo', params => [], id => "1", jsonrpc => "2.0" }, { method => 'parity_chain', params => [], id => "2", jsonrpc => "2.0" }, { method => 'parity_pendingTransactions', params => [], id => "3", jsonrpc => "2.0" } , { method => 'parity_netPeers', params => [], id => "4", jsonrpc => "2.0" }, { method => 'parity_enode', params => [], id => "5", jsonrpc => "2.0" }, { method => 'parity_nodeName', params => [], id => "6", jsonrpc => "2.0" }, { method => 'parity_transactionsLimit', params => [], id => "7", jsonrpc => "2.0" }, { method => 'net_peerCount', params => [], id => "8", jsonrpc => "2.0" } ]; my $result = $options{custom}->request_api(method => 'POST', query_form_post => $query_form_post); my $res_parity_version = @{$result}[0]->{result}->{version}->{major} . '.' . @{$result}[0]->{result}->{version}->{minor} . '.' . @{$result}[0]->{result}->{version}->{patch}; $self->{mempool} = { mempool_usage => scalar(@{$$result[2]->{result}}) / @{$result}[6]->{result} * 100, mempool_size => @{$result}[6]->{result}, tx_pending => scalar(@{$$result[2]->{result}}) }; $self->{peers} = { peers_usage => @{$result}[3]->{result}->{connected} / @{$result}[3]->{result}->{max} * 100, peers_max => @{$result}[3]->{result}->{max}, peers_limit => @{$result}[3]->{result}->{max}, peers_connected => @{$result}[3]->{result}->{connected} }; } 1; __END__ =head1 MODE Check parity module metrics parity (Mempool and peers)centreon-plugins-20220113/blockchain/parity/restapi/plugin.pm000066400000000000000000000027661417000230700241570ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package blockchain::parity::restapi::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}} = ( 'net' => 'blockchain::parity::restapi::mode::net', 'eth' => 'blockchain::parity::restapi::mode::eth', 'parity' => 'blockchain::parity::restapi::mode::parity', 'infos' => 'blockchain::parity::restapi::mode::infos' ); $self->{custom_modes}{api} = 'blockchain::parity::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Parity blockchain with JSON RPC =cut centreon-plugins-20220113/centreon/000077500000000000000000000000001417000230700170515ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/000077500000000000000000000000001417000230700203415ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/adic/000077500000000000000000000000001417000230700212415ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/adic/tape/000077500000000000000000000000001417000230700221725ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/adic/tape/snmp/000077500000000000000000000000001417000230700231475ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/adic/tape/snmp/mode/000077500000000000000000000000001417000230700240735ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/adic/tape/snmp/mode/components/000077500000000000000000000000001417000230700262605ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/adic/tape/snmp/mode/components/component.pm000066400000000000000000000060511417000230700306220ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::adic::tape::snmp::mode::components::component; use strict; use warnings; use centreon::plugins::misc; my %map_status = ( 1 => 'unknown', 2 => 'unused', 3 => 'ok', 4 => 'warning', 5 => 'failed', ); # In MIB 'ADIC-INTELLIGENT-STORAGE-MIB' my $mapping = { componentDisplayName => { oid => '.1.3.6.1.4.1.3764.1.1.30.10.1.3' }, componentStatus => { oid => '.1.3.6.1.4.1.3764.1.1.30.10.1.8', map => \%map_status }, }; my $oid_componentEntry = '.1.3.6.1.4.1.3764.1.1.30.10.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_componentEntry }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking components"); $self->{components}->{component} = {name => 'components', total => 0, skip => 0}; return if ($self->check_filter(section => 'component')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_componentEntry}})) { next if ($oid !~ /^$mapping->{componentStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_componentEntry}, instance => $instance); next if ($self->check_filter(section => 'component', instance => $result->{componentDisplayName})); $self->{components}->{component}->{total}++; $result->{componentDisplayName} =~ s/\s+/ /g; $result->{componentDisplayName} = centreon::plugins::misc::trim($result->{componentDisplayName}); $self->{output}->output_add(long_msg => sprintf("component '%s' status is %s [instance: %s].", $result->{componentDisplayName}, $result->{componentStatus}, $result->{componentDisplayName} )); my $exit = $self->get_severity(section => 'component', value => $result->{componentStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Component '%s' status is %s", $result->{componentDisplayName}, $result->{componentStatus})); } } } 1;centreon-plugins-20220113/centreon/common/adic/tape/snmp/mode/components/fan.pm000066400000000000000000000142371417000230700273710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::adic::tape::snmp::mode::components::fan; use strict; use warnings; my %map_status = ( 1 => 'nominal', 2 => 'warningLow', 3 => 'warningHigh', 4 => 'alarmLow', 5 => 'alarmHigh', 6 => 'notInstalled', 7 => 'noData', ); my $mapping = { coolingFanName => { oid => '.1.3.6.1.4.1.3764.1.1.200.200.40.1.2' }, coolingFanStatus => { oid => '.1.3.6.1.4.1.3764.1.1.200.200.40.1.3', map => \%map_status }, coolingFanRPM => { oid => '.1.3.6.1.4.1.3764.1.1.200.200.40.1.4' }, coolingFanWarningHi => { oid => '.1.3.6.1.4.1.3764.1.1.200.200.40.1.8' }, coolingFanNominalHi => { oid => '.1.3.6.1.4.1.3764.1.1.200.200.40.1.6' }, coolingFanNominalLo => { oid => '.1.3.6.1.4.1.3764.1.1.200.200.40.1.5' }, coolingFanWarningLo => { oid => '.1.3.6.1.4.1.3764.1.1.200.200.40.1.7' }, coolingFanLocation => { oid => '.1.3.6.1.4.1.3764.1.1.200.200.40.1.9' }, }; my $oid_coolingFanEntry = '.1.3.6.1.4.1.3764.1.1.200.200.40.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_coolingFanEntry }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking fans"); $self->{components}->{fan} = {name => 'fans', total => 0, skip => 0}; return if ($self->check_filter(section => 'fan')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_coolingFanEntry}})) { next if ($oid !~ /^$mapping->{coolingFanStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_coolingFanEntry}, instance => $instance); $result->{coolingFanName} =~ s/\s+/ /g; $result->{coolingFanName} = centreon::plugins::misc::trim($result->{coolingFanName}); $result->{coolingFanLocation} =~ s/,/_/g; my $id = $result->{coolingFanName} . '_' . $result->{coolingFanLocation}; next if ($self->check_filter(section => 'fan', instance => $id)); $self->{components}->{fan}->{total}++; $self->{output}->output_add(long_msg => sprintf("fan '%s' status is '%s' [instance = %s] [value = %s]", $id, $result->{coolingFanStatus}, $id, $result->{coolingFanRPM})); my $exit = $self->get_severity(label => 'sensor', section => 'fan', value => $result->{coolingFanStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("fan '%s' status is '%s'", $id, $result->{coolingFanStatus})); next; } if (defined($result->{coolingFanRPM}) && $result->{coolingFanRPM} =~ /[0-9]/) { my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'fan', instance => $instance, value => $result->{coolingFanRPM}); if ($checked == 0) { $result->{coolingFanNominalLo} = (defined($result->{coolingFanNominalLo}) && $result->{coolingFanNominalLo} =~ /[0-9]/) ? $result->{coolingFanNominalLo} : ''; $result->{coolingFanWarningLo} = (defined($result->{coolingFanWarningLo}) && $result->{coolingFanWarningLo} =~ /[0-9]/) ? $result->{coolingFanWarningLo} : ''; $result->{coolingFanNominalHi} = (defined($result->{coolingFanNominalHi}) && $result->{coolingFanNominalHi} =~ /[0-9]/) ? $result->{coolingFanNominalHi} : ''; $result->{coolingFanWarningHi} = (defined($result->{coolingFanWarningHi}) && $result->{coolingFanWarningHi} =~ /[0-9]/) ? $result->{coolingFanWarningHi} : ''; my $warn_th = $result->{coolingFanNominalLo} . ':' . $result->{coolingFanNominalHi}; my $crit_th = $result->{coolingFanWarningLo} . ':' . $result->{coolingFanWarningHi}; $self->{perfdata}->threshold_validate(label => 'warning-fan-instance-' . $instance, value => $warn_th); $self->{perfdata}->threshold_validate(label => 'critical-fan-instance-' . $instance, value => $crit_th); $exit = $self->{perfdata}->threshold_check(value => $result->{coolingFanRPM}, threshold => [ { label => 'critical-fan-instance-' . $instance, exit_litteral => 'critical' }, { label => 'warning-fan-instance-' . $instance, exit_litteral => 'warning' } ]); $warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-fan-instance-' . $instance); $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-fan-instance-' . $instance); } if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Fan '%s' is %s rpm", $id, $result->{coolingFanRPM})); } $self->{output}->perfdata_add( label => 'fan', unit => 'rpm', nlabel => 'hardware.fan.speed.rpm', instances => $id, value => $result->{coolingFanRPM}, warning => $warn, critical => $crit, ); } } } 1; centreon-plugins-20220113/centreon/common/adic/tape/snmp/mode/components/global.pm000066400000000000000000000062571417000230700300700ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::adic::tape::snmp::mode::components::global; use strict; use warnings; my %map_status = ( 1 => 'good', 2 => 'failed', 3 => 'degraded', 4 => 'warning', 5 => 'informational', 6 => 'unknown', 7 => 'invalid', ); my %map_agent_status = ( 1 => 'other', 2 => 'unknown', 3 => 'ok', 4 => 'non-critical', 5 => 'critical', 6 => 'non-recoverable', ); # In MIB 'ADIC-TAPE-LIBRARY-MIB' my $mapping = { GlobalStatus => { oid => '.1.3.6.1.4.1.3764.1.10.10.1.8', map => \%map_status }, # libraryGlobalStatus }; # In MIB 'ADIC-INTELLIGENT-STORAGE-MIB' my $mapping2 = { GlobalStatus => { oid => '.1.3.6.1.4.1.3764.1.1.20.1', map => \%map_agent_status }, # agentGlobalStatus }; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping->{GlobalStatus}->{oid} }, { oid => $mapping2->{GlobalStatus}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking global"); $self->{components}->{global} = {name => 'global', total => 0, skip => 0}; return if ($self->check_filter(section => 'global')); my $instance = '0'; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$mapping->{GlobalStatus}->{oid}}, instance => $instance); if (!defined($result->{GlobalStatus})) { $result = $self->{snmp}->map_instance(mapping => $mapping2, results => $self->{results}->{$mapping2->{GlobalStatus}->{oid}}, instance => $instance); } if (!defined($result->{GlobalStatus})) { $self->{output}->output_add(long_msg => "skipping global status: no value."); return ; } return if ($self->check_filter(section => 'global', instance => $instance)); $self->{components}->{global}->{total}++; $self->{output}->output_add(long_msg => sprintf("library global status is %s [instance: %s].", $result->{GlobalStatus}, $instance )); my $exit = $self->get_severity(section => 'global', label => 'default', value => $result->{GlobalStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Library global status is %s", $result->{GlobalStatus})); } } 1;centreon-plugins-20220113/centreon/common/adic/tape/snmp/mode/components/physicaldrive.pm000066400000000000000000000100061417000230700314610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::adic::tape::snmp::mode::components::physicaldrive; use strict; use warnings; use centreon::plugins::misc; my %map_status = ( 1 => 'good', 2 => 'failed', 3 => 'degraded', 4 => 'warning', 5 => 'informational', 6 => 'unknown', 7 => 'invalid', ); my $mapping = { # 'ADIC-TAPE-LIBRARY-MIB' adic_tape => { phDriveSerialNumber => { oid => '.1.3.6.1.4.1.3764.1.10.10.11.3.1.2' }, phDriveModel => { oid => '.1.3.6.1.4.1.3764.1.10.10.11.3.1.3' }, phDriveRasStatus => { oid => '.1.3.6.1.4.1.3764.1.10.10.11.3.1.11', map => \%map_status }, }, # 'ADIC-MANAGEMENT-MIB' adic_management => { phDriveSerialNumber => { oid => '.1.3.6.1.4.1.3764.1.1.200.20.80.110.1.8' }, phDriveModel => { oid => '.1.3.6.1.4.1.3764.1.1.200.20.80.110.1.7' }, # phDriveProduct phDriveRasStatus => { oid => '.1.3.6.1.4.1.3764.1.1.200.20.80.110.1.31', map => \%map_status }, } }; my %oid_table = ( adic_tape => '.1.3.6.1.4.1.3764.1.10.10.11.3.1', # physicalDriveEntry adic_management => '.1.3.6.1.4.1.3764.1.1.200.20.80.110.1', # phDriveEntry ); sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_table{adic_tape} }, { oid => $oid_table{adic_management} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking physical drives"); $self->{components}->{physicaldrive} = {name => 'physical drives', total => 0, skip => 0}; return if ($self->check_filter(section => 'physicaldrive')); foreach my $label (keys %{$mapping}) { foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_table{$label}}})) { next if ($oid !~ /^$mapping->{$label}->{phDriveRasStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping->{$label}, results => $self->{results}->{$oid_table{$label}}, instance => $instance); $result->{phDriveSerialNumber} = centreon::plugins::misc::trim($result->{phDriveSerialNumber}); next if ($self->check_filter(section => 'physicaldrive', instance => $result->{phDriveSerialNumber})); $self->{components}->{physicaldrive}->{total}++; $self->{output}->output_add(long_msg => sprintf("physical drive '%s' status is %s [instance: %s, model: %s, serial: %s].", $result->{phDriveSerialNumber}, $result->{phDriveRasStatus}, $result->{phDriveSerialNumber}, centreon::plugins::misc::trim($result->{phDriveModel}), centreon::plugins::misc::trim($result->{phDriveSerialNumber}) )); my $exit = $self->get_severity(section => 'physicaldrive', label => 'default', value => $result->{phDriveRasStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Physical drive '%s' status is %s", $result->{phDriveSerialNumber}, $result->{phDriveRasStatus})); } } } } 1;centreon-plugins-20220113/centreon/common/adic/tape/snmp/mode/components/subsystem.pm000066400000000000000000000070601417000230700306570ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::adic::tape::snmp::mode::components::subsystem; use strict; use warnings; my %map_status = ( 1 => 'good', 2 => 'failed', 3 => 'degraded', 4 => 'warning', 5 => 'informational', 6 => 'unknown', 7 => 'invalid', ); # In MIB 'ADIC-TAPE-LIBRARY-MIB' my $mapping = { powerStatus => { oid => '.1.3.6.1.4.1.3764.1.10.10.12.1', map => \%map_status, label => 'power', instance => 1 }, coolingStatus => { oid => '.1.3.6.1.4.1.3764.1.10.10.12.2', map => \%map_status, label => 'cooling', instance => 2 }, controlStatus => { oid => '.1.3.6.1.4.1.3764.1.10.10.12.3', map => \%map_status, label => 'control', instance => 3 }, connectivityStatus => { oid => '.1.3.6.1.4.1.3764.1.10.10.12.4', map => \%map_status, label => 'connectivity', instance => 4 }, roboticsStatus => { oid => '.1.3.6.1.4.1.3764.1.10.10.12.5', map => \%map_status, label => 'robotics', instance => 5 }, mediaStatus => { oid => '.1.3.6.1.4.1.3764.1.10.10.12.6', map => \%map_status, label => 'media', instance => 6 }, driveStatus => { oid => '.1.3.6.1.4.1.3764.1.10.10.12.6', map => \%map_status, label => 'drive', instance => 7 }, }; my $oid_rasSubSystem = '.1.3.6.1.4.1.3764.1.10.10.12'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_rasSubSystem }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking subsystems"); $self->{components}->{subsystem} = {name => 'subsystems', total => 0, skip => 0}; return if ($self->check_filter(section => 'subsystem')); my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_rasSubSystem}, instance => '0'); foreach my $name (keys %$mapping) { if (!defined($result->{$name})) { $self->{output}->output_add(long_msg => sprintf("skipping %s status: no value.", $mapping->{$name}->{label})); next; } next if ($self->check_filter(section => 'subsystem', instance => $mapping->{$name}->{instance})); $self->{components}->{subsystem}->{total}++; $self->{output}->output_add(long_msg => sprintf("%s status is %s [instance: %s].", $mapping->{$name}->{label}, $result->{$name}, $mapping->{$name}->{instance} )); my $exit = $self->get_severity(section => 'subsystem', label => 'default', value => $result->{$name}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("%s status is %s", ucfirst($mapping->{$name}->{label}), $result->{$name})); } } } 1;centreon-plugins-20220113/centreon/common/adic/tape/snmp/mode/components/temperature.pm000066400000000000000000000153521417000230700311610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::adic::tape::snmp::mode::components::temperature; use strict; use warnings; my %map_status = ( 1 => 'nominal', 2 => 'warningLow', 3 => 'warningHigh', 4 => 'alarmLow', 5 => 'alarmHigh', 6 => 'notInstalled', 7 => 'noData', ); my $mapping = { temperatureSensorName => { oid => '.1.3.6.1.4.1.3764.1.1.200.200.30.1.2' }, temperatureSensorStatus => { oid => '.1.3.6.1.4.1.3764.1.1.200.200.30.1.3', map => \%map_status }, temperatureSensorDegreesCelsius => { oid => '.1.3.6.1.4.1.3764.1.1.200.200.30.1.4' }, temperatureSensorWarningHi => { oid => '.1.3.6.1.4.1.3764.1.1.200.200.30.1.8' }, temperatureSensorNominalHi => { oid => '.1.3.6.1.4.1.3764.1.1.200.200.30.1.6' }, temperatureSensorNominalLo => { oid => '.1.3.6.1.4.1.3764.1.1.200.200.30.1.5' }, temperatureSensorWarningLo => { oid => '.1.3.6.1.4.1.3764.1.1.200.200.30.1.7' }, temperatureSensorLocation => { oid => '.1.3.6.1.4.1.3764.1.1.200.200.30.1.9' }, }; my $oid_temperatureSensorEntry = '.1.3.6.1.4.1.3764.1.1.200.200.30.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_temperatureSensorEntry }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking temperatures"); $self->{components}->{temperature} = {name => 'temperatures', total => 0, skip => 0}; return if ($self->check_filter(section => 'temperature')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_temperatureSensorEntry}})) { next if ($oid !~ /^$mapping->{temperatureSensorStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_temperatureSensorEntry}, instance => $instance); $result->{temperatureSensorName} =~ s/\s+/ /g; $result->{temperatureSensorName} = centreon::plugins::misc::trim($result->{temperatureSensorName}); $result->{temperatureSensorLocation} =~ s/,/_/g; my $id = $result->{temperatureSensorName} . '_' . $result->{temperatureSensorLocation}; next if ($self->check_filter(section => 'temperature', instance => $id)); $self->{components}->{temperature}->{total}++; $self->{output}->output_add(long_msg => sprintf("temperature '%s' status is '%s' [instance = %s] [value = %s]", $id, $result->{temperatureSensorStatus}, $id, $result->{temperatureSensorDegreesCelsius})); my $exit = $self->get_severity(label => 'sensor', section => 'temperature', value => $result->{temperatureSensorStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Temperature '%s' status is '%s'", $id, $result->{temperatureSensorStatus})); next; } if (defined($result->{temperatureSensorDegreesCelsius}) && $result->{temperatureSensorDegreesCelsius} =~ /[0-9]/) { my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $instance, value => $result->{temperatureSensorDegreesCelsius}); if ($checked == 0) { $result->{temperatureSensorNominalLo} = (defined($result->{temperatureSensorNominalLo}) && $result->{temperatureSensorNominalLo} =~ /[0-9]/) ? $result->{temperatureSensorNominalLo} : ''; $result->{temperatureSensorWarningLo} = (defined($result->{temperatureSensorWarningLo}) && $result->{temperatureSensorWarningLo} =~ /[0-9]/) ? $result->{temperatureSensorWarningLo} : ''; $result->{temperatureSensorNominalHi} = (defined($result->{temperatureSensorNominalHi}) && $result->{temperatureSensorNominalHi} =~ /[0-9]/) ? $result->{temperatureSensorNominalHi} : ''; $result->{temperatureSensorWarningHi} = (defined($result->{temperatureSensorWarningHi}) && $result->{temperatureSensorWarningHi} =~ /[0-9]/) ? $result->{temperatureSensorWarningHi} : ''; my $warn_th = $result->{temperatureSensorNominalLo} . ':' . $result->{temperatureSensorNominalHi}; my $crit_th = $result->{temperatureSensorWarningLo} . ':' . $result->{temperatureSensorWarningHi}; $self->{perfdata}->threshold_validate(label => 'warning-temperature-instance-' . $instance, value => $warn_th); $self->{perfdata}->threshold_validate(label => 'critical-temperature-instance-' . $instance, value => $crit_th); $exit = $self->{perfdata}->threshold_check(value => $result->{temperatureSensorDegreesCelsius}, threshold => [ { label => 'critical-temperature-instance-' . $instance, exit_litteral => 'critical' }, { label => 'warning-temperature-instance-' . $instance, exit_litteral => 'warning' } ]); $warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-temperature-instance-' . $instance); $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-temperature-instance-' . $instance); } if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Temperature '%s' is %s degree centigrade", $id, $result->{temperatureSensorDegreesCelsius})); } $self->{output}->perfdata_add( label => 'temp', unit => 'C', nlabel => 'hardware.temperature.celsius', instances => $id, value => $result->{temperatureSensorDegreesCelsius}, warning => $warn, critical => $crit, ); } } } 1; centreon-plugins-20220113/centreon/common/adic/tape/snmp/mode/hardware.pm000066400000000000000000000071001417000230700262240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::adic::tape::snmp::mode::hardware; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^(temperature|fan)$'; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { default => [ ['good', 'OK'], ['failed', 'CRITICAL'], ['degraded', 'WARNING'], ['warning', 'WARNING'], ['informational', 'OK'], ['unknown', 'UNKNOWN'], ['invalid', 'CRITICAL'], ['other', 'OK'], ['ok', 'OK'], ['non-critical', 'WARNING'], ['critical', 'CRITICAL'], ['non-recoverable', 'CRITICAL'], ], component => [ ['unknown', 'UNKNOWN'], ['unused', 'OK'], ['ok', 'OK'], ['warning', 'WARNING'], ['failed', 'CRITICAL'], ], sensor => [ ['nominal', 'OK'], ['warningLow', 'WARNING'], ['warningHigh', 'CRITICAL'], ['alarmLow', 'CRITICAL'], ['alarmHigh', 'CRITICAL'], ['notInstalled', 'OK'], ['noData', 'OK'], ], }; $self->{components_path} = 'centreon::common::adic::tape::snmp::mode::components'; $self->{components_module} = ['global', 'physicaldrive', 'subsystem', 'component', 'temperature', 'fan']; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $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; $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: 'global', 'physicaldrive', 'subsystem', 'component', 'temperature', 'fan'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=subsystem) Can also exclude specific instance: --filter=physicaldrive,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='physicaldrive,OK,invalid' =item B<--warning> Set warning threshold (syntax: type,regexp,threshold) Example: --warning='temperature,.*,30' =item B<--critical> Set critical threshold (syntax: type,regexp,threshold) Example: --critical='temperature,.*,40' =back =cut centreon-plugins-20220113/centreon/common/airespace/000077500000000000000000000000001417000230700222755ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/airespace/snmp/000077500000000000000000000000001417000230700232525ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/airespace/snmp/mode/000077500000000000000000000000001417000230700241765ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/airespace/snmp/mode/apchannelinterference.pm000066400000000000000000000153371417000230700310700ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::airespace::snmp::mode::apchannelinterference; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub ap_long_output { my ($self, %options) = @_; return "checking access point '" . $options{instance_value}->{display} . "'"; } sub prefix_ap_output { my ($self, %options) = @_; return "access point '" . $options{instance_value}->{display} . "' "; } sub prefix_channel_output { my ($self, %options) = @_; return "channel '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'ap', type => 3, cb_prefix_output => 'prefix_ap_output', cb_long_output => 'ap_long_output', indent_long_output => ' ', message_multiple => 'All access points are ok', group => [ { name => 'channels', display_long => 1, cb_prefix_output => 'prefix_channel_output', message_multiple => 'channels are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{channels} = [ { label => 'interference-power', nlabel => 'accesspoint.interference.power.count', set => { key_values => [ { name => 'interference_power' }, { name => 'display' } ], output_template => 'interference power: %s', perfdatas => [ { label => 'interference_power', template => '%s', label_extra_instance => 1 } ] } }, { label => 'interference-util', nlabel => 'accesspoint.interference.utilization.percentage', set => { key_values => [ { name => 'interference_util' }, { name => 'display' } ], output_template => 'interference utilization: %s %%', perfdatas => [ { label => 'interference_util', template => '%s', unit => '%', min => 0, max => 100, label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'filter-channel:s' => { name => 'filter_channel' }, 'filter-group:s' => { name => 'filter_group' } }); return $self; } my $mapping = { ap_name => { oid => '.1.3.6.1.4.1.14179.2.2.1.1.3' }, # bsnAPName group_name => { oid => '.1.3.6.1.4.1.14179.2.2.1.1.30' } # bsnAPGroupVlanName }; my $mapping2 = { interference_power => { oid => '.1.3.6.1.4.1.14179.2.2.14.1.2' }, # bsnAPIfInterferencePower interference_util => { oid => '.1.3.6.1.4.1.14179.2.2.14.1.22' } # bsnAPIfInterferenceUtilization }; sub manage_selection { my ($self, %options) = @_; my $request = [ { oid => $mapping->{ap_name}->{oid} }, { oid => $mapping2->{interference_power}->{oid} }, { oid => $mapping2->{interference_util}->{oid} } ]; push @$request, { oid => $mapping->{group_name}->{oid} } if (defined($self->{option_results}->{filter_group}) && $self->{option_results}->{filter_group} ne ''); my $snmp_result = $options{snmp}->get_multiple_table( oids => $request, return_type => 1, nothing_quit => 1 ); foreach (keys %$snmp_result) { next if (! /^$mapping->{ap_name}->{oid}\.(.*)/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $result->{ap_name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{ap_name} . "'.", debug => 1); next; } if (defined($self->{option_results}->{filter_group}) && $self->{option_results}->{filter_group} ne '' && $result->{group_name} !~ /$self->{option_results}->{filter_group}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{ap_name} . "'.", debug => 1); next; } $self->{ap}->{ $result->{ap_name} } = { display => $result->{ap_name}, channels => {} }; foreach my $oid (keys %$snmp_result) { next if ($oid !~ /^$mapping2->{interference_power}->{oid}\.$instance\.(\d+)\.(\d+)$/); my ($slot_id, $channel_id) = ($1, $2); my $result2 = $options{snmp}->map_instance(mapping => $mapping2, results => $snmp_result, instance => $instance . '.' . $slot_id . '.' . $channel_id); my $name = "slot$slot_id:channel$channel_id"; if (defined($self->{option_results}->{filter_channel}) && $self->{option_results}->{filter_channel} ne '' && $name !~ /$self->{option_results}->{filter_channel}/) { $self->{output}->output_add(long_msg => "skipping channel '" . $name . "': no matching filter.", debug => 1); next; } $self->{ap}->{ $result->{ap_name} }->{channels}->{$name} = { display => $name, %$result2 }; } } if (scalar(keys %{$self->{ap}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No entry found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check AP Channel Interference. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='interference-util' =item B<--filter-name> Filter access point name (can be a regexp). =item B<--filter-group> Filter access point group (can be a regexp). =item B<--filter-channel> Filter channel (can be a regexp). Example: --filter-channel='slot0:channel3' =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'interference-power', 'interference-util' (%). =back =cut centreon-plugins-20220113/centreon/common/airespace/snmp/mode/apchannelnoise.pm000066400000000000000000000133401417000230700275240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::airespace::snmp::mode::apchannelnoise; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub ap_long_output { my ($self, %options) = @_; return "checking access point '" . $options{instance_value}->{display} . "'"; } sub prefix_ap_output { my ($self, %options) = @_; return "access point '" . $options{instance_value}->{display} . "' "; } sub prefix_channel_output { my ($self, %options) = @_; return "channel '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'ap', type => 3, cb_prefix_output => 'prefix_ap_output', cb_long_output => 'ap_long_output', indent_long_output => ' ', message_multiple => 'All access points are ok', group => [ { name => 'channels', display_long => 1, cb_prefix_output => 'prefix_channel_output', message_multiple => 'channels are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{channels} = [ { label => 'noise-power', nlabel => 'accesspoint.noise.power.dbm', set => { key_values => [ { name => 'noise_power' }, { name => 'display' } ], output_template => 'noise power: %s dBm', perfdatas => [ { label => 'noise_power', template => '%s', unit => 'dBm', label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'filter-channel:s' => { name => 'filter_channel' }, 'filter-group:s' => { name => 'filter_group' } }); return $self; } my $map_admin_status = { 1 => 'enable', 2 => 'disable' }; my $mapping = { ap_name => { oid => '.1.3.6.1.4.1.14179.2.2.1.1.3' }, # bsnAPName group_name => { oid => '.1.3.6.1.4.1.14179.2.2.1.1.30' } # bsnAPGroupVlanName }; my $oid_bsnAPIfDBNoisePower = '.1.3.6.1.4.1.14179.2.2.15.1.21'; sub manage_selection { my ($self, %options) = @_; my $request = [ { oid => $mapping->{ap_name}->{oid} }, { oid => $oid_bsnAPIfDBNoisePower } ]; push @$request, { oid => $mapping->{group_name}->{oid} } if (defined($self->{option_results}->{filter_group}) && $self->{option_results}->{filter_group} ne ''); my $snmp_result = $options{snmp}->get_multiple_table( oids => $request, return_type => 1, nothing_quit => 1 ); foreach (keys %$snmp_result) { next if (! /^$mapping->{ap_name}->{oid}\.(.*)/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $result->{ap_name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{ap_name} . "'.", debug => 1); next; } if (defined($self->{option_results}->{filter_group}) && $self->{option_results}->{filter_group} ne '' && $result->{group_name} !~ /$self->{option_results}->{filter_group}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{ap_name} . "'.", debug => 1); next; } $self->{ap}->{ $result->{ap_name} } = { display => $result->{ap_name}, channels => {} }; foreach my $oid (keys %$snmp_result) { next if ($oid !~ /^$oid_bsnAPIfDBNoisePower\.$instance\.(\d+)\.(\d+)$/); my ($slot_id, $channel_id) = ($1, $2); my $name = "slot$slot_id:channel$channel_id"; if (defined($self->{option_results}->{filter_channel}) && $self->{option_results}->{filter_channel} ne '' && $name !~ /$self->{option_results}->{filter_channel}/) { $self->{output}->output_add(long_msg => "skipping channel '" . $name . "': no matching filter.", debug => 1); next; } $self->{ap}->{ $result->{ap_name} }->{channels}->{$name} = { display => $name, noise_power => $snmp_result->{$oid} }; } } if (scalar(keys %{$self->{ap}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No entry found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check AP Channel Noise. =over 8 =item B<--filter-name> Filter access point name (can be a regexp). =item B<--filter-group> Filter access point group (can be a regexp). =item B<--filter-channel> Filter channel (can be a regexp). Example: --filter-channel='slot0:channel3' =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'noise-power' (dBm). =back =cut centreon-plugins-20220113/centreon/common/airespace/snmp/mode/apstatus.pm000066400000000000000000000307631417000230700264110ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::airespace::snmp::mode::apstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; my $msg = $self->{result_values}->{admstatus} eq 'disable' ? 'is disabled' : ('status: ' . $self->{result_values}->{opstatus}); return $msg; } sub custom_radio_channel_util_calc { my ($self, %options) = @_; return -10 if ($options{new_datas}->{$self->{instance} . '_admstatus'} eq 'disable'); $self->{result_values}->{channels_util} = $options{new_datas}->{$self->{instance} . '_channels_util'}; return 0; } sub skip_global { my ($self, %options) = @_; scalar(keys %{$self->{ap}}) == 1 ? return(1) : return(0); } sub prefix_global_output { my ($self, %options) = @_; return 'Access points '; } sub ap_long_output { my ($self, %options) = @_; return "checking access point '" . $options{instance_value}->{display} . "'"; } sub prefix_ap_output { my ($self, %options) = @_; return "access point '" . $options{instance_value}->{display} . "' "; } sub prefix_interface_output { my ($self, %options) = @_; return "radio interface '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', cb_init => 'skip_global', }, { name => 'ap', type => 3, cb_prefix_output => 'prefix_ap_output', cb_long_output => 'ap_long_output', indent_long_output => ' ', message_multiple => 'All access points are ok', group => [ { name => 'ap_global', type => 0 }, { name => 'interfaces', type => 1, display_long => 1, cb_prefix_output => 'prefix_interface_output', message_multiple => 'radio interfaces are ok', skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'total', nlabel => 'accesspoints.total.count', set => { key_values => [ { name => 'total' } ], output_template => 'total: %s', perfdatas => [ { label => 'total', template => '%s', min => 0 } ] } }, { label => 'total-associated', nlabel => 'accesspoints.associated.count', set => { key_values => [ { name => 'associated' } ], output_template => 'associated: %s', perfdatas => [ { label => 'total_associated', template => '%s', min => 0 } ] } }, { label => 'total-disassociating', nlabel => 'accesspoints.disassociating.count', set => { key_values => [ { name => 'disassociating' } ], output_template => 'disassociating: %s', perfdatas => [ { label => 'total_disassociating', template => '%s', min => 0 } ] } }, { label => 'total-downloading', nlabel => 'accesspoints.downloading.count', display_ok => 0, set => { key_values => [ { name => 'downloading' } ], output_template => 'downloading: %s', perfdatas => [ { label => 'total_downloading', template => '%s', min => 0 } ] } }, { label => 'total-enabled', nlabel => 'accesspoints.enabled.count', set => { key_values => [ { name => 'enable' } ], output_template => 'enabled: %s', perfdatas => [ { label => 'total_enabled', template => '%s', min => 0 } ] } }, { label => 'total-disabled', nlabel => 'accesspoints.disabled.count', set => { key_values => [ { name => 'disable' } ], output_template => 'disabled: %s', perfdatas => [ { label => 'total_disabled', template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{ap_global} = [ { label => 'status', type => 2, critical_default => '%{admstatus} eq "enable" and %{opstatus} !~ /associated|downloading/', set => { key_values => [ { name => 'opstatus' }, { name => 'admstatus' }, { name => 'display' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{interfaces} = [ { label => 'radio-status', type => 2, critical_default => '%{admstatus} eq "enable" and %{opstatus} eq "down"', set => { key_values => [ { name => 'opstatus' }, { name => 'admstatus' }, { name => 'display' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'radio-interface-channels-utilization', nlabel => 'accesspoint.radio.interface.channels.utilization.percentage', set => { key_values => [ { name => 'channels_util' }, { name => 'admstatus' } ], closure_custom_calc => $self->can('custom_radio_channel_util_calc'), output_template => 'channels utilization: %s %%', perfdatas => [ { label => 'radio_interface_channels_utilization', template => '%s', min => 0, max => 100, unit => '%', label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'filter-group:s' => { name => 'filter_group' }, 'add-radio-interfaces' => { name => 'add_radio_interfaces' } }); return $self; } my $map_admin_status = { 1 => 'enable', 2 => 'disable' }; my $map_operation_status = { 1 => 'associated', 2 => 'disassociating', 3 => 'downloading' }; my $map_radio_operation_status = { 1 => 'down', 2 => 'up' }; my $mapping = { ap_name => { oid => '.1.3.6.1.4.1.14179.2.2.1.1.3' }, # bsnAPName group_name => { oid => '.1.3.6.1.4.1.14179.2.2.1.1.30' } # bsnAPGroupVlanName }; my $mapping2 = { opstatus => { oid => '.1.3.6.1.4.1.14179.2.2.1.1.6', map => $map_operation_status }, # bsnAPOperationStatus admstatus => { oid => '.1.3.6.1.4.1.14179.2.2.1.1.37', map => $map_admin_status } # bsnAPAdminStatus }; my $mapping3 = { opstatus => { oid => '.1.3.6.1.4.1.14179.2.2.2.1.12', map => $map_radio_operation_status }, # bsnAPIfOperStatus admstatus => { oid => '.1.3.6.1.4.1.14179.2.2.2.1.34', map => $map_admin_status }, # bsnAPIfAdminStatus channels_util => { oid => '.1.3.6.1.4.1.14179.2.2.13.1.3' } # bsnAPIfLoadChannelUtilization }; my $oid_agentInventoryMachineModel = '.1.3.6.1.4.1.14179.1.1.1.3'; sub manage_selection { my ($self, %options) = @_; $self->{ap} = {}; $self->{global} = { total => 0, associated => 0, disassociating => 0, downloading => 0, enable => 0, disable => 0 }; my $request = [ { oid => $oid_agentInventoryMachineModel }, { oid => $mapping->{ap_name}->{oid} } ]; push @$request, { oid => $mapping->{group_name}->{oid} } if (defined($self->{option_results}->{filter_group}) && $self->{option_results}->{filter_group} ne ''); my $snmp_result = $options{snmp}->get_multiple_table( oids => $request, return_type => 1, nothing_quit => 1 ); $self->{output}->output_add( long_msg => 'Model: ' . (defined($snmp_result->{$oid_agentInventoryMachineModel . '.0'}) ? $snmp_result->{$oid_agentInventoryMachineModel . '.0'} : 'unknown') ); foreach (keys %$snmp_result) { next if (! /^$mapping->{ap_name}->{oid}\.(.*)/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $result->{ap_name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{ap_name} . "'.", debug => 1); next; } if (defined($self->{option_results}->{filter_group}) && $self->{option_results}->{filter_group} ne '' && $result->{group_name} !~ /$self->{option_results}->{filter_group}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{ap_name} . "'.", debug => 1); next; } $self->{ap}->{ $result->{ap_name} } = { instance => $instance, display => $result->{ap_name}, ap_global => { display => $result->{ap_name} }, interfaces => {} }; } if (scalar(keys %{$self->{ap}}) <= 0) { $self->{output}->output_add(long_msg => 'no AP associated (can be: slave wireless controller or your filter)'); return ; } $options{snmp}->load( oids => [ map($_->{oid}, values(%$mapping2)) ], instances => [ map($_->{instance}, values %{$self->{ap}}) ], instance_regexp => '^(.*)$' ); $snmp_result = $options{snmp}->get_leef(); my $snmp_result_radio; $snmp_result_radio = $options{snmp}->get_multiple_table(oids => [map({ oid => $_->{oid} }, values(%$mapping3))], return_type => 1) if (defined($self->{option_results}->{add_radio_interfaces})); foreach (keys %{$self->{ap}}) { my $result = $options{snmp}->map_instance(mapping => $mapping2, results => $snmp_result, instance => $self->{ap}->{$_}->{instance}); $self->{global}->{total}++; $self->{global}->{ $result->{opstatus} }++; $self->{global}->{ $result->{admstatus} }++; $self->{ap}->{$_}->{ap_global}->{opstatus} = $result->{opstatus}; $self->{ap}->{$_}->{ap_global}->{admstatus} = $result->{admstatus}; next if (!defined($self->{option_results}->{add_radio_interfaces})); foreach my $oid (keys %$snmp_result_radio) { next if ($oid !~ /^$mapping3->{admstatus}->{oid}\.$self->{ap}->{$_}->{instance}\.(\d+)/); my $result_radio = $options{snmp}->map_instance(mapping => $mapping3, results => $snmp_result_radio, instance => $self->{ap}->{$_}->{instance} . '.' . $1); $self->{ap}->{$_}->{interfaces}->{$1} = { display => $1, %$result_radio }; } } } 1; __END__ =head1 MODE Check AP status. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^total-disassociating|total-associated$' =item B<--filter-name> Filter access point name (can be a regexp). =item B<--filter-group> Filter access point group (can be a regexp). =item B<--add-radio-interfaces> Monitor radio interfaces channels utilization. =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{admstatus}, %{opstatus}, %{display} =item B<--critical-status> Set critical threshold for status (Default: '%{admstatus} eq "enable" and %{opstatus} !~ /associated|downloading/'). Can used special variables like: %{admstatus}, %{opstatus}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'total', 'total-associated', 'total-disassociating', 'total-downloading', 'total-enabled', 'total-disabled', 'radio-interface-channels-utilization' (%). =back =cut centreon-plugins-20220113/centreon/common/airespace/snmp/mode/apusers.pm000066400000000000000000000305561417000230700262270ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::airespace::snmp::mode::apusers; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_global_output { my ($self, %options) = @_; return 'Users '; } sub prefix_ssid_output { my ($self, %options) = @_; return "SSID '" . $options{instance_value}->{display} . "' "; } sub prefix_ap_output { my ($self, %options) = @_; return "Access point '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', cb_prefix_output => 'prefix_global_output', type => 0 }, { name => 'ssid', type => 1, cb_prefix_output => 'prefix_ssid_output', message_multiple => 'All users by SSID are ok' }, { name => 'ap', type => 1, cb_prefix_output => 'prefix_ap_output', message_multiple => 'All users by access point are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'total', nlabel => 'users.total.count', set => { key_values => [ { name => 'total' } ], output_template => 'total: %s', perfdatas => [ { label => 'total', template => '%s', unit => 'users', min => 0 }, ] } }, { label => 'total-idle', nlabel => 'users.idle.count', set => { key_values => [ { name => 'total_idle' } ], output_template => 'idle: %s', perfdatas => [ { label => 'total_idle', template => '%s', unit => 'users', min => 0 } ] } }, { label => 'total-aaapending', nlabel => 'users.aaapending.count', set => { key_values => [ { name => 'total_aaapending' } ], output_template => 'aaaPending: %s', perfdatas => [ { label => 'total_aaapending', template => '%s', unit => 'users', min => 0 } ] } }, { label => 'total-authenticated', nlabel => 'users.authenticated.count', set => { key_values => [ { name => 'total_authenticated' } ], output_template => 'authenticated: %s', perfdatas => [ { label => 'total_authenticated', template => '%s', unit => 'users', min => 0 } ] } }, { label => 'total-associated', nlabel => 'users.associated.count', set => { key_values => [ { name => 'total_associated' } ], output_template => 'associated: %s', perfdatas => [ { label => 'total_associated', template => '%s', unit => 'users', min => 0 } ] } }, { label => 'total-disassociated', nlabel => 'users.disassociated.count', set => { key_values => [ { name => 'total_disassociated' } ], output_template => 'disassociated: %s', perfdatas => [ { label => 'total_disassociated', template => '%s', unit => 'users', min => 0 } ] } }, { label => 'total-powersave', nlabel => 'users.powersave.count', set => { key_values => [ { name => 'total_powersave' } ], output_template => 'powersave: %s', perfdatas => [ { label => 'total_powersave', template => '%s', unit => 'users', min => 0 } ] } }, { label => 'total-tobedeleted', nlabel => 'users.tobedeleted.count', set => { key_values => [ { name => 'total_tobedeleted' } ], output_template => 'to be deleted: %s', perfdatas => [ { label => 'total_tobedeleted', template => '%s', unit => 'users', min => 0 } ] } }, { label => 'total-probing', nlabel => 'users.probing.count', set => { key_values => [ { name => 'total_probing' } ], output_template => 'probing: %s', perfdatas => [ { label => 'total_probing', template => '%s', unit => 'users', min => 0 } ] } }, { label => 'total-blacklisted', nlabel => 'users.blacklisted.count', set => { key_values => [ { name => 'total_blacklisted' } ], output_template => 'blacklisted: %s', perfdatas => [ { label => 'total_blacklisted', template => '%s', unit => 'users', min => 0 } ] } } ]; $self->{maps_counters}->{ssid} = [ { label => 'ssid', nlabel => 'ssid.users.total.count', set => { key_values => [ { name => 'total' }, { name => 'display' } ], output_template => 'users: %s', perfdatas => [ { label => 'ssid', template => '%s', unit => 'users', min => 0, label_extra_instance => 1, instance_use => 'display' }, ] } } ]; $self->{maps_counters}->{ap} = [ { label => 'ap', nlabel => 'accesspoint.users.total.count', set => { key_values => [ { name => 'total' }, { name => 'display' } ], output_template => 'users: %s', perfdatas => [ { label => 'ap', template => '%s', unit => 'users', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-ssid:s' => { name => 'filter_ssid' }, 'filter-ap:s' => { name => 'filter_ap' }, 'filter-group:s' => { name => 'filter_group' }, 'ignore-ap-users' => { name => 'ignore_ap_users' } }); return $self; } my $map_station_status = { 0 => 'idle', 1 => 'aaapending', 2 => 'authenticated', 3 => 'associated', 4 => 'powersave', 5 => 'disassociated', 6 => 'tobedeleted', 7 => 'probing', 8 => 'blacklisted' }; my $mapping = { ssid => { oid => '.1.3.6.1.4.1.14179.2.1.4.1.7' }, # bsnMobileStationSsid status => { oid => '.1.3.6.1.4.1.14179.2.1.4.1.9', map => $map_station_status } # bsnMobileStationStatus }; my $mapping2 = { ap_name => { oid => '.1.3.6.1.4.1.14179.2.2.1.1.3' }, # bsnAPName group_name => { oid => '.1.3.6.1.4.1.14179.2.2.1.1.30' } # bsnAPGroupVlanName }; my $oid_agentInventoryMachineModel = '.1.3.6.1.4.1.14179.1.1.1.3'; my $oid_bsnDot11EssSsid = '.1.3.6.1.4.1.14179.2.1.1.1.2'; my $oid_bsnAPIfLoadNumOfClients = '.1.3.6.1.4.1.14179.2.2.13.1.4'; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_multiple_table( oids => [ { oid => $oid_agentInventoryMachineModel }, { oid => $mapping->{status}->{oid} }, { oid => $mapping->{ssid}->{oid} }, { oid => $oid_bsnDot11EssSsid } ], return_type => 1, nothing_quit => 1 ); $self->{output}->output_add( long_msg => "Model: " . (defined($self->{results}->{$oid_agentInventoryMachineModel}->{$oid_agentInventoryMachineModel . '.0'}) ? $self->{results}->{$oid_agentInventoryMachineModel}->{$oid_agentInventoryMachineModel . '.0'} : 'unknown') ); $self->{global} = { total => 0, total_idle => 0, total_aaapending => 0, total_authenticated => 0, total_associated => 0, total_powersave => 0, total_disassociated => 0, total_tobedeleted => 0, total_probing => 0, total_blacklisted => 0 }; $self->{ssid} = {}; foreach my $oid (keys %$snmp_result) { if ($oid =~ /^$oid_bsnDot11EssSsid/ && !defined($self->{ssid}->{ $snmp_result->{$oid} })) { if (defined($self->{option_results}->{filter_ssid}) && $self->{option_results}->{filter_ssid} ne '' && $snmp_result->{$oid} !~ /$self->{option_results}->{filter_ssid}/) { $self->{output}->output_add(long_msg => "skipping '" . $snmp_result->{$oid} . "': no matching filter.", debug => 1); next; } $self->{ssid}->{ $snmp_result->{$oid} } = { display => $snmp_result->{$oid}, total => 0 }; next; } next if ($oid !~ /^$mapping->{ssid}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); if (defined($self->{option_results}->{filter_ssid}) && $self->{option_results}->{filter_ssid} ne '' && $result->{ssid} !~ /$self->{option_results}->{filter_ssid}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{ssid} . "': no matching filter.", debug => 1); next; } $self->{ssid}->{ $result->{ssid} } = { display => $result->{ssid}, total => 0 } if (!defined($self->{ssid}->{ $result->{ssid} })); $self->{ssid}->{ $result->{ssid} }->{total}++; $self->{global}->{total}++; $self->{global}->{'total_' . $result->{status}}++; } return if (defined($self->{option_results}->{ignore_ap_users})); my $request = [ { oid => $mapping2->{ap_name}->{oid} }, { oid => $oid_bsnAPIfLoadNumOfClients } ]; push @$request, { oid => $mapping2->{group_name}->{oid} } if (defined($self->{option_results}->{filter_group}) && $self->{option_results}->{filter_group} ne ''); $snmp_result = $options{snmp}->get_multiple_table( oids => $request, return_type => 1 ); # check by ap $self->{ap} = {}; foreach my $oid (keys %$snmp_result) { next if ($oid !~ /^$mapping2->{ap_name}->{oid}\.(.*)/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping2, results => $snmp_result, instance => $instance); if (defined($self->{option_results}->{filter_ap}) && $self->{option_results}->{filter_ap} ne '' && $result->{ap_name} !~ /$self->{option_results}->{filter_ap}/) { $self->{output}->output_add(long_msg => "skipping access point '" . $result->{ap_name} . "': no matching filter.", debug => 1); next; } if (defined($self->{option_results}->{filter_group}) && $self->{option_results}->{filter_group} ne '' && $result->{group_name} !~ /$self->{option_results}->{filter_group}/) { $self->{output}->output_add(long_msg => "skipping access point '" . $result->{ap_name} . "': no matching filter.", debug => 1); next; } foreach my $oid2 (keys %$snmp_result) { next if ($oid2 !~ /^$oid_bsnAPIfLoadNumOfClients\.$instance\./); $self->{ap}->{$instance} = { display => $result->{ap_name}, total => 0 } if (!defined($self->{ap}->{$instance})); $self->{ap}->{$instance}->{total} += $snmp_result->{$oid2}; } } } 1; __END__ =head1 MODE Check users connected (total, by SSID, by AP). =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^total|total-idle$' =item B<--filter-ssid> Filter by SSID (can be a regexp). =item B<--filter-ap> Filter by access point name (can be a regexp). =item B<--filter-group> Filter by access point group (can be a regexp). =item B<--ignore-ap-users> Unmonitor users by access points. =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'total', 'total-idle', 'total-aaapending', 'total-authenticated', 'total-associated', 'total-powersave', 'total-disassociated', 'total-tobedeleted', 'total-probing', 'total-blacklisted', 'ssid', 'ap'. =back =cut centreon-plugins-20220113/centreon/common/airespace/snmp/mode/components/000077500000000000000000000000001417000230700263635ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/airespace/snmp/mode/components/psu.pm000066400000000000000000000052511417000230700275330ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::airespace::snmp::mode::components::psu; use strict; use warnings; my %map_psu_status = ( 0 => 'not operational', 1 => 'operational', ); # In MIB 'AIRESPACE-SWITCHING-MIB' my $oid_agentSwitchInfoGroup = '.1.3.6.1.4.1.14179.1.1.3'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_agentSwitchInfoGroup }; } 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')); foreach my $instances ([1, 3], [2, 5]) { next if (!defined($self->{results}->{$oid_agentSwitchInfoGroup}->{ $oid_agentSwitchInfoGroup . '.' . $$instances[1] . '.0' })); my $present = $self->{results}->{$oid_agentSwitchInfoGroup}->{ $oid_agentSwitchInfoGroup . '.' . ($$instances[1] - 1) . '.0' }; my $operational = $map_psu_status{ $self->{results}->{$oid_agentSwitchInfoGroup}->{ $oid_agentSwitchInfoGroup . '.' . $$instances[1] . '.0' } }; next if ($self->check_filter(section => 'psu', instance => $$instances[0])); next if ($present =~ /0/i && $self->absent_problem(section => 'psu', instance => $$instances[0])); $self->{components}->{psu}->{total}++; $self->{output}->output_add(long_msg => sprintf("Power supply '%s' status is %s.", $$instances[0], $operational)); my $exit = $self->get_severity(section => 'psu', value => $operational); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Power supply '%s' status is %s.", $$instances[0], $operational)); } } } 1;centreon-plugins-20220113/centreon/common/airespace/snmp/mode/cpu.pm000066400000000000000000000043131417000230700253240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::airespace::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 => 0 } ]; $self->{maps_counters}->{cpu} = [ { label => 'cpu-utilization', nlabel => 'cpu.utilization.percentage', set => { key_values => [ { name => 'cpu_usage' } ], output_template => 'cpu usage is: %.2f%%', perfdatas => [ { template => '%.2f', unit => '%', min => 0, max => 100 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $oid_agentCurrentCPUUtilization = '.1.3.6.1.4.1.14179.1.1.3.1.0'; my $snmp_result = $options{snmp}->get_leef( oids => [ $oid_agentCurrentCPUUtilization ], nothing_quit => 1 ); $self->{cpu} = { cpu_usage => $snmp_result->{$oid_agentCurrentCPUUtilization} }; } 1; __END__ =head1 MODE Check cpu usage (AIRESPACE-SWITCHING-MIB). =over 8 =item B<--warning-cpu-utilization> Threshold warning in percent. =item B<--critical-cpu-utilization> Threshold critical in percent. =back =cut centreon-plugins-20220113/centreon/common/airespace/snmp/mode/discovery.pm000066400000000000000000000117011417000230700265430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::airespace::snmp::mode::discovery; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-admin-down' => { name => 'filter_admin_down' }, 'prettify' => { name => 'prettify' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } my $map_admin_status = { 1 => 'enable', 2 => 'disable' }; my $map_operation_status = { 1 => 'associated', 2 => 'disassociating', 3 => 'downloading' }; my $mapping = { ap_name => { oid => '.1.3.6.1.4.1.14179.2.2.1.1.3' }, # bsnAPName ap_ipaddr => { oid => '.1.3.6.1.4.1.14179.2.2.1.1.19' } # bsnApIpAddress }; my $mapping2 = { opstatus => { oid => '.1.3.6.1.4.1.14179.2.2.1.1.6', map => $map_operation_status }, # bsnAPOperationStatus admstatus => { oid => '.1.3.6.1.4.1.14179.2.2.1.1.37', map => $map_admin_status } # bsnAPAdminStatus }; my $oid_agentInventoryMachineModel = '.1.3.6.1.4.1.14179.1.1.1.3'; sub run { my ($self, %options) = @_; my %ap; my @disco_data; my $disco_stats; $disco_stats->{start_time} = time(); my $request = [ { oid => $oid_agentInventoryMachineModel }, { oid => $mapping->{ap_name}->{oid} }, { oid => $mapping->{ap_ipaddr}->{oid} } ]; my $snmp_result = $options{snmp}->get_multiple_table( oids => $request, return_type => 1, nothing_quit => 1 ); foreach (keys %$snmp_result) { next if (! /^$mapping->{ap_name}->{oid}\.(.*)/); my $instance = $1; my $result = $options{snmp}->map_instance( mapping => $mapping, results => $snmp_result, instance => $instance); $self->{ap}->{ $result->{ap_name} } = { name => $result->{ap_name}, instance => $instance, ip => $result->{ap_ipaddr}, model => defined($snmp_result->{$oid_agentInventoryMachineModel . '.0'}) ? $snmp_result->{$oid_agentInventoryMachineModel . '.0'} : 'unknown' }; } $options{snmp}->load( oids => [ map($_->{oid}, values(%$mapping2)) ], instances => [ map($_->{instance}, values %{$self->{ap}}) ], instance_regexp => '^(.*)$' ); $snmp_result = $options{snmp}->get_leef(); foreach my $ap_name (keys %{$self->{ap}}) { my $result = $options{snmp}->map_instance( mapping => $mapping2, results => $snmp_result, instance => $self->{ap}->{ $ap_name }->{instance} ); $self->{ap}->{ $ap_name }->{admstatus} = $result->{admstatus}; $self->{ap}->{ $ap_name }->{opstatus} = $result->{opstatus}; next if (defined($self->{option_results}->{filter_admin_down}) && $result->{admstatus} eq 'disable'); push @disco_data, $self->{ap}->{ $ap_name }; } $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; $disco_stats->{discovered_items} = @disco_data; $disco_stats->{results} = \@disco_data; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE Cisco WLC/Airspace AP discovery. Note: When the IP Address is 0, that means the switch is operating in layer2 mode Ref: https://cric.grenoble.cnrs.fr/Administrateurs/Outils/MIBS/?oid=1.3.6.1.4.1.14179.2.2.1.1.19 =over 8 =item B<--prettify> Prettify JSON output. =item B<--filter-admin-down> Exclude administratively down access points from the discovery result =back =cut centreon-plugins-20220113/centreon/common/airespace/snmp/mode/hardware.pm000066400000000000000000000047401417000230700263360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::airespace::snmp::mode::hardware; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { psu => [ ['not operational', 'CRITICAL'], ['operational', 'OK'], ], }; $self->{components_path} = 'centreon::common::airespace::snmp::mode::components'; $self->{components_module} = ['psu']; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_performance => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } 1; __END__ =head1 MODE Check Hardware (Power Supplies). =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'psu'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=psu) Can also exclude specific instance: --filter=psu,1 =item B<--absent-problem> Return an error if an entity is not 'present' (default is skipping) (comma seperated list) Can be specific or global: --absent-problem=psu,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,WARNING,not operational' =back =cut centreon-plugins-20220113/centreon/common/airespace/snmp/mode/listgroups.pm000066400000000000000000000060501417000230700267500ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::airespace::snmp::mode::listgroups; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; my $mapping = { description => { oid => '.1.3.6.1.4.1.14179.2.10.2.1.2' } # bsnAPGroupsVlanDescription }; my $snmp_result = $options{snmp}->get_table( oid => $mapping->{description}->{oid} ); my $results = {}; foreach my $oid (keys %$snmp_result) { $oid =~ /^$mapping->{description}->{oid}\.(.*?)\.(.*)$/; my ($num, $index) = ($1, $2); my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $num . '.' . $index); my $name = $self->{output}->decode(join('', map(chr($_), split(/\./, $index)))); $results->{$name} = { description => $result->{description} }; } return $results; } sub run { my ($self, %options) = @_; my $results = $self->manage_selection(snmp => $options{snmp}); foreach my $name (sort keys %$results) { $self->{output}->output_add( long_msg => sprintf( '[name: %s] [description: %s]', $name, $results->{$name}->{description} ) ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List groups:' ); $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', 'description']); } sub disco_show { my ($self, %options) = @_; my $results = $self->manage_selection(snmp => $options{snmp}); foreach my $name (sort keys %$results) { $self->{output}->add_disco_entry( name => $name, description => $results->{$name}->{description} ); } } 1; __END__ =head1 MODE List wireless groups. =over 8 =back =cut centreon-plugins-20220113/centreon/common/airespace/snmp/mode/listradiusaccservers.pm000066400000000000000000000064771417000230700310160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::airespace::snmp::mode::listradiusaccservers; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } my $map_server_status = { 0 => 'disable', 1 => 'enable' }; my $mapping = { address => { oid => '.1.3.6.1.4.1.14179.2.5.2.1.2' }, # bsnRadiusAccServerAddress port => { oid => '.1.3.6.1.4.1.14179.2.5.2.1.3' }, # bsnRadiusAccClientServerPortNumber status => { oid => '.1.3.6.1.4.1.14179.2.5.2.1.5', map => $map_server_status } # bsnRadiusAccServerStatus }; my $oid_bsnRadiusAccServerEntry = '.1.3.6.1.4.1.14179.2.5.2.1'; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_table( oid => $oid_bsnRadiusAccServerEntry, start => $mapping->{address}->{oid}, end => $mapping->{status}->{oid} ); my $results = {}; foreach my $oid (keys %$snmp_result) { next if ($oid !~ /^$mapping->{address}->{oid}\.(.*)$/); my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $1); my $name = $result->{address} . ':' . $result->{port}; $results->{$name} = $result; } return $results; } sub run { my ($self, %options) = @_; my $results = $self->manage_selection(snmp => $options{snmp}); foreach my $name (sort keys %$results) { $self->{output}->output_add( long_msg => sprintf( '[name: %s] [status: %s]', $name, $results->{$name}->{status} ) ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List radius accounting 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', 'status']); } sub disco_show { my ($self, %options) = @_; my $results = $self->manage_selection(snmp => $options{snmp}); foreach my $name (sort keys %$results) { $self->{output}->add_disco_entry( name => $name, status => $results->{$name}->{status} ); } } 1; __END__ =head1 MODE List radius accounting servers. =over 8 =back =cut centreon-plugins-20220113/centreon/common/airespace/snmp/mode/listradiusauthservers.pm000066400000000000000000000065151417000230700312220ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::airespace::snmp::mode::listradiusauthservers; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } my $map_server_status = { 0 => 'disable', 1 => 'enable' }; my $mapping = { address => { oid => '.1.3.6.1.4.1.14179.2.5.1.1.2' }, # bsnRadiusAuthServerAddress port => { oid => '.1.3.6.1.4.1.14179.2.5.1.1.3' }, # bsnRadiusAuthClientServerPortNumber status => { oid => '.1.3.6.1.4.1.14179.2.5.1.1.5', map => $map_server_status } # bsnRadiusAuthServerStatus }; my $oid_bsnRadiusAuthServerEntry = '.1.3.6.1.4.1.14179.2.5.1.1'; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_table( oid => $oid_bsnRadiusAuthServerEntry, start => $mapping->{address}->{oid}, end => $mapping->{status}->{oid} ); my $results = {}; foreach my $oid (keys %$snmp_result) { next if ($oid !~ /^$mapping->{address}->{oid}\.(.*)$/); my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $1); my $name = $result->{address} . ':' . $result->{port}; $results->{$name} = $result; } return $results; } sub run { my ($self, %options) = @_; my $results = $self->manage_selection(snmp => $options{snmp}); foreach my $name (sort keys %$results) { $self->{output}->output_add( long_msg => sprintf( '[name: %s] [status: %s]', $name, $results->{$name}->{status} ) ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List radius authentication 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', 'status']); } sub disco_show { my ($self, %options) = @_; my $results = $self->manage_selection(snmp => $options{snmp}); foreach my $name (sort keys %$results) { $self->{output}->add_disco_entry( name => $name, status => $results->{$name}->{status} ); } } 1; __END__ =head1 MODE List radius authentication servers. =over 8 =back =cut centreon-plugins-20220113/centreon/common/airespace/snmp/mode/memory.pm000066400000000000000000000076751417000230700260630ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::airespace::snmp::mode::memory; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_usage_output { my ($self, %options) = @_; return sprintf( 'Ram total: %s %s used: %s %s (%.2f%%) free: %s %s (%.2f%%)', $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}), $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}), $self->{result_values}->{prct_used}, $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}), $self->{result_values}->{prct_free} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'memory', type => 0, skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{memory} = [ { label => 'usage', nlabel => 'memory.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1 } ] } }, { label => 'usage-free', display_ok => 0, nlabel => 'memory.free.bytes', set => { key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1 } ] } }, { label => 'usage-prct', display_ok => 0, nlabel => 'memory.usage.percentage', set => { key_values => [ { name => 'prct_used' } ], output_template => 'Ram used: %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $oid_agentTotalMemory = '.1.3.6.1.4.1.14179.1.1.5.2.0'; # in Kbytes my $oid_agentFreeMemory = '.1.3.6.1.4.1.14179.1.1.5.3.0'; # in Kbytes my $result = $options{snmp}->get_leef(oids => [$oid_agentTotalMemory, $oid_agentFreeMemory], nothing_quit => 1); my $free = $result->{$oid_agentFreeMemory} * 1024; my $total = $result->{$oid_agentTotalMemory} * 1024; my $prct_used = ($total - $free) * 100 / $total; $self->{memory} = { total => $total, used => $total - $free, free => $free, prct_used => $prct_used, prct_free => 100 - $prct_used } } 1; __END__ =head1 MODE Check memory usage (AIRESPACE-SWITCHING-MIB). =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'usage' (B), 'usage-free' (B), 'usage-prct' (%). =back =cut centreon-plugins-20220113/centreon/common/airespace/snmp/mode/radiusaccservers.pm000066400000000000000000000164361417000230700301160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::airespace::snmp::mode::radiusaccservers; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); sub prefix_servers_output { my ($self, %options) = @_; return "Radius accounting server '" . $options{instance_value}->{name} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'servers', type => 1, cb_prefix_output => 'prefix_servers_output', message_multiple => 'All radius accounting servers are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'accservers-total', nlabel => 'radius.accservers.total.count', display_ok => 0, set => { key_values => [ { name => 'total' } ], output_template => 'total accounting servers: %s', perfdatas => [ { ltemplate => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{servers} = [ { label => 'accservers-roundtrip-time', nlabel => 'radius.accservers.roundtrip.time.milliseconds', set => { key_values => [ { name => 'round_trip_time' }, { name => 'name' } ], output_template => 'round trip time: %s ms', perfdatas => [ { template => '%s', min => 0, unit => 'ms', label_extra_instance => 1, instance_use => 'name' } ] } }, { label => 'accservers-packets-sent', nlabel => 'radius.accservers.packets.sent.persecond', set => { key_values => [ { name => 'requests', per_second => 1 }, { name => 'name' } ], output_template => 'packets sent: %.2f/s', perfdatas => [ { template => '%.2f', min => 0, unit => '/s', label_extra_instance => 1, instance_use => 'name' } ] } }, { label => 'accservers-packets-received', nlabel => 'radius.accservers.packets.received.persecond', set => { key_values => [ { name => 'responses', per_second => 1 }, { name => 'name' } ], output_template => 'packets received: %.2f/s', perfdatas => [ { template => '%.2f', min => 0, unit => '/s', label_extra_instance => 1, instance_use => 'name' } ] } }, { label => 'accservers-clients-timeout', nlabel => 'radius.accservers.clients.timeout.count', set => { key_values => [ { name => 'timeouts', diff => '1' }, { name => 'name' } ], output_template => 'clients timeout: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1, instance_use => 'name' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } my $map_server_status = { 0 => 'disable', 1 => 'enable' }; my $mapping = { address => { oid => '.1.3.6.1.4.1.14179.2.5.2.1.2' }, # bsnRadiusAccServerAddress port => { oid => '.1.3.6.1.4.1.14179.2.5.2.1.3' }, # bsnRadiusAccClientServerPortNumber status => { oid => '.1.3.6.1.4.1.14179.2.5.2.1.5', map => $map_server_status } # bsnRadiusAccServerStatus }; my $mapping2 = { round_trip_time => { oid => '.1.3.6.1.4.1.14179.2.5.4.1.6' }, # bsnRadiusAccClientRoundTripTime requests => { oid => '.1.3.6.1.4.1.14179.2.5.4.1.7' }, # bsnRadiusAccClientRequests responses => { oid => '.1.3.6.1.4.1.14179.2.5.4.1.9' }, # bsnRadiusAccClientResponses timeouts => { oid => '.1.3.6.1.4.1.14179.2.5.4.1.13' } # bsnRadiusAccClientTimeouts }; my $oid_bsnRadiusAccServerEntry = '.1.3.6.1.4.1.14179.2.5.2.1'; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_table( oid => $oid_bsnRadiusAccServerEntry, start => $mapping->{address}->{oid}, end => $mapping->{status}->{oid}, nothing_quit => 1 ); $self->{global} = { total => 0 }; $self->{servers} = {}; foreach my $oid (keys %$snmp_result) { next if ($oid !~ /^$mapping->{status}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); my $name = $result->{address} . ':' . $result->{port}; 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; } if ($result->{status} eq 'disable') { $self->{output}->output_add(long_msg => "skipping '" . $name . "': disabled.", debug => 1); next; } $self->{servers}->{$instance} = { name => $name }; $self->{global}->{total}++; } return if (scalar(keys %{$self->{servers}}) <= 0); $options{snmp}->load( oids => [ map($_->{oid}, values(%$mapping2)) ], instances => [keys %{$self->{servers}}], instance_regexp => '^(.*)$' ); $snmp_result = $options{snmp}->get_leef(nothing_quit => 1); foreach (keys %{$self->{servers}}) { my $result = $options{snmp}->map_instance(mapping => $mapping2, results => $snmp_result, instance => $_); $self->{servers}->{$_} = { %{$self->{servers}->{$_}}, %$result }; } $self->{cache_name} = 'cisco_wlc_' . $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 radius accounting servers. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^total$' =item B<--filter-name> Filter radius servers by name (can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'accservers-total', 'accservers-roundtrip-time', 'accservers-packets-sent', 'accservers-packets-received', 'accservers-clients-timeout'. =back =cut centreon-plugins-20220113/centreon/common/airespace/snmp/mode/radiusauthservers.pm000066400000000000000000000166051417000230700303270ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::airespace::snmp::mode::radiusauthservers; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); sub prefix_servers_output { my ($self, %options) = @_; return "Radius authentication server '" . $options{instance_value}->{name} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'servers', type => 1, cb_prefix_output => 'prefix_servers_output', message_multiple => 'All radius authentication servers are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'authservers-total', nlabel => 'radius.authservers.total.count', display_ok => 0, set => { key_values => [ { name => 'total' } ], output_template => 'total authentication servers: %s', perfdatas => [ { ltemplate => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{servers} = [ { label => 'authserver-roundtrip-time', nlabel => 'radius.authserver.roundtrip.time.milliseconds', set => { key_values => [ { name => 'round_trip_time' }, { name => 'name' } ], output_template => 'round trip time: %s ms', perfdatas => [ { template => '%s', min => 0, unit => 'ms', label_extra_instance => 1, instance_use => 'name' } ] } }, { label => 'authserver-packets-access-requests', nlabel => 'radius.authserver.packets.access.requests.persecond', set => { key_values => [ { name => 'access_requests', per_second => 1 }, { name => 'name' } ], output_template => 'access requests: %.2f/s', perfdatas => [ { template => '%.2f', min => 0, unit => '/s', label_extra_instance => 1, instance_use => 'name' } ] } }, { label => 'authserver-packets-access-accepts', nlabel => 'radius.authserver.packets.access.accepts.persecond', set => { key_values => [ { name => 'access_accepts', per_second => 1 }, { name => 'name' } ], output_template => 'access accepts: %.2f/s', perfdatas => [ { template => '%.2f', min => 0, unit => '/s', label_extra_instance => 1, instance_use => 'name' } ] } }, { label => 'authserver-clients-timeout', nlabel => 'radius.authserver.clients.timeout.count', set => { key_values => [ { name => 'timeouts', diff => '1' }, { name => 'name' } ], output_template => 'clients timeout: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1, instance_use => 'name' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } my $map_server_status = { 0 => 'disable', 1 => 'enable' }; my $mapping = { address => { oid => '.1.3.6.1.4.1.14179.2.5.1.1.2' }, # bsnRadiusAuthServerAddress port => { oid => '.1.3.6.1.4.1.14179.2.5.1.1.3' }, # bsnRadiusAuthClientServerPortNumber status => { oid => '.1.3.6.1.4.1.14179.2.5.1.1.5', map => $map_server_status } # bsnRadiusAuthServerStatus }; my $mapping2 = { round_trip_time => { oid => '.1.3.6.1.4.1.14179.2.5.3.1.6' }, # bsnRadiusAuthClientRoundTripTime access_requests => { oid => '.1.3.6.1.4.1.14179.2.5.3.1.7' }, # bsnRadiusAuthClientAccessRequests access_accepts => { oid => '.1.3.6.1.4.1.14179.2.5.3.1.9' }, # bsnRadiusAuthClientAccessAccepts timeouts => { oid => '.1.3.6.1.4.1.14179.2.5.3.1.15' } # bsnRadiusAuthClientTimeouts }; my $oid_bsnRadiusAuthServerEntry = '.1.3.6.1.4.1.14179.2.5.1.1'; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_table( oid => $oid_bsnRadiusAuthServerEntry, start => $mapping->{address}->{oid}, end => $mapping->{status}->{oid}, nothing_quit => 1 ); $self->{global} = { total => 0 }; $self->{servers} = {}; foreach my $oid (keys %$snmp_result) { next if ($oid !~ /^$mapping->{status}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); my $name = $result->{address} . ':' . $result->{port}; 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; } if ($result->{status} eq 'disable') { $self->{output}->output_add(long_msg => "skipping '" . $name . "': disabled.", debug => 1); next; } $self->{servers}->{$instance} = { name => $name }; $self->{global}->{total}++; } return if (scalar(keys %{$self->{servers}}) <= 0); $options{snmp}->load( oids => [ map($_->{oid}, values(%$mapping2)) ], instances => [keys %{$self->{servers}}], instance_regexp => '^(.*)$' ); $snmp_result = $options{snmp}->get_leef(nothing_quit => 1); foreach (keys %{$self->{servers}}) { my $result = $options{snmp}->map_instance(mapping => $mapping2, results => $snmp_result, instance => $_); $self->{servers}->{$_} = { %{$self->{servers}->{$_}}, %$result }; } $self->{cache_name} = 'cisco_wlc_' . $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 radius authentication servers. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^total$' =item B<--filter-name> Filter radius servers by name (can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'authservers-total', 'authserver-roundtrip-time', 'authserver-packets-access-requests', 'authserver-packets-access-accepts', 'authserver-clients-timeout'. =back =cut centreon-plugins-20220113/centreon/common/aruba/000077500000000000000000000000001417000230700214335ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/aruba/snmp/000077500000000000000000000000001417000230700224105ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/aruba/snmp/mode/000077500000000000000000000000001417000230700233345ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/aruba/snmp/mode/apconnections.pm000066400000000000000000000237741417000230700265520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::aruba::snmp::mode::apconnections; 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, skipped_code => { -10 => 1 } }, { name => 'ap', type => 1, cb_prefix_output => 'prefix_ap_output', message_multiple => 'All access points are ok' }, ]; $self->{maps_counters}->{global} = [ { label => 'total', nlabel => 'accesspoints.connected.current.count', set => { key_values => [ { name => 'total' } ], output_template => 'Total access points connected : %d', perfdatas => [ { label => 'total', value => 'total', template => '%d', min => 0 }, ], } }, ]; $self->{maps_counters}->{ap} = [ { label => 'total-time', nlabel => 'accesspoint.time.connection.current.seconds', set => { key_values => [ { name => 'apTotalTime' }, { name => 'bssid' }, ], output_template => 'Current total connection time : %.3f s', perfdatas => [ { label => 'total_time', value => 'apTotalTime', template => '%.3f', min => 0, unit => 's', label_extra_instance => 1, instance_use => 'bssid' }, ], } }, { label => 'inactive-time', nlabel => 'accesspoint.time.inactive.current.seconds', set => { key_values => [ { name => 'apInactiveTime' }, { name => 'bssid' }, ], output_template => 'Current inactive time : %.3f s', perfdatas => [ { label => 'inactive_time', value => 'apInactiveTime', template => '%.3f', min => 0, unit => 's', label_extra_instance => 1, instance_use => 'bssid' }, ], } }, { label => 'channel-noise', nlabel => 'accesspoint.channel.noise.count', sset => { key_values => [ { name => 'apChannelNoise' }, { name => 'bssid' }, ], output_template => 'Channel noise : %d', perfdatas => [ { label => 'channel_noise', value => 'apChannelNoise', template => '%d', label_extra_instance => 1, instance_use => 'bssid' }, ], } }, { label => 'snr', nlabel => 'accesspoint.signal.noise.ratio.dbm', set => { key_values => [ { name => 'apSignalToNoiseRatio' }, { name => 'bssid' }, ], output_template => 'Signal to noise ratio : %d', perfdatas => [ { label => 'snr', value => 'apSignalToNoiseRatio', template => '%d', label_extra_instance => 1, instance_use => 'bssid' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-ip-address:s" => { name => 'filter_ip_address' }, "filter-bssid:s" => { name => 'filter_bssid' }, "filter-essid:s" => { name => 'filter_essid' }, "filter-type:s" => { name => 'filter_type', default => 'ap' }, "skip-total" => { name => 'skip_total' }, }); return $self; } sub prefix_ap_output { my ($self, %options) = @_; return "AP [bssid: '$options{instance_value}->{bssid}', essid: $options{instance_value}->{apESSID}, ip: $options{instance_value}->{apIpAddress}] Usage "; } my %map_role = ( 1 => 'master', 2 => 'local', 3 => 'standbymaster', ); my %map_type = ( 1 => 'ap', 2 => 'am', ); my $mapping = { apESSID => { oid => '.1.3.6.1.4.1.14823.2.2.1.1.3.3.1.2' }, }; my $mapping2 = { apIpAddress => { oid => '.1.3.6.1.4.1.14823.2.2.1.1.3.3.1.5' }, }; my $mapping3 = { apType => { oid => '.1.3.6.1.4.1.14823.2.2.1.1.3.3.1.7', map => \%map_type }, }; my $mapping4 = { apTotalTime => { oid => '.1.3.6.1.4.1.14823.2.2.1.1.3.3.1.10' }, apInactiveTime => { oid => '.1.3.6.1.4.1.14823.2.2.1.1.3.3.1.11' }, }; my $mapping5 = { apChannelNoise => { oid => '.1.3.6.1.4.1.14823.2.2.1.1.3.3.1.13' }, apSignalToNoiseRatio => { oid => '.1.3.6.1.4.1.14823.2.2.1.1.3.3.1.14' }, }; my $oid_wlsxSwitchRole = '.1.3.6.1.4.1.14823.2.2.1.1.1.4'; my $oid_wlsxSwitchAccessPointTable = '.1.3.6.1.4.1.14823.2.2.1.1.3.3'; my $oid_wlsxSwitchAccessPointEntry = '.1.3.6.1.4.1.14823.2.2.1.1.3.3.1'; my $oid_wlsxSwitchTotalNumAccessPoints = '.1.3.6.1.4.1.14823.2.2.1.1.3.1'; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_multiple_table( oids => [ { oid => $oid_wlsxSwitchTotalNumAccessPoints }, { oid => $oid_wlsxSwitchRole }, { oid => $mapping->{apESSID}->{oid} }, { oid => $mapping2->{apIpAddress}->{oid} }, { oid => $mapping3->{apType}->{oid} }, { oid => $oid_wlsxSwitchAccessPointEntry, start => $mapping4->{apTotalTime}->{oid}, end => $mapping4->{apInactiveTime}->{oid} }, { oid => $oid_wlsxSwitchAccessPointTable, start => $mapping5->{apChannelNoise}->{oid}, end => $mapping5->{apSignalToNoiseRatio}->{oid} }, ], nothing_quit => 1 ); my $role = $map_role{$snmp_result->{$oid_wlsxSwitchRole}->{$oid_wlsxSwitchRole . '.0'}}; if ($role =~ /standbymaster/) { $self->{output}->output_add(severity => 'OK', short_msg => "Cannot get information. Switch role is '" . $role . "'."); $self->{output}->display(); $self->{output}->exit(); } $self->{ap} = {}; foreach my $oid (keys %{$snmp_result->{$mapping->{apESSID}->{oid}}}) { next if ($oid !~ /^$mapping->{apESSID}->{oid}\.(.*)$/); my $bssid = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result->{$mapping->{apESSID}->{oid}}, instance => $bssid); my $result2 = $options{snmp}->map_instance(mapping => $mapping2, results => $snmp_result->{$mapping2->{apIpAddress}->{oid}}, instance => $bssid); my $result3 = $options{snmp}->map_instance(mapping => $mapping3, results => $snmp_result->{$mapping3->{apType}->{oid}}, instance => $bssid); my $result4 = $options{snmp}->map_instance(mapping => $mapping4, results => $snmp_result->{$oid_wlsxSwitchAccessPointEntry}, instance => $bssid); my $result5 = $options{snmp}->map_instance(mapping => $mapping5, results => $snmp_result->{$oid_wlsxSwitchAccessPointTable}, instance => $bssid); if (defined($self->{option_results}->{filter_bssid}) && $self->{option_results}->{filter_bssid} ne '' && $bssid !~ /$self->{option_results}->{filter_bssid}/) { $self->{output}->output_add(long_msg => "skipping '" . $bssid . "': no matching filter bssid."); next; } if (defined($self->{option_results}->{filter_ip_address}) && $self->{option_results}->{filter_ip_address} ne '' && $result2->{apIpAddress} !~ /$self->{option_results}->{filter_ip_address}/) { $self->{output}->output_add(long_msg => "skipping '" . $result2->{apIpAddress} . "': no matching filter ip-address."); next; } if (defined($self->{option_results}->{filter_essid}) && $self->{option_results}->{filter_essid} ne '' && $result->{apESSID} !~ /$self->{option_results}->{filter_essid}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{apESSID} . "': no matching filter essid."); next; } if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' && $result3->{apType} !~ /$self->{option_results}->{filter_type}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{apType} . "': no matching filter type."); next; } $self->{ap}->{$bssid} = { bssid => $bssid, %$result2, %$result, %$result4, %$result5}; $self->{ap}->{$bssid}->{apInactiveTime} *= 0.01 if (defined($self->{ap}->{$bssid}->{apInactiveTime})); $self->{ap}->{$bssid}->{apTotalTime} *= 0.01 if (defined($self->{ap}->{$bssid}->{apTotalTime})); } if (!defined($self->{option_results}->{skip_total}) && defined($snmp_result->{$oid_wlsxSwitchTotalNumAccessPoints}->{$oid_wlsxSwitchTotalNumAccessPoints . '.0'})) { $self->{global} = { total => $snmp_result->{$oid_wlsxSwitchTotalNumAccessPoints}->{$oid_wlsxSwitchTotalNumAccessPoints . '.0'} }; } } 1; __END__ =head1 MODE Check AP connections (Deprecated). =over 8 =item B<--warning-*> Threshold warning. Can be: 'total', 'total-time', 'inactive-time', 'channel-noise', 'snr'. =item B<--critical-*> Threshold critical. Can be: 'total', 'total-time', 'inactive-time', 'channel-noise', 'snr'. =item B<--filter-bssid> Filter by physical address (regexp can be used). =item B<--filter-ip-address> Filter by ip address (regexp can be used). =item B<--filter-essid> Filter by ESSID (regexp can be used). =item B<--filter-type> Filter by type (regexp can be used. Can be: 'ap' or 'am'. Default: 'ap'). =item B<--skip-total> Don't display total AP connected (useful when you check each AP). =back =cut centreon-plugins-20220113/centreon/common/aruba/snmp/mode/apssidstatistics.pm000066400000000000000000000251211417000230700272710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::aruba::snmp::mode::apssidstatistics; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'ap', type => 3, cb_prefix_output => 'prefix_output_ap', cb_long_output => 'long_output', message_multiple => 'All AP BSSID are ok', indent_long_output => ' ', group => [ { name => 'global', type => 0 }, { name => 'essid', display_long => 1, cb_prefix_output => 'prefix_output_essid', message_multiple => 'All ESSID are ok', type => 1 }, { name => 'bssid', display_long => 1, cb_prefix_output => 'prefix_output_bssid', message_multiple => 'All BSSID are ok', type => 1 }, ] } ]; $self->{maps_counters}->{global} = [ { label => 'stations-associated', nlabel => 'stations.associated.count', set => { key_values => [ { name => 'total' } ], output_template => 'Stations Associated: %d', perfdatas => [ { value => 'total', template => '%d', min => 0 }, ], } }, ]; $self->{maps_counters}->{essid} = [ { label => 'essid-stations-associated', nlabel => 'essid.stations.associated.count', set => { key_values => [ { name => 'wlanAPEssidNumAssociatedStations' }, { name => 'wlanAPESSID' } ], output_template => 'Associated Stations: %d', perfdatas => [ { value => 'wlanAPEssidNumAssociatedStations', template => '%d', label_extra_instance => 1 }, ], } }, ]; $self->{maps_counters}->{bssid} = [ { label => 'bssid-stations-associated', nlabel => 'bssid.stations.associated.count', set => { key_values => [ { name => 'wlanAPBssidNumAssociatedStations' }, { name => 'wlanAPBSSID' }, { name => 'wlanAPESSID' } ], output_template => 'Associated Stations: %d', perfdatas => [ { value => 'wlanAPBssidNumAssociatedStations', template => '%d', label_extra_instance => 1 }, ], } }, { label => 'channel-noise', nlabel => 'bssid.channel.noise.count', set => { key_values => [ { name => 'apChannelNoise' }, { name => 'wlanAPBSSID' }, { name => 'wlanAPESSID' } ], output_template => 'Channel Noise: %d', perfdatas => [ { value => 'apChannelNoise', template => '%d', label_extra_instance => 1 }, ], } }, { label => 'signal-noise-ratio', nlabel => 'bssid.signal.noise.ratio.count', set => { key_values => [ { name => 'apSignalToNoiseRatio' }, { name => 'wlanAPBSSID' }, { name => 'wlanAPESSID' } ], output_template => 'Signal To Noise Ratio: %d', perfdatas => [ { value => 'apSignalToNoiseRatio', template => '%d', label_extra_instance => 1 }, ], } }, ]; } sub prefix_output_ap { my ($self, %options) = @_; return "AP '" . $options{instance_value}->{wlanAPName} . "' [Mac: " . $options{instance_value}->{wlanAPMacAddress} . "] "; } sub prefix_output_essid { my ($self, %options) = @_; return "ESSID '" . $options{instance_value}->{wlanAPESSID} . "' "; } sub prefix_output_bssid { my ($self, %options) = @_; return "BSSID '" . $options{instance_value}->{wlanAPBSSID} . "' [ESSID: " . $options{instance_value}->{wlanAPESSID} . "][Protocol: " . $options{instance_value}->{wlanAPBssidPhyType} . "] "; } sub long_output { my ($self, %options) = @_; return "Checking AP '" . $options{instance_value}->{wlanAPName} . "' [Mac: " . $options{instance_value}->{wlanAPMacAddress} . "] "; } 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-ap:s" => { name => 'filter_ap' }, "filter-essid:s" => { name => 'filter_essid' }, "filter-protocol:s" => { name => 'filter_protocol' }, "filter-bssid:s" => { name => 'filter_bssid' }, }); return $self; } my %map_type = ( 1 => '802.11a', 2 => '802.11b', 3 => '802.11g', 4 => '802.11ag', 5 => 'wired' ); my $oid_wlsxSwitchAccessPointTable = '.1.3.6.1.4.1.14823.2.2.1.1.3.3.1'; my $mapping_switch = { apChannelNoise => { oid => '.1.3.6.1.4.1.14823.2.2.1.1.3.3.1.13' }, apSignalToNoiseRatio => { oid => '.1.3.6.1.4.1.14823.2.2.1.1.3.3.1.14' }, }; my $oid_wlsxWlanAPBssidTable = '.1.3.6.1.4.1.14823.2.2.1.5.2.1.7.1'; my $mapping_wlan = { wlanAPESSID => { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.7.1.2' }, wlanAPBssidPhyType => { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.7.1.5', map => \%map_type }, wlanAPBssidUpTime => { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.7.1.9' }, wlanAPBssidInactiveTime => { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.7.1.10' }, wlanAPBssidNumAssociatedStations => { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.7.1.12' }, }; my $oid_wlanAPName = '.1.3.6.1.4.1.14823.2.2.1.5.2.1.4.1.3'; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_multiple_table( oids => [ { oid => $oid_wlsxSwitchAccessPointTable, start => $mapping_switch->{apChannelNoise}->{oid}, end => $mapping_switch->{apSignalToNoiseRatio}->{oid} }, { oid => $oid_wlsxWlanAPBssidTable, start => $mapping_wlan->{wlanAPESSID}->{oid}, end => $mapping_wlan->{wlanAPBssidNumAssociatedStations}->{oid} }, { oid => $oid_wlanAPName }, ], nothing_quit => 1 ); $self->{ap} = {}; foreach my $oid (keys %{$snmp_result->{$oid_wlsxWlanAPBssidTable}}) { next if ($oid !~ /^$mapping_wlan->{wlanAPESSID}->{oid}\.(.*)/); my $instance = $1; my $result = $options{snmp}->map_instance( mapping => $mapping_wlan, results => $snmp_result->{$oid_wlsxWlanAPBssidTable}, instance => $instance ); my @digits = split /\./, $instance; $result->{wlanAPMacAddress} = join(':', unpack("(A2)*", unpack('H*', pack('C*', @digits[0..5])))); $result->{wlanAPBSSID} = join(':', unpack("(A2)*", unpack('H*', pack('C*', @digits[7..12])))); $result->{wlanAPName} = $snmp_result->{$oid_wlanAPName}->{$oid_wlanAPName . '.' . join('.', @digits[0..5])}; $result->{apChannelNoise} = $snmp_result->{$oid_wlsxSwitchAccessPointTable}->{$mapping_switch->{apChannelNoise}->{oid} . '.' . join('.', @digits[7..12])}; $result->{apSignalToNoiseRatio} = $snmp_result->{$oid_wlsxSwitchAccessPointTable}->{$mapping_switch->{apSignalToNoiseRatio}->{oid} . '.' . join('.', @digits[7..12])}; if (defined($self->{option_results}->{filter_ap}) && $self->{option_results}->{filter_ap} ne '' && $result->{wlanAPName} !~ /$self->{option_results}->{filter_ap}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{wlanAPName} . "': no matching filter name.", debug => 1); next; } if (defined($self->{option_results}->{filter_essid}) && $self->{option_results}->{filter_essid} ne '' && $result->{wlanAPESSID} !~ /$self->{option_results}->{filter_essid}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{wlanAPESSID} . "': no matching filter essid.", debug => 1); next; } if (defined($self->{option_results}->{filter_bssid}) && $self->{option_results}->{filter_bssid} ne '' && $result->{wlanAPBSSID} !~ /$self->{option_results}->{filter_bssid}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{wlanAPESSID} . "': no matching filter bssid.", debug => 1); next; } if (defined($self->{option_results}->{filter_protocol}) && $self->{option_results}->{filter_protocol} ne '' && $result->{wlanAPBssidPhyType} !~ /$self->{option_results}->{filter_protocol}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{wlanAPBssidPhyType} . "': no matching filter protocol.", debug => 1); next; } $self->{ap}->{$result->{wlanAPName}}->{global}->{total} += $result->{wlanAPBssidNumAssociatedStations}; $self->{ap}->{$result->{wlanAPName}}->{wlanAPName} = $result->{wlanAPName}; $self->{ap}->{$result->{wlanAPName}}->{wlanAPMacAddress} = $result->{wlanAPMacAddress}; $self->{ap}->{$result->{wlanAPName}}->{essid}->{$result->{wlanAPESSID}}->{wlanAPEssidNumAssociatedStations} += $result->{wlanAPBssidNumAssociatedStations}; $self->{ap}->{$result->{wlanAPName}}->{essid}->{$result->{wlanAPESSID}}->{wlanAPESSID} = $result->{wlanAPESSID}; $self->{ap}->{$result->{wlanAPName}}->{bssid}->{$result->{wlanAPBSSID}} = { %{$result} }; } if (scalar(keys %{$self->{ap}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No AP found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check AP ESSID and BSSID statistics (WLSX-WLAN-MIB, WLSX-SWITCH-MIB). =over 8 =item B<--warning-*> Threshold warning. Can be: 'stations-associated' (ESSID and BSSID), 'channel-noise', 'signal-noise-ratio' (BSSID). =item B<--critical-*> Threshold critical. Can be: 'stations-associated' (ESSID and BSSID), 'channel-noise', 'signal-noise-ratio' (BSSID). =item B<--filter-*> Filter by 'ap', 'essid', 'protocol', 'bssid' (regexp can be used). =back =cut centreon-plugins-20220113/centreon/common/aruba/snmp/mode/apstatus.pm000066400000000000000000000230211417000230700255340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::aruba::snmp::mode::apstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("Status is '%s' [Ip: %s][Group: %s][Location: %s]", $self->{result_values}->{status}, $self->{result_values}->{ip}, $self->{result_values}->{group}, $self->{result_values}->{location} ); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_wlanAPName'}; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_wlanAPStatus'}; $self->{result_values}->{ip} = $options{new_datas}->{$self->{instance} . '_wlanAPIpAddress'}; $self->{result_values}->{group} = $options{new_datas}->{$self->{instance} . '_wlanAPGroupName'}; $self->{result_values}->{location} = $options{new_datas}->{$self->{instance} . '_wlanAPLocation'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_init => 'skip_global' }, { name => 'ap', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All AP status are ok' }, ]; $self->{maps_counters}->{global} = [ { label => 'connected-current', nlabel => 'accesspoints.connected.current.count', set => { key_values => [ { name => 'connected' } ], output_template => 'Total connected AP: %d', perfdatas => [ { value => 'connected', template => '%d', min => 0 }, ], } }, ]; $self->{maps_counters}->{ap} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'wlanAPName' }, { name => 'wlanAPIpAddress' }, { name => 'wlanAPGroupName' }, { name => 'wlanAPLocation' }, { name => 'wlanAPStatus' } ], 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 => \&catalog_status_threshold, } }, { label => 'uptime', nlabel => 'accesspoint.uptime.seconds', set => { key_values => [ { name => 'wlanAPUpTime' }, { name => 'wlanAPName' } ], output_template => 'Uptime: %ss', perfdatas => [ { value => 'wlanAPUpTime', template => '%s', unit => 's', label_extra_instance => 1, instance_use => 'wlanAPName' }, ], } }, { label => 'controller-bootstrap', nlabel => 'accesspoint.controller.bootstrap.count', set => { key_values => [ { name => 'wlanAPNumBootstraps' }, { name => 'wlanAPName' } ], output_template => 'Controller Bootstrap Count: %d', perfdatas => [ { value => 'wlanAPNumBootstraps', template => '%d', label_extra_instance => 1, instance_use => 'wlanAPName' }, ], } }, { label => 'reboot', nlabel => 'accesspoint.reboot.count', set => { key_values => [ { name => 'wlanAPNumReboots' }, { name => 'wlanAPName' } ], output_template => 'Reboot Count: %d', perfdatas => [ { value => 'wlanAPNumReboots', template => '%d', label_extra_instance => 1, instance_use => 'wlanAPName' }, ], } }, ]; } sub skip_global { my ($self, %options) = @_; scalar(keys %{$self->{ap}}) > 1 ? return(0) : return(1); } sub prefix_output { my ($self, %options) = @_; return "AP '" . $options{instance_value}->{wlanAPName} . "' "; } 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-ip:s' => { name => 'filter_ip' }, 'filter-name:s' => { name => 'filter_name' }, 'filter-group:s' => { name => 'filter_group' }, 'warning-status:s' => { name => 'warning_status' }, 'critical-status:s' => { name => 'critical_status', default => '%{status} !~ /up/i' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } my $map_status = { 1 => 'up', 2 => 'down' }; my $oid_wlsxWlanAPTable = '.1.3.6.1.4.1.14823.2.2.1.5.2.1.4.1'; my $mapping_info = { wlanAPIpAddress => { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.4.1.2' }, wlanAPName => { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.4.1.3' }, wlanAPGroupName => { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.4.1.4' }, }; my $mapping_stat = { wlanAPUpTime => { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.4.1.12' }, wlanAPLocation => { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.4.1.14' }, wlanAPStatus => { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.4.1.19', map => $map_status }, wlanAPNumBootstraps => { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.4.1.20' }, wlanAPNumReboots => { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.4.1.21' }, }; sub manage_selection { my ($self, %options) = @_; $self->{global}->{connected} = 0; $self->{ap} = {}; my $snmp_info = $options{snmp}->get_table( oid => $oid_wlsxWlanAPTable, start => $mapping_info->{wlanAPIpAddress}->{oid}, end => $mapping_info->{wlanAPGroupName}->{oid}, nothing_quit => 1 ); foreach my $oid (keys %{$snmp_info}) { next if ($oid !~ /^$mapping_info->{wlanAPIpAddress}->{oid}\.(.*)/); my $instance = $1; my $result = $options{snmp}->map_instance( mapping => $mapping_info, results => $snmp_info, instance => $instance ); if (defined($self->{option_results}->{filter_ip}) && $self->{option_results}->{filter_ip} ne '' && $result->{wlanAPIpAddress} !~ /$self->{option_results}->{filter_ip}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{wlanAPIpAddress} . "': no matching filter ip.", debug => 1); next; } if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $result->{wlanAPName} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{wlanAPName} . "': no matching filter name.", debug => 1); next; } if (defined($self->{option_results}->{filter_group}) && $self->{option_results}->{filter_group} ne '' && $result->{wlanAPGroupName} !~ /$self->{option_results}->{filter_group}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{wlanAPGroupName} . "': no matching filter group.", debug => 1); next; } $self->{ap}->{$instance} = { %{$result} }; } if (scalar(keys %{$self->{ap}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No AP found."); $self->{output}->option_exit(); } $options{snmp}->load( oids => [ $mapping_stat->{wlanAPUpTime}->{oid}, $mapping_stat->{wlanAPLocation}->{oid}, $mapping_stat->{wlanAPStatus}->{oid}, $mapping_stat->{wlanAPNumBootstraps}->{oid}, $mapping_stat->{wlanAPNumReboots}->{oid}, ], instances => [ keys %{$self->{ap}} ], instance_regexp => '^(.*)$' ); my $snmp_result = $options{snmp}->get_leef(nothing_quit => 1); foreach my $oid (keys %{$snmp_result}) { next if ($oid !~ /^$mapping_stat->{wlanAPUpTime}->{oid}\.(.*)/); my $instance = $1; my $result = $options{snmp}->map_instance( mapping => $mapping_stat, results => $snmp_result, instance => $instance ); $self->{ap}->{$instance} = { %{$self->{ap}->{$instance}}, %{$result}, wlanAPUpTime => $result->{wlanAPUpTime} / 100 }; $self->{global}->{connected}++; } } 1; __END__ =head1 MODE Check AP status (WLSX-WLAN-MIB). =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'connected-current' (global), 'uptime', 'controller-bootstrap', 'reboot', 'status' (per AP). 'status' can use special variables like: %{name}, %{status}, %{ip}, %{group}, %{location} (Default: '') =item B<--filter-*> Filter by 'ip', 'name', 'group' (regexp can be used). =back =cut centreon-plugins-20220113/centreon/common/aruba/snmp/mode/apusers.pm000066400000000000000000000254031417000230700253600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::aruba::snmp::mode::apusers; 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 }, { name => 'essid', type => 1, cb_prefix_output => 'prefix_essid_output', message_multiple => 'All users by ESSID are ok' }, { name => 'ap', type => 1, cb_prefix_output => 'prefix_ap_output', message_multiple => 'All users by AP are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'total', set => { key_values => [ { name => 'total' } ], output_template => 'Total Users: %s', perfdatas => [ { label => 'total', template => '%s', unit => 'users', min => 0 } ] } }, { label => 'total-none', set => { key_values => [ { name => 'total_none' } ], output_template => 'Total Auth None: %s', perfdatas => [ { label => 'total_none', template => '%s', unit => 'users', min => 0 } ] } }, { label => 'total-other', set => { key_values => [ { name => 'total_other' } ], output_template => 'Total Auth Other: %s', perfdatas => [ { label => 'total_other', template => '%s', unit => 'users', min => 0 } ] } }, { label => 'total-web', set => { key_values => [ { name => 'total_web' } ], output_template => 'Total Auth Web: %s', perfdatas => [ { label => 'total_web', template => '%s', unit => 'users', min => 0 } ] } }, { label => 'total-dot1x', set => { key_values => [ { name => 'total_dot1x' } ], output_template => 'Total Auth Dot1x: %s', perfdatas => [ { label => 'total_dot1x', template => '%s', unit => 'users', min => 0 } ] } }, { label => 'total-vpn', set => { key_values => [ { name => 'total_vpn' } ], output_template => 'Total Auth Vpn: %s', perfdatas => [ { label => 'total_vpn', template => '%s', unit => 'users', min => 0 } ] } }, { label => 'total-mac', set => { key_values => [ { name => 'total_mac' } ], output_template => 'Total Auth Mac: %s', perfdatas => [ { label => 'total_mac', template => '%s', unit => 'users', min => 0 } ] } }, { label => 'avg-connection-time', set => { key_values => [ { name => 'avg_connection_time' } ], output_template => 'Users average connection time: %.3f seconds', perfdatas => [ { label => 'avg_connection_time', template => '%.3f', unit => 's', min => 0 } ] } } ]; $self->{maps_counters}->{essid} = [ { label => 'total-essid', set => { key_values => [ { name => 'users' }, { name => 'essid' } ], output_template => 'users: %s', perfdatas => [ { label => 'essid', template => '%s', unit => 'users', min => 0, label_extra_instance => 1, instance_use => 'essid' } ] } } ]; $self->{maps_counters}->{ap} = [ { label => 'total-ap', set => { key_values => [ { name => 'users' }, { name => 'ap_id' } ], output_template => 'users: %s', perfdatas => [ { label => 'ap', template => '%s', unit => 'users', min => 0, label_extra_instance => 1, instance_use => 'ap_id' } ] } } ]; } sub prefix_essid_output { my ($self, %options) = @_; return "ESSID '" . $options{instance_value}->{essid} . "' "; } sub prefix_ap_output { my ($self, %options) = @_; return "AP '" . $options{instance_value}->{ap_id} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-ip-address:s' => { name => 'filter_ip_address' }, 'filter-bssid:s' => { name => 'filter_bssid' }, 'filter-essid:s' => { name => 'filter_essid' } }); return $self; } my $map_auth_method = { 0 => 'none', 1 => 'web', 2 => 'mac', 3 => 'vpn', 4 => 'dot1x', 5 => 'kerberos', 7 => 'secureId', 15 => 'pubcookie', 16 => 'xSec', 17 => 'xSecMachine', 28 => 'via-vpn', 255 => 'other' }; my $map_role = { 1 => 'master', 2 => 'local', 3 => 'standbymaster' }; my $mapping = { nUserUpTime => { oid => '.1.3.6.1.4.1.14823.2.2.1.4.1.2.1.5' }, nUserAuthenticationMethod => { oid => '.1.3.6.1.4.1.14823.2.2.1.4.1.2.1.6', map => $map_auth_method } }; my $mapping2 = { nUserApBSSID => { oid => '.1.3.6.1.4.1.14823.2.2.1.4.1.2.1.11' } }; my $oid_wlsxUserEntry = '.1.3.6.1.4.1.14823.2.2.1.4.1.2.1'; my $oid_wlsxSwitchRole = '.1.3.6.1.4.1.14823.2.2.1.1.1.4'; my $oid_apESSID = '.1.3.6.1.4.1.14823.2.2.1.1.3.3.1.2'; my $oid_apIpAddress = '.1.3.6.1.4.1.14823.2.2.1.1.3.3.1.5'; #my $oid_wlanAPName = '.1.3.6.1.4.1.14823.2.2.1.5.2.1.4.1.3'; sub manage_selection { my ($self, %options) = @_; $self->{global} = { total => 0, total_none => 0, total_web => 0, total_mac => 0, total_vpn => 0, total_dot1x => 0, total_kerberos => 0, total_secureId => 0, total_pubcookie => 0, total_xSec => 0, xSecMachine => 0, 'total_via-vpn' => 0, total_other => 0 }; $self->{ap} = {}; $self->{essid} = {}; my $snmp_result = $options{snmp}->get_multiple_table( oids => [ { oid => $oid_wlsxSwitchRole }, { oid => $oid_wlsxUserEntry, start => $mapping->{nUserUpTime}->{oid}, end => $mapping->{nUserAuthenticationMethod}->{oid} }, { oid => $mapping2->{nUserApBSSID}->{oid} }, { oid => $oid_apESSID }, { oid => $oid_apIpAddress } ], nothing_quit => 1 ); my $role = $map_role->{ $snmp_result->{$oid_wlsxSwitchRole}->{$oid_wlsxSwitchRole . '.0'} }; if ($role =~ /standbymaster/) { $self->{output}->output_add( severity => 'OK', short_msg => "Cannot get information. Switch role is '" . $role . "'." ); $self->{output}->display(); $self->{output}->exit(); } my $map_ap = {}; foreach my $oid (keys %{$snmp_result->{$oid_apESSID}}) { $oid =~ /^$oid_apESSID\.(.*)$/; $map_ap->{$1} = { essid => $snmp_result->{$oid_apESSID}->{$oid}, ip => $snmp_result->{$oid_apIpAddress}->{$oid_apIpAddress . '.' . $1} }; } my $total_timeticks = 0; foreach my $oid (keys %{$snmp_result->{$oid_wlsxUserEntry}}) { next if ($oid !~ /^$mapping->{nUserAuthenticationMethod}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result->{$oid_wlsxUserEntry}, instance => $instance); my $result2 = $options{snmp}->map_instance(mapping => $mapping2, results => $snmp_result->{ $mapping2->{nUserApBSSID}->{oid} }, instance => $instance); # security next if (!defined($result2->{nUserApBSSID})); my $bssid = join('.', unpack('C*', $result2->{nUserApBSSID})); next if (defined($self->{option_results}->{filter_ip_address}) && $self->{option_results}->{filter_ip_address} ne '' && defined($map_ap->{$bssid}) && $map_ap->{$bssid}->{ip} !~ /$self->{option_results}->{filter_ip_address}/); next if (defined($self->{option_results}->{filter_essid}) && $self->{option_results}->{filter_essid} ne '' && defined($map_ap->{$bssid}) && $map_ap->{$bssid}->{essid} !~ /$self->{option_results}->{filter_essid}/); next if (defined($self->{option_results}->{filter_bssid}) && $self->{option_results}->{filter_bssid} ne '' && $bssid !~ /$self->{option_results}->{filter_bssid}/); my $ap_id = $bssid; #$ap_id = $self->{results}->{$oid_wlanAPName}->{$oid_wlanAPName . '.' . $bssid} # if (defined($self->{results}->{$oid_wlanAPName}->{$oid_wlanAPName . '.' . $bssid}) && $self->{results}->{$oid_wlanAPName}->{$oid_wlanAPName . '.' . $bssid} ne ''); $self->{ap}->{$bssid} = { users => 0, ap_id => $ap_id } if (!defined($self->{ap}->{$bssid})); $self->{ap}->{$bssid}->{users}++; if (defined($map_ap->{$bssid})) { $self->{essid}->{ $map_ap->{$bssid}->{essid} } = { users => 0, essid => $map_ap->{$bssid}->{essid} } if (!defined($self->{essid}->{ $map_ap->{$bssid}->{essid} })); $self->{essid}->{ $map_ap->{$bssid}->{essid} }->{users}++; } $self->{global}->{total}++; $self->{global}->{'total_' . $result->{nUserAuthenticationMethod}}++; $total_timeticks += $result->{nUserUpTime}; } if ($self->{global}->{total} > 0) { $self->{global}->{avg_connection_time} = $total_timeticks / $self->{global}->{total} * 0.01; } } 1; __END__ =head1 MODE Check total users connected (Deprecated). =over 8 =item B<--warning-*> Threshold warning. Can be: 'total', 'total-none', 'total-other', 'total-web', 'total-dot1x', 'total-vpn', 'total-mac', 'avg-connection-time' (seconds), 'total-ap', 'total-essid'. =item B<--critical-*> Threshold critical. Can be: 'total', 'total-none', 'total-other', 'total-web', 'total-dot1x', 'total-vpn', 'total-mac', 'avg-connection-time' (seconds), 'total-ap', 'total-essid'. =item B<--filter-ip-address> Filter by ip address (regexp can be used). =item B<--filter-essid> Filter by ESSID (regexp can be used). =item B<--filter-bssid> Filter by BSSID (regexp can be used). =back =cut centreon-plugins-20220113/centreon/common/aruba/snmp/mode/components/000077500000000000000000000000001417000230700255215ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/aruba/snmp/mode/components/fan.pm000066400000000000000000000050571417000230700266320ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::aruba::snmp::mode::components::fan; use strict; use warnings; my %map_fan_status = ( 1 => 'active', 2 => 'inactive', ); my $mapping = { sysExtFanStatus => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.17.1.2', map => \%map_fan_status }, }; my $oid_wlsxSysExtFanEntry = '.1.3.6.1.4.1.14823.2.2.1.2.1.17.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_wlsxSysExtFanEntry }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking fans"); $self->{components}->{fan} = {name => 'fans', total => 0, skip => 0}; return if ($self->check_filter(section => 'fan')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_wlsxSysExtFanEntry}})) { next if ($oid !~ /^$mapping->{sysExtFanStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance( mapping => $mapping, results => $self->{results}->{$oid_wlsxSysExtFanEntry}, instance => $instance ); next if ($self->check_filter(section => 'fan', instance => $instance)); $self->{components}->{fan}->{total}++; $self->{output}->output_add( long_msg => sprintf("Fan '%s' status is %s [instance: %s].", $instance, $result->{sysExtFanStatus}, $instance )); my $exit = $self->get_severity(section => 'fan', value => $result->{sysExtFanStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Fan '%s' status is %s", $instance, $result->{sysExtFanStatus} )); } } } 1;centreon-plugins-20220113/centreon/common/aruba/snmp/mode/components/module.pm000066400000000000000000000061451417000230700273520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::aruba::snmp::mode::components::module; use strict; use warnings; my %map_card_type = ( 1 => 'lc1', 2 => 'lc2', 3 => 'sc1', 4 => 'sc2', 5 => 'sw2400', 6 => 'sw800', 7 => 'sw200', 8 => 'm3mk1', 9 => 'sw3200', 10 => 'sw3400', 11 => 'sw3600', 12 => 'sw650', 13 => 'sw651', 14 => 'reserved1', 15 => 'reserved2', 16 => 'sw620', 17 => 'sw3500' ); my %map_module_status = ( 1 => 'active', 2 => 'inactive', ); my $mapping = { sysExtCardType => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.16.1.2', map => \%map_card_type }, sysExtCardStatus => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.16.1.12', map => \%map_module_status }, }; my $oid_wlsxSysExtCardEntry = '.1.3.6.1.4.1.14823.2.2.1.2.1.16.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_wlsxSysExtCardEntry }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking modules"); $self->{components}->{module} = {name => 'modules', total => 0, skip => 0}; return if ($self->check_filter(section => 'module')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_wlsxSysExtCardEntry}})) { next if ($oid !~ /^$mapping->{sysExtCardStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance( mapping => $mapping, results => $self->{results}->{$oid_wlsxSysExtCardEntry}, 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' status is %s [instance: %s].", $result->{sysExtCardType}, $instance, $result->{sysExtCardStatus}, $instance )); my $exit = $self->get_severity(section => 'module', value => $result->{sysExtCardStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Module '%s/%s' status is %s", $result->{sysExtCardType}, $instance, $result->{sysExtCardStatus}) ); } } } 1;centreon-plugins-20220113/centreon/common/aruba/snmp/mode/components/psu.pm000066400000000000000000000052131417000230700266670ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::aruba::snmp::mode::components::psu; use strict; use warnings; my %map_psu_status = ( 1 => 'active', 2 => 'inactive', ); my $mapping = { sysExtPowerSupplyStatus => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.18.1.2', map => \%map_psu_status }, }; my $oid_wlsxSysExtPowerSupplyEntry = '.1.3.6.1.4.1.14823.2.2.1.2.1.18.1.2'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_wlsxSysExtPowerSupplyEntry }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking power supplies"); $self->{components}->{psu} = {name => 'power supplies', total => 0, skip => 0}; return if ($self->check_filter(section => 'psu')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_wlsxSysExtPowerSupplyEntry}})) { next if ($oid !~ /^$mapping->{sysExtPowerSupplyStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance( mapping => $mapping, results => $self->{results}->{$oid_wlsxSysExtPowerSupplyEntry}, 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' status is %s [instance: %s].", $instance, $result->{sysExtPowerSupplyStatus}, $instance )); my $exit = $self->get_severity(section => 'psu', value => $result->{sysExtPowerSupplyStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Power supply '%s' status is %s", $instance, $result->{sysExtPowerSupplyStatus} )); } } } 1;centreon-plugins-20220113/centreon/common/aruba/snmp/mode/controllerstatus.pm000066400000000000000000000174771417000230700273410ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::aruba::snmp::mode::controllerstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("Status is '%s', Role is '%s' [Ip: %s][Version: %s][Location: %s]", $self->{result_values}->{status}, $self->{result_values}->{role}, $self->{result_values}->{ip}, $self->{result_values}->{version}, $self->{result_values}->{location}); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_sysExtSwitchName'}; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_sysExtSwitchStatus'}; $self->{result_values}->{role} = $options{new_datas}->{$self->{instance} . '_sysExtSwitchRole'}; $self->{result_values}->{ip} = $options{new_datas}->{$self->{instance} . '_sysExtSwitchIPAddress'}; $self->{result_values}->{version} = $options{new_datas}->{$self->{instance} . '_sysExtSwitchSWVersion'}; $self->{result_values}->{location} = $options{new_datas}->{$self->{instance} . '_sysExtSwitchLocation'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_init => 'skip_global' }, { name => 'controllers', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All controllers status are ok' }, ]; $self->{maps_counters}->{global} = [ { label => 'connected-current', nlabel => 'controllers.connected.current.count', set => { key_values => [ { name => 'current' } ], output_template => 'Total controllers: %d', perfdatas => [ { value => 'current', template => '%d', min => 0 }, ], } }, ]; $self->{maps_counters}->{controllers} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'sysExtSwitchIPAddress' }, { name => 'sysExtSwitchName' }, { name => 'sysExtSwitchLocation' }, { name => 'sysExtSwitchSWVersion' }, { name => 'sysExtSwitchRole' }, { name => 'sysExtSwitchStatus' } ], 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 => \&catalog_status_threshold, } }, ]; } sub skip_global { my ($self, %options) = @_; scalar(keys %{$self->{controllers}}) > 1 ? return(0) : return(1); } sub prefix_output { my ($self, %options) = @_; return "Controller '" . $options{instance_value}->{sysExtSwitchName} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "filter-ip:s" => { name => 'filter_ip' }, "filter-location:s" => { name => 'filter_location' }, "warning-status:s" => { name => 'warning_status' }, "critical-status:s" => { name => 'critical_status', default => '%{status} !~ /active/i' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } my %map_status = ( 1 => 'active', 2 => 'inactive' ); my %map_role = ( 1 => 'master', 2 => 'local', 3 => 'backupmaster' ); my $oid_wlsxSysExtSwitchListTable = '.1.3.6.1.4.1.14823.2.2.1.2.1.19.1'; my $mapping = { sysExtSwitchRole => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.19.1.2', map => \%map_role }, sysExtSwitchLocation=> { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.19.1.3' }, sysExtSwitchSWVersion => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.19.1.4' }, sysExtSwitchStatus => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.19.1.5', map => \%map_status }, sysExtSwitchName => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.19.1.6' }, }; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_table( oid => $oid_wlsxSysExtSwitchListTable, start => $mapping->{sysExtSwitchRole}->{oid}, end => $mapping->{sysExtSwitchName}->{oid}, nothing_quit => 1 ); $self->{global}->{current} = 0; $self->{controllers} = {}; foreach my $oid (keys %{$snmp_result}) { next if ($oid !~ /^$mapping->{sysExtSwitchRole}->{oid}\.(.*)/); my $instance = $1; my $result = $options{snmp}->map_instance( mapping => $mapping, results => $snmp_result, instance => $instance ); $result->{sysExtSwitchIPAddress} = $instance; if (defined($self->{option_results}->{filter_ip}) && $self->{option_results}->{filter_ip} ne '' && $result->{sysExtSwitchIPAddress} !~ /$self->{option_results}->{filter_ip}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{sysExtSwitchIPAddress} . "': no matching filter ip.", debug => 1); next; } if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $result->{sysExtSwitchName} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{sysExtSwitchName} . "': no matching filter name.", debug => 1); next; } if (defined($self->{option_results}->{filter_location}) && $self->{option_results}->{filter_location} ne '' && $result->{sysExtSwitchLocation} !~ /$self->{option_results}->{filter_location}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{sysExtSwitchLocation} . "': no matching filter location.", debug => 1); next; } $self->{controllers}->{$result->{sysExtSwitchName}} = { %{$result} }; $self->{global}->{current}++; } if (scalar(keys %{$self->{controllers}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No controller found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check controller status (WLSX-SYSTEMEXT-MIB). (Works only on master controller). =over 8 =item B<--warning-*> Threshold warning. Can be: 'connected-current' (global), 'status' (per controller). 'status' can use special variables like: %{name}, %{status}, %{ip}, %{role}, %{location} (Default: '') =item B<--critical-*> Threshold critical. Can be: 'connected-current' (global), 'status' (per controller). 'status' can use special variables like: %{name}, %{status}, %{ip}, %{role}, %{location} (Default: '%{status} !~ /active/i') =item B<--filter-*> Filter by 'ip', 'name', 'location' (regexp can be used). =back =cut centreon-plugins-20220113/centreon/common/aruba/snmp/mode/cpu.pm000066400000000000000000000066161417000230700244720ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::aruba::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_output', message_multiple => 'All CPUs utilization are ok' }, ]; $self->{maps_counters}->{cpu} = [ { label => 'utilization', nlabel => 'cpu.utilization.percentage', set => { key_values => [ { name => 'sysExtProcessorLoad' }, { name => 'sysExtProcessorDescr' } ], output_template => 'Utilization %.2f%%', perfdatas => [ { label => 'utilization', value => 'sysExtProcessorLoad', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'sysExtProcessorDescr' }, ], } }, ]; } sub prefix_output { my ($self, %options) = @_; return "CPU '" . $options{instance_value}->{sysExtProcessorDescr} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } my $oid_wlsxSysExtProcessorEntry = '.1.3.6.1.4.1.14823.2.2.1.2.1.13.1'; my $mapping = { sysExtProcessorDescr => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.13.1.2' }, sysExtProcessorLoad => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.13.1.3' }, }; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_table( oid => $oid_wlsxSysExtProcessorEntry, start => $mapping->{sysExtProcessorDescr}->{oid}, end => $mapping->{sysExtProcessorLoad}->{oid}, nothing_quit => 1 ); $self->{cpu} = {}; foreach my $oid (keys %{$snmp_result}) { next if ($oid !~ /^$mapping->{sysExtProcessorDescr}->{oid}\.(.*)/); my $instance = $1; my $result = $options{snmp}->map_instance( mapping => $mapping, results => $snmp_result, instance => $instance ); $self->{cpu}->{$instance} = { %{$result} }; } if (scalar(keys %{$self->{cpu}}) <= 0) { $self->{output}->add_option_msg(short_msg => "Cannot find CPU informations"); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check CPU usage (over the last minute) (WLSX-SYSTEMEXT-MIB). =over 8 =item B<--warning-utilization> Threshold warning in percent. =item B<--critical-utilization> Threshold critical in percent. =back =cut centreon-plugins-20220113/centreon/common/aruba/snmp/mode/discovery.pm000066400000000000000000000075211417000230700257060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::aruba::snmp::mode::discovery; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "prettify" => { name => 'prettify' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } my %map_status = ( 1 => 'up', 2 => 'down' ); my $oid_wlsxWlanAPTable = '.1.3.6.1.4.1.14823.2.2.1.5.2.1.4.1'; my $mapping = { wlanAPIpAddress => { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.4.1.2' }, wlanAPName => { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.4.1.3' }, wlanAPGroupName=> { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.4.1.4' }, wlanAPUpTime => { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.4.1.12' }, wlanAPLocation => { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.4.1.14' }, wlanAPStatus => { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.4.1.20', map => \%map_status }, wlanAPNumBootstraps => { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.4.1.21' }, wlanAPNumReboots => { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.4.1.22' }, }; sub run { my ($self, %options) = @_; my @disco_data; my $disco_stats; $disco_stats->{start_time} = time(); my $snmp_result = $options{snmp}->get_table( oid => $oid_wlsxWlanAPTable, start => $mapping->{wlanAPIpAddress}->{oid}, end => $mapping->{wlanAPNumReboots}->{oid}, nothing_quit => 1 ); foreach my $oid (keys %{$snmp_result}) { next if ($oid !~ /^$mapping->{wlanAPIpAddress}->{oid}\.(.*)/); my $instance = $1; my $result = $options{snmp}->map_instance( mapping => $mapping, results => $snmp_result, instance => $instance ); my %ap; $ap{name} = $result->{wlanAPName}; $ap{ip} = $result->{wlanAPIpAddress}; $ap{group} = $result->{wlanAPGroupName}; $ap{location} = $result->{wlanAPLocation}; $ap{status} = $result->{wlanAPStatus}; $ap{type} = "ap"; push @disco_data, \%ap; } $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; $disco_stats->{discovered_items} = @disco_data; $disco_stats->{results} = \@disco_data; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE Resources discovery. =over 8 =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/centreon/common/aruba/snmp/mode/hardware.pm000066400000000000000000000050701417000230700254710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::aruba::snmp::mode::hardware; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { fan => [ ['active', 'OK'], ['inactive', 'CRITICAL'], ], psu => [ ['active', 'OK'], ['inactive', 'CRITICAL'], ], module => [ ['active', 'OK'], ['inactive', 'CRITICAL'], ], }; $self->{components_path} = 'centreon::common::aruba::snmp::mode::components'; $self->{components_module} = ['fan', 'psu', 'module']; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_performance => 1, no_absent => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } 1; __END__ =head1 MODE Check hardware (modules, fans, power supplies) (WLSX-SYSTEMEXT-MIB). =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'fan', 'psu', 'module'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=fan --filter=psu) Can also exclude specific instance: --filter=fan,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='fan,OK,inactive' =back =cut centreon-plugins-20220113/centreon/common/aruba/snmp/mode/license.pm000066400000000000000000000140531417000230700253170ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::aruba::snmp::mode::license; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); use Time::Local; sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("Status is '%s', Expires in '%s' [%s]", $self->{result_values}->{flag}, $self->{result_values}->{expires_human}, $self->{result_values}->{expires_date}); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{key} = $options{new_datas}->{$self->{instance} . '_sysExtLicenseKey'}; $self->{result_values}->{flag} = $options{new_datas}->{$self->{instance} . '_sysExtLicenseFlags'}; $self->{result_values}->{service} = $options{new_datas}->{$self->{instance} . '_sysExtLicenseService'}; $self->{result_values}->{expires} = $options{new_datas}->{$self->{instance} . '_sysExtLicenseExpires'}; $self->{result_values}->{expires_date} = $options{new_datas}->{$self->{instance} . '_sysExtLicenseExpires'}; $self->{result_values}->{expires_human} = 'Never'; if ($self->{result_values}->{expires} !~ /Never/) { my ($year, $mon, $mday, $hour, $min, $sec) = split(/[\s\-:]+/, $self->{result_values}->{expires}); $self->{result_values}->{expires} = timelocal($sec, $min, $hour, $mday, $mon - 1, $year) - time(); $self->{result_values}->{expires_human} = centreon::plugins::misc::change_seconds(value => $self->{result_values}->{expires}); $self->{result_values}->{expires_human} = $self->{result_values}->{expires} = 0 if ($self->{result_values}->{expires} < 0); } return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'license', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All licenses status are ok' }, ]; $self->{maps_counters}->{license} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'sysExtLicenseKey' }, { name => 'sysExtLicenseFlags' }, { name => 'sysExtLicenseService' }, { name => 'sysExtLicenseExpires' } ], 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 => \&catalog_status_threshold, } }, ]; } sub prefix_output { my ($self, %options) = @_; return "License '" . $options{instance_value}->{sysExtLicenseService} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { "warning-status:s" => { name => 'warning_status' }, "critical-status:s" => { name => 'critical_status', default => '%{flag} !~ /enabled/i || (%{expires} ne "Never" && %{expires} < 86400)' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } my %map_flags = ( 'E' => 'enabled', 'A' => 'auto-generated', 'R' => 'reboot-required' ); my $oid_wlsxSysExtSwitchLicenseTable = '.1.3.6.1.4.1.14823.2.2.1.2.1.20.1'; my $mapping = { sysExtLicenseKey => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.20.1.2' }, sysExtLicenseInstalled => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.20.1.3' }, sysExtLicenseExpires => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.20.1.4' }, sysExtLicenseFlags => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.20.1.5', map => \%map_flags }, sysExtLicenseService => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.20.1.6' }, }; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_table( oid => $oid_wlsxSysExtSwitchLicenseTable, start => $mapping->{sysExtLicenseKey}->{oid}, end => $mapping->{sysExtLicenseService}->{oid}, nothing_quit => 1 ); foreach my $oid (keys %{$snmp_result}) { $snmp_result->{$oid} = centreon::plugins::misc::trim($snmp_result->{$oid}); } $self->{license} = {}; foreach my $oid (keys %{$snmp_result}) { next if ($oid !~ /^$mapping->{sysExtLicenseKey}->{oid}\.(.*)/); my $instance = $1; my $result = $options{snmp}->map_instance( mapping => $mapping, results => $snmp_result, instance => $instance ); $self->{license}->{$result->{sysExtLicenseService}} = { %{$result} }; } if (scalar(keys %{$self->{license}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No license found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check license (WLSX-SYSTEMEXT-MIB). =over 8 =item B<--warning-status> Threshold warning. Can use special variables like:%{key}, %{service}, %{flag}, %{expires} (Default: '') =item B<--critical-status> Threshold critical. Can use special variables like: %{key}, %{service}, %{flag}, %{expires} (Default: '%{flag} !~ /enabled/i || (%{expires} ne "Never" && %{expires} < 86400)') =back =cut centreon-plugins-20220113/centreon/common/aruba/snmp/mode/memory.pm000066400000000000000000000132571417000230700252120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::aruba::snmp::mode::memory; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_usage_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( instances => $self->{instance}, label => 'usage', nlabel => 'memory.usage.bytes', unit => 'B', value => $self->{result_values}->{used}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), min => 0, max => $self->{result_values}->{total}); } sub custom_usage_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check( value => $self->{result_values}->{prct_used}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, 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}->{total} = $options{new_datas}->{$self->{instance} . '_sysExtMemorySize'} * 1024; $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_sysExtMemoryUsed'} * 1024; $self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used}; $self->{result_values}->{prct_free} = $self->{result_values}->{free} * 100 / $self->{result_values}->{total}; $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'memory', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All memory pools are ok' } ]; $self->{maps_counters}->{memory} = [ { label => 'usage', set => { key_values => [ { name => 'sysExtMemoryUsed' }, { name => 'sysExtMemorySize' } ], 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 prefix_output { my ($self, %options) = @_; return "Memory '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } my $oid_wlsxSysExtMemoryEntry = '.1.3.6.1.4.1.14823.2.2.1.2.1.15.1'; my $mapping = { sysExtMemorySize => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.15.1.2' }, # in KB sysExtMemoryUsed => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.15.1.3' }, # in KB }; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_table( oid => $oid_wlsxSysExtMemoryEntry, start => $mapping->{sysExtMemorySize}->{oid}, end => $mapping->{sysExtMemoryUsed}->{oid}, nothing_quit => 1 ); $self->{memory} = {}; foreach my $oid (keys %{$snmp_result}) { next if ($oid !~ /^$mapping->{sysExtMemorySize}->{oid}\.(.*)/); my $instance = $1; my $result = $options{snmp}->map_instance( mapping => $mapping, results => $snmp_result, instance => $instance ); $self->{memory}->{$instance} = { %{$result}, display => $instance }; } if (scalar(keys %{$self->{memory}}) <= 0) { $self->{output}->add_option_msg(short_msg => "Cannot find memory informations"); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check memory usage (WLSX-SYSTEMEXT-MIB). =over 8 =item B<--warning-usage> Threshold warning in percent. =item B<--critical-usage> Threshold critical in percent. =back =cut centreon-plugins-20220113/centreon/common/aruba/snmp/mode/storage.pm000066400000000000000000000160051417000230700253400ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::aruba::snmp::mode::storage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_usage_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( instances => $self->{instance}, label => 'usage', nlabel => 'storage.usage.bytes', unit => 'B', value => $self->{result_values}->{used}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), min => 0, max => $self->{result_values}->{total}); } sub custom_usage_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check( value => $self->{result_values}->{prct_used}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, 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}->{total} = $options{new_datas}->{$self->{instance} . '_sysExtStorageSize'} * 1024 * 1024; $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_sysExtStorageUsed'} * 1024 * 1024; $self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used}; $self->{result_values}->{prct_free} = $self->{result_values}->{free} * 100 / $self->{result_values}->{total}; $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'storage', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All storages are ok' }, ]; $self->{maps_counters}->{storage} = [ { label => 'usage', set => { key_values => [ { name => 'sysExtStorageUsed' }, { name => 'sysExtStorageSize' }, { name => 'sysExtStorageName' } ], 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 prefix_output { my ($self, %options) = @_; return "Storage '" . $options{instance_value}->{sysExtStorageName} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'filter-type:s' => { name => 'filter_type' } }); return $self; } my $oid_wlsxSysExtStorageEntry = '.1.3.6.1.4.1.14823.2.2.1.2.1.14.1'; my %map_storage_type = ( 1 => 'ram', 2 => 'flashMemory' ); my $mapping = { sysExtStorageType => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.14.1.2', map => \%map_storage_type }, sysExtStorageSize => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.14.1.3' }, # MB sysExtStorageUsed => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.14.1.4' }, # MB sysExtStorageName => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.14.1.5' } }; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_table( oid => $oid_wlsxSysExtStorageEntry, start => $mapping->{sysExtStorageType}->{oid}, end => $mapping->{sysExtStorageName}->{oid}, nothing_quit => 1 ); $self->{storage} = {}; foreach my $oid (keys %{$snmp_result}) { next if ($oid !~ /^$mapping->{sysExtStorageType}->{oid}\.(.*)/); my $instance = $1; my $result = $options{snmp}->map_instance( mapping => $mapping, results => $snmp_result, instance => $instance ); if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $result->{sysExtStorageName} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => sprintf("Skipping storage '%s'.", $result->{sysExtStorageName}), debug => 1); next; } if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' && $result->{sysExtStorageType} !~ /$self->{option_results}->{filter_type}/i) { $self->{output}->output_add(long_msg => sprintf("Skipping storage '%s'.", $result->{sysExtStorageType}), debug => 1); next; } $self->{storage}->{$result->{sysExtStorageName}} = { %{$result} }; } if (scalar(keys %{$self->{storage}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No storage found"); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check storage device usage (WLSX-SYSTEMEXT-MIB). =over 8 =item B<--warning-usage> Threshold warning in percent. =item B<--critical-usage> Threshold critical in percent. =item B<--filter-name> Filter storage device name (regexp can be used). =item B<--filter-type> Filter storage device type (regexp can be used). Can use: 'ram', 'flashMemory' =back =cut centreon-plugins-20220113/centreon/common/avaya/000077500000000000000000000000001417000230700214425ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/avaya/snmp/000077500000000000000000000000001417000230700224175ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/avaya/snmp/mode/000077500000000000000000000000001417000230700233435ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/avaya/snmp/mode/cpu.pm000066400000000000000000000065641417000230700245030ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::avaya::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 CPUs are ok' }, ]; $self->{maps_counters}->{cpu} = [ { label => 'usage', nlabel => 'cpu.utilization.percentage', set => { key_values => [ { name => 'cpu' }, { name => 'display' } ], output_template => 'usage : %s %%', perfdatas => [ { label => 'cpu_usage', value => 'cpu', template => '%s', unit => '%', min => 0, max => 100, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } 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, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my $map_cpu_monitoring = { 1 => 'disabled', 2 => 'enabled' }; my $mapping = { genCpuUtilizationEnableMonitoring => { oid => '.1.3.6.1.4.1.6889.2.1.11.1.1.1.1.2', map => $map_cpu_monitoring }, genCpuAverageUtilization => { oid => '.1.3.6.1.4.1.6889.2.1.11.1.1.1.1.5' }, }; sub manage_selection { my ($self, %options) = @_; my $oid_genCpuUtilizationEntry = '.1.3.6.1.4.1.6889.2.1.11.1.1.1.1'; my $results = $options{snmp}->get_table(oid => $oid_genCpuUtilizationEntry, nothing_quit => 1); $self->{cpu} = {}; foreach my $oid (keys %{$results}) { next if ($oid !~ /^$mapping->{genCpuAverageUtilization}->{oid}\.(.*)/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $results, instance => $instance); if ($result->{genCpuUtilizationEnableMonitoring} eq 'disabled') { next; } $self->{cpu}->{$instance} = { display => $instance, cpu => $result->{genCpuAverageUtilization}, }; } if (scalar(keys %{$self->{cpu}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No entry found (or cpu monitoring is disabled)."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check CPU usage. =over 8 =item B<--warning-usage> Threshold warning. =item B<--critical-usage> Threshold critical. =back =cut centreon-plugins-20220113/centreon/common/avaya/snmp/mode/memory.pm000066400000000000000000000137121417000230700252150ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::avaya::snmp::mode::memory; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_usage_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => 'used', unit => 'B', nlabel => $self->{nlabel}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, value => $self->{result_values}->{used}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), min => 0, max => $self->{result_values}->{total} ); } sub custom_usage_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check(value => $self->{result_values}->{prct_used}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, 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("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_free} = $self->{result_values}->{free} * 100 / $self->{result_values}->{total}; $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; 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 memory usages are ok' } ]; $self->{maps_counters}->{memory} = [ { label => 'usage', nlabel => 'memory.usage.bytes', set => { key_values => [ { name => 'display' }, { name => 'total' }, { name => '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'), closure_custom_threshold_check => $self->can('custom_usage_threshold'), } }, ]; } sub prefix_memory_output { my ($self, %options) = @_; if ($self->{multiple} == 1) { return "Memory '" . $options{instance_value}->{display} . "' "; } return ''; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my $mapping = { genMemUtilizationPhyRam => { oid => '.1.3.6.1.4.1.6889.2.1.11.1.2.6.1.2' }, # in Bytes genMemUtilizationPercentUsed => { oid => '.1.3.6.1.4.1.6889.2.1.11.1.2.6.1.3' }, }; sub manage_selection { my ($self, %options) = @_; my $oid_genMemUtilizationEntry = '.1.3.6.1.4.1.6889.2.1.11.1.2.6.1'; my $results = $options{snmp}->get_table(oid => $oid_genMemUtilizationEntry, nothing_quit => 1); $self->{memory} = {}; foreach my $oid (keys %{$results}) { next if ($oid !~ /^$mapping->{genMemUtilizationPercentUsed}->{oid}\.(.*)/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $results, instance => $instance); my $total = $result->{genMemUtilizationPhyRam}; my $used = sprintf('%d', $total * $result->{genMemUtilizationPercentUsed} / 100); $self->{memory}->{$instance} = { display => $instance, used => $used, total => $total }; } if (scalar(keys %{$self->{memory}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No entry found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check memory usages. =over 8 =item B<--warning-usage> Threshold warning (in percent). =item B<--critical-usage> Threshold critical (in percent). =back =cut centreon-plugins-20220113/centreon/common/bluearc/000077500000000000000000000000001417000230700217565ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/bluearc/snmp/000077500000000000000000000000001417000230700227335ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/bluearc/snmp/mode/000077500000000000000000000000001417000230700236575ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/bluearc/snmp/mode/clusterstatus.pm000066400000000000000000000122311417000230700271410ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::bluearc::snmp::mode::clusterstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'node', type => 1, cb_prefix_output => 'prefix_node_output', message_multiple => 'All nodes are ok' } ]; $self->{maps_counters}->{node} = [ { 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 => \&catalog_status_threshold, } }, ]; } 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} . '_state'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub prefix_node_output { my ($self, %options) = @_; return "Node '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "unknown-status:s" => { name => 'unknown_status', default => '%{state} =~ /unknown/' }, "warning-status:s" => { name => 'warning_status', default => '' }, "critical-status:s" => { name => 'critical_status', default => '%{state} =~ /offline/i' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status', 'unknown_status']); } my %map_vnode_status = ( 1 => 'unknown', 2 => 'onLine', 3 => 'offLine', ); my $mapping = { clusterVNodeName => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.2.5.11.1.2' }, clusterVNodeStatus => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.2.5.11.1.4', map => \%map_vnode_status }, }; my $oid_clusterVNodeEntry = '.1.3.6.1.4.1.11096.6.1.1.1.2.5.11.1'; sub manage_selection { my ($self, %options) = @_; $self->{node} = {}; $self->{results} = $options{snmp}->get_table(oid => $oid_clusterVNodeEntry, nothing_quit => 1); foreach my $oid (keys %{$self->{results}}) { next if ($oid !~ /^$mapping->{clusterVNodeStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $self->{results}, instance => $instance); if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $result->{clusterVNodeName} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{clusterVNodeName} . "': no matching filter.", debug => 1); next; } $self->{node}->{$instance} = { display => $result->{clusterVNodeName}, state => $result->{clusterVNodeStatus}}; } if (scalar(keys %{$self->{node}}) <= 0) { $self->{output}->output_add(severity => 'OK', short_msg => 'No node(s) found'); } } 1; __END__ =head1 MODE Check node status. =over 8 =item B<--filter-name> Filter node name (can be a regexp). =item B<--unknown-status> Set warning threshold for status (Default: '%{state} =~ /unknown/'). Can used special variables like: %{state}, %{display} =item B<--warning-status> Set warning threshold for status (Default: -). Can used special variables like: %{state}, %{display} =item B<--critical-status> Set critical threshold for status (Default: '%{state} =~ /offline/i'). Can used special variables like: %{state}, %{display} =back =cut centreon-plugins-20220113/centreon/common/bluearc/snmp/mode/components/000077500000000000000000000000001417000230700260445ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/bluearc/snmp/mode/components/battery.pm000066400000000000000000000054161417000230700300620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::bluearc::snmp::mode::components::battery; use strict; use warnings; my %map_status = ( 1 => 'ok', 2 => 'fault', 3 => 'notFitted', 4 => 'initializing', 5 => 'normalCharging', 6 => 'discharged', 7 => 'cellTesting', 8 => 'notResponding', 9 => 'low', 10 => 'veryLow', 11 => 'ignore' ); my $mapping = { batteryStatus => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.2.1.17.1.3', map => \%map_status }, }; my $oid_batteryEntry = '.1.3.6.1.4.1.11096.6.1.1.1.2.1.17.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_batteryEntry }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking batteries"); $self->{components}->{battery} = {name => 'battery', total => 0, skip => 0}; return if ($self->check_filter(section => 'battery')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_batteryEntry}})) { next if ($oid !~ /^$mapping->{batteryStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_batteryEntry}, instance => $instance); next if ($self->check_filter(section => 'battery', instance => $instance)); $self->{components}->{battery}->{total}++; $self->{output}->output_add(long_msg => sprintf("Battery '%s' status is '%s' [instance: %s].", $instance, $result->{batteryStatus}, $instance )); my $exit = $self->get_severity(section => 'battery', value => $result->{batteryStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Battery '%s' status is '%s'", $instance, $result->{batteryStatus})); } } } 1; centreon-plugins-20220113/centreon/common/bluearc/snmp/mode/components/fan.pm000066400000000000000000000070471417000230700271560ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::bluearc::snmp::mode::components::fan; use strict; use warnings; my %map_speed_status = ( 1 => 'ok', 2 => 'warning', 3 => 'severe', 4 => 'unknown', ); my $mapping = { fanSpeedStatus => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.2.1.11.1.4', map => \%map_speed_status }, fanSpeed => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.2.1.11.1.5' }, }; my $oid_fanEntry = '.1.3.6.1.4.1.11096.6.1.1.1.2.1.11.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_fanEntry }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking fans"); $self->{components}->{fan} = {name => 'fans', total => 0, skip => 0}; return if ($self->check_filter(section => 'fan')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_fanEntry}})) { next if ($oid !~ /^$mapping->{fanSpeedStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_fanEntry}, instance => $instance); next if ($self->check_filter(section => 'fan', instance => $instance)); $self->{components}->{fan}->{total}++; $self->{output}->output_add(long_msg => sprintf("fan '%s' status is '%s' [instance = %s] [value = %s]", $instance, $result->{fanSpeedStatus}, $instance, $result->{fanSpeedStatus})); my $exit = $self->get_severity(section => 'fan.speed', value => $result->{fanSpeedStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Fan '%s' status is '%s'", $instance, $result->{fanSpeedStatus})); next; } if (defined($result->{fanSpeedStatus}) && $result->{fanSpeedStatus} =~ /[0-9]/) { my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'fan', instance => $instance, value => $result->{temperatureSensorCReading}); if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit2, short_msg => sprintf("Fan '%s' is %s rpm", $instance, $result->{fanSpeedStatus})); } $self->{output}->perfdata_add( label => 'fan', unit => 'rpm', nlabel => 'hardware.fan.speed.rpm', instances => $instance, value => $result->{fanSpeedStatus}, warning => $warn, critical => $crit, min => 0, ); } } } 1; centreon-plugins-20220113/centreon/common/bluearc/snmp/mode/components/psu.pm000066400000000000000000000051051417000230700272120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::bluearc::snmp::mode::components::psu; use strict; use warnings; my %map_status = ( 1 => 'ok', 2 => 'failed', 3 => 'notFitted', 4 => 'unknown', ); my $mapping = { psuStatus => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.2.1.13.1.3', map => \%map_status }, }; my $oid_psuEntry = '.1.3.6.1.4.1.11096.6.1.1.1.2.1.13.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_psuEntry }; } 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')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_psuEntry}})) { next if ($oid !~ /^$mapping->{psuStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_psuEntry}, 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' status is '%s' [instance: %s].", $instance, $result->{psuStatus}, $instance )); my $exit = $self->get_severity(section => 'psu', value => $result->{psuStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Power supply '%s' status is '%s'", $instance, $result->{psuStatus})); } } } 1;centreon-plugins-20220113/centreon/common/bluearc/snmp/mode/components/sysdrive.pm000066400000000000000000000055631417000230700302630ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::bluearc::snmp::mode::components::sysdrive; use strict; use warnings; my %map_status = ( 1 => 'online', 2 => 'corrupt', 3 => 'failed', 4 => 'notPresent', 5 => 'disconnected', 6 => 'offline', 7 => 'initializing', 8 => 'formatting', 9 => 'unknown', ); my $mapping = { sysDriveWWN => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.3.4.2.1.2' }, sysDriveStatus => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.3.4.2.1.4', map => \%map_status }, }; my $oid_sysDriveEntry = '.1.3.6.1.4.1.11096.6.1.1.1.3.4.2.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_sysDriveEntry }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking system drives"); $self->{components}->{sysdrive} = {name => 'sysdrives', total => 0, skip => 0}; return if ($self->check_filter(section => 'sysdrive')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_sysDriveEntry}})) { next if ($oid !~ /^$mapping->{sysDriveStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_sysDriveEntry}, instance => $instance); next if ($self->check_filter(section => 'sysdrive', instance => $result->{sysDriveWWN})); $self->{components}->{sysdrive}->{total}++; $self->{output}->output_add(long_msg => sprintf("system drive '%s' status is '%s' [instance: %s].", $result->{sysDriveWWN}, $result->{sysDriveStatus}, $result->{sysDriveWWN} )); my $exit = $self->get_severity(section => 'sysdrive', value => $result->{sysDriveStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("System drive '%s' status is '%s'", $result->{sysDriveWWN}, $result->{sysDriveStatus})); } } } 1;centreon-plugins-20220113/centreon/common/bluearc/snmp/mode/components/temperature.pm000066400000000000000000000075151417000230700307470ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::bluearc::snmp::mode::components::temperature; use strict; use warnings; my %map_status = ( 1 => 'ok', 2 => 'tempWarning', 3 => 'tempSevere', 4 => 'tempSensorFailed', 5 => 'tempSensorWarning', 6 => 'unknown', ); my $mapping = { temperatureSensorStatus => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.2.1.9.1.3', map => \%map_status }, temperatureSensorCReading => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.2.1.9.1.4' }, }; my $oid_temperatureSensorEntry = '.1.3.6.1.4.1.11096.6.1.1.1.2.1.9.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_temperatureSensorEntry }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking temperatures"); $self->{components}->{temperature} = {name => 'temperatures', total => 0, skip => 0}; return if ($self->check_filter(section => 'temperature')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_temperatureSensorEntry}})) { next if ($oid !~ /^$mapping->{temperatureSensorStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_temperatureSensorEntry}, instance => $instance); next if ($self->check_filter(section => 'temperature', instance => $instance)); $self->{components}->{temperature}->{total}++; $self->{output}->output_add(long_msg => sprintf("temperature '%s' status is '%s' [instance = %s] [value = %s]", $instance, $result->{temperatureSensorStatus}, $instance, $result->{temperatureSensorCReading})); my $exit = $self->get_severity(section => 'temperature', value => $result->{temperatureSensorStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Temperature '%s' status is '%s'", $instance, $result->{temperatureSensorStatus})); next; } if (defined($result->{temperatureSensorCReading}) && $result->{temperatureSensorCReading} =~ /[0-9]/) { my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $instance, value => $result->{temperatureSensorCReading}); if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit2, short_msg => sprintf("Temperature '%s' is %s degree centigrade", $instance, $result->{temperatureSensorCReading})); } $self->{output}->perfdata_add( label => 'temp', unit => 'C', nlabel => 'hardware.temperature.celsius', instances => $instance, value => $result->{temperatureSensorCReading}, warning => $warn, critical => $crit, ); } } } 1; centreon-plugins-20220113/centreon/common/bluearc/snmp/mode/hardware.pm000066400000000000000000000076221417000230700260210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::bluearc::snmp::mode::hardware; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^(temperature|fan)$'; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { psu => [ ['ok', 'OK'], ['failed', 'CRITICAL'], ['notFitted', 'WARNING'], ['unknown', 'UNKNOWN'], ], 'fan.speed' => [ ['ok', 'OK'], ['warning', 'WARNING'], ['severe', 'CRITICAL'], ['unknown', 'UNKNOWN'], ], temperature => [ ['ok', 'OK'], ['tempWarning', 'WARNING'], ['tempSevere', 'CRITICAL'], ['tempSensorFailed', 'CRITICAL'], ['tempSensorWarning', 'CRITICAL'], ['unknown', 'UNKNOWN'], ], sysdrive => [ ['online', 'OK'], ['corrupt', 'WARNING'], ['failed', 'CRITICAL'], ['notPresent', 'OK'], ['disconnected', 'WARNING'], ['offline', 'OK'], ['initializing', 'OK'], ['formatting', 'OK'], ['unknown', 'UNKNOWN'], ], battery => [ ['ok', 'OK'], ['fault', 'CRITICAL'], ['notFitted', 'WARNING'], ['initializing', 'OK'], ['normalCharging', 'OK'], ['discharged', 'CRITICAL'], ['cellTesting', 'OK'], ['notResponding', 'CRITICAL'], ['low', 'WARNING'], ['veryLow', 'CRITICAL'], ['ignore', 'UNKNOWN'], ], }; $self->{components_path} = 'centreon::common::bluearc::snmp::mode::components'; $self->{components_module} = ['temperature', 'fan', 'psu', 'sysdrive', 'battery' ]; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $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; $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: 'temperature', 'fan', 'psu', 'sysdrive', 'battery'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=sysdrive) Can also exclude specific instance: --filter=sysdrive,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='sysdrive,OK,formatting' =item B<--warning> Set warning threshold (syntax: type,regexp,threshold) Example: --warning='temperature,.*,30' =item B<--critical> Set critical threshold (syntax: type,regexp,threshold) Example: --critical='temperature,.*,40' =back =cut centreon-plugins-20220113/centreon/common/bluearc/snmp/mode/volumeusage.pm000066400000000000000000000227071417000230700265610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::bluearc::snmp::mode::volumeusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); 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} . '_status'}; $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($self->{instance_mode}->{option_results}->{free})) { $label = 'free'; $value_perf = $self->{result_values}->{free}; } my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } $self->{output}->perfdata_add( label => $label, unit => 'B', instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, 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} ); } sub custom_usage_threshold { my ($self, %options) = @_; my ($exit, $threshold_value); $threshold_value = $self->{result_values}->{used}; $threshold_value = $self->{result_values}->{free} if (defined($self->{instance_mode}->{option_results}->{free})); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; $threshold_value = $self->{result_values}->{prct_free} if (defined($self->{instance_mode}->{option_results}->{free})); } $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel}, 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 => 'volume', type => 1, cb_prefix_output => 'prefix_volume_output', message_multiple => 'All volumes are ok' } ]; $self->{maps_counters}->{volume} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { 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 => \&catalog_status_threshold, } }, { 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; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "warning-status:s" => { name => 'warning_status', default => '%{status} =~ /needsChecking/i' }, "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); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub prefix_volume_output { my ($self, %options) = @_; return "Volume '" . $options{instance_value}->{display} . "' "; } my %map_volume_status = ( 1 => 'unformatted', 2 => 'mounted', 3 => 'formatted', 4 => 'needsChecking', ); my $mapping = { volumeLabel => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.3.5.2.1.3' }, volumeStatus => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.3.5.2.1.4', map => \%map_volume_status }, volumeCapacity => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.3.5.2.1.5' }, volumeFreeCapacity => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.3.5.2.1.6' }, }; my $oid_volumeEntry = '.1.3.6.1.4.1.11096.6.1.1.1.3.5.2.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->{volume} = {}; $self->{results} = $options{snmp}->get_table(oid => $oid_volumeEntry, nothing_quit => 1); foreach my $oid (keys %{$self->{results}}) { next if ($oid !~ /^$mapping->{volumeStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $self->{results}, instance => $instance); if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $result->{volumeLabel} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{volumeLabel} . "': no matching filter.", debug => 1); next; } $self->{volume}->{$instance} = { display => $result->{volumeLabel}, status => $result->{volumeStatus}, total => $result->{volumeCapacity}, used => $result->{volumeCapacity} - $result->{volumeFreeCapacity} }; } if (scalar(keys %{$self->{volume}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No volume found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check volume usages. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^status$' =item B<--filter-name> Filter volume name (can be a regexp). =item B<--warning-status> Set warning threshold for status (Default: '%{status} =~ /needsChecking/i'). Can used special variables like: %{status}, %{display} =item B<--critical-status> Set critical threshold for status (Default: -). Can used special variables like: %{status}, %{display} =item B<--warning-*> Threshold warning. Can be: 'usage'. =item B<--critical-*> Threshold critical. Can be: 'usage'. =item B<--units> Units of thresholds (Default: '%') ('%', 'B'). =item B<--free> Thresholds are on free space left. =back =cut centreon-plugins-20220113/centreon/common/broadcom/000077500000000000000000000000001417000230700221275ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/broadcom/fastpath/000077500000000000000000000000001417000230700237415ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/broadcom/fastpath/snmp/000077500000000000000000000000001417000230700247165ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/broadcom/fastpath/snmp/mode/000077500000000000000000000000001417000230700256425ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/broadcom/fastpath/snmp/mode/components/000077500000000000000000000000001417000230700300275ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/broadcom/fastpath/snmp/mode/components/fan.pm000066400000000000000000000077001417000230700311350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::broadcom::fastpath::snmp::mode::components::fan; use strict; use warnings; my %map_fan_status = ( 1 => 'notpresent', 2 => 'operational', 3 => 'failed', 4 => 'powering', 5 => 'nopower', 6 => 'notpowering', 7 => 'incompatible' ); my $mapping = { boxServicesFanItemState => { oid => '.1.3.6.1.4.1.4413.1.1.43.1.6.1.3', map => \%map_fan_status }, boxServicesFanSpeed => { oid => '.1.3.6.1.4.1.4413.1.1.43.1.6.1.4' } }; my $oid_boxServicesFansEntry = '.1.3.6.1.4.1.4413.1.1.43.1.6.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_boxServicesFansEntry, start => $mapping->{boxServicesFanItemState}->{oid}, end => $mapping->{boxServicesFanSpeed}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking fans"); $self->{components}->{fan} = {name => 'fans', total => 0, skip => 0}; return if ($self->check_filter(section => 'fan')); my ($exit, $warn, $crit, $checked); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_boxServicesFansEntry}})) { next if ($oid !~ /^$mapping->{boxServicesFanItemState}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_boxServicesFansEntry}, instance => $instance); next if ($self->check_filter(section => 'fan', instance => $instance)); if ($result->{boxServicesFanItemState} =~ /notpresent/i) { $self->absent_problem(section => 'fan', instance => $instance); next; } $self->{components}->{fan}->{total}++; $self->{output}->output_add( long_msg => sprintf( "fan '%s' status is '%s' [instance = %s, speed = %s]", $instance, $result->{boxServicesFanItemState}, $instance, defined($result->{boxServicesFanSpeed}) ? $result->{boxServicesFanSpeed} : 'unknown' ) ); $exit = $self->get_severity(label => 'default', section => 'fan', value => $result->{boxServicesFanItemState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Fan '%s' status is '%s'", $instance, $result->{boxServicesFanItemState}) ); } next if (!defined($result->{boxServicesFanSpeed}) || $result->{boxServicesFanSpeed} !~ /[0-9]+/); ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'fan', instance => $instance, value => $result->{boxServicesFanSpeed}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Fan '%s' is '%s' rpm", $instance, $result->{boxServicesFanSpeed}) ); } $self->{output}->perfdata_add( nlabel => 'hardware.fan.speed.rpm', unit => 'rpm', instances => $instance, value => $result->{boxServicesFanSpeed}, warning => $warn, critical => $crit, min => 0 ); } } 1; centreon-plugins-20220113/centreon/common/broadcom/fastpath/snmp/mode/components/psu.pm000066400000000000000000000056511417000230700312030ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::broadcom::fastpath::snmp::mode::components::psu; use strict; use warnings; my %map_psu_status = ( 1 => 'notpresent', 2 => 'operational', 3 => 'failed', 4 => 'powering', 5 => 'nopower', 6 => 'notpowering', 7 => 'incompatible' ); my $mapping = { boxServicesPowSupplyItemState => { oid => '.1.3.6.1.4.1.4413.1.1.43.1.7.1.3', map => \%map_psu_status }, }; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping->{boxServicesPowSupplyItemState}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking power supplies"); $self->{components}->{psu} = {name => 'psu', total => 0, skip => 0}; return if ($self->check_filter(section => 'psu')); my ($exit, $warn, $crit, $checked); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$mapping->{boxServicesPowSupplyItemState}->{oid}}})) { next if ($oid !~ /^$mapping->{boxServicesPowSupplyItemState}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$mapping->{boxServicesPowSupplyItemState}->{oid}}, instance => $instance); next if ($self->check_filter(section => 'psu', instance => $instance)); if ($result->{boxServicesPowSupplyItemState} =~ /notpresent/i) { $self->absent_problem(section => 'psu', instance => $instance); next; } $self->{components}->{psu}->{total}++; $self->{output}->output_add( long_msg => sprintf( "power supply '%s' status is '%s' [instance = %s]", $instance, $result->{boxServicesPowSupplyItemState}, $instance ) ); $exit = $self->get_severity(label => 'default', section => 'psu', value => $result->{boxServicesPowSupplyItemState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Power supply '%s' status is '%s'", $instance, $result->{boxServicesPowSupplyItemState}) ); } } } 1; centreon-plugins-20220113/centreon/common/broadcom/fastpath/snmp/mode/components/temperature.pm000066400000000000000000000102761417000230700327300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::broadcom::fastpath::snmp::mode::components::temperature; use strict; use warnings; my %map_temp_status = ( 0 => 'low', 1 => 'normal', 2 => 'warning', 3 => 'critical', 4 => 'shutdown', 5 => 'notpresent', 6 => 'notoperational' ); my $mapping = { boxServicesTempSensorState => { oid => '.1.3.6.1.4.1.4413.1.1.43.1.8.1.4', map => \%map_temp_status }, boxServicesTempSensorTemperature => { oid => '.1.3.6.1.4.1.4413.1.1.43.1.8.1.5' } }; my $oid_boxServicesTempSensorsEntry = '.1.3.6.1.4.1.4413.1.1.43.1.8.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_boxServicesTempSensorsEntry, start => $mapping->{boxServicesTempSensorState}->{oid}, end => $mapping->{boxServicesTempSensorTemperature}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking temperatures"); $self->{components}->{temperature} = {name => 'temperatures', total => 0, skip => 0}; return if ($self->check_filter(section => 'temperature')); my ($exit, $warn, $crit, $checked); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_boxServicesTempSensorsEntry}})) { next if ($oid !~ /^$mapping->{boxServicesTempSensorState}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_boxServicesTempSensorsEntry}, instance => $instance); next if ($self->check_filter(section => 'temperature', instance => $instance)); if ($result->{boxServicesTempSensorState} =~ /notpresent/i) { $self->absent_problem(section => 'temperature', instance => $instance); next; } $self->{components}->{temperature}->{total}++; $self->{output}->output_add( long_msg => sprintf( "temperature '%s' status is '%s' [instance = %s, temperature = %s]", $instance, $result->{boxServicesTempSensorState}, $instance, defined($result->{boxServicesTempSensorTemperature}) ? $result->{boxServicesTempSensorTemperature} : 'unknown' ) ); $exit = $self->get_severity(section => 'temperature', value => $result->{boxServicesTempSensorState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Temperature '%s' status is '%s'", $instance, $result->{boxServicesTempSensorState}) ); } next if (!defined($result->{boxServicesTempSensorTemperature}) || $result->{boxServicesTempSensorTemperature} !~ /[0-9]+/); ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $instance, value => $result->{boxServicesTempSensorTemperature}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Temperature '%s' is '%s' rpm", $instance, $result->{boxServicesTempSensorTemperature}) ); } $self->{output}->perfdata_add( nlabel => 'hardware.temperature.celsius', unit => 'C', instances => $instance, value => $result->{boxServicesTempSensorTemperature}, warning => $warn, critical => $crit ); } } 1; centreon-plugins-20220113/centreon/common/broadcom/fastpath/snmp/mode/cpu.pm000066400000000000000000000066521417000230700270000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::broadcom::fastpath::snmp::mode::cpu; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_cpu_output { my ($self, %options) = @_; return 'CPU '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_cpu_output' } ]; $self->{maps_counters}->{global} = [ { label => '5s', nlabel => 'cpu.utilization.5s.percentage', set => { key_values => [ { name => 'usage_5s' } ], output_template => '%.2f %% (5sec)', output_error_template => "%s (5sec)", perfdatas => [ { template => '%.2f', unit => '%', min => 0, max => 100 } ] } }, { label => '1m', nlabel => 'cpu.utilization.1m.percentage', set => { key_values => [ { name => 'usage_1m' } ], output_template => '%.2f %% (1m)', output_error_template => "%s (1min)", perfdatas => [ { template => '%.2f', unit => '%', min => 0, max => 100 } ] } }, { label => '5m', nlabel => 'cpu.utilization.5m.percentage', set => { key_values => [ { name => 'usage_5m' } ], output_template => '%.2f %% (5min)', output_error_template => "%s (5min)", perfdatas => [ { template => '%.2f', unit => '%', min => 0, max => 100 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub manage_selection { my ($self, %options) = @_; # STRING: " 5 Secs ( 43.2625%) 60 Secs ( 13.9157%) 300 Secs ( 8.9274%)" my $oid_agentSwitchCpuProcessTotalUtilization = '.1.3.6.1.4.1.4413.1.1.1.1.4.9.0'; my $snmp_result = $options{snmp}->get_leef(oids => [$oid_agentSwitchCpuProcessTotalUtilization], nothing_quit => 1); $snmp_result->{$oid_agentSwitchCpuProcessTotalUtilization} =~ /\s*5\s*Secs\s*\(\s*(.*?)%\s*\)\s*60\s*Secs\s*\(\s*(.*?)%\s*\)\s*300\s*Secs\s*\(\s*(.*?)%\s*\)/i; $self->{global} = { usage_5s => $1, usage_1m => $2, usage_5m => $3 }; } 1; __END__ =head1 MODE Check CPU usage. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='5m' =item B<--warning-*> Threshold warning. Can be: '5s', '1m', '5m'. =item B<--critical-*> Threshold critical. Can be: '5s', '1m', '5m'. =back =cut centreon-plugins-20220113/centreon/common/broadcom/fastpath/snmp/mode/hardware.pm000066400000000000000000000065351417000230700300060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::broadcom::fastpath::snmp::mode::hardware; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^(temperature|fan)$'; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { default => [ ['notPresent', 'OK'], ['operational', 'OK'], ['failed', 'CRITICAL'], ['notpowering', 'WARNING'], ['powering', 'OK'], ['nopower', 'OK'], ['incompatible', 'WARNING'] ], temperature => [ ['low', 'OK'], ['normal', 'OK'], ['warning', 'WARNING'], ['critical', 'CRITICAL'], ['notpresent', 'OK'], ['shutdown', 'OK'], ['notoperational', 'WARNING'] ] }; $self->{components_path} = 'centreon::common::broadcom::fastpath::snmp::mode::components'; $self->{components_module} = ['fan', 'psu', 'temperature']; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } 1; __END__ =head1 MODE Check hardware. =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'fan', 'psu', 'temperature'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=fan --filter=psu) Can also exclude specific instance: --filter=fan,1.1 =item B<--absent-problem> Return an error if an entity is not 'present' (default is skipping) (comma seperated list) Can be specific or global: --absent-problem=fan,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,^(?!(operational)$)' =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 centreon-plugins-20220113/centreon/common/broadcom/fastpath/snmp/mode/memory.pm000066400000000000000000000114341417000230700275130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::broadcom::fastpath::snmp::mode::memory; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_usage_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => 'memory.usage.bytes', unit => 'B', value => $self->{result_values}->{used}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), min => 0, max => $self->{result_values}->{total} ); } sub custom_usage_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check( value => $self->{result_values}->{prct_used}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, 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}); return sprintf( "Memory Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", $total_size_value . " " . $total_size_unit, $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}, $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free} ); } sub custom_usage_calc { my ($self, %options) = @_; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_total'}; $self->{result_values}->{prct_used} = $options{new_datas}->{$self->{instance} . '_prct_used'}; $self->{result_values}->{used} = int($self->{result_values}->{prct_used} * $self->{result_values}->{total} / 100); $self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used}; $self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'memory', type => 0 } ]; $self->{maps_counters}->{memory} = [ { label => 'usage', set => { key_values => [ { name => 'prct_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, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments =>{ }); return $self; } sub manage_selection { my ($self, %options) = @_; my $oid_agentSwitchCpuProcessMemFree = '.1.3.6.1.4.1.4413.1.1.1.1.4.1.0'; # KB my $oid_agentSwitchCpuProcessMemAvailable = '.1.3.6.1.4.1.4413.1.1.1.1.4.2.0'; # KB my $snmp_result = $options{snmp}->get_leef(oids => [$oid_agentSwitchCpuProcessMemFree, $oid_agentSwitchCpuProcessMemAvailable], nothing_quit => 1); my $total = $snmp_result->{$oid_agentSwitchCpuProcessMemAvailable} * 1024; $self->{memory} = { prct_used => ($total - $snmp_result->{$oid_agentSwitchCpuProcessMemFree} * 1024) * 100 / $total, total => $total }; } 1; __END__ =head1 MODE Check memory usage. =over 8 =item B<--warning-usage> Threshold warning (in percent). =item B<--critical-usage> Threshold critical (in percent). =back =cut centreon-plugins-20220113/centreon/common/broadcom/megaraid/000077500000000000000000000000001417000230700237005ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/broadcom/megaraid/snmp/000077500000000000000000000000001417000230700246555ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/broadcom/megaraid/snmp/mode/000077500000000000000000000000001417000230700256015ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/broadcom/megaraid/snmp/mode/components/000077500000000000000000000000001417000230700277665ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/broadcom/megaraid/snmp/mode/components/alarm.pm000066400000000000000000000061051417000230700314220ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::broadcom::megaraid::snmp::mode::components::alarm; use strict; use warnings; my %map_alarm_status = ( 1 => 'status-invalid', 2 => 'status-ok', 3 => 'status-critical', 4 => 'status-nonCritical', 5 => 'status-unrecoverable', 6 => 'status-not-installed', 7 => 'status-unknown', 8 => 'status-not-available' ); my $mapping = { enclosureId_EAT => { oid => '.1.3.6.1.4.1.3582.4.1.5.7.1.2' }, alarmStatus => { oid => '.1.3.6.1.4.1.3582.4.1.5.7.1.3', map => \%map_alarm_status }, }; my $oid_enclosureAlarmEntry= '.1.3.6.1.4.1.3582.4.1.5.7.1'; sub load { my ($self) = @_; push @{$self->{requEAT}}, { oid => $oid_enclosureAlarmEntry, start => $mapping->{enclosureId_EAT}->{oid}, end => $mapping->{alarmStatus}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking alarms"); $self->{components}->{alarm} = {name => 'alarms', total => 0, skip => 0}; return if ($self->check_filter(section => 'alarm')); my ($exit, $warn, $crit, $checked); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_enclosureAlarmEntry}})) { next if ($oid !~ /^$mapping->{alarmStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_enclosureAlarmEntry}, instance => $instance); next if ($self->check_filter(section => 'alarm', instance => $instance)); if ($result->{alarmStatus} =~ /status-not-installed/i) { $self->absent_problem(section => 'alarm', instance => $instance); next; } $self->{components}->{alarm}->{total}++; $self->{output}->output_add(long_msg => sprintf("Alarm '%s' status is '%s' [instance = %s, enclosure = %s]", $instance, $result->{alarmStatus}, $instance, $result->{enclosureId_EAT})); $exit = $self->get_severity(label => 'default', section => 'alarm', value => $result->{alarmStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Alarm '%s' status is '%s'", $instance, $result->{alarmStatus})); } } } 1; centreon-plugins-20220113/centreon/common/broadcom/megaraid/snmp/mode/components/fan.pm000066400000000000000000000060111417000230700310660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::broadcom::megaraid::snmp::mode::components::fan; use strict; use warnings; my %map_fan_status = ( 1 => 'status-invalid', 2 => 'status-ok', 3 => 'status-critical', 4 => 'status-nonCritical', 5 => 'status-unrecoverable', 6 => 'status-not-installed', 7 => 'status-unknown', 8 => 'status-not-available' ); my $mapping = { enclosureId => { oid => '.1.3.6.1.4.1.3582.4.1.5.3.1.2' }, fanStatus => { oid => '.1.3.6.1.4.1.3582.4.1.5.3.1.3', map => \%map_fan_status }, }; my $oid_enclosureFanEntry = '.1.3.6.1.4.1.3582.4.1.5.3.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_enclosureFanEntry, start => $mapping->{enclosureId}->{oid}, end => $mapping->{fanStatus}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking fans"); $self->{components}->{fan} = {name => 'fan', total => 0, skip => 0}; return if ($self->check_filter(section => 'fan')); my ($exit, $warn, $crit, $checked); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_enclosureFanEntry}})) { next if ($oid !~ /^$mapping->{fanStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_enclosureFanEntry}, instance => $instance); next if ($self->check_filter(section => 'fan', instance => $instance)); if ($result->{fanStatus} =~ /status-not-installed/i) { $self->absent_problem(section => 'fan', instance => $instance); next; } $self->{components}->{fan}->{total}++; $self->{output}->output_add(long_msg => sprintf("Fan '%s' status is '%s' [instance = %s, enclosure = %s]", $instance, $result->{fanStatus}, $instance, $result->{enclosureId})); $exit = $self->get_severity(label => 'default', section => 'fan', value => $result->{fanStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Fan '%s' status is '%s'", $instance, $result->{fanStatus})); } } } 1; centreon-plugins-20220113/centreon/common/broadcom/megaraid/snmp/mode/components/pdrive.pm000066400000000000000000000062061417000230700316210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::broadcom::megaraid::snmp::mode::components::pdrive; use strict; use warnings; my %map_pdrive_status = ( 0 => 'unconfigured-good', 1 => 'unconfigured-bad', 2 => 'hot-spare', 16 => 'offline', 17 => 'failed', 20 => 'rebuild', 24 => 'online', 32 => 'copyback', 64 => 'system', 128 => 'UNCONFIGURED-SHIELDED', 130 => 'HOTSPARE-SHIELDED', 144 => 'CONFIGURED-SHIELDED' ); my $mapping = { pdState => { oid => '.1.3.6.1.4.1.3582.4.1.4.2.1.2.1.10', map => \%map_pdrive_status }, pdSerialNumber => { oid => '.1.3.6.1.4.1.3582.4.1.4.2.1.2.1.37' }, }; my $oid_virtualDriveEntry = '.1.3.6.1.4.1.3582.4.1.4.2.1.2.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_virtualDriveEntry, start => $mapping->{pdState}->{oid}, end => $mapping->{pdSerialNumber}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking physical drives"); $self->{components}->{pdrive} = {name => 'pdrives', total => 0, skip => 0}; return if ($self->check_filter(section => 'pdrive')); my ($exit, $warn, $crit, $checked); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_virtualDriveEntry}})) { next if ($oid !~ /^$mapping->{pdState}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_virtualDriveEntry}, instance => $instance); next if ($self->check_filter(section => 'pdrive', instance => $instance)); if ($result->{pdState} =~ /status-not-installed/i) { $self->absent_problem(section => 'pdrive', instance => $instance); next; } $self->{components}->{pdrive}->{total}++; $self->{output}->output_add(long_msg => sprintf("Physical drive '%s' status is '%s' [instance = %s, SN = %s]", $instance, $result->{pdState}, $instance, $result->{pdSerialNumber})); $exit = $self->get_severity(label => 'pdrive', section => 'pdrive', value => $result->{pdState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Physical drive '%s' status is '%s'", $instance, $result->{pdState})); } } } 1; centreon-plugins-20220113/centreon/common/broadcom/megaraid/snmp/mode/components/psu.pm000066400000000000000000000062141417000230700311360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::broadcom::megaraid::snmp::mode::components::psu; use strict; use warnings; my %map_psu_status = ( 1 => 'status-invalid', 2 => 'status-ok', 3 => 'status-critical', 4 => 'status-nonCritical', 5 => 'status-unrecoverable', 6 => 'status-not-installed', 7 => 'status-unknown', 8 => 'status-not-available' ); my $mapping = { enclosureId_EPST => { oid => '.1.3.6.1.4.1.3582.4.1.5.5.1.2' }, powerSupplyStatus => { oid => '.1.3.6.1.4.1.3582.4.1.5.5.1.3', map => \%map_psu_status }, }; my $oid_enclosurePowerSupplyEntry = '.1.3.6.1.4.1.3582.4.1.5.5.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_enclosurePowerSupplyEntry, start => $mapping->{enclosureId_EPST}->{oid}, end => $mapping->{powerSupplyStatus}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking power supplies"); $self->{components}->{psu} = {name => 'psu', total => 0, skip => 0}; return if ($self->check_filter(section => 'psu')); my ($exit, $warn, $crit, $checked); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_enclosurePowerSupplyEntry}})) { next if ($oid !~ /^$mapping->{powerSupplyStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_enclosurePowerSupplyEntry}, instance => $instance); next if ($self->check_filter(section => 'psu', instance => $instance)); if ($result->{powerSupplyStatus} =~ /status-not-installed/i) { $self->absent_problem(section => 'psu', instance => $instance); next; } $self->{components}->{psu}->{total}++; $self->{output}->output_add(long_msg => sprintf("Power supply '%s' status is '%s' [instance = %s, enclosure = %s]", $instance, $result->{powerSupplyStatus}, $instance, $result->{enclosureId_EPST})); $exit = $self->get_severity(label => 'default', section => 'psu', value => $result->{powerSupplyStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Power supply '%s' status is '%s'", $instance, $result->{powerSupplyStatus})); } } } 1; centreon-plugins-20220113/centreon/common/broadcom/megaraid/snmp/mode/components/sim.pm000066400000000000000000000060421417000230700311160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::broadcom::megaraid::snmp::mode::components::sim; use strict; use warnings; my %map_slot_status = ( 1 => 'status-invalid', 2 => 'status-ok', 3 => 'status-critical', 4 => 'status-nonCritical', 5 => 'status-unrecoverable', 6 => 'status-not-installed', 7 => 'status-unknown', 8 => 'status-not-available' ); my $mapping = { enclosureId_ESIT => { oid => '.1.3.6.1.4.1.3582.4.1.5.8.1.2' }, slotStatus => { oid => '.1.3.6.1.4.1.3582.4.1.5.8.1.3', map => \%map_slot_status }, }; my $oid_enclosureSIMEntry = '.1.3.6.1.4.1.3582.4.1.5.8.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_enclosureSIMEntry, start => $mapping->{enclosureId_ESIT}->{oid}, end => $mapping->{slotStatus}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking SIMs"); $self->{components}->{sim} = {name => 'sims', total => 0, skip => 0}; return if ($self->check_filter(section => 'sim')); my ($exit, $warn, $crit, $checked); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_enclosureSIMEntry}})) { next if ($oid !~ /^$mapping->{slotStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_enclosureSIMEntry}, instance => $instance); next if ($self->check_filter(section => 'sim', instance => $instance)); if ($result->{slotStatus} =~ /status-not-installed/i) { $self->absent_problem(section => 'sim', instance => $instance); next; } $self->{components}->{sim}->{total}++; $self->{output}->output_add(long_msg => sprintf("Sim '%s' status is '%s' [instance = %s, enclosure = %s]", $instance, $result->{slotStatus}, $instance, $result->{enclosureId_ESIT})); $exit = $self->get_severity(label => 'default', section => 'sim', value => $result->{slotStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Sim '%s' status is '%s'", $instance, $result->{slotStatus})); } } } 1; centreon-plugins-20220113/centreon/common/broadcom/megaraid/snmp/mode/components/slot.pm000066400000000000000000000060561417000230700313140ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::broadcom::megaraid::snmp::mode::components::slot; use strict; use warnings; my %map_slot_status = ( 1 => 'status-invalid', 2 => 'status-ok', 3 => 'status-critical', 4 => 'status-nonCritical', 5 => 'status-unrecoverable', 6 => 'status-not-installed', 7 => 'status-unknown', 8 => 'status-not-available' ); my $mapping = { enclosureId_EST => { oid => '.1.3.6.1.4.1.3582.4.1.5.4.1.2' }, slotStatus => { oid => '.1.3.6.1.4.1.3582.4.1.5.4.1.3', map => \%map_slot_status }, }; my $oid_enclosureSlotEntry = '.1.3.6.1.4.1.3582.4.1.5.4.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_enclosureSlotEntry, start => $mapping->{enclosureId_EST}->{oid}, end => $mapping->{slotStatus}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking slots"); $self->{components}->{slot} = {name => 'slots', total => 0, skip => 0}; return if ($self->check_filter(section => 'slot')); my ($exit, $warn, $crit, $checked); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_enclosureSlotEntry}})) { next if ($oid !~ /^$mapping->{slotStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_enclosureSlotEntry}, instance => $instance); next if ($self->check_filter(section => 'slot', instance => $instance)); if ($result->{slotStatus} =~ /status-not-installed/i) { $self->absent_problem(section => 'slot', instance => $instance); next; } $self->{components}->{slot}->{total}++; $self->{output}->output_add(long_msg => sprintf("Slot '%s' status is '%s' [instance = %s, enclosure = %s]", $instance, $result->{slotStatus}, $instance, $result->{enclosureId_EST})); $exit = $self->get_severity(label => 'default', section => 'slot', value => $result->{slotStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Slot '%s' status is '%s'", $instance, $result->{slotStatus})); } } } 1; centreon-plugins-20220113/centreon/common/broadcom/megaraid/snmp/mode/components/temperature.pm000066400000000000000000000104071417000230700326630ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::broadcom::megaraid::snmp::mode::components::temperature; use strict; use warnings; my %map_temp_status = ( 1 => 'status-invalid', 2 => 'status-ok', 3 => 'status-critical', 4 => 'status-nonCritical', 5 => 'status-unrecoverable', 6 => 'status-not-installed', 7 => 'status-unknown', 8 => 'status-not-available' ); my $mapping = { enclosureId_ETST => { oid => '.1.3.6.1.4.1.3582.4.1.5.6.1.2' }, tempSensorStatus => { oid => '.1.3.6.1.4.1.3582.4.1.5.6.1.3', map => \%map_temp_status }, enclosureTemperature => { oid => '.1.3.6.1.4.1.3582.4.1.5.6.1.4' }, }; my $oid_enclosureTempSensorEntry = '.1.3.6.1.4.1.3582.4.1.5.6.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_enclosureTempSensorEntry, start => $mapping->{enclosureId_ETST}->{oid}, end => $mapping->{enclosureTemperature}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking temperatures"); $self->{components}->{temperature} = {name => 'temperatures', total => 0, skip => 0}; return if ($self->check_filter(section => 'temperature')); my ($exit, $warn, $crit, $checked); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_enclosureTempSensorEntry}})) { next if ($oid !~ /^$mapping->{tempSensorStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_enclosureTempSensorEntry}, instance => $instance); next if ($self->check_filter(section => 'temperature', instance => $instance)); if ($result->{tempSensorStatus} =~ /status-not-installed/i) { $self->absent_problem(section => 'temperature', instance => $instance); next; } $self->{components}->{temperature}->{total}++; $self->{output}->output_add(long_msg => sprintf("Temperature '%s' status is '%s' [instance = %s, enclosure = %s, temperature = %s C]", $instance, $result->{tempSensorStatus}, $instance, $result->{enclosureId_ETST}, defined($result->{enclosureTemperature}) ? $result->{enclosureTemperature} : 'unknown')); $exit = $self->get_severity(section => 'default', value => $result->{tempSensorStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Temperature '%s' status is '%s'", $instance, $result->{tempSensorStatus})); } next if (!defined($result->{enclosureTemperature}) || $result->{enclosureTemperature} !~ /[0-9]+/); ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $instance, value => $result->{enclosureTemperature}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Temperature '%s' is '%s' C", $instance, $result->{enclosureTemperature})); } $self->{output}->perfdata_add( label => 'temp', unit => 'C', nlabel => 'hardware.temperature.celsius', instances => $instance, value => $result->{enclosureTemperature}, warning => $warn, critical => $crit, ); } } 1; centreon-plugins-20220113/centreon/common/broadcom/megaraid/snmp/mode/components/vdrive.pm000066400000000000000000000056301417000230700316270ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::broadcom::megaraid::snmp::mode::components::vdrive; use strict; use warnings; my %map_vdrive_status = ( 0 => 'offline', 1 => 'partially-degraded', 2 => 'degraded', 3 => 'optimal' ); my $mapping = { state => { oid => '.1.3.6.1.4.1.3582.4.1.4.3.1.2.1.5', map => \%map_vdrive_status }, name => { oid => '.1.3.6.1.4.1.3582.4.1.4.3.1.2.1.6' }, }; my $oid_virtualDriveEntry = '.1.3.6.1.4.1.3582.4.1.4.3.1.2.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_virtualDriveEntry, start => $mapping->{state}->{oid}, end => $mapping->{name}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking virtual drives"); $self->{components}->{vdrive} = {name => 'vdrives', total => 0, skip => 0}; return if ($self->check_filter(section => 'vdrive')); my ($exit, $warn, $crit, $checked); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_virtualDriveEntry}})) { next if ($oid !~ /^$mapping->{state}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_virtualDriveEntry}, instance => $instance); next if ($self->check_filter(section => 'vdrive', instance => $instance)); if ($result->{state} =~ /status-not-installed/i) { $self->absent_problem(section => 'vdrive', instance => $instance); next; } $self->{components}->{vdrive}->{total}++; $self->{output}->output_add(long_msg => sprintf("Virtual drive '%s' status is '%s' [instance = %s, name = %s]", $instance, $result->{state}, $instance, $result->{name})); $exit = $self->get_severity(label => 'vdrive', section => 'vdrive', value => $result->{state}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Virtual drive '%s' status is '%s'", $instance, $result->{state})); } } } 1; centreon-plugins-20220113/centreon/common/broadcom/megaraid/snmp/mode/hardware.pm000066400000000000000000000076241417000230700277450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::broadcom::megaraid::snmp::mode::hardware; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^(temperature)$'; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { default => [ ['status-invalid', 'CRITICAL'], ['status-ok', 'OK'], ['status-critical', 'CRITICAL'], ['status-nonCritical', 'WARNING'], ['status-unrecoverable', 'CRITICAL'], ['status-not-installed', 'OK'], ['status-unknown', 'UNKNOWN'], ['status-not-available', 'WARNING'], ], vdrive => [ ['offline', 'UNKNOWN'], ['partially-degraded', 'WARNING'], ['degraded', 'CRITICAL'], ['optimal', 'OK'], ], pdrive => [ ['unconfigured-good', 'OK'], ['unconfigured-bad', 'CRITICAL'], ['hot-spare', 'OK'], ['offline', 'UNKNOWN'], ['failed', 'CRITICAL'], ['rebuild', 'OK'], ['online', 'OK'], ['copyback', 'OK'], ['system', 'OK'], ['UNCONFIGURED-SHIELDED', 'UNKNOWN'], ['HOTSPARE-SHIELDED', 'UNKNOWN'], ['CONFIGURED-SHIELDED', 'UNKNOWN'], ], }; $self->{components_path} = 'centreon::common::broadcom::megaraid::snmp::mode::components'; $self->{components_module} = ['alarm', 'fan', 'sim', 'slot', 'psu', 'temperature', 'pdrive', 'vdrive']; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } 1; __END__ =head1 MODE Check hardware (LSI-MegaRAID-SAS-MIB). =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'alarm', 'fan', 'sim', 'slot', 'psu', 'temperature', 'pdrive', 'vdrive'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=fan --filter=psu) Can also exclude specific instance: --filter=fan,3 =item B<--absent-problem> Return an error if an entity is not 'present' (default is skipping) (comma seperated list) Can be specific or global: --absent-problem=fan,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,OK,^(?!(status-unrecoverable)$)' =item B<--warning> Set warning threshold for 'temperature' (syntax: type,regexp,threshold) Example: --warning='temperature,.*,40' =item B<--critical> Set critical threshold for 'temperature' (syntax: type,regexp,threshold) Example: --critical='temperature,.*,50' =back =cut centreon-plugins-20220113/centreon/common/cisco/000077500000000000000000000000001417000230700214415ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/cisco/ironport/000077500000000000000000000000001417000230700233155ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/cisco/ironport/snmp/000077500000000000000000000000001417000230700242725ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/cisco/ironport/snmp/mode/000077500000000000000000000000001417000230700252165ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/cisco/ironport/snmp/mode/components/000077500000000000000000000000001417000230700274035ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/cisco/ironport/snmp/mode/components/fan.pm000066400000000000000000000054061417000230700305120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::ironport::snmp::mode::components::fan; use strict; use warnings; my $mapping = { fanRPMs => { oid => '.1.3.6.1.4.1.15497.1.1.1.10.1.2' }, fanName => { oid => '.1.3.6.1.4.1.15497.1.1.1.10.1.3' }, }; my $oid_fanEntry = '.1.3.6.1.4.1.15497.1.1.1.10.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_fanEntry, start => $mapping->{fanRPMs}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking fans"); $self->{components}->{fan} = {name => 'fans', total => 0, skip => 0}; return if ($self->check_filter(section => 'fan')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_fanEntry}})) { next if ($oid !~ /^$mapping->{fanRPMs}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_fanEntry}, instance => $instance); next if ($self->check_filter(section => 'fan', instance => $instance)); $self->{components}->{fan}->{total}++; $self->{output}->output_add(long_msg => sprintf("Fan '%s' is '%s' rpm [instance = %s]", $result->{fanName}, $result->{fanRPMs}, $instance)); my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'fan', instance => $instance, value => $result->{fanRPMs}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Fan '%s' is '%s' rpm", $result->{fanName}, $result->{fanRPMs})); } $self->{output}->perfdata_add( label => 'fan', unit => 'rpm', nlabel => 'hardware.fan.speed.rpm', instances => $result->{fanName}, value => $result->{fanRPMs}, warning => $warn, critical => $crit, min => 0 ); } } 1; centreon-plugins-20220113/centreon/common/cisco/ironport/snmp/mode/components/psu.pm000066400000000000000000000056421417000230700305570ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::ironport::snmp::mode::components::psu; use strict; use warnings; my %map_psu_status = ( 1 => 'powerSupplyNotInstalled', 2 => 'powerSupplyHealthy', 3 => 'powerSupplyNoAC', 4 => 'powerSupplyFaulty', ); my $mapping = { powerSupplyStatus => { oid => '.1.3.6.1.4.1.15497.1.1.1.8.1.2', map => \%map_psu_status }, powerSupplyName => { oid => '.1.3.6.1.4.1.15497.1.1.1.8.1.4' }, }; my $oid_powerSupplyEntry = '.1.3.6.1.4.1.15497.1.1.1.8.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_powerSupplyEntry, start => $mapping->{powerSupplyStatus}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking power supplies"); $self->{components}->{psu} = {name => 'power supplies', total => 0, skip => 0}; return if ($self->check_filter(section => 'psu')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_powerSupplyEntry}})) { next if ($oid !~ /^$mapping->{powerSupplyStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_powerSupplyEntry}, instance => $instance); next if ($self->check_filter(section => 'psu', instance => $instance)); if ($result->{powerSupplyStatus} =~ /powerSupplyNotInstalled/i) { $self->absent_problem(section => 'psu', instance => $instance); next; } $self->{components}->{psu}->{total}++; $self->{output}->output_add(long_msg => sprintf("Power supply '%s' status is '%s' [instance = %s]", $result->{powerSupplyName}, $result->{powerSupplyStatus}, $instance)); my $exit = $self->get_severity(section => 'psu', value => $result->{powerSupplyStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Power supply '%s' status is '%s'", $result->{powerSupplyName}, $result->{powerSupplyStatus})); } } } 1; centreon-plugins-20220113/centreon/common/cisco/ironport/snmp/mode/components/raid.pm000066400000000000000000000051061417000230700306620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::ironport::snmp::mode::components::raid; use strict; use warnings; my %map_raid_status = ( 1 => 'driveHealthy', 2 => 'driveFailure', 3 => 'driveRebuild', ); my $mapping = { raidStatus => { oid => '.1.3.6.1.4.1.15497.1.1.1.18.1.2', map => \%map_raid_status }, raidID => { oid => '.1.3.6.1.4.1.15497.1.1.1.18.1.3' }, }; my $oid_raidEntry = '.1.3.6.1.4.1.15497.1.1.1.18.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_raidEntry, start => $mapping->{raidStatus}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking raids"); $self->{components}->{raid} = {name => 'raids', total => 0, skip => 0}; return if ($self->check_filter(section => 'raid')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_raidEntry}})) { next if ($oid !~ /^$mapping->{raidStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_raidEntry}, instance => $instance); next if ($self->check_filter(section => 'raid', instance => $instance)); $self->{components}->{raid}->{total}++; $self->{output}->output_add(long_msg => sprintf("Raid '%s' status is '%s' [instance = %s]", $result->{raidID}, $result->{raidStatus}, $instance)); my $exit = $self->get_severity(section => 'raid', value => $result->{raidStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Raid '%s' status is '%s'", $result->{raidID}, $result->{raidStatus})); } } } 1; centreon-plugins-20220113/centreon/common/cisco/ironport/snmp/mode/components/temperature.pm000066400000000000000000000063461417000230700323070ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::ironport::snmp::mode::components::temperature; use strict; use warnings; my %map_temp_status = ( 1 => 'noStatus', 2 => 'normal', 3 => 'highWarning', 4 => 'highCritical', 5 => 'lowWarning', 6 => 'lowCritical', 7 => 'sensorError', ); my %map_temp_online = ( 1 => 'online', 2 => 'offline', ); my $mapping = { degreesCelsius => { oid => '.1.3.6.1.4.1.15497.1.1.1.9.1.2' }, temperatureName => { oid => '.1.3.6.1.4.1.15497.1.1.1.9.1.3' }, }; my $oid_temperatureEntry = '.1.3.6.1.4.1.15497.1.1.1.9.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_temperatureEntry, start => $mapping->{degreesCelsius}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking temperatures"); $self->{components}->{temperature} = {name => 'temperatures', total => 0, skip => 0}; return if ($self->check_filter(section => 'temperature')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_temperatureEntry}})) { next if ($oid !~ /^$mapping->{degreesCelsius}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_temperatureEntry}, instance => $instance); next if ($self->check_filter(section => 'temperature', instance => $instance)); $self->{components}->{temperature}->{total}++; $self->{output}->output_add(long_msg => sprintf("Temperature '%s' is '%s' degree centigrade [instance = %s]", $result->{temperatureName}, $result->{degreesCelsius}, $instance)); my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $instance, value => $result->{degreesCelsius}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Temperature '%s' is %s degree centigrade", $result->{temperatureName}, $result->{degreesCelsius})); } $self->{output}->perfdata_add( label => 'temp', unit => 'C', nlabel => 'hardware.temperature.celsius', instances => $result->{temperatureName}, value => $result->{degreesCelsius}, warning => $warn, critical => $crit, ); } } 1; centreon-plugins-20220113/centreon/common/cisco/ironport/snmp/mode/cpu.pm000066400000000000000000000056061417000230700263520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::ironport::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 => ' - ', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ { label => 'global-utilization', nlabel => 'cpu.global.utilization.percentage', set => { key_values => [ { name => 'perCentCPUUtilization' } ], output_template => 'cpu global usage is: %.2f%%', perfdatas => [ { value => 'perCentCPUUtilization', template => '%.2f', min => 0, max => 100, unit => '%' }, ], } }, { label => 'proxy-utilization', nlabel => 'cpu.proxy.utilization.percentage', set => { key_values => [ { name => 'cacheCpuUsage' } ], output_template => 'cpu proxy usage is: %.2f%%', perfdatas => [ { value => 'cacheCpuUsage', template => '%.2f', min => 0, max => 100, unit => '%' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my %oids = ( perCentCPUUtilization => '.1.3.6.1.4.1.15497.1.1.1.2.0', cacheCpuUsage => '.1.3.6.1.4.1.15497.1.2.3.1.2.0', ); my $result = $options{snmp}->get_leef(oids => [values %oids], nothing_quit => 1); $self->{global} = {}; foreach (keys %oids) { $self->{global}->{$_} = $result->{$oids{$_}} if (defined($result->{$oids{$_}})); } } 1; __END__ =head1 MODE Check cpu usage of web security and mail (ASYNCOS-MAIL-MIB, ASYNCOSWEBSECURITYAPPLIANCE-MIB). =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'global-utilization', 'proxy-utilization'. =back =cut centreon-plugins-20220113/centreon/common/cisco/ironport/snmp/mode/hardware.pm000066400000000000000000000062431417000230700273560ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::ironport::snmp::mode::hardware; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^(temperature|fan)$'; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { psu => [ ['powerSupplyNotInstalled', 'OK'], ['powerSupplyHealthy', 'OK'], ['powerSupplyNoAC', 'WARNING'], ['powerSupplyFaulty', 'CRITICAL'], ], raid => [ ['driveHealthy', 'OK'], ['driveFailure', 'CRITICAL'], ['driveRebuild', 'WARNING'], ], }; $self->{components_path} = 'centreon::common::cisco::ironport::snmp::mode::components'; $self->{components_module} = ['fan', 'temperature', 'psu', 'raid']; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } 1; __END__ =head1 MODE Check Hardware (Fans, Power Supplies, Temperatures, Raids). =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'fan', 'temperature', 'psu', 'raid'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=fan --filter=temperature) Can also exclude specific instance: --filter=fan,1 =item B<--absent-problem> Return an error if an entity is not 'present' (default is skipping) (comma seperated list) Can be specific or global: --absent-problem=psu#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,^(?!(powerSupplyHealthy)$)' =item B<--warning> Set warning threshold for temperatures (syntax: type,regexp,threshold) Example: --warning='temperature,.*,30' =item B<--critical> Set critical threshold for temperatures (syntax: type,regexp,threshold) Example: --critical='fan,.*,6000' =back =cut centreon-plugins-20220113/centreon/common/cisco/ironport/snmp/mode/mailusage.pm000066400000000000000000000256071417000230700275350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::ironport::snmp::mode::mailusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); use Digest::MD5 qw(md5_hex); sub custom_status_output { my ($self, %options) = @_; my $msg = 'queue status: ' . $self->{result_values}->{queue_status} . ' [resource conservation: ' . $self->{result_values}->{resource_conservation} . ']'; return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'keys', type => 1, cb_prefix_output => 'prefix_keys_output', message_multiple => 'All keys are ok' }, { name => 'updates', type => 1, cb_prefix_output => 'prefix_updates_output', message_multiple => 'All service updates are ok' }, ]; $self->{maps_counters}->{global} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'queue_status' }, { name => 'resource_conservation' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold, } }, { label => 'messages-workqueue', nlabel => 'system.queue.messages.workqueue.count', display_ok => 0, set => { key_values => [ { name => 'msgs_in_work_queue' } ], output_template => 'messages in work queue: %s', perfdatas => [ { value => 'msgs_in_work_queue', template => '%s', min => 0 }, ], } }, { label => 'dns-requests-outstanding', nlabel => 'system.dns.requests.outstanding.count', display_ok => 0, set => { key_values => [ { name => 'outstandingDNSRequests' } ], output_template => 'dns requests with no reply: %s', perfdatas => [ { value => 'outstandingDNSRequests', template => '%s', min => 0 }, ], } }, { label => 'dns-requests-pending', nlabel => 'system.dns.requests.pending.count', display_ok => 0, set => { key_values => [ { name => 'pendingDNSRequests' } ], output_template => 'dns requests pending: %s', perfdatas => [ { value => 'pendingDNSRequests', template => '%s', min => 0 }, ], } }, { label => 'fd-opened', nlabel => 'system.fd.opened.count', display_ok => 0, set => { key_values => [ { name => 'openFilesOrSockets' } ], output_template => 'fd opened: %s', perfdatas => [ { value => 'openFilesOrSockets', template => '%s', min => 0 }, ], } }, { label => 'threads-mail', nlabel => 'system.threads.mail.count', display_ok => 0, set => { key_values => [ { name => 'mailTransferThreads' } ], output_template => 'threads mail: %s', perfdatas => [ { value => 'mailTransferThreads', template => '%s', min => 0 }, ], } }, ]; $self->{maps_counters}->{updates} = [ { label => 'update-failures', nlabel => 'service.update.failures.count', set => { key_values => [ { name => 'updateFailures', diff => 1 }, { name => 'updateServiceName' } ], output_template => 'update failures: %s', perfdatas => [ { value => 'updateFailures', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'updateServiceName' }, ], } }, ]; $self->{maps_counters}->{keys} = [ { label => 'time-expiration', nlabel => 'key.time.expiration.seconds', set => { key_values => [ { name => 'seconds' }, { name => 'msg' }, { name => 'display' } ], output_template => '%s remaining before expiration', output_use => 'msg', perfdatas => [ { value => 'seconds', template => '%s', unit => 's', label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub prefix_keys_output { my ($self, %options) = @_; return "Key '" . $options{instance_value}->{display} . "' "; } sub prefix_updates_output { my ($self, %options) = @_; return "Service '" . $options{instance_value}->{updateServiceName} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'unknown-status:s' => { name => 'unknown_status', default => '' }, 'warning-status:s' => { name => 'warning_status', default => '%{resource_conservation} =~ /memoryShortage|queueSpaceShortage/i || %{queue_status} =~ /queueSpaceShortage/i' }, 'critical-status:s' => { name => 'critical_status', default => '%{resource_conservation} =~ /queueFull/i || %{queue_status} =~ /queueFull/i' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['unknown_status', 'warning_status', 'critical_status']); } my $mapping = { keyDescription => { oid => '.1.3.6.1.4.1.15497.1.1.1.12.1.2' }, keyIsPerpetual => { oid => '.1.3.6.1.4.1.15497.1.1.1.12.1.3' }, keySecondsUntilExpire => { oid => '.1.3.6.1.4.1.15497.1.1.1.12.1.4' }, }; my $oid_keyExpirationEntry = '.1.3.6.1.4.1.15497.1.1.1.12.1'; my $mapping2 = { updateServiceName => { oid => '.1.3.6.1.4.1.15497.1.1.1.13.1.2' }, updateFailures => { oid => '.1.3.6.1.4.1.15497.1.1.1.13.1.4' }, }; my $oid_updateEntry = '.1.3.6.1.4.1.15497.1.1.1.13.1'; my $map_conservation_reason = { 1 => 'noResourceConservation', 2 => 'memoryShortage', 3 => 'queueSpaceShortage', 4 => 'queueFull' }; my $map_queue_status = { 1 => 'queueSpaceAvailable', 2 => 'queueSpaceShortage', 3 => 'queueFull', }; my $mapping3 = { queueAvailabilityStatus => { oid => '.1.3.6.1.4.1.15497.1.1.1.5', map => $map_queue_status }, resourceConservationReason => { oid => '.1.3.6.1.4.1.15497.1.1.1.6', map => $map_conservation_reason }, workQueueMessages => { oid => '.1.3.6.1.4.1.15497.1.1.1.11' }, outstandingDNSRequests => { oid => '.1.3.6.1.4.1.15497.1.1.1.15' }, pendingDNSRequests => { oid => '.1.3.6.1.4.1.15497.1.1.1.16' }, openFilesOrSockets => { oid => '.1.3.6.1.4.1.15497.1.1.1.19' }, mailTransferThreads => { oid => '.1.3.6.1.4.1.15497.1.1.1.20' }, }; sub manage_selection { my ($self, %options) = @_; my $snmp_result2 = $options{snmp}->get_leef( oids => [ map($_->{oid} . '.0', values(%$mapping3)) ], nothing_quit => 1 ); my $snmp_result = $options{snmp}->get_multiple_table( oids => [ { oid => $oid_keyExpirationEntry }, { oid => $oid_updateEntry }, ], ); $self->{updates} = {}; foreach my $oid (keys %{$snmp_result->{$oid_updateEntry}}) { next if ($oid !~ /^$mapping2->{updateServiceName}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping2, results => $snmp_result->{$oid_updateEntry}, instance => $instance); $self->{updates}->{$instance} = { %$result }; } $self->{keys} = {}; foreach my $oid (keys %{$snmp_result->{$oid_keyExpirationEntry}}) { next if ($oid !~ /^$mapping->{keySecondsUntilExpire}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result->{$oid_keyExpirationEntry}, instance => $instance); next if ($result->{keyIsPerpetual} == 1); $self->{keys}->{$instance} = { display => $result->{keyDescription}, seconds => $result->{keySecondsUntilExpire}, msg => centreon::plugins::misc::change_seconds(value => $result->{keySecondsUntilExpire}), }; } my $result = $options{snmp}->map_instance(mapping => $mapping3, results => $snmp_result2, instance => 0); $self->{global} = { queue_status => $result->{queueAvailabilityStatus}, resource_conservation => $result->{resourceConservationReason}, msgs_in_work_queue => $result->{workQueueMessages}, outstandingDNSRequests => $result->{outstandingDNSRequests}, pendingDNSRequests => $result->{pendingDNSRequests}, openFilesOrSockets => $result->{openFilesOrSockets}, mailTransferThreads => $result->{mailTransferThreads}, }; $self->{cache_name} = "cisco_ironport_" . $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')); } 1; __END__ =head1 MODE Check email security usage. =over 8 =item B<--unknown-status> Set warning threshold for status (Default: ''). Can used special variables like: %{queue_status}, %{resource_conservation} =item B<--warning-status> Set warning threshold for status (Default: '%{resource_conservation} =~ /memoryShortage|queueSpaceShortage/i || %{queue_status} =~ /queueSpaceShortage/i'). Can used special variables like: %{queue_status}, %{resource_conservation} =item B<--critical-status> Set critical threshold for status (Default: '%{resource_conservation} =~ /queueFull/i || %{queue_status} =~ /queueFull/i'). Can used special variables like: %{queue_status}, %{resource_conservation} =item B<--warning-*> B<--critical-*> Warning threshold. Can be: 'messages-workqueue', 'dns-requests-outstanding', 'dns-requests-pending', 'fd-opened', 'threads-mail', 'update-failures', 'time-expiration'. =back =cut centreon-plugins-20220113/centreon/common/cisco/ironport/snmp/mode/memory.pm000066400000000000000000000064051417000230700270710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::ironport::snmp::mode::memory; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "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) = @_; $self->{snmp} = $options{snmp}; my $oid_perCentMemoryUtilization = '.1.3.6.1.4.1.15497.1.1.1.1.0'; my $result = $self->{snmp}->get_leef(oids => [$oid_perCentMemoryUtilization], nothing_quit => 1); my $exit_code = $self->{perfdata}->threshold_check(value => $result->{$oid_perCentMemoryUtilization}, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("Memory usage is: %.2f%%", $result->{$oid_perCentMemoryUtilization})); $self->{output}->perfdata_add(label => 'used', unit => '%', value => sprintf("%.2f", $result->{$oid_perCentMemoryUtilization}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0, max => 100); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check memory usage (ASYNCOS-MAIL-MIB). =over 8 =item B<--warning> Threshold warning in percent. =item B<--critical> Threshold critical in percent. =back =cut centreon-plugins-20220113/centreon/common/cisco/ironport/snmp/mode/proxyusage.pm000066400000000000000000000232361417000230700277700ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::ironport::snmp::mode::proxyusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); sub custom_data_calc { my ($self, %options) = @_; my $delta_value = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{hit_ref}} - $options{old_datas}->{$self->{instance} . '_' . $options{extra_options}->{hit_ref}}; my $delta_total = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{total_ref}} - $options{old_datas}->{$self->{instance} . '_' . $options{extra_options}->{total_ref}}; $self->{result_values}->{hits_prct} = 100; if ($delta_total > 0) { $self->{result_values}->{hits_prct} = $delta_value * 100 / $delta_total; } return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'global_http', type => 0, cb_prefix_output => 'prefix_http_output', skipped_code => { -10 => 1 } }, { name => 'global_icp', type => 0, cb_prefix_output => 'prefix_icp_output', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global_http} = [ { label => 'client-http-hits-rate', nlabel => 'client.http.hits.percentage', set => { key_values => [ { name => 'cacheClientRequests', diff => 1 }, { name => 'cacheClientHits', diff => 1 } ], closure_custom_calc => $self->can('custom_data_calc'), closure_custom_calc_extra_options => { hit_ref => 'cacheClientHits', total_ref => 'cacheClientRequests' }, output_template => 'client hits rate: %.2f %%', output_use => 'hits_prct', threshold_use => 'hits_prct', perfdatas => [ { value => 'hits_prct', template => '%.2f', min => 0, max => 100, unit => '%' }, ], } }, { label => 'client-http-errors', display_ok => 0, nlabel => 'client.http.errors.count', set => { key_values => [ { name => 'cacheClientErrors', diff => 1 } ], output_template => 'client errors: %s', perfdatas => [ { template => '%s', min => 0 }, ], } }, { label => 'client-http-traffic-in', display_ok => 0, nlabel => 'client.http.traffic.in.bitspersecond', set => { key_values => [ { name => 'cacheClientInKb', per_second => 1 } ], output_template => 'client traffic in: %s %s/s', output_change_bytes => 2, perfdatas => [ { template => '%s', min => 0, unit => 'b/s' }, ], } }, { label => 'client-http-traffic-out', display_ok => 0, nlabel => 'client.http.traffic.out.bitspersecond', set => { key_values => [ { name => 'cacheClientOutKb', per_second => 1 } ], output_template => 'client traffic out: %s %s/s', output_change_bytes => 2, perfdatas => [ { template => '%s', min => 0, unit => 'b/s' }, ], } }, { label => 'total-con-clients', nlabel => 'client.http.total.connections.count', set => { key_values => [ { name => 'cacheClientTotalConns' } ], output_template => 'total number of clients: %s', perfdatas => [ { template => '%s', min => 0 }, ], } }, { label => 'client-http-requests', display_ok => 0, nlabel => 'client.http.requests.persecond', set => { key_values => [ { name => 'cacheClientRequests', per_second => 1 } ], output_template => 'client requests: %.2f/s', perfdatas => [ { template => '%.2f', min => 0, unit => '/s' }, ], } }, ]; $self->{maps_counters}->{global_icp} = [ { label => 'client-icp-hits-rate', nlabel => 'client.icp.hits.percentage', set => { key_values => [ { name => 'cacheClientICPRequests', diff => 1 }, { name => 'cacheClientICPHits', diff => 1 } ], closure_custom_calc_extra_options => { hit_ref => 'cacheClientICPHits', total_ref => 'cacheClientICPRequests' }, closure_custom_calc => $self->can('custom_data_calc'), output_template => 'client hits rate: %.2f %%', output_use => 'hits_prct', threshold_use => 'hits_prct', perfdatas => [ { value => 'hits_prct', template => '%.2f', min => 0, max => 100, unit => '%' }, ], } }, ]; $self->{maps_counters}->{global} = [ { label => 'http-mean-time', nlabel => 'http.response.mean.time.milliseconds', set => { key_values => [ { name => 'cacheMeanRespTime' } ], output_template => 'http mean response time: %s ms', perfdatas => [ { template => '%s', min => 0, unit => 'ms' }, ], } }, { label => 'server-traffic-in', display_ok => 0, nlabel => 'server.traffic.in.bitspersecond', set => { key_values => [ { name => 'cacheServerInKb', per_second => 1 } ], output_template => 'server traffic in: %s %s/s', output_change_bytes => 2, perfdatas => [ { template => '%s', min => 0, unit => 'b/s' }, ], } }, { label => 'server-traffic-out', display_ok => 0, nlabel => 'server.traffic.out.bitspersecond', set => { key_values => [ { name => 'cacheServerOutKb', per_second => 1 } ], output_template => 'server traffic out: %s %s/s', output_change_bytes => 2, perfdatas => [ { template => '%s', min => 0, unit => 'b/s' }, ], } }, ]; } sub prefix_http_output { my ($self, %options) = @_; return 'http '; } sub prefix_icp_output { my ($self, %options) = @_; return 'icp '; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my %oids = ( cacheClientRequests => '.1.3.6.1.4.1.15497.1.2.3.2.2.0', cacheClientHits => '.1.3.6.1.4.1.15497.1.2.3.2.3.0', cacheClientErrors => '.1.3.6.1.4.1.15497.1.2.3.2.4.0', cacheClientInKb => '.1.3.6.1.4.1.15497.1.2.3.2.5.0', cacheClientOutKb => '.1.3.6.1.4.1.15497.1.2.3.2.6.0', cacheClientICPRequests => '.1.3.6.1.4.1.15497.1.2.3.2.11.0', cacheClientICPHits => '.1.3.6.1.4.1.15497.1.2.3.2.12.0', cacheServerInKb => '.1.3.6.1.4.1.15497.1.2.3.3.5.0', cacheServerOutKb => '.1.3.6.1.4.1.15497.1.2.3.3.6.0', cacheClientTotalConns => '.1.3.6.1.4.1.15497.1.2.3.2.8.0', cacheMeanRespTime => '.1.3.6.1.4.1.15497.1.2.3.6.2.0', ); my $snmp_result = $options{snmp}->get_leef(oids => [ values %oids ], nothing_quit => 1 ); $self->{global_http} = { cacheClientRequests => $snmp_result->{$oids{cacheClientRequests}}, cacheClientHits => $snmp_result->{$oids{cacheClientHits}}, cacheClientErrors => $snmp_result->{$oids{cacheClientErrors}}, cacheClientInKb => $snmp_result->{$oids{cacheClientInKb}} * 1024 * 8, cacheClientOutKb => $snmp_result->{$oids{cacheClientOutKb}} * 1024 * 8, cacheClientTotalConns => $snmp_result->{$oids{cacheClientTotalConns}}, }; $self->{global_icp} = { cacheClientICPRequests => $snmp_result->{$oids{cacheClientICPRequests}}, cacheClientICPHits => $snmp_result->{$oids{cacheClientICPHits}}, }; $self->{global} = { cacheMeanRespTime => $snmp_result->{$oids{cacheMeanRespTime}}, cacheServerInKb => $snmp_result->{$oids{cacheServerInKb}} * 1024 * 8, cacheServerOutKb => $snmp_result->{$oids{cacheServerOutKb}} * 1024 * 8, }; $self->{cache_name} = "cisco_ironport_" . $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')); } 1; __END__ =head1 MODE Check proxy usage (websecurity appliance). =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='http' =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'client-http-hits-rate', 'client-http-errors', 'client-http-traffic-in', 'client-http-traffic-out', 'client-http-requests', 'total-con-clients', 'client-icp-hits-rate', 'server-traffic-in', 'server-traffic-out', 'http-mean-time'. =back =cut centreon-plugins-20220113/centreon/common/cisco/ironport/xmlapi/000077500000000000000000000000001417000230700246075ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/cisco/ironport/xmlapi/mode/000077500000000000000000000000001417000230700255335ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/cisco/ironport/xmlapi/mode/systemusage.pm000066400000000000000000000266741417000230700304610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::ironport::xmlapi::mode::systemusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); use centreon::plugins::http; use XML::Simple; use Digest::MD5 qw(md5_hex); sub custom_status_output { my ($self, %options) = @_; my $msg = 'system status: ' . $self->{result_values}->{system_status}; return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{system_status} = $options{new_datas}->{$self->{instance} . '_system_status'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'system-status', threshold => 0, set => { key_values => [ { name => 'system_status' } ], 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 => \&catalog_status_threshold } }, { label => 'memory', nlabel => 'system.memory.usage.percentage', set => { key_values => [ { name => 'ram_utilization' } ], output_template => 'memory usage: %.2f %%', perfdatas => [ { template => '%.2f', unit => '%', min => 0, max => 100 }, ], } }, { label => 'cpu-total', nlabel => 'system.cpu.total.utilization.percentage', set => { key_values => [ { name => 'total_utilization' } ], output_template => 'total cpu usage: %.2f %%', perfdatas => [ { template => '%.2f', unit => '%', min => 0, max => 100 }, ], } }, { label => 'diskio', nlabel => 'system.disk.io.usage.percentage', set => { key_values => [ { name => 'disk_utilization' } ], output_template => 'disk i/o usage: %.2f %%', perfdatas => [ { template => '%.2f', unit => '%', min => 0, max => 100 }, ], } }, { label => 'log', nlabel => 'system.logging.disk.usage.percentage', set => { key_values => [ { name => 'log_used' } ], output_template => 'logging disk usage: %.2f %%', perfdatas => [ { template => '%.2f', unit => '%', min => 0, max => 100 }, ], } }, { label => 'resource-conservation', nlabel => 'system.resource.conservation.current.count', set => { key_values => [ { name => 'resource_conservation' } ], output_template => 'resource conservation mode: %s', perfdatas => [ { template => '%s', min => 0 }, ], } }, { label => 'connections-in', nlabel => 'system.connections.inbound.current.count', set => { key_values => [ { name => 'conn_in' } ], output_template => 'current inbound connections: %s', perfdatas => [ { template => '%s', min => 0 }, ], } }, { label => 'connections-out', nlabel => 'system.connections.outbound.current.count', set => { key_values => [ { name => 'conn_out' } ], output_template => 'current outbound connections: %s', perfdatas => [ { template => '%s', min => 0 }, ], } }, { label => 'queue-active-recipients', nlabel => 'system.queue.recipients.active.current.count', set => { key_values => [ { name => 'active_recips' } ], output_template => 'queue active recipients: %s', perfdatas => [ { value => 'active_recips', template => '%s', min => 0 }, ], } }, { label => 'messages-quarantine', nlabel => 'system.queue.messages.quarantine.current.count', set => { key_values => [ { name => 'msgs_in_quarantine' } ], output_template => 'messages in quarantine: %s', perfdatas => [ { template => '%s', min => 0 }, ], } }, { label => 'messages-workqueue', nlabel => 'system.queue.messages.workqueue.current.count', set => { key_values => [ { name => 'msgs_in_work_queue' } ], output_template => 'messages in work queue: %s', perfdatas => [ { template => '%s', min => 0 }, ], } }, { label => 'messages-received', nlabel => 'system.queue.messages.received.persecond', set => { key_values => [ { name => 'msgs_received_lifetime', per_second => 1 } ], output_template => 'messages received: %.2f/s', perfdatas => [ { template => '%.2f', unit => '/s', min => 0 }, ], } }, { label => 'queuedisk', nlabel => 'system.queue.disk.usage.percentage', set => { key_values => [ { name => 'queuedisk' } ], output_template => 'queue disk usage: %.2f %%', perfdatas => [ { template => '%.2f', unit => '%', min => 0, max => 100 }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port', }, 'proto:s' => { name => 'proto', default => 'https' }, 'urlpath:s' => { name => 'url_path', default => "/xml/status" }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'timeout:s' => { name => 'timeout' }, 'unknown-http-status:s' => { name => 'unknown_http_status' }, 'warning-http-status:s' => { name => 'warning_http_status' }, 'critical-http-status:s' => { name => 'critical_http_status' }, 'warning-system-status:s' => { name => 'warning_system_status', default => '' }, 'critical-system-status:s' => { name => 'critical_system_status', default => '%{system_status} !~ /online/i' }, }); $self->{http} = centreon::plugins::http->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{hostname}) || $self->{option_results}->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify hostname option."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{username}) || $self->{option_results}->{username} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify username option."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{password}) || $self->{option_results}->{password} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify password option."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{curl_opt})) { $self->{option_results}->{curl_opt} = ['CURLOPT_SSL_VERIFYPEER => 0']; } if (!defined($self->{option_results}->{ssl_opt})) { $self->{option_results}->{ssl_opt} = ['SSL_verify_mode => SSL_VERIFY_NONE']; } $self->{option_results}->{credentials} = 1; $self->{http}->set_options(%{$self->{option_results}}); $self->change_macros(macros => ['warning_system_status', 'critical_system_status']); } sub manage_selection { my ($self, %options) = @_; my ($content) = $self->{http}->request( unknown_status => $self->{option_results}->{unknown_http_status}, warning_status => $self->{option_results}->{warning_http_status}, critical_status => $self->{option_results}->{critical_http_status}, ); my $xml_result; eval { $xml_result = XMLin($content, ForceArray => [], KeyAttr => [], SuppressEmpty => '' ); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode xml response: $@"); $self->{output}->option_exit(); } $self->{global} = { system_status => $xml_result->{system}->{status}, }; foreach (@{$xml_result->{gauges}->{gauge}}) { $self->{global}->{$_->{name}} = $_->{current}; } foreach (@{$xml_result->{counnters}->{counter}}) { $self->{global}->{$_->{name} . '_lifetime'} = $_->{lifetime}; } $self->{global}->{queuedisk} = $self->{global}->{kbytes_used} * 100 / ($self->{global}->{kbytes_used} + $self->{global}->{kbytes_free}); $self->{cache_name} = "cisco_ironport_" . $self->{option_results}->{hostname} . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check system usage. =over 8 =item B<--hostname> IP Address or FQDN of the webserver host =item B<--port> Port used. =item B<--proto> Protocol used http or https (Default: https) =item B<--urlpath> Set path to get server-status page in auto mode (Default: '/xml/status') =item B<--username> Specify username for authentication =item B<--password> Specify password for authentication =item B<--timeout> Threshold for HTTP timeout =item B<--unknown-http-status> Threshold unknown for http response code (Default: '%{http_code} < 200 or %{http_code} >= 300') =item B<--warning-http-status> Threshold warning for http response code =item B<--critical-http-status> Threshold critical for http response code =item B<--warning-system-status> Set warning threshold for status (Default: ''). Can used special variables like: %{system_status} =item B<--critical-system-status> Set critical threshold for status (Default: '%{system_status} !~ /online/i'). Can used special variables like: %{system_status} =item B<--warning-*> B<--critical-*> Warning threshold. Can be: 'memory' (%), 'cpu-total' (%), 'diskio' (%), 'log' (%), 'resource-conservation', 'connections-in', 'connections-out', 'queue-active-recipients', 'messages-quarantine', 'messages-workqueue', 'queuedisk' (%), 'messages-received'. =back =cut centreon-plugins-20220113/centreon/common/cisco/smallbusiness/000077500000000000000000000000001417000230700243255ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/cisco/smallbusiness/snmp/000077500000000000000000000000001417000230700253025ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/cisco/smallbusiness/snmp/mode/000077500000000000000000000000001417000230700262265ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/cisco/smallbusiness/snmp/mode/components/000077500000000000000000000000001417000230700304135ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/cisco/smallbusiness/snmp/mode/components/fan.pm000066400000000000000000000145151417000230700315230ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::smallbusiness::snmp::mode::components::fan; use strict; use warnings; use centreon::common::cisco::smallbusiness::snmp::mode::components::resources qw( $rl_envmon_state $oid_rlPhdUnitEnvParamMonitorAutoRecoveryEnable $oid_rlPhdUnitEnvParamEntry ); my $mapping_stack = { new => { rlPhdUnitEnvParamFan1Status => { oid => '.1.3.6.1.4.1.9.6.1.101.53.15.1.4', map => $rl_envmon_state }, rlPhdUnitEnvParamFan2Status => { oid => '.1.3.6.1.4.1.9.6.1.101.53.15.1.5', map => $rl_envmon_state }, rlPhdUnitEnvParamFan3Status => { oid => '.1.3.6.1.4.1.9.6.1.101.53.15.1.6', map => $rl_envmon_state }, rlPhdUnitEnvParamFan4Status => { oid => '.1.3.6.1.4.1.9.6.1.101.53.15.1.7', map => $rl_envmon_state }, rlPhdUnitEnvParamFan5Status => { oid => '.1.3.6.1.4.1.9.6.1.101.53.15.1.8', map => $rl_envmon_state }, rlPhdUnitEnvParamFan6Status => { oid => '.1.3.6.1.4.1.9.6.1.101.53.15.1.9', map => $rl_envmon_state } }, old => { rlPhdUnitEnvParamFan1Status => { oid => '.1.3.6.1.4.1.9.6.1.101.53.15.1.4', map => $rl_envmon_state }, rlPhdUnitEnvParamFan2Status => { oid => '.1.3.6.1.4.1.9.6.1.101.53.15.1.5', map => $rl_envmon_state }, rlPhdUnitEnvParamFan3Status => { oid => '.1.3.6.1.4.1.9.6.1.101.53.15.1.6', map => $rl_envmon_state }, rlPhdUnitEnvParamFan4Status => { oid => '.1.3.6.1.4.1.9.6.1.101.53.15.1.7', map => $rl_envmon_state }, rlPhdUnitEnvParamFan5Status => { oid => '.1.3.6.1.4.1.9.6.1.101.53.15.1.8', map => $rl_envmon_state } } }; my $mapping = { rlEnvMonFanStatusDescr => { oid => '.1.3.6.1.4.1.9.6.1.101.83.1.1.1.2' }, rlEnvMonFanState => { oid => '.1.3.6.1.4.1.9.6.1.101.83.1.1.1.3', map => $rl_envmon_state } }; my $oid_rlEnvMonFanStatusEntry = '.1.3.6.1.4.1.9.6.1.101.83.1.1.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_rlEnvMonFanStatusEntry, start => $mapping->{rlEnvMonFanStatusDescr}->{oid}, end => $mapping->{rlEnvMonFanState}->{oid} }; } sub check_fan_stack { my ($self) = @_; my $num_fans = 5; $num_fans = 6 if ($self->{sb_new} == 1); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_rlPhdUnitEnvParamEntry}})) { next if ($oid !~ /^$mapping_stack->{new}->{rlPhdUnitEnvParamFan1Status}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance( mapping => $self->{sb_new} == 1 ? $mapping_stack->{new} : $mapping_stack->{old}, results => $self->{results}->{$oid_rlPhdUnitEnvParamEntry}, instance => $instance ); for (my $i = 1; $i <= $num_fans; $i++) { my $instance2 = 'stack.' . $instance . '.fan.' . $i; my $name = 'rlPhdUnitEnvParamFan' . $i . 'Status'; next if ($self->check_filter(section => 'fan', instance => $instance2)); next if ($result->{$name} =~ /notPresent/i && $self->absent_problem(section => 'fan', instance => $instance2)); $self->{components}->{fan}->{total}++; $self->{output}->output_add( long_msg => sprintf( "fan '%s' status is '%s' [instance: %s]", $instance2, $result->{$name}, $instance2 ) ); my $exit = $self->get_severity(label => 'default', section => 'fan', value => $result->{$name}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Fan '%s' status is '%s'", $instance2, $result->{$name} ) ); } } } } sub check_fan { my ($self) = @_; foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_rlEnvMonFanStatusEntry}})) { next if ($oid !~ /^$mapping->{rlEnvMonFanState}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_rlEnvMonFanStatusEntry}, instance => $instance); next if ($self->check_filter(section => 'fan', instance => $instance)); if ($result->{rlEnvMonFanState} =~ /notPresent/i) { $self->absent_problem(section => 'fan', instance => $instance); next; } $self->{components}->{fan}->{total}++; $self->{output}->output_add( long_msg => sprintf( "fan '%s' status is '%s' [instance: %s]", $result->{rlEnvMonFanStatusDescr}, $result->{rlEnvMonFanState}, $instance ) ); my $exit = $self->get_severity(label => 'default', section => 'fan', value => $result->{rlEnvMonFanState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Fan '%s' status is '%s'", $result->{rlEnvMonFanStatusDescr}, $result->{rlEnvMonFanState} ) ); } } } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking fans"); $self->{components}->{fan} = { name => 'fan', total => 0, skip => 0 }; return if ($self->check_filter(section => 'fan')); check_fan($self); check_fan_stack($self); } 1; centreon-plugins-20220113/centreon/common/cisco/smallbusiness/snmp/mode/components/psu.pm000066400000000000000000000123221417000230700315600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::smallbusiness::snmp::mode::components::psu; use strict; use warnings; use centreon::common::cisco::smallbusiness::snmp::mode::components::resources qw( $rl_envmon_state $oid_rlPhdUnitEnvParamEntry ); my $mapping_stack = { rlPhdUnitEnvParamMainPSStatus => { oid => '.1.3.6.1.4.1.9.6.1.101.53.15.1.2', map => $rl_envmon_state }, rlPhdUnitEnvParamRedundantPSStatus => { oid => '.1.3.6.1.4.1.9.6.1.101.53.15.1.3', map => $rl_envmon_state } }; my $mapping = { rlEnvMonSupplyStatusDescr => { oid => '.1.3.6.1.4.1.9.6.1.101.83.1.2.1.2' }, rlEnvMonSupplyState => { oid => '.1.3.6.1.4.1.9.6.1.101.83.1.2.1.3', map => $rl_envmon_state } }; my $oid_rlEnvMonSupplyStatusEntry = '.1.3.6.1.4.1.9.6.1.101.83.1.2.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_rlEnvMonSupplyStatusEntry, $mapping->{rlEnvMonSupplyStatusDescr}->{oid}, $mapping->{rlEnvMonSupplyState}->{oid} }; } sub check_psu_stack { my ($self) = @_; foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_rlPhdUnitEnvParamEntry}})) { next if ($oid !~ /^$mapping_stack->{rlPhdUnitEnvParamMainPSStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping_stack, results => $self->{results}->{$oid_rlPhdUnitEnvParamEntry}, instance => $instance); foreach (['rlPhdUnitEnvParamMainPSStatus', 'main.psu'], ['rlPhdUnitEnvParamRedundantPSStatus', 'redundant.psu']) { my $instance2 = 'stack.' . $instance . '.' . $_->[1]; next if ($self->check_filter(section => 'psu', instance => $instance2)); next if ($result->{$_->[0]} =~ /notPresent/i && $self->absent_problem(section => 'psu', instance => $instance2)); $self->{components}->{psu}->{total}++; $self->{output}->output_add( long_msg => sprintf( "power supply '%s' status is '%s' [instance: %s]", $instance2, $result->{$_->[0]}, $instance2 ) ); my $exit = $self->get_severity(label => 'default', section => 'psu', value => $result->{$_->[0]}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Power supply '%s' status is '%s'", $instance2, $result->{$_->[0]} ) ); } } } } sub check_psu { my ($self) = @_; foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_rlEnvMonSupplyStatusEntry}})) { next if ($oid !~ /^$mapping->{rlEnvMonSupplyState}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_rlEnvMonSupplyStatusEntry}, instance => $instance); next if ($self->check_filter(section => 'psu', instance => $instance)); if ($result->{rlEnvMonSupplyState} =~ /notPresent/i) { $self->absent_problem(section => 'psu', instance => $instance); next; } $self->{components}->{psu}->{total}++; $self->{output}->output_add( long_msg => sprintf( "power supply '%s' status is '%s' [instance: %s]", $result->{rlEnvMonSupplyStatusDescr}, $result->{rlEnvMonSupplyState}, $instance ) ); my $exit = $self->get_severity(label => 'default', section => 'psu', value => $result->{rlEnvMonSupplyState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Power supply '%s' status is '%s'", $result->{rlEnvMonSupplyStatusDescr}, $result->{rlEnvMonSupplyState} ) ); } } } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking power supplies"); $self->{components}->{psu} = { name => 'psu', total => 0, skip => 0 }; return if ($self->check_filter(section => 'psu')); check_psu($self); check_psu_stack($self); } 1; centreon-plugins-20220113/centreon/common/cisco/smallbusiness/snmp/mode/components/resources.pm000066400000000000000000000027741417000230700327750ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::smallbusiness::snmp::mode::components::resources; use strict; use warnings; use Exporter; our $rl_envmon_state; our $oid_rlPhdUnitEnvParamMonitorAutoRecoveryEnable; our $oid_rlPhdUnitEnvParamEntry; our @ISA = qw(Exporter); our @EXPORT_OK = qw( $rl_envmon_state $oid_rlPhdUnitEnvParamMonitorAutoRecoveryEnable $oid_rlPhdUnitEnvParamEntry ); $rl_envmon_state = { 1 => 'normal', 2 => 'warning', 3 => 'critical', 4 => 'shutdown', 5 => 'notPresent', 6 => 'notFunctioning', 7 => 'notAvailable', 8 => 'backingUp', 9 => 'readingFailed' }; $oid_rlPhdUnitEnvParamMonitorAutoRecoveryEnable = '.1.3.6.1.4.1.9.6.1.101.53.15.1.15'; $oid_rlPhdUnitEnvParamEntry = '.1.3.6.1.4.1.9.6.1.101.53.15.1'; 1; centreon-plugins-20220113/centreon/common/cisco/smallbusiness/snmp/mode/components/temperature.pm000066400000000000000000000130641417000230700333120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::smallbusiness::snmp::mode::components::temperature; use strict; use warnings; use centreon::common::cisco::smallbusiness::snmp::mode::components::resources qw($oid_rlPhdUnitEnvParamEntry); my $map_entity_sensor = { 1 => 'ok', 2 => 'unavailable', 3 => 'nonoperational' }; my $mapping = { new => { rlPhdUnitEnvParamTempSensorValue => { oid => '.1.3.6.1.4.1.9.6.1.101.53.15.1.10' }, rlPhdUnitEnvParamTempSensorStatus => { oid => '.1.3.6.1.4.1.9.6.1.101.53.15.1.11', map => $map_entity_sensor }, rlPhdUnitEnvParamTempSensorWarningThresholdValue => { oid => '.1.3.6.1.4.1.9.6.1.101.53.15.1.12' }, rlPhdUnitEnvParamTempSensorCriticalThresholdValue => { oid => '.1.3.6.1.4.1.9.6.1.101.53.15.1.13' } }, old => { rlPhdUnitEnvParamTempSensorValue => { oid => '.1.3.6.1.4.1.9.6.1.101.53.15.1.9' }, rlPhdUnitEnvParamTempSensorStatus => { oid => '.1.3.6.1.4.1.9.6.1.101.53.15.1.10', map => $map_entity_sensor }, } }; sub load {} sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking temperatures"); $self->{components}->{temperature} = { name => 'temperatures', total => 0, skip => 0 }; return if ($self->check_filter(section => 'temperature')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_rlPhdUnitEnvParamEntry}})) { next if ($oid !~ /^$mapping->{new}->{rlPhdUnitEnvParamTempSensorValue}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance( mapping => $self->{sb_new} == 1 ? $mapping->{new} : $mapping->{old}, results => $self->{results}->{$oid_rlPhdUnitEnvParamEntry}, instance => $instance ); next if ($self->check_filter(section => 'temperature', instance => $instance)); $self->{components}->{temperature}->{total}++; $self->{output}->output_add( long_msg => sprintf( "temperature '%s' status is '%s' [instance = %s, value: %s degree centigrade]", $instance, $result->{rlPhdUnitEnvParamTempSensorStatus}, $instance, $result->{rlPhdUnitEnvParamTempSensorValue} ) ); my $exit = $self->get_severity(section => 'temperature', value => $result->{rlPhdUnitEnvParamTempSensorStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Temperature '%s' status is '%s'", $instance, $result->{rlPhdUnitEnvParamTempSensorStatus} ) ); } my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $instance, value => $result->{rlPhdUnitEnvParamTempSensorValue}); if ($checked == 0 && defined($result->{rlPhdUnitEnvParamTempSensorWarningThresholdValue})) { my $warn_th = ':' . $result->{rlPhdUnitEnvParamTempSensorWarningThresholdValue}; my $crit_th = ':' . $result->{rlPhdUnitEnvParamTempSensorCriticalThresholdValue}; $self->{perfdata}->threshold_validate(label => 'warning-temperature-instance-' . $instance, value => $warn_th); $self->{perfdata}->threshold_validate(label => 'critical-temperature-instance-' . $instance, value => $crit_th); $exit2 = $self->{perfdata}->threshold_check( value => $result->{rlPhdUnitEnvParamTempSensorValue}, threshold => [ { label => 'critical-temperature-instance-' . $instance, exit_litteral => 'critical' }, { label => 'warning-temperature-instance-' . $instance, exit_litteral => 'warning' } ] ); $warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-temperature-instance-' . $instance); $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-temperature-instance-' . $instance); } if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit2, short_msg => sprintf( "Temperature '%s' is %s degree centigrade", $instance, $result->{rlPhdUnitEnvParamTempSensorValue} ) ); } $self->{output}->perfdata_add( label => 'temp', unit => 'C', nlabel => 'hardware.temperature.celsius', instances => $instance, value => $result->{rlPhdUnitEnvParamTempSensorValue}, warning => $warn, critical => $crit ); } } 1; centreon-plugins-20220113/centreon/common/cisco/smallbusiness/snmp/mode/cpu.pm000066400000000000000000000146371417000230700273660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::smallbusiness::snmp::mode::cpu; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning:s" => { name => 'warning', default => '' }, "critical:s" => { name => 'critical', default => '' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); ($self->{warn1s}, $self->{warn1m}, $self->{warn5m}) = split /,/, $self->{option_results}->{warning}; ($self->{crit1s}, $self->{crit1m}, $self->{crit5m}) = split /,/, $self->{option_results}->{critical}; if (($self->{perfdata}->threshold_validate(label => 'warn1s', value => $self->{warn1s})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning (1sec) threshold '" . $self->{warn1s} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'warn1m', value => $self->{warn1m})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning (1min) threshold '" . $self->{warn1m} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'warn5m', value => $self->{warn5m})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning (5min) threshold '" . $self->{warn5m} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'crit1s', value => $self->{crit1s})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical (1sec) threshold '" . $self->{crit1s} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'crit1m', value => $self->{crit1m})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical (1min) threshold '" . $self->{crit1m} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'crit5m', value => $self->{crit5m})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical (5min) threshold '" . $self->{crit5m} . "'."); $self->{output}->option_exit(); } } sub run { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; my $oid_rlCpuUtilDuringLastSecond = '.1.3.6.1.4.1.9.6.1.101.1.7.0'; my $oid_rlCpuUtilDuringLastMinute = '.1.3.6.1.4.1.9.6.1.101.1.8.0'; my $oid_rlCpuUtilDuringLast5Minutes = '.1.3.6.1.4.1.9.6.1.101.1.9.0'; $self->{results} = $self->{snmp}->get_leef(oids => [$oid_rlCpuUtilDuringLastSecond, $oid_rlCpuUtilDuringLastMinute, $oid_rlCpuUtilDuringLast5Minutes], nothing_quit => 1); my $cpu1sec = $self->{results}->{$oid_rlCpuUtilDuringLastSecond}; my $cpu1min = $self->{results}->{$oid_rlCpuUtilDuringLastMinute}; my $cpu5min = $self->{results}->{$oid_rlCpuUtilDuringLast5Minutes}; my $exit1 = $self->{perfdata}->threshold_check(value => $cpu1sec, threshold => [ { label => 'crit1s', exit_litteral => 'critical' }, { label => 'warn1s', exit_litteral => 'warning' } ]); my $exit2 = $self->{perfdata}->threshold_check(value => $cpu1min, threshold => [ { label => 'crit1m', exit_litteral => 'critical' }, { label => 'warn1m', exit_litteral => 'warning' } ]); my $exit3 = $self->{perfdata}->threshold_check(value => $cpu5min, threshold => [ { label => 'crit5m', exit_litteral => 'critical' }, { label => 'warn5m', exit_litteral => 'warning' } ]); my $exit = $self->{output}->get_most_critical(status => [ $exit1, $exit2, $exit3 ]); $self->{output}->output_add(severity => $exit, short_msg => sprintf("CPU: %.2f%% (1sec), %.2f%% (1min), %.2f%% (5min)", $cpu1sec, $cpu1min, $cpu5min)); $self->{output}->perfdata_add(label => "cpu_1s", unit => '%', value => $cpu1sec, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warn1s'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'crit1s'), min => 0, max => 100); $self->{output}->perfdata_add(label => "cpu_1m", unit => '%', value => $cpu1min, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warn1m'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'crit1m'), min => 0, max => 100); $self->{output}->perfdata_add(label => "cpu_5m", unit => '%', value => $cpu5min, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warn5m'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'crit5m'), min => 0, max => 100); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check cpu usage (CISCOSBmng.mib). =over 8 =item B<--warning> Threshold warning in percent (1s,1min,5min). =item B<--critical> Threshold critical in percent (1s,1min,5min). =back =cut centreon-plugins-20220113/centreon/common/cisco/smallbusiness/snmp/mode/environment.pm000066400000000000000000000072631417000230700311400ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::smallbusiness::snmp::mode::environment; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; use centreon::common::cisco::smallbusiness::snmp::mode::components::resources qw( $oid_rlPhdUnitEnvParamEntry $oid_rlPhdUnitEnvParamMonitorAutoRecoveryEnable ); sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^temperature$'; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { default => [ ['normal', 'OK'], ['notPresent', 'OK'], ['warning', 'WARNING'], ['critical', 'CRITICAL'], ['shutdown', 'CRITICAL'], ['notFunctioning', 'CRITICAL'] ], temperature => [ ['ok', 'OK'], ['unavailable', 'OK'], ['nonoperational', 'CRITICAL'] ] }; $self->{components_path} = 'centreon::common::cisco::smallbusiness::snmp::mode::components'; $self->{components_module} = ['psu', 'fan', 'temperature']; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; push @{$self->{request}}, { oid => $oid_rlPhdUnitEnvParamEntry, start => '.1.3.6.1.4.1.9.6.1.101.53.15.1.2', # rlPhdUnitEnvParamMainPSStatus end => $oid_rlPhdUnitEnvParamMonitorAutoRecoveryEnable }; $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); $self->{sb_new} = 0; foreach (keys %{$self->{results}->{$oid_rlPhdUnitEnvParamEntry}}) { if (/^$oid_rlPhdUnitEnvParamMonitorAutoRecoveryEnable\./) { $self->{sb_new} = 1; last; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } 1; __END__ =head1 MODE Check environment. =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'fan', 'psu', 'temperature'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=psu) Can also exclude specific instance: --filter=psu,0 =item B<--absent-problem> Return an error if an entity is not 'present' (default is skipping) (comma seperated list) Can be specific or global: --absent-problem=fan#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='fan,CRITICAL,^(?!(normal)$)' =item B<--warning> Set warning threshold (syntax: type,regexp,threshold) Example: --warning='temperature,.*,30' =item B<--critical> Set critical threshold (syntax: type,regexp,threshold) Example: --critical='temperature,.*,40' =back =cut centreon-plugins-20220113/centreon/common/cisco/standard/000077500000000000000000000000001417000230700232415ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/cisco/standard/snmp/000077500000000000000000000000001417000230700242165ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/cisco/standard/snmp/mode/000077500000000000000000000000001417000230700251425ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/cisco/standard/snmp/mode/aaaservers.pm000066400000000000000000000301101417000230700276270ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::standard::snmp::mode::aaaservers; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use Digest::MD5 qw(md5_hex); sub custom_status_output { my ($self, %options) = @_; return sprintf( 'status: %s', $self->{result_values}->{status} ); } sub prefix_aaa_output { my ($self, %options) = @_; return sprintf( "Server '%s' [protocol: %s] ", $options{instance_value}->{name}, $options{instance_value}->{protocol} ); } sub aaa_long_output { my ($self, %options) = @_; return sprintf( "checking server '%s' [protocol: %s]", $options{instance_value}->{name}, $options{instance_value}->{protocol} ); } sub prefix_auth_output { my ($self, %options) = @_; return 'authentication '; } sub prefix_acc_output { my ($self, %options) = @_; return 'accounting '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'aaa', type => 3, cb_prefix_output => 'prefix_aaa_output', cb_long_output => 'aaa_long_output', indent_long_output => ' ', message_multiple => 'All AAA servers are ok', group => [ { name => 'global_status', type => 0, skipped_code => { -10 => 1 } }, { name => 'global_auth', type => 0, cb_prefix_output => 'prefix_auth_output', skipped_code => { -10 => 1 } }, { name => 'global_acc', type => 0, cb_prefix_output => 'prefix_acc_output', skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'total', nlabel => 'aaa_servers.total.count', display_ok => 0, set => { key_values => [ { name => 'total' } ], output_template => 'total servers: %s', perfdatas => [ { template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{global_status} = [ { label => 'status', type => 2, critical_default => '%{status} =~ /dead/i', set => { key_values => [ { name => 'status' }, { name => 'name' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{global_auth} = [ { label => 'auth-requests', nlabel => 'aaa_server.authentication.requests.persecond', set => { key_values => [ { name => 'auth_requests', per_second => 1 } ], output_template => 'requests: %.2f/s', perfdatas => [ { template => '%.2f', min => 0, unit => '/s', label_extra_instance => 1 } ] } }, { label => 'auth-requests-timeout', nlabel => 'aaa_server.authentication.requests.timeout.count', set => { key_values => [ { name => 'auth_timeouts', diff => 1 } ], output_template => 'requests timeout: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } }, { label => 'auth-transactions-suceeded', nlabel => 'aaa_server.authentication.transactions.succeeded.persecond', set => { key_values => [ { name => 'auth_trans_success', per_second => 1 } ], output_template => 'transactions succeeded: %.2f/s', perfdatas => [ { template => '%.2f', min => 0, unit => '/s', label_extra_instance => 1 } ] } }, { label => 'auth-roundtrip-time', nlabel => 'aaa_server.authentication.roundtrip.time.milliseconds', set => { key_values => [ { name => 'auth_reponse_time' } ], output_template => 'round trip time: %s ms', perfdatas => [ { template => '%s', min => 0, unit => 'ms', label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{global_acc} = [ { label => 'acc-requests', nlabel => 'aaa_server.accounting.requests.persecond', set => { key_values => [ { name => 'acc_requests', per_second => 1 } ], output_template => 'requests: %.2f/s', perfdatas => [ { template => '%.2f', min => 0, unit => '/s', label_extra_instance => 1 } ] } }, { label => 'acc-requests-timeout', nlabel => 'aaa_server.accounting.requests.timeout.count', set => { key_values => [ { name => 'acc_timeouts', diff => 1 } ], output_template => 'requests timeout: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } }, { label => 'acc-transactions-suceeded', nlabel => 'aaa_server.accounting.transactions.succeeded.persecond', set => { key_values => [ { name => 'acc_trans_success', per_second => 1 } ], output_template => 'transactions succeeded: %.2f/s', perfdatas => [ { template => '%.2f', min => 0, unit => '/s', label_extra_instance => 1 } ] } }, { label => 'acc-roundtrip-time', nlabel => 'aaa_server.accounting.roundtrip.time.milliseconds', set => { key_values => [ { name => 'acc_reponse_time' } ], output_template => 'round trip time: %s ms', perfdatas => [ { template => '%s', min => 0, unit => 'ms', label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } my $map_protocol = { 1 => 'tacacsplus', 2 => 'radius', 3 => 'ldap', 4 => 'kerberos', 5 => 'ntlm', 6 => 'sdi', 7 => 'other' }; my $map_status = { 1 => 'up', 2 => 'dead' }; my $mapping = { auth_requests => { oid => '.1.3.6.1.4.1.9.10.56.1.2.1.1.1' }, # casAuthenRequests auth_timeouts => { oid => '.1.3.6.1.4.1.9.10.56.1.2.1.1.2' }, # casAuthenRequestTimeouts auth_reponse_time => { oid => '.1.3.6.1.4.1.9.10.56.1.2.1.1.6' }, # casAuthenResponseTime (unit 0.01 of sec) auth_trans_success => { oid => '.1.3.6.1.4.1.9.10.56.1.2.1.1.7' }, # casAuthenTransactionSuccesses acc_requests => { oid => '.1.3.6.1.4.1.9.10.56.1.2.1.1.17' }, # casAcctRequests acc_timeouts => { oid => '.1.3.6.1.4.1.9.10.56.1.2.1.1.18' }, # casAcctRequestTimeouts acc_reponse_time => { oid => '.1.3.6.1.4.1.9.10.56.1.2.1.1.22' }, # casAcctResponseTime (unit 0.01 of sec) acc_trans_success => { oid => '.1.3.6.1.4.1.9.10.56.1.2.1.1.23' }, # casAcctTransactionSuccesses status => { oid => '.1.3.6.1.4.1.9.10.56.1.2.1.1.25', map => $map_status } # casState }; my $mapping_name = { address => { oid => '.1.3.6.1.4.1.9.10.56.1.1.2.1.3' }, # casAddress authen_port => { oid => '.1.3.6.1.4.1.9.10.56.1.1.2.1.4' }, # casAuthenPort acc_port => { oid => '.1.3.6.1.4.1.9.10.56.1.1.2.1.5' } # casAcctPort }; sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = 'cisco_standard_' . $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')); my $oid_casConfigEntry = '.1.3.6.1.4.1.9.10.56.1.1.2.1'; my $snmp_result = $options{snmp}->get_table( oid => $oid_casConfigEntry, start => $mapping_name->{address}->{oid}, end => $mapping_name->{acc_port}->{oid}, nothing_quit => 1 ); $self->{aaa} = {}; foreach (keys %$snmp_result) { next if (! /^$mapping_name->{address}->{oid}\.((\d+).*)$/); my ($instance, $protocol) = ($1, $map_protocol->{$2}); my $result = $options{snmp}->map_instance(mapping => $mapping_name, results => $snmp_result, instance => $instance); my $name = $result->{address} . ':' . $result->{authen_port} . ':' . $result->{acc_port}; 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->{aaa}->{$name} = { %$result, name => $name, protocol => $protocol, instance => $instance }; } $self->{global} = { total => scalar(keys %{$self->{aaa}}) }; return if (scalar(keys %{$self->{aaa}}) <= 0); $options{snmp}->load(oids => [ map($_->{oid}, values(%$mapping)) ], instances => [map($_->{instance}, values(%{$self->{aaa}}))], instance_regexp => '^(.*)$' ); $snmp_result = $options{snmp}->get_leef(nothing_quit => 1); foreach (keys %{$self->{aaa}}) { my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $self->{aaa}->{$_}->{instance}); $self->{aaa}->{$_}->{global_status} = { name => $self->{aaa}->{$_}->{name}, status => $result->{status} }; $self->{aaa}->{$_}->{global_auth} = { auth_requests => $result->{auth_requests}, auth_timeouts => $result->{auth_timeouts}, auth_trans_success => $result->{auth_trans_success}, auth_reponse_time => $result->{auth_reponse_time} * 10 }; $self->{aaa}->{$_}->{global_acc} = { acc_requests => $result->{acc_requests}, acc_timeouts => $result->{acc_timeouts}, acc_trans_success => $result->{acc_trans_success}, acc_reponse_time => $result->{acc_reponse_time} * 10 }; } } 1; __END__ =head1 MODE Check AAA servers. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='auth' =item B<--filter-name> Filter AAA server by name (E.g.: 10.199.126.100:1812:1813. Format: [address]:[authPort]:[accPort]). =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{status}, %{name} =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{status}, %{name} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /dead/i'). Can used special variables like: %{status}, %{name} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'total', 'auth-requests', 'auth-requests-timeout', 'auth-transactions-suceeded', 'auth-roundtrip-time', 'acc-requests', 'acc-requests-timeout', 'acc-transactions-suceeded', 'acc-roundtrip-time'. =back =cut centreon-plugins-20220113/centreon/common/cisco/standard/snmp/mode/components/000077500000000000000000000000001417000230700273275ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/cisco/standard/snmp/mode/components/fan.pm000066400000000000000000000115751417000230700304420ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::standard::snmp::mode::components::fan; use strict; use warnings; my %map_fan_state1 = ( 1 => 'normal', 2 => 'warning', 3 => 'critical', 4 => 'shutdown', 5 => 'not present', 6 => 'not functioning', ); my %map_fan_state2 = ( 1 => 'unknown', 2 => 'up', 3 => 'down', 4 => 'warning', ); my $oid_ciscoEnvMonFanStatusEntry = '.1.3.6.1.4.1.9.9.13.1.4.1'; # CISCO-ENVMON-MIB my $oid_cefcFanTrayOperStatus = '.1.3.6.1.4.1.9.9.117.1.4.1.1.1'; # CISCO-ENTITY-SENSOR-MIB sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_ciscoEnvMonFanStatusEntry }, { oid => $oid_cefcFanTrayOperStatus }; } sub check_fan_envmon { my ($self) = @_; my $mapping = { ciscoEnvMonFanStatusDescr => { oid => '.1.3.6.1.4.1.9.9.13.1.4.1.2' }, ciscoEnvMonFanState => { oid => '.1.3.6.1.4.1.9.9.13.1.4.1.3', map => \%map_fan_state1 }, }; foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_ciscoEnvMonFanStatusEntry}})) { next if ($oid !~ /^$mapping->{ciscoEnvMonFanStatusDescr}->{oid}\./); $oid =~ /\.([0-9]+)$/; my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_ciscoEnvMonFanStatusEntry}, instance => $instance); next if ($self->check_filter(section => 'fan', instance => $instance, name => $result->{ciscoEnvMonFanStatusDescr})); next if ($result->{ciscoEnvMonFanState} =~ /not present/i && $self->absent_problem(section => 'fan', instance => $instance, name => $result->{ciscoEnvMonFanStatusDescr})); $self->{components}->{fan}->{total}++; $self->{output}->output_add( long_msg => sprintf( "fan '%s' status is %s [instance: %s].", $result->{ciscoEnvMonFanStatusDescr}, $result->{ciscoEnvMonFanState}, $instance ) ); my $exit = $self->get_severity(section => 'fan', instance => $instance, value => $result->{ciscoEnvMonFanState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "fan '%s' status is %s", $result->{ciscoEnvMonFanStatusDescr}, $result->{ciscoEnvMonFanState} ) ); } } } sub check_fan_entity { my ($self) = @_; my $mapping = { cefcFanTrayOperStatus => { oid => '.1.3.6.1.4.1.9.9.117.1.4.1.1.1', map => \%map_fan_state2 } }; foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_cefcFanTrayOperStatus}})) { $oid =~ /\.([0-9]+)$/; my $instance = $1; my $fan_descr = $self->{results}->{ $self->{physical_name} }->{ $self->{physical_name} . '.' . $instance }; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_cefcFanTrayOperStatus}, instance => $instance); next if ($self->check_filter(section => 'fan', instance => $instance, name => $fan_descr)); $self->{components}->{fan}->{total}++; $self->{output}->output_add( long_msg => sprintf( "fan '%s' status is %s [instance: %s]", $fan_descr, $result->{cefcFanTrayOperStatus}, $instance ) ); my $exit = $self->get_severity(section => 'fan', instance => $instance, value => $result->{cefcFanTrayOperStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Fan '%s/%s' status is %s", $fan_descr, $instance, $result->{cefcFanTrayOperStatus}) ); } } } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking fans"); $self->{components}->{fan} = { name => 'fans', total => 0, skip => 0 }; return if ($self->check_filter(section => 'fan')); check_fan_envmon($self); check_fan_entity($self); } 1; centreon-plugins-20220113/centreon/common/cisco/standard/snmp/mode/components/module.pm000066400000000000000000000066371417000230700311660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::standard::snmp::mode::components::module; use strict; use warnings; my %map_module_state = ( 1 => 'unknown', 2 => 'ok', 3 => 'disabled', 4 => 'okButDiagFailed', 5 => 'boot', 6 => 'selfTest', 7 => 'failed', 8 => 'missing', 9 => 'mismatchWithParent', 10 => 'mismatchConfig', 11 => 'diagFailed', 12 => 'dormant', 13 => 'outOfServiceAdmin', 14 => 'outOfServiceEnvTemp', 15 => 'poweredDown', 16 => 'poweredUp', 17 => 'powerDenied', 18 => 'powerCycled', 19 => 'okButPowerOverWarning', 20 => 'okButPowerOverCritical', 21 => 'syncInProgress', 22 => 'upgrading', 23 => 'okButAuthFailed', 24 => 'mdr', 25 => 'fwMismatchFound', 26 => 'fwDownloadSuccess', 27 => 'fwDownloadFailure' ); # In MIB 'CISCO-ENTITY-FRU-CONTROL-MIB' my $mapping = { cefcModuleOperStatus => { oid => '.1.3.6.1.4.1.9.9.117.1.2.1.1.2', map => \%map_module_state } }; my $oid_cefcModuleOperStatus = '.1.3.6.1.4.1.9.9.117.1.2.1.1.2'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_cefcModuleOperStatus }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking modules"); $self->{components}->{module} = {name => 'modules', total => 0, skip => 0}; return if ($self->check_filter(section => 'module')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_cefcModuleOperStatus}})) { $oid =~ /\.([0-9]+)$/; my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_cefcModuleOperStatus}, instance => $instance); my $module_descr = $self->{results}->{$self->{physical_name} }->{ $self->{physical_name} . '.' . $instance }; next if ($self->check_filter(section => 'module', instance => $instance, name => $module_descr)); $self->{components}->{module}->{total}++; $self->{output}->output_add( long_msg => sprintf( "module '%s' status is %s [instance: %s]", $module_descr, $result->{cefcModuleOperStatus}, $instance ) ); my $exit = $self->get_severity(section => 'module', instance => $instance, value => $result->{cefcModuleOperStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Module '%s/%s' status is %s", $module_descr, $instance, $result->{cefcModuleOperStatus} ) ); } } } 1; centreon-plugins-20220113/centreon/common/cisco/standard/snmp/mode/components/physical.pm000066400000000000000000000060111417000230700314770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::standard::snmp::mode::components::physical; use strict; use warnings; my %map_physical_state = ( 1 => 'other', 2 => 'supported', 3 => 'unsupported', 4 => 'incompatible', ); # In MIB 'CISCO-ENTITY-SENSOR-MIB' my $mapping = { cefcPhysicalStatus => { oid => '.1.3.6.1.4.1.9.9.117.1.5.1.1.1', map => \%map_physical_state } }; my $oid_cefcPhysicalStatus = '.1.3.6.1.4.1.9.9.117.1.5.1.1.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_cefcPhysicalStatus }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking physicals"); $self->{components}->{physical} = {name => 'physical', total => 0, skip => 0}; return if ($self->check_filter(section => 'physical')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_cefcPhysicalStatus}})) { $oid =~ /\.([0-9]+)$/; my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_cefcPhysicalStatus}, instance => $instance); my $physical_descr = $self->{results}->{ $self->{physical_name} }->{ $self->{physical_name} . '.' . $instance}; if (!defined($physical_descr)) { $self->{output}->output_add(long_msg => sprintf("skipped instance '%s': no description", $instance)); next; } next if ($self->check_filter(section => 'physical', instance => $instance, name => $physical_descr)); $self->{components}->{physical}->{total}++; $self->{output}->output_add( long_msg => sprintf( "physical '%s' status is %s [instance: %s]", $physical_descr, $result->{cefcPhysicalStatus}, $instance ) ); my $exit = $self->get_severity(section => 'physical', instance => $instance, value => $result->{cefcPhysicalStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Physical '%s/%s' status is %s", $physical_descr, $instance, $result->{cefcPhysicalStatus} ) ); } } } 1; centreon-plugins-20220113/centreon/common/cisco/standard/snmp/mode/components/psu.pm000066400000000000000000000130031417000230700304710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::standard::snmp::mode::components::psu; use strict; use warnings; my %map_psu_source = ( 1 => 'unknown', 2 => 'ac', 3 => 'dc', 4 => 'externalPowerSupply', 5 => 'internalRedundant' ); my %map_psu_state1 = ( 1 => 'normal', 2 => 'warning', 3 => 'critical', 4 => 'shutdown', 5 => 'not present', 6 => 'not functioning' ); my %map_psu_state2 = ( 1 => 'offEnvOther', 2 => 'on', 3 => 'offAdmin', 4 => 'offDenied', 5 => 'offEnvPower', 6 => 'offEnvTemp', 7 => 'offEnvFan', 8 => 'failed', 9 => 'onButFanFail', 10 => 'offCooling', 11 => 'offConnectorRating', 12 => 'onButInlinePowerFail' ); my $oid_ciscoEnvMonSupplyStatusEntry = '.1.3.6.1.4.1.9.9.13.1.5.1'; # CISCO-ENVMON-MIB my $oid_cefcFRUPowerOperStatus = '.1.3.6.1.4.1.9.9.117.1.1.2.1.2'; # CISCO-ENTITY-SENSOR-MIB sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_ciscoEnvMonSupplyStatusEntry }, { oid => $oid_cefcFRUPowerOperStatus }; } sub check_psu_envmon { my ($self) = @_; my $mapping = { ciscoEnvMonSupplyStatusDescr => { oid => '.1.3.6.1.4.1.9.9.13.1.5.1.2' }, ciscoEnvMonSupplyState => { oid => '.1.3.6.1.4.1.9.9.13.1.5.1.3', map => \%map_psu_state1 }, ciscoEnvMonSupplySource => { oid => '.1.3.6.1.4.1.9.9.13.1.5.1.4', map => \%map_psu_source } }; foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_ciscoEnvMonSupplyStatusEntry}})) { next if ($oid !~ /^$mapping->{ciscoEnvMonSupplyStatusDescr}->{oid}\./); $oid =~ /\.([0-9]+)$/; my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_ciscoEnvMonSupplyStatusEntry}, instance => $instance); next if ($self->check_filter(section => 'psu', instance => $instance, name => $result->{ciscoEnvMonSupplyStatusDescr})); next if ($result->{ciscoEnvMonSupplyState} =~ /not present/i && $self->absent_problem(section => 'psu', instance => $instance, name => $result->{ciscoEnvMonSupplyStatusDescr})); $self->{components}->{psu}->{total}++; $self->{output}->output_add( long_msg => sprintf( "power supply '%s' status is %s [instance: %s] [source: %s]", $result->{ciscoEnvMonSupplyStatusDescr}, $result->{ciscoEnvMonSupplyState}, $instance, $result->{ciscoEnvMonSupplySource} ) ); my $exit = $self->get_severity(section => 'psu', instance => $instance, value => $result->{ciscoEnvMonSupplyState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Power supply '%s' status is %s", $result->{ciscoEnvMonSupplyStatusDescr}, $result->{ciscoEnvMonSupplyState} ) ); } } } sub check_psu_entity { my ($self) = @_; my $mapping = { cefcFRUPowerOperStatus => { oid => '.1.3.6.1.4.1.9.9.117.1.1.2.1.2', map => \%map_psu_state2 } }; foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_cefcFRUPowerOperStatus}})) { $oid =~ /\.([0-9]+)$/; my $instance = $1; my $psu_descr = $self->{results}->{ $self->{physical_name} }->{ $self->{physical_name} . '.' . $instance }; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_cefcFRUPowerOperStatus}, instance => $instance); next if ($self->check_filter(section => 'psu', instance => $instance, name => $psu_descr)); $self->{components}->{psu}->{total}++; $self->{output}->output_add( long_msg => sprintf( "Power supply '%s' status is %s [instance: %s]", $psu_descr, $result->{cefcFRUPowerOperStatus}, $instance ) ); my $exit = $self->get_severity(section => 'psu', instance => $instance, value => $result->{cefcFRUPowerOperStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Power supply '%s/%s' status is %s", $psu_descr, $instance, $result->{cefcFRUPowerOperStatus} ) ); } } } 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')); check_psu_envmon($self); check_psu_entity($self); } 1; centreon-plugins-20220113/centreon/common/cisco/standard/snmp/mode/components/sensor.pm000066400000000000000000000326431417000230700312060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::standard::snmp::mode::components::sensor; use strict; use warnings; use centreon::plugins::misc; my %map_sensor_status = ( 1 => 'ok', 2 => 'unavailable', 3 => 'nonoperational', ); my %map_sensor_type = ( 1 => 'other', 2 => 'unknown', 3 => 'voltsAC', 4 => 'voltsDC', 5 => 'amperes', 6 => 'watts', 7 => 'hertz', 8 => 'celsius', 9 => 'percentRH', 10 => 'rpm', 11 => 'cmm', 12 => 'truthvalue', 13 => 'specialEnum', 14 => 'dBm' ); my %map_scale = ( 1 => -24, # yocto, 2 => -21, # zepto 3 => -18, # atto 4 => -15, # femto 5 => -12, # pico 6 => -9, # nano 7 => -6, # micro 8 => -3, # milli 9 => 0, #units 10 => 3, #kilo 11 => 6, #mega 12 => 9, #giga 13 => 12, #tera 14 => 18, #exa 15 => 15, #peta 16 => 21, #zetta 17 => 24 #yotta ); my %map_severity = ( 1 => 'other', 10 => 'minor', 20 => 'major', 30 => 'critical' ); my %map_relation = ( 1 => 'lessThan', 2 => 'lessOrEqual', 3 => 'greaterThan', 4 => 'greaterOrEqual', 5 => 'equalTo', 6 => 'notEqualTo' ); my %perfdata_unit = ( 'other' => '', 'unknown' => '', 'voltsAC' => 'V', 'voltsDC' => 'V', 'amperes' => 'A', 'watts' => 'W', 'hertz' => 'Hz', 'celsius' => 'C', 'percentRH' => '%', 'rpm' => 'rpm', 'cmm' => '', 'truthvalue' => '', 'specialEnum' => '', 'dBm' => 'dBm' ); # In MIB 'CISCO-ENTITY-SENSOR-MIB' my $mapping = { entSensorType => { oid => '.1.3.6.1.4.1.9.9.91.1.1.1.1.1', map => \%map_sensor_type }, entSensorScale => { oid => '.1.3.6.1.4.1.9.9.91.1.1.1.1.2', map => \%map_scale }, entSensorPrecision => { oid => '.1.3.6.1.4.1.9.9.91.1.1.1.1.3' }, entSensorValue => { oid => '.1.3.6.1.4.1.9.9.91.1.1.1.1.4' }, entSensorStatus => { oid => '.1.3.6.1.4.1.9.9.91.1.1.1.1.5', map => \%map_sensor_status }, entSensorValueUpdateRate => { oid => '.1.3.6.1.4.1.9.9.91.1.1.1.1.7' } # 0 means no threshold check }; my $mapping2 = { entSensorThresholdSeverity => { oid => '.1.3.6.1.4.1.9.9.91.1.2.1.1.2', map => \%map_severity }, entSensorThresholdRelation => { oid => '.1.3.6.1.4.1.9.9.91.1.2.1.1.3', map => \%map_relation }, entSensorThresholdValue => { oid => '.1.3.6.1.4.1.9.9.91.1.2.1.1.4' } }; my $oid_entSensorValueEntry = '.1.3.6.1.4.1.9.9.91.1.1.1.1'; my $oid_entSensorThresholdEntry = '.1.3.6.1.4.1.9.9.91.1.2.1.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_entSensorValueEntry, end => $mapping->{entSensorStatus}->{oid} }, { oid => $oid_entSensorThresholdEntry, end => $mapping2->{entSensorThresholdValue}->{oid} }; } sub get_default_warning_threshold { my ($self, %options) = @_; my ($high_th, $low_th); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_entSensorThresholdEntry}})) { next if ($oid !~ /^$mapping2->{entSensorThresholdSeverity}->{oid}\.$options{instance}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping2, results => $self->{results}->{$oid_entSensorThresholdEntry}, instance => $options{instance} . '.' . $instance); next if ($result->{entSensorThresholdSeverity} ne 'minor'); my $value = $result->{entSensorThresholdValue} * (10 ** ($options{result}->{entSensorScale}) * (10 ** -($options{result}->{entSensorPrecision}))); if ($result->{entSensorThresholdRelation} eq 'greaterOrEqual') { $high_th = $value - (1 * (10 ** ($options{result}->{entSensorScale}) * (10 ** -($options{result}->{entSensorPrecision})))); } elsif ($result->{entSensorThresholdRelation} eq 'greaterThan') { $high_th = $value; } elsif ($result->{entSensorThresholdRelation} eq 'lessOrEqual') { $low_th = $value + (1 * (10 ** ($options{result}->{entSensorScale}) * (10 ** -($options{result}->{entSensorPrecision})))); } elsif ($result->{entSensorThresholdRelation} eq 'lessThan') { $low_th = $value; } } # when it's the same value. Means no threshold. if (defined($low_th) && defined($high_th) && $high_th <= $low_th) { return ''; } my $th = ''; $th = centreon::plugins::misc::expand_exponential(value => $low_th) . ':' if (defined($low_th)); $th .= centreon::plugins::misc::expand_exponential(value => $high_th) if (defined($high_th)); $th = '~:' . $high_th if (defined($high_th) && !defined($low_th)); return $th; } sub get_default_critical_threshold { my ($self, %options) = @_; my ($high_th, $low_th); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_entSensorThresholdEntry}})) { next if ($oid !~ /^$mapping2->{entSensorThresholdSeverity}->{oid}\.$options{instance}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping2, results => $self->{results}->{$oid_entSensorThresholdEntry}, instance => $options{instance} . '.' . $instance); next if ($result->{entSensorThresholdSeverity} !~ /major|critical/); my $value = $result->{entSensorThresholdValue} * (10 ** ($options{result}->{entSensorScale}) * (10 ** -($options{result}->{entSensorPrecision}))); if ($result->{entSensorThresholdRelation} eq 'greaterOrEqual') { $high_th = $value - (1 * (10 ** ($options{result}->{entSensorScale}) * (10 ** -($options{result}->{entSensorPrecision})))); } elsif ($result->{entSensorThresholdRelation} eq 'greaterThan') { $high_th = $value; } elsif ($result->{entSensorThresholdRelation} eq 'lessOrEqual') { $low_th = $value + (1 * (10 ** ($options{result}->{entSensorScale}) * (10 ** -($options{result}->{entSensorPrecision})))); } elsif ($result->{entSensorThresholdRelation} eq 'lessThan') { $low_th = $value; } } # when it's the same value. Means no threshold. if (defined($low_th) && defined($high_th) && $high_th <= $low_th) { return ''; } my $th = ''; $th = centreon::plugins::misc::expand_exponential(value => $low_th) . ':' if (defined($low_th)); $th .= centreon::plugins::misc::expand_exponential(value => $high_th) if (defined($high_th)); $th = '~:' . $high_th if (defined($high_th) && !defined($low_th)); return $th; } 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 $verify_th_update = {}; foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_entSensorValueEntry}})) { next if ($oid !~ /^$mapping->{entSensorStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_entSensorValueEntry}, instance => $instance); next if (!defined($self->{results}->{ $self->{physical_name} }->{ $self->{physical_name} . '.' . $instance })); my $sensor_descr = $self->{results}->{ $self->{physical_name} }->{ $self->{physical_name} . '.' . $instance }; next if ($self->check_filter(section => 'sensor', instance => $result->{entSensorType} . '.' . $instance, name => $sensor_descr)); $self->{components}->{sensor}->{total}++; $result->{entSensorValue} = defined($result->{entSensorValue}) ? $result->{entSensorValue} * (10 ** ($result->{entSensorScale}) * (10 ** -($result->{entSensorPrecision}))) : undef; $self->{output}->output_add( long_msg => sprintf( "sensor '%s' status is '%s' [instance: %s] [value: %s %s]", $sensor_descr, $result->{entSensorStatus}, $instance, defined($result->{entSensorValue}) ? $result->{entSensorValue} : '-', $result->{entSensorType} ) ); my $exit = $self->get_severity(section => $result->{entSensorType}, label => 'sensor', value => $result->{entSensorStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Sensor '%s/%s' status is '%s'", $sensor_descr, $instance, $result->{entSensorStatus} ) ); } next if (!defined($result->{entSensorValue}) || $result->{entSensorValue} !~ /[0-9]/); my $component = 'sensor.' . $result->{entSensorType}; my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric( section => $component, instance => $instance, name => $sensor_descr, value => $result->{entSensorValue} ); if ($checked == 0) { my $warn_th = get_default_warning_threshold($self, instance => $instance, result => $result); my $crit_th = get_default_critical_threshold($self, instance => $instance, result => $result); $self->{perfdata}->threshold_validate(label => 'warning-' . $component . '-instance-' . $instance, value => $warn_th); $self->{perfdata}->threshold_validate(label => 'critical-' . $component . '-instance-' . $instance, value => $crit_th); $warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $component . '-instance-' . $instance); $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $component . '-instance-' . $instance); $exit2 = $self->{perfdata}->threshold_check( value => $result->{entSensorValue}, threshold => [ { label => 'critical-' . $component . '-instance-' . $instance, exit_litteral => 'critical' }, { label => 'warning-' . $component . '-instance-' . $instance, exit_litteral => 'warning' } ] ); } if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) { # we verify if it's a entSensorValueUpdateRate is not zero if ($checked == 0) { $verify_th_update->{$instance} = { result => $result, warn => $warn, crit => $crit, sensor_descr => $sensor_descr, status => $exit2 }; next; } $self->{output}->output_add( severity => $exit2, short_msg => sprintf( "Sensor '%s/%s' is %s %s", $sensor_descr, $instance, $result->{entSensorValue}, $perfdata_unit{$result->{entSensorType}} ) ); } $self->{output}->perfdata_add( label => $component, unit => $perfdata_unit{$result->{entSensorType}}, nlabel => 'hardware.' . $component, instances => $sensor_descr, value => $result->{entSensorValue}, warning => $warn, critical => $crit ); } return if (scalar(keys %$verify_th_update) <= 0); my $snmp_result = $self->{snmp}->get_leef(oids => [map($mapping->{entSensorValueUpdateRate}->{oid} . '.' . $_, keys(%$verify_th_update))]); foreach (keys %$verify_th_update) { my ($warn, $crit) = ($verify_th_update->{$_}->{warn}, $verify_th_update->{$_}->{crit}); if (defined($snmp_result->{$mapping->{entSensorValueUpdateRate}->{oid} . '.' . $_}) && $snmp_result->{$mapping->{entSensorValueUpdateRate}->{oid} . '.' . $_} == 0) { ($warn, $crit) = ('', ''); $verify_th_update->{$_}->{status} = 'ok'; } if (!$self->{output}->is_status(value => $verify_th_update->{$_}->{status}, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $verify_th_update->{$_}->{status}, short_msg => sprintf( "Sensor '%s/%s' is %s %s", $verify_th_update->{$_}->{sensor_descr}, $_, $verify_th_update->{$_}->{result}->{entSensorValue}, $perfdata_unit{ $verify_th_update->{$_}->{result}->{entSensorType} } ) ); } $self->{output}->perfdata_add( label => 'sensor.' . $verify_th_update->{$_}->{result}->{entSensorType}, unit => $perfdata_unit{ $verify_th_update->{$_}->{result}->{entSensorType} }, nlabel => 'hardware.sensor.' . $verify_th_update->{$_}->{result}->{entSensorType}, instances => $verify_th_update->{$_}->{sensor_descr}, value => $verify_th_update->{$_}->{result}->{entSensorValue}, warning => $warn, critical => $crit ); } } 1; centreon-plugins-20220113/centreon/common/cisco/standard/snmp/mode/components/temperature.pm000066400000000000000000000117631417000230700322320ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::standard::snmp::mode::components::temperature; use strict; use warnings; my %map_temperature_state = ( 1 => 'normal', 2 => 'warning', 3 => 'critical', 4 => 'shutdown', 5 => 'not present', 6 => 'not functioning' ); # In MIB 'CISCO-ENVMON-MIB' my $mapping = { ciscoEnvMonTemperatureStatusDescr => { oid => '.1.3.6.1.4.1.9.9.13.1.3.1.2' }, ciscoEnvMonTemperatureStatusValue => { oid => '.1.3.6.1.4.1.9.9.13.1.3.1.3' }, ciscoEnvMonTemperatureThreshold => { oid => '.1.3.6.1.4.1.9.9.13.1.3.1.4' }, ciscoEnvMonTemperatureState => { oid => '.1.3.6.1.4.1.9.9.13.1.3.1.6', map => \%map_temperature_state } }; my $oid_ciscoEnvMonTemperatureStatusEntry = '.1.3.6.1.4.1.9.9.13.1.3.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_ciscoEnvMonTemperatureStatusEntry }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking temperatures"); $self->{components}->{temperature} = { name => 'temperatures', total => 0, skip => 0 }; return if ($self->check_filter(section => 'temperature')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_ciscoEnvMonTemperatureStatusEntry}})) { next if ($oid !~ /^$mapping->{ciscoEnvMonTemperatureState}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_ciscoEnvMonTemperatureStatusEntry}, instance => $instance); next if ($self->check_filter(section => 'temperature', instance => $instance, name => $result->{ciscoEnvMonTemperatureStatusDescr})); $self->{components}->{temperature}->{total}++; $self->{output}->output_add( long_msg => sprintf( "temperature '%s' status is %s [instance: %s] [value: %s C]", $result->{ciscoEnvMonTemperatureStatusDescr}, $result->{ciscoEnvMonTemperatureState}, $instance, defined($result->{ciscoEnvMonTemperatureStatusValue}) ? $result->{ciscoEnvMonTemperatureStatusValue} : '-' ) ); my $exit = $self->get_severity(section => 'temperature', instance => $instance, value => $result->{ciscoEnvMonTemperatureState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Temperature '%s' status is %s", $result->{ciscoEnvMonTemperatureStatusDescr}, $result->{ciscoEnvMonTemperatureState} ) ); } next if (!defined($result->{ciscoEnvMonTemperatureStatusValue})); my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $instance, name => $result->{ciscoEnvMonTemperatureStatusDescr}, value => $result->{ciscoEnvMonTemperatureStatusValue}); if ($checked == 0) { my $warn_th = undef; my $crit_th = '~:' . $result->{ciscoEnvMonTemperatureThreshold}; $self->{perfdata}->threshold_validate(label => 'warning-temperature-instance-' . $instance, value => $warn_th); $self->{perfdata}->threshold_validate(label => 'critical-temperature-instance-' . $instance, value => $crit_th); $warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-temperature-instance-' . $instance); $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-temperature-instance-' . $instance); } if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit2, short_msg => sprintf("Temperature '%s' is %s degree centigrade", $result->{ciscoEnvMonTemperatureStatusDescr}, $result->{ciscoEnvMonTemperatureStatusValue}) ); } $self->{output}->perfdata_add( label => "temp", unit => 'C', nlabel => 'hardware.temperature.celsius', instances => $result->{ciscoEnvMonTemperatureStatusDescr}, value => $result->{ciscoEnvMonTemperatureStatusValue}, warning => $warn, critical => $crit ); } } 1; centreon-plugins-20220113/centreon/common/cisco/standard/snmp/mode/components/voltage.pm000066400000000000000000000123241417000230700313300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::standard::snmp::mode::components::voltage; use strict; use warnings; my %map_voltage_state = ( 1 => 'normal', 2 => 'warning', 3 => 'critical', 4 => 'shutdown', 5 => 'not present', 6 => 'not functioning' ); # In MIB 'CISCO-ENVMON-MIB' my $mapping = { ciscoEnvMonVoltageStatusDescr => { oid => '.1.3.6.1.4.1.9.9.13.1.2.1.2' }, ciscoEnvMonVoltageStatusValue => { oid => '.1.3.6.1.4.1.9.9.13.1.2.1.3' }, ciscoEnvMonVoltageThresholdLow => { oid => '.1.3.6.1.4.1.9.9.13.1.2.1.4' }, ciscoEnvMonVoltageThresholdHigh => { oid => '.1.3.6.1.4.1.9.9.13.1.2.1.5' }, ciscoEnvMonVoltageState => { oid => '.1.3.6.1.4.1.9.9.13.1.2.1.7', map => \%map_voltage_state } }; my $oid_ciscoEnvMonVoltageStatusEntry = '.1.3.6.1.4.1.9.9.13.1.2.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_ciscoEnvMonVoltageStatusEntry }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking voltages"); $self->{components}->{voltage} = { name => 'voltages', total => 0, skip => 0 }; return if ($self->check_filter(section => 'voltage')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_ciscoEnvMonVoltageStatusEntry}})) { next if ($oid !~ /^$mapping->{ciscoEnvMonVoltageState}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_ciscoEnvMonVoltageStatusEntry}, instance => $instance); next if ($self->check_filter(section => 'voltage', instance => $instance, name => $result->{ciscoEnvMonVoltageStatusDescr})); $self->{components}->{voltage}->{total}++; $self->{output}->output_add( long_msg => sprintf( "voltage '%s' status is %s [instance: %s] [value: %s C]", $result->{ciscoEnvMonVoltageStatusDescr}, $result->{ciscoEnvMonVoltageState}, $instance, $result->{ciscoEnvMonVoltageStatusValue} ) ); my $exit = $self->get_severity(section => 'voltage', instance => $instance, value => $result->{ciscoEnvMonVoltageState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Voltage '%s' status is %s", $result->{ciscoEnvMonVoltageStatusDescr}, $result->{ciscoEnvMonVoltageState} ) ); } $result->{ciscoEnvMonVoltageStatusValue} = $result->{ciscoEnvMonVoltageStatusValue} / 1000; my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'voltage', instance => $instance, name => $result->{ciscoEnvMonVoltageStatusDescr}, value => $result->{ciscoEnvMonVoltageStatusValue}); if ($checked == 0) { my $warn_th = undef; my $crit_th = ((defined($result->{ciscoEnvMonVoltageThresholdLow}) && $result->{ciscoEnvMonVoltageThresholdLow} =~ /\d/) ? sprintf("%.3f", $result->{ciscoEnvMonVoltageThresholdLow} / 1000) : 0) . ':' . ((defined($result->{ciscoEnvMonVoltageThresholdHigh}) && $result->{ciscoEnvMonVoltageThresholdHigh} =~ /\d/) ? sprintf("%.3f", $result->{ciscoEnvMonVoltageThresholdHigh} / 1000) : ''); $self->{perfdata}->threshold_validate(label => 'warning-voltage-instance-' . $instance, value => $warn_th); $self->{perfdata}->threshold_validate(label => 'critical-voltage-instance-' . $instance, value => $crit_th); $warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-voltage-instance-' . $instance); $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-voltage-instance-' . $instance); } if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit2, short_msg => sprintf("Voltage '%s' is %.3f V", $result->{ciscoEnvMonVoltageStatusDescr}, $result->{ciscoEnvMonVoltageStatusValue}) ); } $self->{output}->perfdata_add( label => 'voltage', unit => 'V', nlabel => 'hardware.voltage.volt', instances => $result->{ciscoEnvMonVoltageStatusDescr}, value => sprintf('%.3f', $result->{ciscoEnvMonVoltageStatusValue}), warning => $warn, critical => $crit ); } } 1; centreon-plugins-20220113/centreon/common/cisco/standard/snmp/mode/configuration.pm000066400000000000000000000131271417000230700303530ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::standard::snmp::mode::configuration; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add(label => 'running_last_changed', unit => 's', value => sprintf("%d", $self->{result_values}->{running_last_changed}), min => 0); $self->{output}->perfdata_add(label => 'running_last_saved', unit => 's', value => sprintf("%d", $self->{result_values}->{running_last_saved}), min => 0); $self->{output}->perfdata_add(label => 'startup_last_changed', unit => 's', value => sprintf("%d", $self->{result_values}->{startup_last_changed}), min => 0); } sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("Configuration Running Last Changed: %s, Running Last Saved: %s, Startup Last Changed: %s", ($self->{result_values}->{running_last_changed} > 0) ? centreon::plugins::misc::change_seconds(value => $self->{result_values}->{running_last_changed}) : "-", ($self->{result_values}->{running_last_saved} > 0) ? centreon::plugins::misc::change_seconds(value => $self->{result_values}->{running_last_saved}) : "-", ($self->{result_values}->{startup_last_changed} > 0) ? centreon::plugins::misc::change_seconds(value => $self->{result_values}->{startup_last_changed}) : "-"); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{running_last_changed} = $options{new_datas}->{$self->{instance} . '_running_last_changed'}; $self->{result_values}->{running_last_saved} = $options{new_datas}->{$self->{instance} . '_running_last_saved'}; $self->{result_values}->{startup_last_changed} = $options{new_datas}->{$self->{instance} . '_startup_last_changed'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, ]; $self->{maps_counters}->{global} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'running_last_changed' }, { name => 'running_last_saved' }, { name => 'startup_last_changed' } ], closure_custom_calc => $self->can('custom_status_calc'), closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => $self->can('custom_status_perfdata'), closure_custom_threshold_check => \&catalog_status_threshold, } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning-status:s" => { name => 'warning_status', default => '' }, "critical-status:s" => { name => 'critical_status', default => '%{running_last_changed} > %{running_last_saved}' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } my $oid_ccmHistoryRunningLastChanged = '.1.3.6.1.4.1.9.9.43.1.1.1.0'; my $oid_ccmHistoryRunningLastSaved = '.1.3.6.1.4.1.9.9.43.1.1.2.0'; my $oid_ccmHistoryStartupLastChanged = '.1.3.6.1.4.1.9.9.43.1.1.3.0'; sub manage_selection { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{global} = {}; $self->{results} = $self->{snmp}->get_leef(oids => [ $oid_ccmHistoryRunningLastChanged, $oid_ccmHistoryRunningLastSaved, $oid_ccmHistoryStartupLastChanged ], nothing_quit => 1); $self->{global} = { running_last_changed => $self->{results}->{$oid_ccmHistoryRunningLastChanged} / 100, running_last_saved => $self->{results}->{$oid_ccmHistoryRunningLastSaved} / 100, startup_last_changed => $self->{results}->{$oid_ccmHistoryStartupLastChanged} / 100, } } 1; __END__ =head1 MODE Check Cisco changed and saved configurations (CISCO-CONFIG-MAN-MIB). =over 8 =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{running_last_changed}, %{running_last_saved}, %{startup_last_changed} =item B<--critical-status> Set critical threshold for status (Default: '%{running_last_changed} > %{running_last_saved}'). Can used special variables like: %{running_last_changed}, %{running_last_saved}, %{startup_last_changed} =back =cut centreon-plugins-20220113/centreon/common/cisco/standard/snmp/mode/cpu.pm000066400000000000000000000240141417000230700262700ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::standard::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_avg', type => 0, cb_prefix_output => 'prefix_cpu_avg_output', message_separator => ' ', skipped_code => { -10 => 1 } }, { name => 'cpu_core', type => 1, cb_prefix_output => 'prefix_cpu_core_output', message_separator => ' ', message_multiple => 'All core cpu are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{cpu_avg} = [ { label => 'average-5s', nlabel => 'cpu.utilization.5s.percentage', set => { key_values => [ { name => 'average_5s' } ], output_template => '%.2f %% (5s)', perfdatas => [ { label => 'total_cpu_5s_avg', value => 'average_5s', template => '%.2f', min => 0, max => 100, unit => '%' }, ], } }, { label => 'average-1m', nlabel => 'cpu.utilization.1m.percentage', set => { key_values => [ { name => 'average_1m' } ], output_template => '%.2f %% (1m)', perfdatas => [ { label => 'total_cpu_1m_avg', value => 'average_1m', template => '%.2f', min => 0, max => 100, unit => '%' }, ], } }, { label => 'average-5m', nlabel => 'cpu.utilization.5m.percentage', set => { key_values => [ { name => 'average_5m' } ], output_template => '%.2f %% (5m)', perfdatas => [ { label => 'total_cpu_5m_avg', value => 'average_5m', template => '%.2f', min => 0, max => 100, unit => '%' }, ], } }, ]; $self->{maps_counters}->{cpu_core} = [ { label => 'core-5s', nlabel => 'core.cpu.utilization.5s.percentage', set => { key_values => [ { name => 'cpu_5s' }, { name => 'display' } ], output_template => '%.2f %% (5s)', perfdatas => [ { label => 'cpu_5s', value => 'cpu_5s', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'core-1m', nlabel => 'core.cpu.utilization.1m.percentage', set => { key_values => [ { name => 'cpu_1m' }, { name => 'display' } ], output_template => '%.2f %% (1m)', perfdatas => [ { label => 'cpu_1m', value => 'cpu_1m', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'core-5m', nlabel => 'core.cpu.utilization.5m.percentage', set => { key_values => [ { name => 'cpu_5m' }, { name => 'display' } ], output_template => '%.2f %% (5m)', perfdatas => [ { label => 'cpu_5m', value => 'cpu_5m', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub prefix_cpu_avg_output { my ($self, %options) = @_; return $self->{cpu_avg}->{count} . " CPU(s) average usage is "; } sub prefix_cpu_core_output { my ($self, %options) = @_; return "CPU '" . $options{instance_value}->{display} . "' usage "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'check-order:s' => { name => 'check_order', default => 'process,old_sys,system_ext' }, }); return $self; } sub check_nexus_cpu { my ($self, %options) = @_; return if (!defined($options{snmp_result}->{$options{oid} . '.0'})); my $instance = 0; $self->{cpu_core}->{$instance} = { display => $instance, cpu_5m => $options{snmp_result}->{$options{oid} . '.0'}, }; $self->{checked_cpu} = 1; } sub check_table_cpu { my ($self, %options) = @_; return if ($self->{checked_cpu} == 1); my $instances = {}; foreach my $oid (keys %{$options{snmp_result}}) { $oid =~ /\.([0-9]+)$/; next if (defined($instances->{$1})); $instances->{$1} = 1; my $instance = $1; my $cpu5sec = defined($options{snmp_result}->{$options{sec5} . '.' . $instance}) ? $options{snmp_result}->{$options{sec5} . '.' . $instance} : undef; my $cpu1min = defined($options{snmp_result}->{$options{min1} . '.' . $instance}) ? $options{snmp_result}->{$options{min1} . '.' . $instance} : undef; my $cpu5min = defined($options{snmp_result}->{$options{min5} . '.' . $instance}) ? $options{snmp_result}->{$options{min5} . '.' . $instance} : undef; # Case that it's maybe other CPU oid in table for datas. next if (!defined($cpu5sec) && !defined($cpu1min) && !defined($cpu5min)); $self->{checked_cpu} = 1; $self->{cpu_core}->{$instance} = { display => $instance, cpu_5s => $cpu5sec, cpu_1m => $cpu1min, cpu_5m => $cpu5min, }; } } sub check_cpu_average { my ($self, %options) = @_; my $count = scalar(keys %{$self->{cpu_core}}); my ($avg_5s, $avg_1m, $avg_5m); foreach (values %{$self->{cpu_core}}) { $avg_5s = defined($avg_5s) ? $avg_5s + $_->{cpu_5s} : $_->{cpu_5s} if (defined($_->{cpu_5s})); $avg_1m = defined($avg_1m) ? $avg_1m + $_->{cpu_1m} : $_->{cpu_1m} if (defined($_->{cpu_1m})); $avg_5m = defined($avg_5m) ? $avg_5m + $_->{cpu_5m} : $_->{cpu_5m} if (defined($_->{cpu_5m})); } $self->{cpu_avg} = { average_5s => defined($avg_5s) ? $avg_5s / $count : undef, average_1m => defined($avg_1m) ? $avg_1m / $count : undef, average_5m => defined($avg_5m) ? $avg_5m / $count : undef, count => $count, }; } sub check_cpu_process { my ($self, %options) = @_; return if ($self->{checked_cpu} == 1); # Cisco IOS Software releases later to 12.0(3)T and prior to 12.2(3.5) my $oid_cpmCPUTotalEntry = '.1.3.6.1.4.1.9.9.109.1.1.1.1'; my $oid_cpmCPUTotal5sec = '.1.3.6.1.4.1.9.9.109.1.1.1.1.3'; my $oid_cpmCPUTotal1min = '.1.3.6.1.4.1.9.9.109.1.1.1.1.4'; my $oid_cpmCPUTotal5min = '.1.3.6.1.4.1.9.9.109.1.1.1.1.5'; # Cisco IOS Software releases 12.2(3.5) or later my $oid_cpmCPUTotal5minRev = '.1.3.6.1.4.1.9.9.109.1.1.1.1.8'; my $oid_cpmCPUTotal1minRev = '.1.3.6.1.4.1.9.9.109.1.1.1.1.7'; my $oid_cpmCPUTotal5secRev = '.1.3.6.1.4.1.9.9.109.1.1.1.1.6'; my $snmp_result = $self->{snmp}->get_table( oid => $oid_cpmCPUTotalEntry, start => $oid_cpmCPUTotal5sec, end => $oid_cpmCPUTotal5minRev ); $self->check_table_cpu(snmp_result => $snmp_result, sec5 => $oid_cpmCPUTotal5secRev, min1 => $oid_cpmCPUTotal1minRev, min5 => $oid_cpmCPUTotal5minRev); $self->check_table_cpu(snmp_result => $snmp_result, sec5 => $oid_cpmCPUTotal5sec, min1 => $oid_cpmCPUTotal1min, min5 => $oid_cpmCPUTotal5min); } sub check_cpu_old_sys { my ($self, %options) = @_; return if ($self->{checked_cpu} == 1); # Cisco IOS Software releases prior to 12.0(3)T my $oid_lcpu = '.1.3.6.1.4.1.9.2.1'; my $oid_busyPer = '.1.3.6.1.4.1.9.2.1.56'; # .0 in reality my $oid_avgBusy1 = '.1.3.6.1.4.1.9.2.1.57'; # .0 in reality my $oid_avgBusy5 = '.1.3.6.1.4.1.9.2.1.58'; # .0 in reality my $snmp_result = $self->{snmp}->get_table( oid => $oid_lcpu, start => $oid_busyPer, end => $oid_avgBusy5 ); $self->check_table_cpu(snmp_result => $snmp_result, sec5 => $oid_busyPer, min1 => $oid_avgBusy1, min5 => $oid_avgBusy5); } sub check_cpu_system_ext { my ($self, %options) = @_; return if ($self->{checked_cpu} == 1); # Cisco Nexus my $oid_cseSysCPUUtilization = '.1.3.6.1.4.1.9.9.305.1.1.1'; # .0 in reality my $snmp_result = $self->{snmp}->get_table( oid => $oid_cseSysCPUUtilization ); $self->check_nexus_cpu(snmp_result => $snmp_result, oid => $oid_cseSysCPUUtilization); } sub manage_selection { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{cpu_avg} = {}; $self->{cpu_core} = {}; $self->{checked_cpu} = 0; foreach (split /,/, $self->{option_results}->{check_order}) { my $method = $self->can('check_cpu_' . $_); if ($method) { $self->$method(); } } if ($self->{checked_cpu} == 0) { $self->{output}->add_option_msg(short_msg => "Cannot find CPU informations"); $self->{output}->option_exit(); } $self->check_cpu_average(); } 1; __END__ =head1 MODE Check cpu usage (CISCO-PROCESS-MIB and CISCO-SYSTEM-EXT-MIB). =over 8 =item B<--check-order> Check cpu in standard cisco mib. If you have some issue (wrong cpu information in a specific mib), you can change the order (Default: 'process,old_sys,system_ext'). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'core-5s', 'core-1m', 'core-5m', 'average-5s', 'average-1m', 'average-5m'. =back =cut centreon-plugins-20220113/centreon/common/cisco/standard/snmp/mode/environment.pm000066400000000000000000000146311417000230700300510ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::standard::snmp::mode::environment; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; use centreon::plugins::misc; sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^(temperature|voltage|sensor.*)$'; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { fan => [ ['normal', 'OK'], ['warning', 'WARNING'], ['critical', 'CRITICAL'], ['shutdown', 'CRITICAL'], ['not present', 'OK'], ['not functioning', 'WARNING'], ['unknown', 'UNKNOWN'], ['down', 'CRITICAL'], ['up', 'OK'] ], psu => [ ['normal', 'OK'], ['warning', 'WARNING'], ['critical', 'CRITICAL'], ['shutdown', 'CRITICAL'], ['not present', 'OK'], ['not functioning', 'WARNING'], ['^off*', 'WARNING'], ['failed', 'CRITICAL'], ['onButFanFail|onButInlinePowerFail', 'WARNING'], ['on', 'OK'] ], temperature => [ ['normal', 'OK'], ['warning', 'WARNING'], ['critical', 'CRITICAL'], ['shutdown', 'CRITICAL'], ['not present', 'OK'], ['not functioning', 'WARNING'] ], voltage => [ ['normal', 'OK'], ['warning', 'WARNING'], ['critical', 'CRITICAL'], ['shutdown', 'CRITICAL'], ['not present', 'OK'], ['not functioning', 'WARNING'] ], module => [ ['unknown|mdr', 'UNKNOWN'], ['disabled|okButDiagFailed|missing|mismatchWithParent|mismatchConfig|dormant|outOfServiceAdmin|outOfServiceEnvTemp|powerCycled|okButPowerOverWarning|okButAuthFailed|fwMismatchFound|fwDownloadFailure', 'WARNING'], ['failed|diagFailed|poweredDown|powerDenied|okButPowerOverCritical', 'CRITICAL'], ['boot|selfTest|poweredUp|syncInProgress|upgrading|fwDownloadSuccess|ok', 'OK'] ], physical => [ ['other', 'UNKNOWN'], ['incompatible|unsupported', 'CRITICAL'], ['supported', 'OK'] ], sensor => [ ['ok', 'OK'], ['unavailable', 'OK'], ['nonoperational', 'CRITICAL'] ] }; $self->{components_path} = 'centreon::common::cisco::standard::snmp::mode::components'; $self->{components_module} = ['fan', 'psu', 'temperature', 'voltage', 'module', 'physical', 'sensor']; } my $oid_ciscoEnvMonPresent = '.1.3.6.1.4.1.9.9.13.1.1'; my %map_type_mon = ( 1 => 'oldAgs', 2 => 'ags', 3 => 'c7000', 4 => 'ci', 6 => 'cAccessMon', 7 => 'cat6000', 8 => 'ubr7200', 9 => 'cat4000', 10 => 'c10000', 11 => 'osr7600', 12 => 'c7600', 13 => 'c37xx', 14 => 'other' ); sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{physical_name} = defined($self->{option_results}->{use_physical_name}) ? '.1.3.6.1.2.1.47.1.1.1.1.7' : '.1.3.6.1.2.1.47.1.1.1.1.2'; push @{$self->{request}}, { oid => $self->{physical_name} }, { oid => $oid_ciscoEnvMonPresent }; $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); while (my ($key, $value) = each %{$self->{results}->{ $self->{physical_name} }}) { $self->{results}->{ $self->{physical_name} }->{$key} = centreon::plugins::misc::trim($value); } $self->{output}->output_add( long_msg => sprintf( 'Environment type: %s', defined($self->{results}->{$oid_ciscoEnvMonPresent}->{$oid_ciscoEnvMonPresent . '.0'}) && defined($map_type_mon{$self->{results}->{$oid_ciscoEnvMonPresent}->{$oid_ciscoEnvMonPresent . '.0'}} ) ? $map_type_mon{$self->{results}->{$oid_ciscoEnvMonPresent}->{$oid_ciscoEnvMonPresent . '.0'}} : 'unknown' ) ); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'use-physical-name' => { name => 'use_physical_name' } }); return $self; } 1; __END__ =head1 MODE Check environment (Power Supplies, Fans, Temperatures, Voltages, Modules, Physical Entities). =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'fan', 'psu', 'temperature', 'voltage', 'module', 'physical', 'sensor'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=fan --filter=psu) Can also exclude specific instance: --filter=fan,1 =item B<--add-name-instance> Add literal description for instance value (used in filter, absent-problem and threshold options). =item B<--use-physical-name> Use entPhysicalName OID instead of entPhysicalDescr. =item B<--absent-problem> Return an error if an entity is not 'present' (default is skipping) (comma seperated list) Can be specific or global: --absent-problem=fan,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,status,regexp) It used before default thresholds (order stays). Example: --threshold-overload='fan,CRITICAL,^(?!(up|normal)$)' =item B<--warning> Set warning threshold for temperatures, voltages, sensors (syntax: type,regexp,threshold) Example: --warning='temperature,.*,30' =item B<--critical> Set critical threshold for temperatures, voltages, sensors (syntax: type,regexp,threshold) Example: --critical='temperature,.*,40' =back =cut centreon-plugins-20220113/centreon/common/cisco/standard/snmp/mode/hsrp.pm000066400000000000000000000111441417000230700264550ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::standard::snmp::mode::hsrp; use base qw(centreon::plugins::mode); use strict; use warnings; my %map_row_status = ( 1 => 'active', 2 => 'notInService', 3 => 'notReady', 4 => 'createAndGo', 5 => 'createAndWait', 6 => 'destroy' ); my %map_states = ( 1 => 'initial', 2 => 'learn', 3 => 'listen', 4 => 'speak', 5 => 'standby', 6 => 'active', ); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'role:s' => { name => 'role', default => 'primary' }, 'filter-vrid:s' => { name => 'filter_vrid' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if ($self->{option_results}->{role} !~ /^primary|secondary$/) { $self->{output}->add_option_msg(short_msg => "You must use either primary either secondary for --role option"); $self->{output}->option_exit(); } } sub run { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; my $vridout = ''; my $oid_cHsrpGrpStandbyState = ".1.3.6.1.4.1.9.9.106.1.2.1.1.15"; # HSRP Oper Status my $oid_cHsrpGrpEntryRowStatus = ".1.3.6.1.4.1.9.9.106.1.2.1.1.17"; # HSRP Admin Status my $results = $self->{snmp}->get_multiple_table(oids => [ { oid => $oid_cHsrpGrpStandbyState }, { oid => $oid_cHsrpGrpEntryRowStatus }, ], nothing_quit => 1 ); $self->{output}->output_add(severity => 'OK', short_msg => sprintf("Router is in its expected state : '%s'", $self->{option_results}->{role})); foreach my $oid (keys %{$results->{$oid_cHsrpGrpStandbyState}}) { $oid =~ /(\d+\.\d+)$/; my $vrid = $1; if (defined($self->{option_results}->{filter_vrid}) && $self->{option_results}->{filter_vrid} ne '' && $vrid !~ /$self->{option_results}->{filter_vrid}/) { $self->{output}->output_add(long_msg => "skipping vrid '" . $vrid . "': no matching filter.", debug => 1); next; } my $operState = $results->{$oid_cHsrpGrpEntryRowStatus}->{$oid_cHsrpGrpEntryRowStatus . "." . $vrid}; my $adminState = $results->{$oid_cHsrpGrpStandbyState}->{$oid}; $self->{output}->output_add(long_msg => sprintf("[Vrid : %s] [Admin Status is '%s'] [Oper Status is '%s']", $vrid, $map_states{$adminState}, $map_row_status{$operState})); if ($map_row_status{$operState} !~ /^active$/i) { $self->{output}->output_add(severity => 'CRITICAL', short_msg => sprintf("VRID %s operational state is '%s'", $vrid, $map_row_status{$operState})); } if (($self->{option_results}->{role} eq 'primary' && $map_states{$adminState} !~ /^active$/) || ($self->{option_results}->{role} eq 'secondary' && $map_states{$adminState} !~ /^standby$/)) { $vridout .= sprintf("(VRID %s is '%s')", $vrid, $map_states{$adminState}); } } if ($vridout ne '') { $self->{output}->output_add(severity => 'CRITICAL', short_msg => sprintf("%s - Router isn't in the expected state (%s)", $vridout, $self->{option_results}->{role})); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check Cisco HSRP (CISCO-HSRP-MIB). Trigger a critical if not in the expected state or if a VRID is not in an active state. =over 8 =item B<--filter-vrid> Filter VRID (can be a regexp). =item B<--role> If role is 'primary', an error if HSRPs are 'standby' states. If role is 'secondary', an error if HSRPs are 'active' states. (Default: 'primary') =back =cut centreon-plugins-20220113/centreon/common/cisco/standard/snmp/mode/interfaces.pm000066400000000000000000000270341417000230700276310ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::standard::snmp::mode::interfaces; use base qw(snmp_standard::mode::interfaces); use strict; use warnings; sub custom_status_output { my ($self, %options) = @_; my $msg = 'Status : ' . $self->{result_values}->{opstatus} . ' (admin: ' . $self->{result_values}->{admstatus} . ')'; if (defined($self->{instance_mode}->{option_results}->{add_duplex_status})) { $msg .= ' (duplex: ' . $self->{result_values}->{duplexstatus} . ')'; } if (defined($self->{instance_mode}->{option_results}->{add_err_disable})) { $msg .= ' (error disable: ' . $self->{result_values}->{errdisable} . ')'; } return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->SUPER::custom_status_calc(%options); $self->{result_values}->{errdisable} = $options{new_datas}->{$self->{instance} . '_errdisable'}; return 0; } sub set_key_values_status { my ($self, %options) = @_; return [ { name => 'opstatus' }, { name => 'admstatus' }, { name => 'duplexstatus' }, { name => 'errdisable' }, { name => 'display' } ]; } sub set_oids_status { my ($self, %options) = @_; $self->SUPER::set_oids_status(%options); $self->{oid_cErrDisableIfStatusCause} = '.1.3.6.1.4.1.9.9.548.1.3.1.1.2'; $self->{oid_cErrDisableIfStatusCause_mapping} = { 1 => 'udld', 2 => 'bpduGuard', 3 => 'channelMisconfig', 4 => 'pagpFlap', 5 => 'dtpFlap', 6 => 'linkFlap', 7 => 'l2ptGuard', 8 => 'dot1xSecurityViolation', 9 => 'portSecurityViolation', 10 => 'gbicInvalid', 11 => 'dhcpRateLimit', 12 => 'unicastFlood', 13 => 'vmps', 14 => 'stormControl', 15 => 'inlinePower', 16 => 'arpInspection', 17 => 'portLoopback', 18 => 'packetBuffer', 19 => 'macLimit', 20 => 'linkMonitorFailure', 21 => 'oamRemoteFailure', 22 => 'dot1adIncompEtype', 23 => 'dot1adIncompTunnel', 24 => 'sfpConfigMismatch', 25 => 'communityLimit', 26 => 'invalidPolicy', 27 => 'lsGroup', 28 => 'ekey', 29 => 'portModeFailure', 30 => 'pppoeIaRateLimit', 31 => 'oamRemoteCriticalEvent', 32 => 'oamRemoteDyingGasp', 33 => 'oamRemoteLinkFault', 34 => 'mvrp', 35 => 'tranceiverIncomp', 36 => 'other', 37 => 'portReinitLimitReached', 38 => 'adminRxBBCreditPerfBufIncomp', 39 => 'ficonNotEnabled', 40 => 'adminModeIncomp', 41 => 'adminSpeedIncomp', 42 => 'adminRxBBCreditIncomp', 43 => 'adminRxBufSizeIncomp', 44 => 'eppFailure', 45 => 'osmEPortUp', 46 => 'osmNonEPortUp', 47 => 'udldUniDir', 48 => 'udldTxRxLoop', 49 => 'udldNeighbourMismatch', 50 => 'udldEmptyEcho', 51 => 'udldAggrasiveModeLinkFailed', 52 => 'excessivePortInterrupts', 53 => 'channelErrDisabled', 54 => 'hwProgFailed', 55 => 'internalHandshakeFailed', 56 => 'stpInconsistencyOnVpcPeerLink', 57 => 'stpPortStateFailure', 58 => 'ipConflict', 59 => 'multipleMSapIdsRcvd', 60 => 'oneHundredPdusWithoutAck', 61 => 'ipQosCompatCheckFailure', }; } sub set_oids_errors { my ($self, %options) = @_; $self->SUPER::set_oids_errors(%options); $self->{oid_ifInFCSError} = '.1.3.6.1.2.1.10.7.2.1.3'; # dot3StatsFCSErrors $self->{oid_ifInCrc} = '.1.3.6.1.4.1.9.2.2.1.1.12'; } sub set_counters_errors { my ($self, %options) = @_; $self->SUPER::set_counters_errors(%options); push @{$self->{maps_counters}->{int}}, { label => 'in-crc', filter => 'add_errors', nlabel => 'interface.packets.in.crc.count', set => { key_values => [ { name => 'incrc', diff => 1 }, { name => 'total_in_packets', diff => 1 }, { name => 'display' }, { name => 'mode_cast' } ], closure_custom_calc => $self->can('custom_errors_calc'), closure_custom_calc_extra_options => { label_ref1 => 'in', label_ref2 => 'crc' }, closure_custom_output => $self->can('custom_errors_output'), output_error_template => 'Packets In Crc : %s', closure_custom_perfdata => $self->can('custom_errors_perfdata'), closure_custom_threshold_check => $self->can('custom_errors_threshold') } }, { label => 'in-fcserror', filter => 'add_errors', nlabel => 'interface.packets.in.fcserror.count', set => { key_values => [ { name => 'infcserror', diff => 1 }, { name => 'total_in_packets', diff => 1 }, { name => 'display' }, { name => 'mode_cast' } ], closure_custom_calc => $self->can('custom_errors_calc'), closure_custom_calc_extra_options => { label_ref1 => 'in', label_ref2 => 'fcserror' }, closure_custom_output => $self->can('custom_errors_output'), output_error_template => 'Packets In FCS Error : %s', closure_custom_perfdata => $self->can('custom_errors_perfdata'), closure_custom_threshold_check => $self->can('custom_errors_threshold') } } ; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'add-err-disable' => { name => 'add_err_disable' } }); return $self; } sub load_errors { my ($self, %options) = @_; $self->set_oids_errors(); $self->{snmp}->load( oids => [ $self->{oid_ifInDiscards}, $self->{oid_ifInErrors}, $self->{oid_ifOutDiscards}, $self->{oid_ifOutErrors}, $self->{oid_ifInCrc}, $self->{oid_ifInFCSError} ], instances => $self->{array_interface_selected} ); } sub load_status { my ($self, %options) = @_; $self->SUPER::load_status(%options); if (defined($self->{option_results}->{add_err_disable})) { $self->{snmp_errdisable_result} = $self->{snmp}->get_table(oid => $self->{oid_cErrDisableIfStatusCause}); } } sub add_result_errors { my ($self, %options) = @_; $self->{int}->{$options{instance}}->{indiscard} = $self->{results}->{$self->{oid_ifInDiscards} . '.' . $options{instance}}; $self->{int}->{$options{instance}}->{inerror} = $self->{results}->{$self->{oid_ifInErrors} . '.' . $options{instance}}; $self->{int}->{$options{instance}}->{outdiscard} = $self->{results}->{$self->{oid_ifOutDiscards} . '.' . $options{instance}}; $self->{int}->{$options{instance}}->{outerror} = $self->{results}->{$self->{oid_ifOutErrors} . '.' . $options{instance}}; $self->{int}->{$options{instance}}->{incrc} = $self->{results}->{$self->{oid_ifInCrc} . '.' . $options{instance}}; $self->{int}->{$options{instance}}->{infcserror} = $self->{results}->{$self->{oid_ifInFCSError} . '.' . $options{instance}}; } sub add_result_status { my ($self, %options) = @_; $self->SUPER::add_result_status(%options); $self->{int}->{$options{instance}}->{errdisable} = ''; if (defined($self->{option_results}->{add_err_disable})) { my $append = ''; # ifIndex.vlanIndex (if physical interface, vlanIndex = 0) foreach (keys %{$self->{snmp_errdisable_result}}) { next if (! /^$self->{oid_cErrDisableIfStatusCause}\.$options{instance}\.(.*)/); if ($1 == 0) { $self->{int}->{$options{instance}}->{errdisable} = $self->{oid_cErrDisableIfStatusCause_mapping}->{ $self->{snmp_errdisable_result}->{$_} }; last; } $self->{int}->{$options{instance}}->{errdisable} .= $append . 'vlan' . $1 . ':' . $self->{oid_cErrDisableIfStatusCause_mapping}->{ $self->{snmp_errdisable_result}->{$_} }; $append = ','; } } $self->{int}->{$options{instance}}->{errdisable} = '-' if ($self->{int}->{$options{instance}}->{errdisable} eq ''); } 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-err-disable> Check error disable (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> Set warning threshold for status. Can used special variables like: %{admstatus}, %{opstatus}, %{duplexstatus}, %{errdisable}, %{display} =item B<--critical-status> Set critical threshold for status (Default: '%{admstatus} eq "up" and %{opstatus} ne "up"'). Can used special variables like: %{admstatus}, %{opstatus}, %{duplexstatus}, %{errdisable}, %{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-crc', 'in-fcserror', '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', 'counter'). =item B<--units-cast> Units of thresholds for communication types (Default: 'percent_delta') ('percent_delta', 'percent', 'delta', '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 interface'). =item B<--name> Allows to use interface name with option --interface instead of interface oid index (Can be a regexp) =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<--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> Choose OID used to filter interface (default: ifName) (values: ifDesc, ifAlias, ifName, IpAddr). =item B<--oid-display> Choose OID used to display interface (default: ifName) (values: ifDesc, ifAlias, ifName, IpAddr). =item B<--oid-extra-display> Add an OID to display. =item B<--display-transform-src> Regexp src to transform display value. =item B<--display-transform-dst> Regexp dst to transform display value. =item B<--show-cache> Display cache interface datas. =back =cut centreon-plugins-20220113/centreon/common/cisco/standard/snmp/mode/ipsectunnel.pm000066400000000000000000000425041417000230700300360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::standard::snmp::mode::ipsectunnel; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use Socket; sub custom_traffic_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => 'traffic_' . lc($self->{result_values}->{label}), unit => 'b/s', instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, value => sprintf("%.2f", $self->{result_values}->{traffic_per_seconds}), 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_traffic_threshold { my ($self, %options) = @_; return $self->{perfdata}->threshold_check(value => $self->{result_values}->{traffic_per_seconds}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ]); } sub custom_traffic_output { my ($self, %options) = @_; my ($traffic_value, $traffic_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{traffic_per_seconds}, network => 1); return sprintf( 'traffic %s: %s/s', lc($self->{result_values}->{label}), $traffic_value . $traffic_unit ); } sub custom_traffic_calc { my ($self, %options) = @_; if (!defined($options{old_datas}->{$self->{instance} . '_display'})) { $self->{error_msg} = "Buffer creation"; return -1; } my $total_bytes = 0; foreach (keys %{$options{new_datas}}) { if (/$self->{instance}_cipSecTunHc$options{extra_options}->{label_ref}Octets_(\d+)/) { my $new_bytes = $options{new_datas}->{$_}; next if (!defined($options{old_datas}->{$_})); my $old_bytes = $options{old_datas}->{$_}; my $diff_bytes = $new_bytes - $old_bytes; $total_bytes += (($diff_bytes < 0) ? $new_bytes : $diff_bytes); } elsif (/$self->{instance}_cipSecTun$options{extra_options}->{label_ref}Octets_(\d+)/) { my $new_bytes = $options{new_datas}->{$_}; my $new_wraps = $options{new_datas}->{$self->{instance} . '_cipSecTun' . $options{extra_options}->{label_ref} . 'OctWraps_' . $1}; next if (!defined($options{old_datas}->{$_})); my ($old_bytes, $old_wraps) = ($options{old_datas}->{$_}, $options{old_datas}->{$self->{instance} . '_cipSecTun' . $options{extra_options}->{label_ref} . 'OctWraps_' . $1}); my $diff_bytes = $new_bytes - $old_bytes + (($new_wraps - $old_wraps) * (2**32)); $total_bytes += (($diff_bytes < 0) ? $new_bytes : $diff_bytes); } } $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{traffic_per_seconds} = ($total_bytes * 8) / $options{delta_time}; $self->{result_values}->{label} = $options{extra_options}->{label_ref}; return 0; } sub custom_drop_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => 'drop_' . lc($self->{result_values}->{label}), unit => 'pkts/s', instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, value => sprintf("%.2f", $self->{result_values}->{pkts_per_seconds}), 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_drop_threshold { my ($self, %options) = @_; return $self->{perfdata}->threshold_check(value => $self->{result_values}->{pkts_per_seconds}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ]); } sub custom_drop_output { my ($self, %options) = @_; return sprintf( 'drop %s: %s pkts/s', lc($self->{result_values}->{label}), $self->{result_values}->{pkts_per_seconds} ); } sub custom_drop_calc { my ($self, %options) = @_; if (!defined($options{old_datas}->{$self->{instance} . '_display'})) { $self->{error_msg} = "Buffer creation"; return -1; } my $total_pkts = 0; foreach (keys %{$options{new_datas}}) { if (/$self->{instance}_cipSecTun$options{extra_options}->{label_ref}DropPkts_(\d+)/) { next if (!defined($options{old_datas}->{$_})); my $diff_pkts = $options{new_datas}->{$_} - $options{old_datas}->{$_}; $total_pkts += (($diff_pkts < 0) ? $options{new_datas}->{$_} : $diff_pkts); } } $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{pkts_per_seconds} = $total_pkts / $options{delta_time}; $self->{result_values}->{label} = $options{extra_options}->{label_ref}; return 0; } sub prefix_tunnel_output { my ($self, %options) = @_; return "Tunnel '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'tunnel', type => 1, cb_prefix_output => 'prefix_tunnel_output', message_multiple => 'All tunnels are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'tunnels-total', set => { key_values => [ { name => 'total' } ], output_template => 'Total tunnels: %s', perfdatas => [ { label => 'total_tunnels', template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{tunnel} = [ { label => 'traffic-in', set => { key_values => [], manual_keys => 1, closure_custom_calc => $self->can('custom_traffic_calc'), closure_custom_calc_extra_options => { label_ref => 'In' }, closure_custom_output => $self->can('custom_traffic_output'), closure_custom_perfdata => $self->can('custom_traffic_perfdata'), closure_custom_threshold_check => $self->can('custom_traffic_threshold') } }, { label => 'traffic-out', set => { key_values => [], manual_keys => 1, closure_custom_calc => $self->can('custom_traffic_calc'), closure_custom_calc_extra_options => { label_ref => 'Out' }, closure_custom_output => $self->can('custom_traffic_output'), closure_custom_perfdata => $self->can('custom_traffic_perfdata'), closure_custom_threshold_check => $self->can('custom_traffic_threshold') } }, { label => 'drop-in', set => { key_values => [], manual_keys => 1, closure_custom_calc => $self->can('custom_drop_calc'), closure_custom_calc_extra_options => { label_ref => 'In' }, closure_custom_output => $self->can('custom_drop_output'), closure_custom_perfdata => $self->can('custom_drop_perfdata'), closure_custom_threshold_check => $self->can('custom_drop_threshold') } }, { label => 'drop-out', set => { key_values => [], manual_keys => 1, closure_custom_calc => $self->can('custom_drop_calc'), closure_custom_calc_extra_options => { label_ref => 'Out' }, closure_custom_output => $self->can('custom_drop_output'), closure_custom_perfdata => $self->can('custom_drop_perfdata'), closure_custom_threshold_check => $self->can('custom_drop_threshold') } }, { label => 'sa-total', set => { key_values => [ { name => 'sa' }, { name => 'display' } ], output_template => 'total sa: %s', perfdatas => [ { label => 'total_sa', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'filter-sa:s' => { name => 'filter_sa' } }); return $self; } my $mapping = { cikeTunLocalValue => { oid => '.1.3.6.1.4.1.9.9.171.1.2.3.1.3' }, cikeTunRemoteValue => { oid => '.1.3.6.1.4.1.9.9.171.1.2.3.1.7' } }; my $oid_cikeTunActiveTime = '.1.3.6.1.4.1.9.9.171.1.2.3.1.16'; my $mapping2 = { cipSecTunInOctets => { oid => '.1.3.6.1.4.1.9.9.171.1.3.2.1.26' }, cipSecTunHcInOctets => { oid => '.1.3.6.1.4.1.9.9.171.1.3.2.1.27' }, cipSecTunInOctWraps => { oid => '.1.3.6.1.4.1.9.9.171.1.3.2.1.28' }, # seems buggy cipSecTunInDropPkts => { oid => '.1.3.6.1.4.1.9.9.171.1.3.2.1.33' }, cipSecTunOutOctets => { oid => '.1.3.6.1.4.1.9.9.171.1.3.2.1.39' }, cipSecTunHcOutOctets => { oid => '.1.3.6.1.4.1.9.9.171.1.3.2.1.40' }, # seems buggy cipSecTunOutOctWraps => { oid => '.1.3.6.1.4.1.9.9.171.1.3.2.1.41' }, cipSecTunOutDropPkts => { oid => '.1.3.6.1.4.1.9.9.171.1.3.2.1.46' } }; my $mapping3 = { cipSecEndPtLocalAddr2 => { oid => '.1.3.6.1.4.1.9.9.171.1.3.3.1.5' }, cipSecEndPtRemoteAddr1 => { oid => '.1.3.6.1.4.1.9.9.171.1.3.3.1.10' }, cipSecEndPtRemoteAddr2 => { oid => '.1.3.6.1.4.1.9.9.171.1.3.3.1.11' } }; my $oid_cipSecEndPtLocalAddr1 = '.1.3.6.1.4.1.9.9.171.1.3.3.1.4'; my $oid_cipSecTunIkeTunnelIndex = '.1.3.6.1.4.1.9.9.171.1.3.2.1.2'; sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = 'cisco_ipsectunnel_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_sa}) ? md5_hex($self->{option_results}->{filter_sa}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); $self->{global} = { total => 0 }; my $snmp_result = $options{snmp}->get_multiple_table( oids => [ { oid => $mapping->{cikeTunLocalValue}->{oid} }, { oid => $mapping->{cikeTunRemoteValue}->{oid} } ], return_type => 1 ); # The MIB doesn't give IPSec tunnel type (site-to-site or dynamic client) # You surely need to filter on SA. Dynamic client usually doesn't push local routes. $self->{tunnel} = {}; my $ike_idx = {}; foreach (keys %$snmp_result) { next if (!/$mapping->{cikeTunRemoteValue}->{oid}\.(\d+)/); my $cike_tun_index = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $cike_tun_index); my $name = $result->{cikeTunLocalValue} . '_' . $result->{cikeTunRemoteValue}; 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 name.", debug => 1); next; } $ike_idx->{$cike_tun_index} = 1; $self->{tunnel}->{$name} = { display => $name, sa => 0, ike_tun_idx => $cike_tun_index }; } $snmp_result = $options{snmp}->get_multiple_table( oids => [ { oid => $oid_cipSecTunIkeTunnelIndex }, { oid => $oid_cipSecEndPtLocalAddr1 } ] ); my $sectun_idx_instances = {}; my $sectun_idx_select = {}; foreach (keys %{$snmp_result->{$oid_cipSecTunIkeTunnelIndex}}) { next if (!defined($ike_idx->{ $snmp_result->{$oid_cipSecTunIkeTunnelIndex}->{$_} })); /^$oid_cipSecTunIkeTunnelIndex\.(\d+)/; if (!defined($sectun_idx_instances->{ $snmp_result->{$oid_cipSecTunIkeTunnelIndex}->{$_} })) { $sectun_idx_instances->{ $snmp_result->{$oid_cipSecTunIkeTunnelIndex}->{$_} } = []; } $sectun_idx_select->{$1} = 1; push @{$sectun_idx_instances->{ $snmp_result->{$oid_cipSecTunIkeTunnelIndex}->{$_} }}, $1; } foreach my $name (keys %{$self->{tunnel}}) { delete $self->{tunnel}->{$name} if (!defined($sectun_idx_instances->{ $self->{tunnel}->{$name}->{ike_tun_idx} })); } return if (scalar(keys %{$self->{tunnel}}) <= 0); my $sec_endpoint_idx_select = {}; my $sec_endpoint_idx_instances = []; foreach (keys %{$snmp_result->{$oid_cipSecEndPtLocalAddr1}}) { /(\d+)\.(\d+)$/; next if (!defined($sectun_idx_select->{$1})); push @$sec_endpoint_idx_instances, $1 . '.' . $2; $sec_endpoint_idx_select->{$1} = [] if (!defined($sec_endpoint_idx_select->{$1})); $sec_endpoint_idx_select->{$1} = [$2, $snmp_result->{$oid_cipSecEndPtLocalAddr1}->{$_}]; } $options{snmp}->load( oids => [ map($_->{oid}, values(%$mapping2)) ], instances => [ map(@$_, values(%$sectun_idx_instances)) ], instance_regexp => '^(.*)$' ); $options{snmp}->load( oids => [$oid_cikeTunActiveTime], instances => [ map($_->{ike_tun_idx}, values(%{$self->{tunnel}})) ], instance_regexp => '^(.*)$' ); $options{snmp}->load( oids => [ map($_->{oid}, values(%$mapping3)) ], instances => $sec_endpoint_idx_instances, instance_regexp => '^(.*)$' ); $snmp_result = $options{snmp}->get_leef(); foreach my $name (keys %{$self->{tunnel}}) { foreach my $cip_sec_tun_idx (@{$sectun_idx_instances->{ $self->{tunnel}->{$name}->{ike_tun_idx} }}) { my $result = $options{snmp}->map_instance(mapping => $mapping2, results => $snmp_result, instance => $cip_sec_tun_idx); my $sa_name = ''; if (defined($sec_endpoint_idx_select->{$cip_sec_tun_idx})) { my $result3 = $options{snmp}->map_instance(mapping => $mapping3, results => $snmp_result, instance => $cip_sec_tun_idx . '.' . $sec_endpoint_idx_select->{$cip_sec_tun_idx}->[0]); $sa_name = inet_ntoa($sec_endpoint_idx_select->{$cip_sec_tun_idx}->[1]) . ':' . inet_ntoa($result3->{cipSecEndPtLocalAddr2}) . '_' . inet_ntoa($result3->{cipSecEndPtRemoteAddr1}) . ':' . inet_ntoa($result3->{cipSecEndPtRemoteAddr2}); } if (defined($self->{option_results}->{filter_sa}) && $self->{option_results}->{filter_sa} ne '' && $sa_name !~ /$self->{option_results}->{filter_sa}/) { $self->{output}->output_add(long_msg => "skipping '" . $sa_name . "': no matching filter sa.", debug => 1); next; } if (defined($result->{cipSecTunHcInOctets}) && defined($result->{cipSecTunHcOutOctets})) { delete $result->{cipSecTunInOctets}; delete $result->{cipSecTunInOctWraps}; delete $result->{cipSecTunOutOctets}; delete $result->{cipSecTunOutOctWraps}; } foreach my $oid_name (keys %$mapping2) { $self->{tunnel}->{$name}->{ $oid_name . '_' . $cip_sec_tun_idx } = $result->{$oid_name} if (defined($result->{$oid_name})); } $self->{tunnel}->{$name}->{cikeTunActiveTime} = $snmp_result->{ $oid_cikeTunActiveTime . '.' . $self->{tunnel}->{$name}->{ike_tun_idx} }; $self->{tunnel}->{$name}->{sa}++; } } foreach my $name (keys %{$self->{tunnel}}) { delete $self->{tunnel}->{$name} if ($self->{tunnel}->{$name}->{sa} == 0); } $self->{global} = { total => scalar(keys %{$self->{tunnel}}) }; } 1; __END__ =head1 MODE Check IPsec tunnels. =over 8 =item B<--filter-name> Filter name (can be a regexp). Example (format localaddr_remoteaddr): =item B<--filter-sa> Filter IPSec Security Associations (can be a regexp). Example (format localaddr:localmask_remoteaddr:remotemask): =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^(tunnels-total)$' =item B<--warning-*> Threshold warning. Can be: 'tunnels-total', 'traffic-in', 'traffic-out', 'drop-in', 'drop-out', 'sa-total'. =item B<--critical-*> Threshold critical. Can be: 'tunnels-total', 'traffic-in', 'traffic-out', 'drop-in', 'drop-out', 'sa-total'. =back =cut centreon-plugins-20220113/centreon/common/cisco/standard/snmp/mode/ipsla.pm000066400000000000000000001436621417000230700266240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::standard::snmp::mode::ipsla; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use Math::Complex; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'tag', type => 1, cb_prefix_output => 'prefix_tag_output', message_multiple => 'All RTT controls are ok', skipped_code => { -2 => 1, -3 => 1, -10 => 1 } } ]; $self->{maps_counters}->{tag} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'rttMonCtrlAdminStatus' }, { name => 'rttMonCtrlAdminTag' }, { name => 'rttMonCtrlAdminRttType' }, { name => 'rttMonCtrlAdminThreshold' }, { name => 'rttMonEchoAdminPrecision' }, { name => 'rttMonLatestRttOperCompletionTime' }, { name => 'rttMonLatestRttOperSense' }, { name => 'rttMonLatestRttOperApplSpecificSense' }, ], 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 => 'CompletionTime', set => { key_values => [ { name => 'rttMonLatestRttOperCompletionTime' }, { name => 'rttMonEchoAdminPrecision' }, { name => 'rttMonCtrlAdminTag' } ], output_template => 'Completion Time : %s', perfdatas => [ { label => 'completion_time', value => 'rttMonLatestRttOperCompletionTime', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, { label => 'NumberOverThresholds', set => { key_values => [ { name => 'rttMonCtrlAdminStatus' }, { name => 'rttMonCtrlAdminRttType' }, { name => 'OverThresholds_1' }, { name => 'OverThresholds_2' }, { name => 'OverThresholds_times' }, ], closure_custom_calc => $self->can('custom_NumberOverThresholds_calc'), closure_custom_output => $self->can('custom_generic_output'), output_template => 'Number Over Thresholds : %s', threshold_use => 'value', perfdatas => [ { label => 'number_over_thresholds', value => 'value', template => '%s', label_extra_instance => 1 }, ], } }, { label => 'AverageDelaySD', set => { key_values => [ { name => 'rttMonCtrlAdminStatus' }, { name => 'rttMonCtrlAdminRttType' }, { name => 'OWSumSD_1' }, { name => 'OWSumSD_2' }, { name => 'OWSumSD_times' }, { name => 'NumOfOW_1' }, { name => 'NumOfOW_2' }, { name => 'NumOfOW_times' }, ], closure_custom_calc => $self->can('custom_AverageDelaySD_calc'), closure_custom_output => $self->can('custom_generic_output'), output_template => 'Average Delay SD : %.2f ms', threshold_use => 'value', perfdatas => [ { label => 'average_delay_sd', value => 'value', template => '%.2f', unit => 'ms', label_extra_instance => 1 }, ], } }, { label => 'AverageDelayDS', set => { key_values => [ { name => 'rttMonCtrlAdminStatus' }, { name => 'rttMonCtrlAdminRttType' }, { name => 'OWSumDS_1' }, { name => 'OWSumDS_2' }, { name => 'OWSumDS_times' }, { name => 'NumOfOW_1' }, { name => 'NumOfOW_2' }, { name => 'NumOfOW_times' }, ], closure_custom_calc => $self->can('custom_AverageDelayDS_calc'), closure_custom_output => $self->can('custom_generic_output'), output_template => 'Average Delay DS : %.2f ms', threshold_use => 'value', perfdatas => [ { label => 'average_delay_ds', value => 'value', template => '%.2f', unit => 'ms', label_extra_instance => 1 }, ], } }, { label => 'PacketLossRatio', set => { key_values => [ { name => 'rttMonCtrlAdminStatus' }, { name => 'rttMonCtrlAdminRttType' }, { name => 'PacketLossDS_1' }, { name => 'PacketLossDS_2' }, { name => 'PacketLossDS_times' }, { name => 'PacketLossSD_1' }, { name => 'PacketLossSD_2' }, { name => 'PacketLossSD_times' }, { name => 'PacketMIA_1' }, { name => 'PacketMIA_2' }, { name => 'PacketMIA_times' }, { name => 'PacketLateArrival_1' }, { name => 'PacketLateArrival_2' }, { name => 'PacketLateArrival_times' }, { name => 'PacketOutOfSequence_1' }, { name => 'PacketOutOfSequence_2' }, { name => 'PacketOutOfSequence_times' }, { name => 'NumOfRTT_1' }, { name => 'NumOfRTT_2' }, { name => 'NumOfRTT_times' }, ], closure_custom_calc => $self->can('custom_PacketLossRatio_calc'), closure_custom_output => $self->can('custom_generic_output'), output_template => 'Packet Loss Ratio : %.2f %%', threshold_use => 'value', perfdatas => [ { label => 'packet_loss_ratio', value => 'value', template => '%.2f', unit => '%', label_extra_instance => 1, min => 0, max => 100 }, ], } }, { label => 'PercentagePacketsPositiveJitter', set => { key_values => [ { name => 'rttMonCtrlAdminStatus' }, { name => 'rttMonCtrlAdminRttType' }, { name => 'NumOfPositivesSD_1' }, { name => 'NumOfPositivesSD_2' }, { name => 'NumOfPositivesSD_times' }, { name => 'NumOfRTT_1' }, { name => 'NumOfRTT_2' }, { name => 'NumOfRTT_times' }, ], closure_custom_calc => $self->can('custom_PercentagePacketsPositiveJitter_calc'), closure_custom_output => $self->can('custom_generic_output'), output_template => 'Percentage of Packets that had Positive Jitter : %.2f', threshold_use => 'value', perfdatas => [ { label => 'prct_jitter_per_packet_positive_jitter', value => 'value', template => '%.2f', label_extra_instance => 1, }, ], } }, { label => 'AverageJitterPerPacketPositiveJitter', set => { key_values => [ { name => 'rttMonCtrlAdminStatus' }, { name => 'rttMonCtrlAdminRttType' }, { name => 'SumOfPositivesSD_1' }, { name => 'SumOfPositivesSD_2' }, { name => 'SumOfPositivesSD_times' }, { name => 'NumOfRTT_1' }, { name => 'NumOfRTT_2' }, { name => 'NumOfRTT_times' }, ], closure_custom_calc => $self->can('custom_AverageJitterPerPacketPositiveJitter_calc'), closure_custom_output => $self->can('custom_generic_output'), output_template => 'Average Jitter per Packet that had Positive Jitter : %.2f', threshold_use => 'value', perfdatas => [ { label => 'average_jitter_per_packet_positive_jitter', value => 'value', template => '%.2f', label_extra_instance => 1 }, ], } }, { label => 'PercentagePacketsNegativeJitter', set => { key_values => [ { name => 'rttMonCtrlAdminStatus' }, { name => 'rttMonCtrlAdminRttType' }, { name => 'NumOfNegativesSD_1' }, { name => 'NumOfNegativesSD_2' }, { name => 'NumOfNegativesSD_times' }, { name => 'NumOfRTT_1' }, { name => 'NumOfRTT_2' }, { name => 'NumOfRTT_times' }, ], closure_custom_calc => $self->can('custom_PercentagePacketsNegativeJitter_calc'), closure_custom_output => $self->can('custom_generic_output'), output_template => 'Percentage of Packets that had Negative Jitter : %.2f', threshold_use => 'value', perfdatas => [ { label => 'prct_jitter_per_packet_negative_jitter', value => 'value', template => '%.2f', label_extra_instance => 1, }, ], } }, { label => 'AverageJitterPerPacketNegativeJitter', set => { key_values => [ { name => 'rttMonCtrlAdminStatus' }, { name => 'rttMonCtrlAdminRttType' }, { name => 'SumOfNegativesSD_1' }, { name => 'SumOfNegativesSD_2' }, { name => 'SumOfNegativesSD_times' }, { name => 'NumOfRTT_1' }, { name => 'NumOfRTT_2' }, { name => 'NumOfRTT_times' }, ], closure_custom_calc => $self->can('custom_AverageJitterPerPacketNegativeJitter_calc'), closure_custom_output => $self->can('custom_generic_output'), output_template => 'Average Jitter per Packet that had Negative Jitter : %.2f', threshold_use => 'value', perfdatas => [ { label => 'average_jitter_per_packet_negative_jitter', value => 'value', template => '%.2f', label_extra_instance => 1 }, ], } }, { label => 'AverageJitter', set => { key_values => [ { name => 'rttMonCtrlAdminStatus' }, { name => 'rttMonCtrlAdminRttType' }, { name => 'SumOfPositivesDS_1' }, { name => 'SumOfPositivesDS_2' }, { name => 'SumOfPositivesDS_times' }, { name => 'SumOfNegativesDS_1' }, { name => 'SumOfNegativesDS_2' }, { name => 'SumOfNegativesDS_times' }, { name => 'SumOfPositivesSD_1' }, { name => 'SumOfPositivesSD_2' }, { name => 'SumOfPositivesSD_times' }, { name => 'SumOfNegativesSD_1' }, { name => 'SumOfNegativesSD_2' }, { name => 'SumOfNegativesSD_times' }, { name => 'NumOfPositivesDS_1' }, { name => 'NumOfPositivesDS_2' }, { name => 'NumOfPositivesDS_times' }, { name => 'NumOfNegativesDS_1' }, { name => 'NumOfNegativesDS_2' }, { name => 'NumOfNegativesDS_times' }, { name => 'NumOfPositivesSD_1' }, { name => 'NumOfPositivesSD_2' }, { name => 'NumOfPositivesSD_times' }, { name => 'NumOfNegativesSD_1' }, { name => 'NumOfNegativesSD_2' }, { name => 'NumOfNegativesSD_times' }, ], closure_custom_calc => $self->can('custom_AverageJitter_calc'), closure_custom_output => $self->can('custom_generic_output'), output_template => 'Average Jitter : %.2f ms', threshold_use => 'value', perfdatas => [ { label => 'average_jitter', value => 'value', template => '%.2f', unit => 'ms', label_extra_instance => 1 }, ], } }, { label => 'RTTStandardDeviation', set => { key_values => [ { name => 'rttMonCtrlAdminStatus' }, { name => 'rttMonCtrlAdminRttType' }, { name => 'RTTSum2High_1' }, { name => 'RTTSum2High_2' }, { name => 'RTTSum2High_times' }, { name => 'RTTSum2Low_1' }, { name => 'RTTSum2Low_2' }, { name => 'RTTSum2Low_times' }, { name => 'NumOfRTT_1' }, { name => 'NumOfRTT_2' }, { name => 'NumOfRTT_times' }, { name => 'RTTSum_1' }, { name => 'RTTSum_2' }, { name => 'RTTSum_times' }, ], closure_custom_calc => $self->can('custom_RTTStandardDeviation_calc'), closure_custom_output => $self->can('custom_generic_output'), output_template => 'Round-Trip Time Standard Deviation : %.2f ms', threshold_use => 'value', perfdatas => [ { label => 'rtt_standard_deviation', value => 'value', template => '%.2f', unit => 'ms', label_extra_instance => 1 }, ], } }, { label => 'DelaySource2DestinationStandardDeviation', set => { key_values => [ { name => 'rttMonCtrlAdminStatus' }, { name => 'rttMonCtrlAdminRttType' }, { name => 'OWSum2SDHigh_1' }, { name => 'OWSum2SDHigh_2' }, { name => 'OWSum2SDHigh_times' }, { name => 'OWSum2SDLow_1' }, { name => 'OWSum2SDLow_2' }, { name => 'OWSum2SDLow_times' }, { name => 'NumOfOW_1' }, { name => 'NumOfOW_2' }, { name => 'NumOfOW_times' }, { name => 'OWSumSD_1' }, { name => 'OWSumSD_2' }, { name => 'OWSumSD_times' }, ], closure_custom_calc => $self->can('custom_DelaySource2DestinationStandardDeviation_calc'), closure_custom_output => $self->can('custom_generic_output'), output_template => 'One-Way Delay Source to Destination Standard Deviation : %.2f ms', threshold_use => 'value', perfdatas => [ { label => 'delay_src2dest_stdev', value => 'value', template => '%.2f', unit => 'ms', label_extra_instance => 1 }, ], } }, { label => 'DelayDestination2SourceStandardDeviation', set => { key_values => [ { name => 'rttMonCtrlAdminStatus' }, { name => 'rttMonCtrlAdminRttType' }, { name => 'OWSum2DSHigh_1' }, { name => 'OWSum2DSHigh_2' }, { name => 'OWSum2DSHigh_times' }, { name => 'OWSum2DSLow_1' }, { name => 'OWSum2DSLow_2' }, { name => 'OWSum2DSLow_times' }, { name => 'NumOfOW_1' }, { name => 'NumOfOW_2' }, { name => 'NumOfOW_times' }, { name => 'OWSumDS_1' }, { name => 'OWSumDS_2' }, { name => 'OWSumDS_times' }, ], closure_custom_calc => $self->can('custom_DelayDestination2SourceStandardDeviation_calc'), closure_custom_output => $self->can('custom_generic_output'), output_template => 'One-Way Delay Destination to Source Standard Deviation : %.2f ms', threshold_use => 'value', perfdatas => [ { label => 'delay_dest2src_stdev', value => 'value', template => '%.2f', unit => 'ms', label_extra_instance => 1 }, ], } }, { label => 'JitterSource2DestinationStandardDeviation', set => { key_values => [ { name => 'rttMonCtrlAdminStatus' }, { name => 'rttMonCtrlAdminRttType' }, { name => 'Sum2PositivesSDHigh_1' }, { name => 'Sum2PositivesSDHigh_2' }, { name => 'Sum2PositivesSDHigh_times' }, { name => 'Sum2PositivesSDLow_1' }, { name => 'Sum2PositivesSDLow_2' }, { name => 'Sum2PositivesSDLow_times' }, { name => 'Sum2NegativesSDHigh_1' }, { name => 'Sum2NegativesSDHigh_2' }, { name => 'Sum2NegativesSDHigh_times' }, { name => 'Sum2NegativesSDLow_1' }, { name => 'Sum2NegativesSDLow_2' }, { name => 'Sum2NegativesSDLow_times' }, { name => 'SumOfPositivesSD_1' }, { name => 'SumOfPositivesSD_2' }, { name => 'SumOfPositivesSD_times' }, { name => 'SumOfNegativesSD_1' }, { name => 'SumOfNegativesSD_2' }, { name => 'SumOfNegativesSD_times' }, { name => 'NumOfPositivesSD_1' }, { name => 'NumOfPositivesSD_2' }, { name => 'NumOfPositivesSD_times' }, { name => 'NumOfNegativesSD_1' }, { name => 'NumOfNegativesSD_2' }, { name => 'NumOfNegativesSD_times' }, ], closure_custom_calc => $self->can('custom_JitterSource2DestinationStandardDeviation_calc'), closure_custom_output => $self->can('custom_generic_output'), output_template => 'One-Way Jitter Source to Destination Standard Deviation : %.2f ms', threshold_use => 'value', perfdatas => [ { label => 'jitter_src2dest_stdev', value => 'value', template => '%.2f', unit => 'ms', label_extra_instance => 1 }, ], } }, { label => 'JitterDestination2SourceStandardDeviation', set => { key_values => [ { name => 'rttMonCtrlAdminStatus' }, { name => 'rttMonCtrlAdminRttType' }, { name => 'Sum2PositivesDSHigh_1' }, { name => 'Sum2PositivesDSHigh_2' }, { name => 'Sum2PositivesDSHigh_times' }, { name => 'Sum2PositivesDSLow_1' }, { name => 'Sum2PositivesDSLow_2' }, { name => 'Sum2PositivesDSLow_times' }, { name => 'Sum2NegativesDSHigh_1' }, { name => 'Sum2NegativesDSHigh_2' }, { name => 'Sum2NegativesDSHigh_times' }, { name => 'Sum2NegativesDSLow_1' }, { name => 'Sum2NegativesDSLow_2' }, { name => 'Sum2NegativesDSLow_times' }, { name => 'SumOfPositivesDS_1' }, { name => 'SumOfPositivesDS_2' }, { name => 'SumOfPositivesDS_times' }, { name => 'SumOfNegativesDS_1' }, { name => 'SumOfNegativesDS_2' }, { name => 'SumOfNegativesDS_times' }, { name => 'NumOfPositivesDS_1' }, { name => 'NumOfPositivesDS_2' }, { name => 'NumOfPositivesDS_times' }, { name => 'NumOfNegativesDS_1' }, { name => 'NumOfNegativesDS_2' }, { name => 'NumOfNegativesDS_times' }, ], closure_custom_calc => $self->can('custom_JitterDestination2SourceStandardDeviation_calc'), closure_custom_output => $self->can('custom_generic_output'), output_template => 'One-Way Jitter Destination to Source Standard Deviation : %.2f ms', threshold_use => 'value', perfdatas => [ { label => 'jitter_dest2src_stdev', value => 'value', template => '%.2f', unit => 'ms', label_extra_instance => 1 }, ], } }, ]; } sub prefix_tag_output { my ($self, %options) = @_; return "RTT '" . $options{instance_value}->{rttMonCtrlAdminTag} . "' "; } my $ipsla; my $thresholds = { opersense => [ ['ok', 'OK'], ['.*', 'CRITICAL'], ], applspecificsense => [ ['.*', 'OK'], ], }; ###### Common func ###### sub get_my_delta { my ($self, %options) = @_; my $value; my ($old_time1, $old_time2) = split /_/, $options{old_datas}->{$self->{instance} . '_' . $options{name} . '_times'}; my ($new_time1, $new_time2) = split /_/, $options{new_datas}->{$self->{instance} . '_' . $options{name} . '_times'}; if (defined($old_time1) && defined($new_time1) && $old_time1 == $new_time1) { $value = $options{new_datas}->{$self->{instance} . '_' . $options{name} . '_1'} - $options{old_datas}->{$self->{instance} . '_' . $options{name} . '_1'} + $options{new_datas}->{$self->{instance} . '_' . $options{name} . '_2'} - $options{old_datas}->{$self->{instance} . '_' . $options{name} . '_2'}; } else { $value = $options{new_datas}->{$self->{instance} . '_' . $options{name} . '_1'} - $options{old_datas}->{$self->{instance} . '_' . $options{name} . '_2'} + $options{new_datas}->{$self->{instance} . '_' . $options{name} . '_2'}; } return $value; } sub custom_generic_output { my ($self, %options) = @_; return sprintf($self->{output_template}, $self->{result_values}->{value}); } sub check_buffer_creation { my ($self, %options) = @_; if (!defined($options{old_datas}->{$self->{instance} . '_' . $options{name} . '_1'})) { $self->{error_msg} = "Buffer creation"; return 1; } return 0; } ###### STATUS ###### sub custom_status_threshold { my ($self, %options) = @_; my $status = 'ok'; if ($self->{result_values}->{rttMonCtrlAdminStatus} !~ /active/) { return $status; } $status = $ipsla->get_severity(section => $self->{result_values}->{section}, value => $self->{result_values}->{opersense}); return $status; } sub custom_status_output { my ($self, %options) = @_; my $msg = 'Status : '; if ($self->{result_values}->{rttMonCtrlAdminStatus} !~ /active/) { $msg .= 'not active (' . $self->{result_values}->{rttMonCtrlAdminStatus} . ')'; return $msg; } $msg .= "operation sense is '" . $self->{result_values}->{opersense} . "'"; return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{rttMonCtrlAdminStatus} = $options{new_datas}->{$self->{instance} . '_rttMonCtrlAdminStatus'}; $self->{result_values}->{rttMonCtrlAdminTag} = $options{new_datas}->{$self->{instance} . '_rttMonCtrlAdminTag'}; $self->{result_values}->{rttMonCtrlAdminRttType} = $options{new_datas}->{$self->{instance} . '_rttMonCtrlAdminRttType'}; $self->{result_values}->{rttMonCtrlAdminThreshold} = $options{new_datas}->{$self->{instance} . '_rttMonCtrlAdminThreshold'}; $self->{result_values}->{rttMonEchoAdminPrecision} = $options{new_datas}->{$self->{instance} . '_rttMonEchoAdminPrecision'}; $self->{result_values}->{rttMonLatestRttOperCompletionTime} = $options{new_datas}->{$self->{instance} . '_rttMonLatestRttOperCompletionTime'}; $self->{result_values}->{rttMonLatestRttOperSense} = $options{new_datas}->{$self->{instance} . '_rttMonLatestRttOperSense'}; $self->{result_values}->{rttMonLatestRttOperApplSpecificSense} = $options{new_datas}->{$self->{instance} . '_rttMonLatestRttOperApplSpecificSense'}; $self->{result_values}->{opersense} = $self->{result_values}->{rttMonLatestRttOperSense}; $self->{result_values}->{section} = 'opersense'; if ($self->{result_values}->{opersense} =~ /applicationSpecific/i) { $self->{result_values}->{opersense} = $self->{result_values}->{rttMonLatestRttOperApplSpecificSense}; $self->{result_values}->{section} = 'applspecificsense'; } return 0; } ####### 1 - Number Over Thresholds ####### sub custom_NumberOverThresholds_calc { my ($self, %options) = @_; if ($options{new_datas}->{$self->{instance} . '_rttMonCtrlAdminStatus'} !~ /active/ && $options{new_datas}->{$self->{instance} . '_rttMonCtrlAdminRttType'} !~ /jitter/) { return -2; } return -1 if (check_buffer_creation($self, %options, name => 'OverThresholds')); $self->{result_values}->{value} = get_my_delta($self, %options, name => 'OverThresholds'); return 0; } ####### 2 - Average Delay SD ####### sub custom_AverageDelaySD_calc { my ($self, %options) = @_; if ($options{new_datas}->{$self->{instance} . '_rttMonCtrlAdminStatus'} !~ /active/ && $options{new_datas}->{$self->{instance} . '_rttMonCtrlAdminRttType'} !~ /jitter/) { return -2; } return -1 if (check_buffer_creation($self, %options, name => 'OWSumSD')); my $num_of_ow = get_my_delta($self, %options, name => 'NumOfOW'); if ($num_of_ow == 0) { $self->{error_msg} = "wait new values"; return -3; } $self->{result_values}->{value} = get_my_delta($self, %options, name => 'OWSumSD') / $num_of_ow; return 0; } ####### 3 - Average Delay DS ####### sub custom_AverageDelayDS_calc { my ($self, %options) = @_; if ($options{new_datas}->{$self->{instance} . '_rttMonCtrlAdminStatus'} !~ /active/ && $options{new_datas}->{$self->{instance} . '_rttMonCtrlAdminRttType'} !~ /jitter/) { return -2; } return -1 if (check_buffer_creation($self, %options, name => 'OWSumDS')); my $num_of_ow = get_my_delta($self, %options, name => 'NumOfOW'); if ($num_of_ow == 0) { $self->{error_msg} = "wait new values"; return -3; } $self->{result_values}->{value} = get_my_delta($self, %options, name => 'OWSumDS') / $num_of_ow; return 0; } ####### 4 - Packet Loss Ratio ####### sub custom_PacketLossRatio_calc { my ($self, %options) = @_; if ($options{new_datas}->{$self->{instance} . '_rttMonCtrlAdminStatus'} !~ /active/ && $options{new_datas}->{$self->{instance} . '_rttMonCtrlAdminRttType'} !~ /jitter/) { return -2; } return -1 if (check_buffer_creation($self, %options, name => 'PacketLossDS')); my $divide = (get_my_delta($self, %options, name => 'PacketLossSD') + get_my_delta($self, %options, name => 'PacketLossDS') + get_my_delta($self, %options, name => 'PacketMIA') + get_my_delta($self, %options, name => 'PacketLateArrival') + get_my_delta($self, %options, name => 'PacketOutOfSequence') + get_my_delta($self, %options, name => 'NumOfRTT')); if ($divide == 0) { $self->{error_msg} = "wait new values"; return -3; } $self->{result_values}->{value} = ((get_my_delta($self, %options, name => 'PacketLossDS') + get_my_delta($self, %options, name => 'PacketLossSD') + get_my_delta($self, %options, name => 'PacketMIA')) * 100 ) / $divide; return 0; } ####### 5 - Percentage of Packets that had Positive Jitter ####### sub custom_PercentagePacketsPositiveJitter_calc { my ($self, %options) = @_; if ($options{new_datas}->{$self->{instance} . '_rttMonCtrlAdminStatus'} !~ /active/ && $options{new_datas}->{$self->{instance} . '_rttMonCtrlAdminRttType'} !~ /jitter/) { return -2; } return -1 if (check_buffer_creation($self, %options, name => 'NumOfPositivesSD')); my $num_of_rtt = get_my_delta($self, %options, name => 'NumOfRTT'); if ($num_of_rtt == 0) { $self->{error_msg} = "wait new values"; return -3; } $self->{result_values}->{value} = get_my_delta($self, %options, name => 'NumOfPositivesSD') / $num_of_rtt; return 0; } ####### 6 - Average Jitter per Packet that had Positive Jitter ####### sub custom_AverageJitterPerPacketPositiveJitter_calc { my ($self, %options) = @_; if ($options{new_datas}->{$self->{instance} . '_rttMonCtrlAdminStatus'} !~ /active/ && $options{new_datas}->{$self->{instance} . '_rttMonCtrlAdminRttType'} !~ /jitter/) { return -2; } return -1 if (check_buffer_creation($self, %options, name => 'SumOfPositivesSD')); my $num_of_rtt = get_my_delta($self, %options, name => 'NumOfRTT'); if ($num_of_rtt == 0) { $self->{error_msg} = "wait new values"; return -3; } $self->{result_values}->{value} = get_my_delta($self, %options, name => 'SumOfPositivesSD') / $num_of_rtt; return 0; } ####### 7 - Percentage of Packets that had Negative Jitter ####### sub custom_PercentagePacketsNegativeJitter_calc { my ($self, %options) = @_; if ($options{new_datas}->{$self->{instance} . '_rttMonCtrlAdminStatus'} !~ /active/ && $options{new_datas}->{$self->{instance} . '_rttMonCtrlAdminRttType'} !~ /jitter/) { return -2; } return -1 if (check_buffer_creation($self, %options, name => 'NumOfNegativesSD')); my $num_of_rtt = get_my_delta($self, %options, name => 'NumOfRTT'); if ($num_of_rtt == 0) { $self->{error_msg} = "wait new values"; return -3; } $self->{result_values}->{value} = get_my_delta($self, %options, name => 'NumOfNegativesSD') / $num_of_rtt; return 0; } ####### 8 - Average Jitter per Packet that had Negative Jitter ####### sub custom_AverageJitterPerPacketNegativeJitter_calc { my ($self, %options) = @_; if ($options{new_datas}->{$self->{instance} . '_rttMonCtrlAdminStatus'} !~ /active/ && $options{new_datas}->{$self->{instance} . '_rttMonCtrlAdminRttType'} !~ /jitter/) { return -2; } return -1 if (check_buffer_creation($self, %options, name => 'SumOfNegativesSD')); my $num_of_rtt = get_my_delta($self, %options, name => 'NumOfRTT'); if ($num_of_rtt == 0) { $self->{error_msg} = "wait new values"; return -3; } $self->{result_values}->{value} = get_my_delta($self, %options, name => 'SumOfNegativesSD') / $num_of_rtt; return 0; } ####### 9 - Average Jitter ####### sub custom_AverageJitter_calc { my ($self, %options) = @_; if ($options{new_datas}->{$self->{instance} . '_rttMonCtrlAdminStatus'} !~ /active/ && $options{new_datas}->{$self->{instance} . '_rttMonCtrlAdminRttType'} !~ /jitter/) { return -2; } return -1 if (check_buffer_creation($self, %options, name => 'SumOfPositivesDS')); my $divide = (get_my_delta($self, %options, name => 'NumOfPositivesDS') + get_my_delta($self, %options, name => 'NumOfNegativesDS') + get_my_delta($self, %options, name => 'NumOfPositivesSD') + get_my_delta($self, %options, name => 'NumOfNegativesSD')); if ($divide == 0) { $self->{error_msg} = "wait new values"; return -3; } $self->{result_values}->{value} = ( get_my_delta($self, %options, name => 'SumOfPositivesDS') + get_my_delta($self, %options, name => 'SumOfNegativesDS') + get_my_delta($self, %options, name => 'SumOfPositivesSD') + get_my_delta($self, %options, name => 'SumOfNegativesSD')) / $divide; return 0; } ####### 10 - Round-Trip Time Standard Deviation ####### sub custom_RTTStandardDeviation_calc { my ($self, %options) = @_; if ($options{new_datas}->{$self->{instance} . '_rttMonCtrlAdminStatus'} !~ /active/ && $options{new_datas}->{$self->{instance} . '_rttMonCtrlAdminRttType'} !~ /jitter/) { return -2; } return -1 if (check_buffer_creation($self, %options, name => 'NumOfRTT')); my $num_of_rtt = get_my_delta($self, %options, name => 'NumOfRTT'); if ($num_of_rtt == 0) { $self->{error_msg} = "wait new values"; return -3; } $self->{result_values}->{value} = sqrt( ((get_my_delta($self, %options, name => 'RTTSum2High') * 2 ** 32 + get_my_delta($self, %options, name => 'RTTSum2Low')) / $num_of_rtt) - (get_my_delta($self, %options, name => 'RTTSum') / $num_of_rtt) ** 2 ); return 0; } ####### 11 - One-Way Delay Source to Destination Standard Deviation ####### sub custom_DelaySource2DestinationStandardDeviation_calc { my ($self, %options) = @_; if ($options{new_datas}->{$self->{instance} . '_rttMonCtrlAdminStatus'} !~ /active/ && $options{new_datas}->{$self->{instance} . '_rttMonCtrlAdminRttType'} !~ /jitter/) { return -2; } return -1 if (check_buffer_creation($self, %options, name => 'NumOfOW')); my $num_of_ow = get_my_delta($self, %options, name => 'NumOfOW'); if ($num_of_ow == 0) { $self->{error_msg} = "wait new values"; return -3; } $self->{result_values}->{value} = sqrt( ((get_my_delta($self, %options, name => 'OWSum2SDHigh') * 2 ** 32 + get_my_delta($self, %options, name => 'OWSum2SDLow')) / $num_of_ow) - (get_my_delta($self, %options, name => 'OWSumSD') / $num_of_ow) ** 2 ); return 0; } ####### 12 - One-Way Delay Destination to Source Standard Deviation ####### sub custom_DelayDestination2SourceStandardDeviation_calc { my ($self, %options) = @_; if ($options{new_datas}->{$self->{instance} . '_rttMonCtrlAdminStatus'} !~ /active/ && $options{new_datas}->{$self->{instance} . '_rttMonCtrlAdminRttType'} !~ /jitter/) { return -2; } return -1 if (check_buffer_creation($self, %options, name => 'NumOfOW')); my $num_of_ow = get_my_delta($self, %options, name => 'NumOfOW'); if ($num_of_ow == 0) { $self->{error_msg} = "wait new values"; return -3; } $self->{result_values}->{value} = sqrt( ((get_my_delta($self, %options, name => 'OWSum2DSHigh') * 2 ** 32 + get_my_delta($self, %options, name => 'OWSum2DSLow')) / $num_of_ow) - (get_my_delta($self, %options, name => 'OWSumDS') / $num_of_ow) ** 2 ); return 0; } ####### 13 - One-Way Jitter Source to Destination Standard Deviation ####### sub custom_JitterSource2DestinationStandardDeviation_calc { my ($self, %options) = @_; if ($options{new_datas}->{$self->{instance} . '_rttMonCtrlAdminStatus'} !~ /active/ && $options{new_datas}->{$self->{instance} . '_rttMonCtrlAdminRttType'} !~ /jitter/) { return -2; } return -1 if (check_buffer_creation($self, %options, name => 'NumOfPositivesSD')); my $divide = (get_my_delta($self, %options, name => 'NumOfPositivesSD') + get_my_delta($self, %options, name => 'NumOfNegativesSD')); if ($divide == 0) { $self->{error_msg} = "wait new values"; return -3; } $self->{result_values}->{value} = sqrt( ((get_my_delta($self, %options, name => 'Sum2PositivesSDHigh') * 2 ** 32 + get_my_delta($self, %options, name => 'Sum2PositivesSDLow') + get_my_delta($self, %options, name => 'Sum2NegativesSDHigh') * 2 ** 32 + get_my_delta($self, %options, name => 'Sum2NegativesSDLow')) / $divide) - ((get_my_delta($self, %options, name => 'SumOfPositivesSD') + get_my_delta($self, %options, name => 'SumOfNegativesSD')) / $divide) ** 2 ); return 0; } ####### 14 - JitterDestination2SourceStandardDeviation ####### sub custom_JitterDestination2SourceStandardDeviation_calc { my ($self, %options) = @_; if ($options{new_datas}->{$self->{instance} . '_rttMonCtrlAdminStatus'} !~ /active/ && $options{new_datas}->{$self->{instance} . '_rttMonCtrlAdminRttType'} !~ /jitter/) { return -2; } return -1 if (check_buffer_creation($self, %options, name => 'NumOfPositivesDS')); my $divide = (get_my_delta($self, %options, name => 'NumOfPositivesDS') + get_my_delta($self, %options, name => 'NumOfNegativesDS')); if ($divide == 0) { $self->{error_msg} = "wait new values"; return -3; } $self->{result_values}->{value} = sqrt( ((get_my_delta($self, %options, name => 'Sum2PositivesDSHigh') * 2 ** 32 + get_my_delta($self, %options, name => 'Sum2PositivesDSLow') + get_my_delta($self, %options, name => 'Sum2NegativesDSHigh') * 2 ** 32 + get_my_delta($self, %options, name => 'Sum2NegativesDSLow')) / $divide) - ((get_my_delta($self, %options, name => 'SumOfPositivesDS') + get_my_delta($self, %options, name => 'SumOfNegativesDS')) / $divide) ** 2 ); return 0; } my $oid_rttMonCtrlAdminEntry = '.1.3.6.1.4.1.9.9.42.1.2.1.1'; my $oid_rttMonEchoAdminPrecision = '.1.3.6.1.4.1.9.9.42.1.2.2.1.37'; my $oid_rttMonLatestRttOperEntry = '.1.3.6.1.4.1.9.9.42.1.2.10.1'; # Packet Loss Ratio (unit: %): # [(RttMonJitterStatsPacketLossDS + RttMonJitterStatsPacketLossSD + RttMonJitterStatsPacketMIA) * 100 ] / # [RttMonJitterStatsPacketLossSD + RttMonJitterStatsPacketLossDS + RttMonJitterStatsPacketMIA + # RttMonJitterStatsPacketLateArrival + RttMonJitterStatsPacketOutOfSequence + RttMonJitterStatsNumOfRTT ] # Percentage (unit: %): # NumOfPositiveSD/NumOfRTT (Percentage of Packets that had Positive Jitter) # SumOfPositiveSD/NumOfRTT (Average Jitter per Packet that had Positive Jitter) # NumOfNegativeSD/NumOfRTT (Percentage of Packets that had Negative Jitter) # SumOfNegativeSD/NumOfRTT (Average Jitter per Packet that had Negative Jitter) # # Average Jitter (unit: ms): # jitterSum = sumOfPositivesDS + sumOfNegativesDS + sumOfPositivesSD + sumOfNegativesSD; # jitterNum = numOfPositivesDS + numOfNegativesDS + numOfPositivesSD + numOfNegativesSD; # avgJitter = jitterSum/jitterNum; # Delays (unit: ms): # RttMonJitterStatsOWSumSD / RttMonJitterStatsNumOfOW # RttMonJitterStatsOWSumDS / RttMonJitterStatsNumOfOW # Round-Trip Time Standard Deviation (unit: ms): # Square Root of [ ((RttMonJitterStatsRTTSum2High * 2^32 + RttMonJitterStatsRTTSum2Low) / RttMonJitterStatsNumOfRTT) - (RttMonJitterStatsRTTSum / RttMonJitterStatsNumOfRTT)^2 ] # One-Way Delay Source to Destination Standard Deviation (unit: ms): # Square Root of [ ((RttMonJitterStatsOWSum2SDHigh * 2^32 + RttMonJitterStatsOWSum2SDLow) / RttMonJitterStatsNumOfOW) - (RttMonJitterStatsOWSumSD / RttMonJitterStatsNumOfOW)^2 ] # One-Way Delay Destination to Source Standard Deviation (unit: ms): # Square Root of [ ((RttMonJitterStatsOWSum2DSHigh * 2^32 + RttMonJitterStatsOWSum2DSLow) / RttMonJitterStatsNumOfOW) - (RttMonJitterStatsOWSumDS / RttMonJitterStatsNumOfOW)^2 ] # One-Way Jitter Source to Destination Standard Deviation (unit: ms): # Square Root of [ ((RttMonJitterStatsSum2PositivesSDHigh * 2^32 + RttMonJitterStatsSum2PositivesSDLow + RttMonJitterStatsSum2NegativesSDHigh * 2^32 + RttMonJitterStatsSum2NegativesSDLow) / (RttMonJitterStatsNumOfPositivesSD + RttMonJitterStatsNumOfNegativesSD)) - ((RttMonJitterStatsSumOfPositivesSD + RttMonJitterStatsSumOfNegativesSD) / (RttMonJitterStatsNumOfPositivesSD + RttMonJitterStatsNumOfNegativesSD))^2 ] # One-Way Jitter Destination to Source Standard Deviation (unit: ms): # Square Root of [ ((RttMonJitterStatsSum2PositivesDSHigh * 2^32 + RttMonJitterStatsSum2PositivesDSLow + RttMonJitterStatsSum2NegativesDSHigh * 2^32 + RttMonJitterStatsSum2NegativesDSLow) / (RttMonJitterStatsNumOfPositivesDS + RttMonJitterStatsNumOfNegativesDS)) - ((RttMonJitterStatsSumOfPositivesDS + RttMonJitterStatsSumOfNegativesDS) / (RttMonJitterStatsNumOfPositivesDS + RttMonJitterStatsNumOfNegativesDS))^2 ] my $oid_rttMonJitterStatsEntry = '.1.3.6.1.4.1.9.9.42.1.3.5.1'; my $oids_jitter_stats = { NumOfRTT => '.1.3.6.1.4.1.9.9.42.1.3.5.1.4', OverThresholds => '.1.3.6.1.4.1.9.9.42.1.3.5.1.3', RTTSum => '.1.3.6.1.4.1.9.9.42.1.3.5.1.5', RTTSum2Low => '.1.3.6.1.4.1.9.9.42.1.3.5.1.6', RTTSum2High => '.1.3.6.1.4.1.9.9.42.1.3.5.1.7', NumOfOW => '.1.3.6.1.4.1.9.9.42.1.3.5.1.51', OWSumSD => '.1.3.6.1.4.1.9.9.42.1.3.5.1.41', # low OWSumSDHigh => '.1.3.6.1.4.1.9.9.42.1.3.5.1.67', # high OWSumDS => '.1.3.6.1.4.1.9.9.42.1.3.5.1.46', # low OWSumDSHigh => '.1.3.6.1.4.1.9.9.42.1.3.5.1.68', # high SumOfPositivesSD => '.1.3.6.1.4.1.9.9.42.1.3.5.1.13', SumOfNegativesSD => '.1.3.6.1.4.1.9.9.42.1.3.5.1.19', SumOfPositivesDS => '.1.3.6.1.4.1.9.9.42.1.3.5.1.25', SumOfNegativesDS => '.1.3.6.1.4.1.9.9.42.1.3.5.1.31', NumOfNegativesSD => '.1.3.6.1.4.1.9.9.42.1.3.5.1.18', Sum2NegativesSDLow => '.1.3.6.1.4.1.9.9.42.1.3.5.1.20', Sum2NegativesSDHigh => '.1.3.6.1.4.1.9.9.42.1.3.5.1.21', NumOfNegativesDS => '.1.3.6.1.4.1.9.9.42.1.3.5.1.30', Sum2NegativesDSLow => '.1.3.6.1.4.1.9.9.42.1.3.5.1.32', Sum2NegativesDSHigh => '.1.3.6.1.4.1.9.9.42.1.3.5.1.33', NumOfPositivesSD => '.1.3.6.1.4.1.9.9.42.1.3.5.1.12', Sum2PositivesSDLow => '.1.3.6.1.4.1.9.9.42.1.3.5.1.14', Sum2PositivesSDHigh => '.1.3.6.1.4.1.9.9.42.1.3.5.1.15', NumOfPositivesDS => '.1.3.6.1.4.1.9.9.42.1.3.5.1.24', Sum2PositivesDSLow => '.1.3.6.1.4.1.9.9.42.1.3.5.1.26', Sum2PositivesDSHigh => '.1.3.6.1.4.1.9.9.42.1.3.5.1.27', PacketLossSD => '.1.3.6.1.4.1.9.9.42.1.3.5.1.34', PacketLossDS => '.1.3.6.1.4.1.9.9.42.1.3.5.1.35', PacketOutOfSequence => '.1.3.6.1.4.1.9.9.42.1.3.5.1.36', PacketMIA => '.1.3.6.1.4.1.9.9.42.1.3.5.1.37', PacketLateArrival => '.1.3.6.1.4.1.9.9.42.1.3.5.1.38', OWSum2SDLow => '.1.3.6.1.4.1.9.9.42.1.3.5.1.42', OWSum2SDHigh => '.1.3.6.1.4.1.9.9.42.1.3.5.1.43', OWSum2DSLow => '.1.3.6.1.4.1.9.9.42.1.3.5.1.47', OWSum2DSHigh => '.1.3.6.1.4.1.9.9.42.1.3.5.1.48', MaxOfICPIF => '.1.3.6.1.4.1.9.9.42.1.3.5.1.59', MaxOfMOS => '.1.3.6.1.4.1.9.9.42.1.3.5.1.57', }; my %map_admin_rtt_type = ( 1 => 'echo1', 2 => 'pathEcho', 3 => 'fileIO', 4 => 'script', 5 => 'udpEcho', 6 => 'tcpConnect', 7 => 'http', 8 => 'dns', 9 => 'jitter', 10 => 'dlsw', 11 => 'dhcp', 12 => 'ftp', 13 => 'voip', 14 => 'rtp', 15 => 'lspGroup', 16 => 'icmpjitter', 17 => 'lspPing', 18 => 'lspTrace', 19 => 'ethernetPing', 20 => 'ethernetJitter', 21 => 'lspPingPseudowire', 22 => 'video', 23 => 'y1731Delay', 24 => 'y1731Loss', 25 => 'mcastJitter', ); my %map_admin_status = ( 1 => 'active', 2 => 'notInService', 3 => 'notReady', 4 => 'createAndGo', 5 => 'createAndWait', 6 => 'destroy', ); my %map_admin_precision = ( 1 => 'ms', 2 => 'us', ); my %map_rtt_oper_sense = ( 0 => 'other', 1 => 'ok', 2 => 'disconnected', 3 => 'overThreshold', 4 => 'timeout', 5 => 'busy', 6 => 'notConnected', 7 => 'dropped', 8 => 'sequenceError', 9 => 'verifyError', 10 => 'applicationSpecific', 11 => 'dnsServerTimeout', 12 => 'tcpConnectTimeout', 13 => 'httpTransactionTimeout', 14 => 'dnsQueryError', 15 => 'httpError', 16 => 'error', 17 => 'mplsLspEchoTxError', 18 => 'mplsLspUnreachable', 19 => 'mplsLspMalformedReq', 20 => 'mplsLspReachButNotFEC', 21 => 'enableOk', 22 => 'enableNoConnect', 23 => 'enableVersionFail', 24 => 'enableInternalError', 25 => 'enableAbort', 26 => 'enableFail', 27 => 'enableAuthFail', 28 => 'enableFormatError', 29 => 'enablePortInUse', 30 => 'statsRetrieveOk', 31 => 'statsRetrieveNoConnect', 32 => 'statsRetrieveVersionFail', 33 => 'statsRetrieveInternalError', 34 => 'statsRetrieveAbort', 35 => 'statsRetrieveFail', 36 => 'statsRetrieveAuthFail', 37 => 'statsRetrieveFormatError', 38 => 'statsRetrievePortInUse', ); my $mapping = { rttMonCtrlAdminTag => { oid => '.1.3.6.1.4.1.9.9.42.1.2.1.1.3' }, rttMonCtrlAdminRttType => { oid => '.1.3.6.1.4.1.9.9.42.1.2.1.1.4', map => \%map_admin_rtt_type }, rttMonCtrlAdminThreshold => { oid => '.1.3.6.1.4.1.9.9.42.1.2.1.1.5' }, rttMonCtrlAdminStatus => { oid => '.1.3.6.1.4.1.9.9.42.1.2.1.1.9', map => \%map_admin_status }, }; my $mapping2 = { rttMonEchoAdminPrecision => { oid => '.1.3.6.1.4.1.9.9.42.1.2.2.1.37', map => \%map_admin_precision }, }; my $mapping3 = { rttMonLatestRttOperCompletionTime => { oid => '.1.3.6.1.4.1.9.9.42.1.2.10.1.1' }, rttMonLatestRttOperSense => { oid => '.1.3.6.1.4.1.9.9.42.1.2.10.1.2', map => \%map_rtt_oper_sense }, rttMonLatestRttOperApplSpecificSense => { oid => '.1.3.6.1.4.1.9.9.42.1.2.10.1.3' }, }; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-tag:s' => { name => 'filter_tag', default => '.*' }, 'threshold-overload:s@' => { name => 'threshold_overload' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $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}; } # to be used on custom function $ipsla = $self; } sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = "cache_cisco_" . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_tag}) ? md5_hex($self->{option_results}->{filter_tag}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); $self->{results} = $options{snmp}->get_multiple_table( oids => [ { oid => $oid_rttMonCtrlAdminEntry, end => $mapping->{rttMonCtrlAdminStatus}->{oid} }, { oid => $oid_rttMonEchoAdminPrecision }, { oid => $oid_rttMonLatestRttOperEntry, end => $mapping3->{rttMonLatestRttOperApplSpecificSense}->{oid} }, { oid => $oid_rttMonJitterStatsEntry }, ], nothing_quit => 1 ); $self->{tag} = {}; foreach my $oid ($options{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_rttMonCtrlAdminEntry}})) { next if ($oid !~ /^$mapping->{rttMonCtrlAdminTag}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_rttMonCtrlAdminEntry}, instance => $instance); $result->{rttMonCtrlAdminTag} = defined($result->{rttMonCtrlAdminTag}) && $result->{rttMonCtrlAdminTag} ne '' ? $result->{rttMonCtrlAdminTag} : $instance; my $tag_name = $result->{rttMonCtrlAdminTag}; if (!defined($tag_name) || $tag_name eq '') { $self->{output}->output_add(long_msg => "skipping: please set a tag name"); next; } if (defined($self->{tag}->{$tag_name})) { $self->{output}->output_add(long_msg => "skipping '" . $tag_name . "': duplicate (please change the tag name)."); next; } if (defined($self->{option_results}->{filter_tag}) && $self->{option_results}->{filter_tag} ne '' && $tag_name !~ /$self->{option_results}->{filter_tag}/) { $self->{output}->output_add(long_msg => "skipping '" . $tag_name . "': no matching filter."); next; } $self->{tag}->{$tag_name} = { %{$result} }; $result = $options{snmp}->map_instance(mapping => $mapping2, results => $self->{results}->{$oid_rttMonEchoAdminPrecision}, instance => $instance); $self->{tag}->{$tag_name} = { %{$result}, %{$self->{tag}->{$tag_name}} }; $result = $options{snmp}->map_instance(mapping => $mapping3, results => $self->{results}->{$oid_rttMonLatestRttOperEntry}, instance => $instance); $self->{tag}->{$tag_name} = { %{$result}, %{$self->{tag}->{$tag_name}} }; # there are two entries with rotation: 1 -> last hour, 2 -> current hour. foreach my $key (keys %{$oids_jitter_stats}) { $self->{tag}->{$tag_name}->{$key . '_1'} = 0; $self->{tag}->{$tag_name}->{$key . '_2'} = 0; my $i = 1; my $instances = []; foreach my $oid2 ($options{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_rttMonJitterStatsEntry}})) { next if ($oid2 !~ /^$oids_jitter_stats->{$key}\.$instance.(\d+)/); push @{$instances}, $1; $self->{tag}->{$tag_name}->{$key . '_' . $i} = $self->{results}->{$oid_rttMonJitterStatsEntry}->{$oid2}; $i++; } $self->{tag}->{$tag_name}->{$key . '_times'} = join('_', @{$instances}); } } if (scalar(keys %{$self->{tag}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No entry found."); $self->{output}->option_exit(); } } 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__ =head1 MODE Check RTT Controls (CISCO-RTT-MON) =over 8 =item B<--filter-tag> Filter tag (Default: '.*') =item B<--threshold-overload> Set to overload default threshold values (syntax: section,status,regexp) It used before default thresholds (order stays). Example: --threshold-overload='opersense,CRITICAL,^(?!(ok)$)' =item B<--warning-*> Threshold warning. Can be: 'CompletionTime', 'NumberOverThresholds', 'AverageDelaySD', 'AverageDelayDS', 'PacketLossRatio', 'PercentagePacketsPositiveJitter', 'AverageJitterPerPacketPositiveJitter', 'PercentagePacketsNegativeJitter', 'AverageJitterPerPacketNegativeJitter', 'AverageJitter', 'RTTStandardDeviation', 'DelaySource2DestinationStandardDeviation', 'DelayDestination2SourceStandardDeviation', 'JitterSource2DestinationStandardDeviation', 'JitterDestination2SourceStandardDeviation'. =item B<--critical-*> Threshold critical. Can be: 'CompletionTime', 'NumberOverThresholds', 'AverageDelaySD', 'AverageDelayDS', 'PacketLossRatio', 'PercentagePacketsPositiveJitter', 'AverageJitterPerPacketPositiveJitter', 'PercentagePacketsNegativeJitter', 'AverageJitterPerPacketNegativeJitter', 'AverageJitter', 'RTTStandardDeviation', 'DelaySource2DestinationStandardDeviation', 'DelayDestination2SourceStandardDeviation', 'JitterSource2DestinationStandardDeviation', 'JitterDestination2SourceStandardDeviation'. =back =cut centreon-plugins-20220113/centreon/common/cisco/standard/snmp/mode/listaaaservers.pm000066400000000000000000000064531417000230700305400ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::standard::snmp::mode::listaaaservers; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } my $map_protocol = { 1 => 'tacacsplus', 2 => 'radius', 3 => 'ldap', 4 => 'kerberos', 5 => 'ntlm', 6 => 'sdi', 7 => 'other' }; my $mapping = { address => { oid => '.1.3.6.1.4.1.9.10.56.1.1.2.1.3' }, # casAddress authen_port => { oid => '.1.3.6.1.4.1.9.10.56.1.1.2.1.4' }, # casAuthenPort acc_port => { oid => '.1.3.6.1.4.1.9.10.56.1.1.2.1.5' } # casAcctPort }; my $oid_casConfigEntry = '.1.3.6.1.4.1.9.10.56.1.1.2.1'; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_table( oid => $oid_casConfigEntry, start => $mapping->{address}->{oid}, end => $mapping->{acc_port}->{oid}, nothing_quit => 1 ); my $results = {}; foreach (keys %$snmp_result) { next if (! /^$mapping->{address}->{oid}\.((\d+).*)$/); my ($instance, $protocol) = ($1, $map_protocol->{$2}); $results->{$instance} = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); $results->{$instance}->{protocol} = $protocol; } return $results; } sub run { my ($self, %options) = @_; my $results = $self->manage_selection(snmp => $options{snmp}); foreach my $name (sort keys %$results) { $self->{output}->output_add(long_msg => join('', map("[$_ = " . $results->{$name}->{$_} . ']', keys(%$mapping))) . '[protocol = ' . $results->{$name}->{protocol} . ']' ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List AAA 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 => ['protocol', keys %$mapping]); } sub disco_show { my ($self, %options) = @_; my $results = $self->manage_selection(snmp => $options{snmp}); foreach (sort keys %$results) { $self->{output}->add_disco_entry( %{$results->{$_}} ); } } 1; __END__ =head1 MODE List AAA servers. =over 8 =back =cut centreon-plugins-20220113/centreon/common/cisco/standard/snmp/mode/load.pm000066400000000000000000000116351417000230700264250ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::standard::snmp::mode::load; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_cpu_core_output { my ($self, %options) = @_; return "CPU '" . $options{instance_value}->{display} . "' load "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'cpu_core', type => 1, cb_prefix_output => 'prefix_cpu_core_output', message_separator => ' ', message_multiple => 'All core cpu loads are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{cpu_core} = [ { label => 'core-load-1m', nlabel => 'core.cpu.load.1m.count', set => { key_values => [ { name => 'cpmCPULoadAvg1min' }, { name => 'display' } ], output_template => '%.2f (1m)', perfdatas => [ { template => '%.2f', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'core-load-5m', nlabel => 'core.cpu.load.5m.count', set => { key_values => [ { name => 'cpmCPULoadAvg5min' }, { name => 'display' } ], output_template => '%.2f (5m)', perfdatas => [ { template => '%.2f', min => 0, label_extra_instance => 1, instance_use => 'display' }, ] } }, { label => 'core-load-15m', nlabel => 'core.cpu.load.15m.count', set => { key_values => [ { name => 'cpmCPULoadAvg15min' }, { name => 'display' } ], output_template => '%.2f (15m)', perfdatas => [ { template => '%.2f', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my $mapping = { cpmCPUTotalPhysicalIndex => { oid => '.1.3.6.1.4.1.9.9.109.1.1.1.1.2' }, cpmCPULoadAvg1min => { oid => '.1.3.6.1.4.1.9.9.109.1.1.1.1.24' }, cpmCPULoadAvg5min => { oid => '.1.3.6.1.4.1.9.9.109.1.1.1.1.25' }, cpmCPULoadAvg15min => { oid => '.1.3.6.1.4.1.9.9.109.1.1.1.1.26' } }; sub manage_selection { my ($self, %options) = @_; my $oid_cpmCPUTotalEntry = '.1.3.6.1.4.1.9.9.109.1.1.1.1'; my $snmp_result = $options{snmp}->get_multiple_table( oids => [ { oid => $oid_cpmCPUTotalEntry, start => $mapping->{cpmCPULoadAvg1min}->{oid}, end => $mapping->{cpmCPULoadAvg15min}->{oid} }, { oid => $mapping->{cpmCPUTotalPhysicalIndex}->{oid} } ], return_type => 1, nothing_quit => 1 ); $self->{cpu_core} = {}; foreach my $oid (keys %$snmp_result) { next if ($oid !~ /^$mapping->{cpmCPULoadAvg1min}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); $result->{cpmCPULoadAvg1min} *= 0.01 if (defined($result->{cpmCPULoadAvg1min})); $result->{cpmCPULoadAvg5min} *= 0.01 if (defined($result->{cpmCPULoadAvg5min})); $result->{cpmCPULoadAvg15min} *= 0.01 if (defined($result->{cpmCPULoadAvg15min})); $self->{cpu_core}->{$instance} = { display => $instance, %$result }; } my $oid_entPhysicalDescr = '.1.3.6.1.2.1.47.1.1.1.1.2'; $snmp_result = $options{snmp}->get_leef( oids => [ map($_->{cpmCPUTotalPhysicalIndex} != 0 ? $oid_entPhysicalDescr . '.' . $_->{cpmCPUTotalPhysicalIndex} : (), values(%{$self->{cpu_core}})) ] ); foreach (values %{$self->{cpu_core}}) { next if (!defined($snmp_result->{ $oid_entPhysicalDescr . '.' . $_->{cpmCPUTotalPhysicalIndex} })); $_->{display} = $snmp_result->{ $oid_entPhysicalDescr . '.' . $_->{cpmCPUTotalPhysicalIndex} }; } } 1; __END__ =head1 MODE Check cpu load usage. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'core-load-1m', 'core-load-5m', 'core-load-15m'. =back =cut centreon-plugins-20220113/centreon/common/cisco/standard/snmp/mode/memory.pm000066400000000000000000000346431417000230700270220ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::standard::snmp::mode::memory; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_usage_perfdata { my ($self, %options) = @_; my ($label, $nlabel, $unit, $total) = ('used', $self->{nlabel}, '%', 100); my $value_perf = $self->{result_values}->{prct_used}; my %total_options = (); if ($self->{result_values}->{total} != -1) { $nlabel = 'memory.usage.bytes'; $unit = 'B'; $total = $self->{result_values}->{total}; $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; $value_perf = $self->{result_values}->{used}; } $self->{output}->perfdata_add( label => $label, unit => $unit, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, nlabel => $nlabel, 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 => $total ); } sub custom_usage_threshold { my ($self, %options) = @_; return $self->{perfdata}->threshold_check(value => $self->{result_values}->{prct_used}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel}, exit_litteral => 'warning' } ]); } sub custom_usage_output { my ($self, %options) = @_; my $msg; if ($self->{result_values}->{total} != -1) { 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}); $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} ); } else { $msg = sprintf("Usage : %.2f %%", $self->{result_values}->{prct_used}); } return $msg; } sub custom_usage_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{prct_used} = $options{new_datas}->{$self->{instance} . '_prct_used'}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_total'}; $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_used'}; if ($self->{result_values}->{total} != -1) { $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 prefix_memory_output { my ($self, %options) = @_; return "Memory '" . $options{instance_value}->{display} . "' "; } 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', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{memory} = [ { label => 'usage', nlabel => 'memory.usage.percentage', set => { key_values => [ { name => 'display' }, { name => 'used' }, { name => 'total' }, { name => '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'), 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; $options{options}->add_options(arguments => { 'filter-pool:s' => { name => 'filter_pool' }, 'check-order:s' => { name => 'check_order', default => 'enhanced_pool,pool,process,system_ext' } }); return $self; } my $mapping_memory_pool = { ciscoMemoryPoolName => { oid => '.1.3.6.1.4.1.9.9.48.1.1.1.2' }, ciscoMemoryPoolUsed => { oid => '.1.3.6.1.4.1.9.9.48.1.1.1.5' }, # in B ciscoMemoryPoolFree => { oid => '.1.3.6.1.4.1.9.9.48.1.1.1.6' } # in B }; my $oid_ciscoMemoryPoolEntry = '.1.3.6.1.4.1.9.9.48.1.1.1'; sub check_memory_pool { my ($self, %options) = @_; return if ($self->{checked_memory} == 1); my $snmp_result = $self->{snmp}->get_table( oid => $oid_ciscoMemoryPoolEntry, start => $mapping_memory_pool->{ciscoMemoryPoolName}->{oid}, end => $mapping_memory_pool->{ciscoMemoryPoolFree}->{oid} ); foreach my $oid (keys %{$snmp_result}) { next if ($oid !~ /^$mapping_memory_pool->{ciscoMemoryPoolName}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping_memory_pool, results => $snmp_result, instance => $instance); $self->{checked_memory} = 1; if (defined($self->{option_results}->{filter_pool}) && $self->{option_results}->{filter_pool} ne '' && $result->{ciscoMemoryPoolName} !~ /$self->{option_results}->{filter_pool}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{ciscoMemoryPoolName} . "': no matching filter.", debug => 1); next; } $self->{memory}->{$instance} = { display => $result->{ciscoMemoryPoolName}, total => $result->{ciscoMemoryPoolFree} + $result->{ciscoMemoryPoolUsed}, used => $result->{ciscoMemoryPoolUsed}, prct_used => -1, }; } } my $oid_cseSysMemoryUtilization = '.1.3.6.1.4.1.9.9.305.1.1.2'; sub check_memory_system_ext { my ($self, %options) = @_; return if ($self->{checked_memory} == 1); my $snmp_result = $self->{snmp}->get_table( oid => $oid_cseSysMemoryUtilization, ); foreach my $oid (keys %{$snmp_result}) { my $used = $snmp_result->{$oid}; next if ($used eq ''); my $display = 'system'; $self->{checked_memory} = 1; if (defined($self->{option_results}->{filter_pool}) && $self->{option_results}->{filter_pool} ne '' && $display !~ /$self->{option_results}->{filter_pool}/) { $self->{output}->output_add(long_msg => "skipping '" . $display . "': no matching filter.", debug => 1); next; } $self->{memory}->{system} = { display => 'system', total => -1, used => -1, prct_used => $used, }; } } my $mapping_enh_memory_pool = { cempMemPoolName => { oid => '.1.3.6.1.4.1.9.9.221.1.1.1.1.3' }, cempMemPoolUsed => { oid => '.1.3.6.1.4.1.9.9.221.1.1.1.1.7' }, # in B cempMemPoolFree => { oid => '.1.3.6.1.4.1.9.9.221.1.1.1.1.8' }, # in B cempMemPoolHCUsed => { oid => '.1.3.6.1.4.1.9.9.221.1.1.1.1.18' }, # in B cempMemPoolHCFree => { oid => '.1.3.6.1.4.1.9.9.221.1.1.1.1.20' }, # in B }; sub check_memory_enhanced_pool { my ($self, %options) = @_; return if ($self->{checked_memory} == 1); my $oids = [ { oid => $mapping_enh_memory_pool->{cempMemPoolName}->{oid} }, { oid => $mapping_enh_memory_pool->{cempMemPoolUsed}->{oid} }, { oid => $mapping_enh_memory_pool->{cempMemPoolFree}->{oid} }, ]; if (!$self->{snmp}->is_snmpv1()) { push @{$oids}, { oid => $mapping_enh_memory_pool->{cempMemPoolHCUsed}->{oid} }, { oid => $mapping_enh_memory_pool->{cempMemPoolHCFree}->{oid} }; } my $snmp_result = $self->{snmp}->get_multiple_table( oids => $oids, return_type => 1 ); my $physical_array = {}; foreach my $oid (keys %{$snmp_result}) { next if ($oid !~ /^$mapping_enh_memory_pool->{cempMemPoolName}->{oid}\.(.*?)\.(.*)$/); my ($physical_index, $mem_index) = ($1, $2); my $result = $self->{snmp}->map_instance(mapping => $mapping_enh_memory_pool, results => $snmp_result, instance => $physical_index . '.' . $mem_index); $self->{checked_memory} = 1; my $used = defined($result->{cempMemPoolHCUsed}) ? $result->{cempMemPoolHCUsed} : $result->{cempMemPoolUsed}; my $free = defined($result->{cempMemPoolHCFree}) ? $result->{cempMemPoolHCFree} : $result->{cempMemPoolFree}; if ($used + $free <= 0) { $self->{output}->output_add(long_msg => "skipping '" . $result->{cempMemPoolName} . "': no total.", debug => 1); next; } $physical_array->{$physical_index} = 1; $self->{memory}->{$physical_index . '.' . $mem_index} = { display => $result->{cempMemPoolName}, total => $used + $free, used => $used, prct_used => -1, physical_index => $physical_index, }; } if (scalar(keys %$physical_array) > 0) { my $oid_entPhysicalName = '.1.3.6.1.2.1.47.1.1.1.1.7'; $self->{snmp}->load( oids => [$oid_entPhysicalName], instances => [keys %$physical_array], instance_regexp => '^(.*)$' ); $snmp_result = $self->{snmp}->get_leef(); foreach (keys %{$self->{memory}}) { if (defined($snmp_result->{ $oid_entPhysicalName . '.' . $self->{memory}->{$_}->{physical_index} })) { my $display = $snmp_result->{ $oid_entPhysicalName . '.' . $self->{memory}->{$_}->{physical_index} } . '_' . $self->{memory}->{$_}->{display}; if (defined($self->{option_results}->{filter_pool}) && $self->{option_results}->{filter_pool} ne '' && $display !~ /$self->{option_results}->{filter_pool}/) { $self->{output}->output_add(long_msg => "skipping '" . $display . "': no matching filter.", debug => 1); delete $self->{memory}->{$_}; next; } $self->{memory}->{$_}->{display} = $display; } else { if (defined($self->{option_results}->{filter_pool}) && $self->{option_results}->{filter_pool} ne '' && $self->{memory}->{$_}->{display} !~ /$self->{option_results}->{filter_pool}/) { $self->{output}->output_add(long_msg => "skipping '" . $self->{memory}->{$_}->{display} . "': no matching filter.", debug => 1); delete $self->{memory}->{$_}; } } } } } my $mapping_memory_process = { cpmCPUMemoryUsed => { oid => '.1.3.6.1.4.1.9.9.109.1.1.1.1.12' }, # in KB cpmCPUMemoryFree => { oid => '.1.3.6.1.4.1.9.9.109.1.1.1.1.13' }, # in KB cpmCPUMemoryUsedOvrflw => { oid => '.1.3.6.1.4.1.9.9.109.1.1.1.1.16' }, # in KB cpmCPUMemoryFreeOvrflw => { oid => '.1.3.6.1.4.1.9.9.109.1.1.1.1.18' }, # in KB }; sub check_memory_process { my ($self, %options) = @_; return if ($self->{checked_memory} == 1); my $oid_cpmCPUTotalEntry = '.1.3.6.1.4.1.9.9.109.1.1.1.1'; my $snmp_result = $self->{snmp}->get_table( oid => $oid_cpmCPUTotalEntry, start => $mapping_memory_process->{cpmCPUMemoryUsed}->{oid}, end => $mapping_memory_process->{cpmCPUMemoryFreeOvrflw}->{oid}, ); foreach my $oid (keys %{$snmp_result}) { next if ($oid !~ /^$mapping_memory_process->{cpmCPUMemoryUsed}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping_memory_process, results => $snmp_result, instance => $instance); $self->{checked_memory} = 1; my $used = ( defined($result->{cpmCPUMemoryUsedOvrflw}) ? ($result->{cpmCPUMemoryUsedOvrflw} << 32) + ($result->{cpmCPUMemoryUsed}) : $result->{cpmCPUMemoryUsed} ) * 1024; my $free = ( defined($result->{cpmCPUMemoryFreeOvrflw}) ? ($result->{cpmCPUMemoryFreeOvrflw} << 32) + ($result->{cpmCPUMemoryFree}) : $result->{cpmCPUMemoryFree} ) * 1024; $self->{memory}->{$instance} = { display => $instance, total => $used + $free, used => $used, prct_used => -1, }; } } sub manage_selection { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{checked_memory} = 0; $self->{memory} = {}; foreach (split /,/, $self->{option_results}->{check_order}) { my $method = $self->can('check_memory_' . $_); if ($method) { $self->$method(); } } if ($self->{checked_memory} == 0) { $self->{output}->add_option_msg(short_msg => "Cannot find memory informations"); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check memory usage (CISCO-MEMORY-POOL-MIB, CISCO-ENHANCED-MEMPOOL-MIB, CISCO-PROCESS-MIB, CISCO-SYSTEM-EXT-MIB). =over 8 =item B<--warning-usage> Threshold warning in percent. =item B<--critical-usage> Threshold critical in percent. =item B<--filter-pool> Filter pool to check (can use regexp). =item B<--check-order> Check memory in standard cisco mib. If you have some issue (wrong memory information in a specific mib), you can change the order (Default: 'enhanced_pool,pool,process,system_ext'). =back =cut centreon-plugins-20220113/centreon/common/cisco/standard/snmp/mode/memoryflash.pm000066400000000000000000000202361417000230700300310ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::standard::snmp::mode::memoryflash; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); sub custom_status_output { my ($self, %options) = @_; my $msg = 'status : ' . $self->{result_values}->{status}; return $msg; } sub custom_mem_output { my ($self, %options) = @_; my $msg = sprintf("Total: %s %s Used: %s %s (%.2f%%) Free: %s %s (%.2f%%)", $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}), $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}), $self->{result_values}->{prct_used}, $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}), $self->{result_values}->{prct_free}); return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'memory', type => 1, cb_prefix_output => 'prefix_memory_output', message_multiple => 'All memory flash partitions are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{memory} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'display' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold, } }, { label => 'usage', nlabel => 'memory.flash.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' }, { name => 'display' } ], closure_custom_output => $self->can('custom_mem_output'), perfdatas => [ { value => 'used', template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'usage-free', display_ok => 0, nlabel => 'memory.flash.free.bytes', set => { key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' }, { name => 'display' } ], closure_custom_output => $self->can('custom_mem_output'), perfdatas => [ { value => 'free', template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'usage-prct', display_ok => 0, nlabel => 'memory.flash.usage.percentage', set => { key_values => [ { name => 'prct_used' }, { name => 'display' } ], output_template => 'Used : %.2f %%', perfdatas => [ { value => 'prct_used', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'unknown-status:s' => { name => 'unknown_status', default => '%{status} =~ /readOnly/i' }, '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); $self->change_macros(macros => ['warning_status', 'critical_status', 'unknown_status']); } sub prefix_memory_output { my ($self, %options) = @_; return "Partition '" . $options{instance_value}->{display} . "' "; } my $map_status = { 1 => 'readOnly', 2 => 'runFromFlash', 3 => 'readWrite' }; my $mapping = { ciscoFlashPartitionSize => { oid => '.1.3.6.1.4.1.9.9.10.1.1.4.1.1.4' }, ciscoFlashPartitionFreeSpace => { oid => '.1.3.6.1.4.1.9.9.10.1.1.4.1.1.5' }, ciscoFlashPartitionStatus => { oid => '.1.3.6.1.4.1.9.9.10.1.1.4.1.1.8', map => $map_status }, ciscoFlashPartitionName => { oid => '.1.3.6.1.4.1.9.9.10.1.1.4.1.1.10' }, ciscoFlashPartitionSizeExtended => { oid => '.1.3.6.1.4.1.9.9.10.1.1.4.1.1.13' }, ciscoFlashPartitionFreeSpaceExtended => { oid => '.1.3.6.1.4.1.9.9.10.1.1.4.1.1.14' }, }; sub manage_selection { my ($self, %options) = @_; my $ciscoFlashPartitionEntry = '.1.3.6.1.4.1.9.9.10.1.1.4.1.1'; my $snmp_result = $options{snmp}->get_table( oid => $ciscoFlashPartitionEntry, nothing_quit => 1 ); $self->{memory} = {}; foreach my $oid (keys %$snmp_result) { next if ($oid !~ /^$mapping->{ciscoFlashPartitionSize}->{oid}\.(.*)/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $result->{ciscoFlashPartitionName} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{ciscoFlashPartitionName} . "': no matching filter.", debug => 1); next; } my $total = $result->{ciscoFlashPartitionSize}; if (defined($result->{ciscoFlashPartitionSizeExtended})) { $total = $result->{ciscoFlashPartitionSizeExtended}; } my $free = $result->{ciscoFlashPartitionFreeSpace}; if (defined($result->{ciscoFlashPartitionFreeSpaceExtended})) { $free = $result->{ciscoFlashPartitionFreeSpaceExtended}; } my ($used, $prct_used, $prct_free); if ($total > 0) { $used = $total - $free; $prct_used = $used * 100 / $total; $prct_free = 100 - $prct_used; } $self->{memory}->{$instance} = { display => $result->{ciscoFlashPartitionName}, status => $result->{ciscoFlashPartitionStatus}, free => $free, used => $used, prct_used => $prct_used, prct_free => $prct_free, total => $total, }; } if (scalar(keys %{$self->{memory}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No flash memory found.'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check memory flash usages. =over 8 =item B<--unknown-status> Set unknown threshold for status (Default: '%{status} =~ /readOnly/i'). Can used special variables like: %{status}, %{display} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{display} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{status}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'usage' (B), 'usage-free' (B), 'usage-prct' (%). =item B<--filter-name> Filter partition name (can be a regexp). =back =cut centreon-plugins-20220113/centreon/common/cisco/standard/snmp/mode/qosusage.pm000066400000000000000000000527631417000230700273440ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::standard::snmp::mode::qosusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use bigint; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'total', type => 0 }, { name => 'interface_classmap', type => 1, cb_prefix_output => 'prefix_intcmap_output', message_multiple => 'All interface classmaps are ok' }, { name => 'classmap', type => 1, cb_prefix_output => 'prefix_cmap_output', message_multiple => 'All classmaps are ok' } ]; $self->{maps_counters}->{interface_classmap} = [ { label => 'int-cmap-traffic', set => { key_values => [ { name => 'traffic_usage', diff => 1 }, { name => 'total' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_traffic_calc'), closure_custom_output => $self->can('custom_traffic_output'), closure_custom_perfdata => $self->can('custom_traffic_perfdata'), closure_custom_threshold_check => $self->can('custom_traffic_threshold') } }, { label => 'int-cmap-drop', set => { key_values => [ { name => 'drop_usage', per_second => 1 }, { name => 'display' } ], output_change_bytes => 2, output_template => 'Drop : %s %s/s', perfdatas => [ { label => 'icmap_drop', template => '%d', unit => 'b/s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } } ]; $self->{maps_counters}->{classmap} = [ { label => 'cmap-traffic', set => { key_values => [ { name => 'traffic_usage', per_second => 1 }, { name => 'display' } ], output_change_bytes => 2, output_template => 'Traffic : %s %s/s', perfdatas => [ { label => 'cmap_traffic', template => '%d', unit => 'b/s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'cmap-drop', set => { key_values => [ { name => 'drop_usage', per_second => 1 }, { name => 'display' } ], output_change_bytes => 2, output_template => 'Drop : %s %s/s', perfdatas => [ { label => 'cmap_drop', template => '%d', unit => 'b/s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } } ]; $self->{maps_counters}->{total} = [ { label => 'total-traffic', set => { key_values => [ { name => 'traffic_usage', per_second => 1 } ], output_change_bytes => 2, output_template => 'Total Traffic : %s %s/s', perfdatas => [ { label => 'total_traffic', template => '%d', unit => 'b/s', min => 0 } ] } }, { label => 'total-drop', set => { key_values => [ { name => 'drop_usage', per_second => 1 } ], output_change_bytes => 2, output_template => 'Total Drop : %s %s/s', perfdatas => [ { label => 'total_drop', template => '%d', unit => 'b/s', min => 0 } ] } } ]; } sub custom_traffic_perfdata { my ($self, %options) = @_; my ($warning, $critical); if ($self->{instance_mode}->{option_results}->{units_traffic} eq '%' && (defined($self->{result_values}->{total}) && $self->{result_values}->{total} =~ /[0-9]/)) { $warning = $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1); $critical = $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1); } elsif ($self->{instance_mode}->{option_results}->{units_traffic} eq 'b/s') { $warning = $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}); $critical = $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}); } $self->{output}->perfdata_add( label => 'icmap_traffic', unit => 'b/s', instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, value => sprintf("%.2f", $self->{result_values}->{traffic_per_seconds}), warning => $warning, critical => $critical, min => 0, max => ($self->{result_values}->{total} =~ /[0-9]/ ? $self->{result_values}->{total} : undef) ); } sub custom_traffic_threshold { my ($self, %options) = @_; my $exit = 'ok'; if ($self->{instance_mode}->{option_results}->{units_traffic} eq '%' && (defined($self->{result_values}->{total}) && $self->{result_values}->{total} =~ /[0-9]/)) { $exit = $self->{perfdata}->threshold_check(value => $self->{result_values}->{traffic_prct}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ]); } elsif ($self->{instance_mode}->{option_results}->{units_traffic} eq 'b/s') { $exit = $self->{perfdata}->threshold_check(value => $self->{result_values}->{traffic_per_seconds}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ]); } return $exit; } sub custom_traffic_output { my ($self, %options) = @_; my ($traffic_value, $traffic_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{traffic_per_seconds}, network => 1); return sprintf( 'Traffic : %s/s (%s)', $traffic_value . $traffic_unit, defined($self->{result_values}->{traffic_prct}) ? sprintf("%.2f%%", $self->{result_values}->{traffic_prct}) : '-' ); } sub custom_traffic_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_total'}; $self->{result_values}->{traffic_usage} = $options{new_datas}->{$self->{instance} . '_traffic_usage'}; my $diff_traffic = ($options{new_datas}->{$self->{instance} . '_traffic_usage'} - $options{old_datas}->{$self->{instance} . '_traffic_usage'}); $self->{result_values}->{traffic_per_seconds} = $diff_traffic / $options{delta_time}; if ($options{new_datas}->{$self->{instance} . '_total'} =~ /[1-9]/) { $self->{result_values}->{traffic_prct} = $self->{result_values}->{traffic_per_seconds} * 100 / $options{new_datas}->{$self->{instance} . '_total'}; } return 0; } sub prefix_intcmap_output { my ($self, %options) = @_; return "Interface classmap '" . $options{instance_value}->{display} . "' "; } sub prefix_cmap_output { my ($self, %options) = @_; return "Classmap '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-source:s' => { name => 'filter_source' }, 'oid-filter:s' => { name => 'oid_filter', default => 'ifname' }, 'oid-display:s' => { name => 'oid_display', default => 'ifname' }, 'units-traffic:s' => { name => 'units_traffic', default => '%' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{oids_label} = { 'ifdesc' => '.1.3.6.1.2.1.2.2.1.2', 'ifalias' => '.1.3.6.1.2.1.31.1.1.1.18', 'ifname' => '.1.3.6.1.2.1.31.1.1.1.1', }; $self->check_oids_label(); } sub check_oids_label { my ($self, %options) = @_; foreach (('oid_filter', 'oid_display')) { $self->{option_results}->{$_} = lc($self->{option_results}->{$_}) if (defined($self->{option_results}->{$_})); if (!defined($self->{oids_label}->{$self->{option_results}->{$_}})) { my $label = $_; $label =~ s/_/-/g; $self->{output}->add_option_msg(short_msg => "Unsupported oid in --" . $label . " option."); $self->{output}->option_exit(); } } } my $mapping = { cbQosCMPostPolicyByteOverflow => { oid => '.1.3.6.1.4.1.9.9.166.1.15.1.1.8' }, cbQosCMPostPolicyByte => { oid => '.1.3.6.1.4.1.9.9.166.1.15.1.1.9' }, cbQosCMPostPolicyByte64 => { oid => '.1.3.6.1.4.1.9.9.166.1.15.1.1.10' }, cbQosCMDropByteOverflow => { oid => '.1.3.6.1.4.1.9.9.166.1.15.1.1.15' }, cbQosCMDropByte => { oid => '.1.3.6.1.4.1.9.9.166.1.15.1.1.16' }, cbQosCMDropByte64 => { oid => '.1.3.6.1.4.1.9.9.166.1.15.1.1.17' } }; my $mapping2 = { cbQosTSCfgRate => { oid => '.1.3.6.1.4.1.9.9.166.1.13.1.1.1' }, # bps cbQosTSCfgRate64 => { oid => '.1.3.6.1.4.1.9.9.166.1.13.1.1.11' } # bps }; my $mapping3 = { cbQosQueueingCfgBandwidth => { oid => '.1.3.6.1.4.1.9.9.166.1.9.1.1.1' }, cbQosQueueingCfgBandwidthUnits => { oid => '.1.3.6.1.4.1.9.9.166.1.9.1.1.2' } }; my $oid_cbQosIfIndex = '.1.3.6.1.4.1.9.9.166.1.1.1.1.4'; my $oid_cbQosConfigIndex = '.1.3.6.1.4.1.9.9.166.1.5.1.1.2'; my $oid_cbQosParentObjectsIndex = '.1.3.6.1.4.1.9.9.166.1.5.1.1.4'; # Classmap information my $oid_cbQosCMName = '.1.3.6.1.4.1.9.9.166.1.7.1.1.1'; my $oid_cbQosCMStatsEntry = '.1.3.6.1.4.1.9.9.166.1.15.1.1'; # Can be linked to a classmap also my $oid_cbQosPolicyMapName = '.1.3.6.1.4.1.9.9.166.1.6.1.1.1'; # Shaping : Linked to a classmap my $oid_cbQosTSCfgEntry = '.1.3.6.1.4.1.9.9.166.1.13.1.1'; # Linked to a classmap my $oid_cbQosQueueingCfgEntry = '.1.3.6.1.4.1.9.9.166.1.9.1.1'; sub build_qos_information { my ($self, %options) = @_; my $qos_data = { complete_name => $options{class_name} }; # Need to try and find the queueing (it's a child) $qos_data->{queueing} = $options{link_queueing}->{$options{policy_index} . '.' . $options{object_index}} if (defined($options{link_queueing}->{$options{policy_index} . '.' . $options{object_index}})); $qos_data->{shaping} = $options{link_shaping}->{$options{policy_index} . '.' . $options{object_index}} if (!defined($qos_data->{shaping}) && defined($options{link_shaping}->{$options{policy_index} . '.' . $options{object_index}})); while (($options{object_index} = $self->{results}->{$oid_cbQosParentObjectsIndex}->{$oid_cbQosParentObjectsIndex . '.' . $options{policy_index} . '.' . $options{object_index}}) != 0) { my $config_index = $self->{results}->{$oid_cbQosConfigIndex}->{$oid_cbQosConfigIndex . '.' . $options{policy_index} . '.' . $options{object_index}}; my $tmp_name = ''; # try to find policy_map or class_map if (defined($self->{results}->{$oid_cbQosCMName}->{$oid_cbQosCMName . '.' . $config_index})) { $tmp_name = $self->{results}->{$oid_cbQosCMName}->{$oid_cbQosCMName . '.' . $config_index}; } elsif (defined($self->{results}->{$oid_cbQosPolicyMapName}->{$oid_cbQosPolicyMapName . '.' . $config_index})) { $tmp_name = $self->{results}->{$oid_cbQosPolicyMapName}->{$oid_cbQosPolicyMapName . '.' . $config_index}; } $qos_data->{shaping} = $options{link_shaping}->{$options{policy_index} . '.' . $options{object_index}} if (!defined($qos_data->{shaping}) && defined($options{link_shaping}->{$options{policy_index} . '.' . $options{object_index}})); $qos_data->{complete_name} = $tmp_name . ':' . $qos_data->{complete_name}; } return $qos_data; } sub manage_selection { my ($self, %options) = @_; $self->{interface_classmap} = {}; $self->{classmap} = {}; $self->{total} = { drop_usage => 0, total_usage => 0 }; my $request_oids = [ { oid => $self->{oids_label}->{$self->{option_results}->{oid_filter}} }, { oid => $oid_cbQosPolicyMapName }, { oid => $oid_cbQosIfIndex }, { oid => $oid_cbQosConfigIndex }, { oid => $oid_cbQosCMName }, { oid => $oid_cbQosQueueingCfgEntry, end => $mapping3->{cbQosQueueingCfgBandwidthUnits}->{oid} }, { oid => $oid_cbQosCMStatsEntry, start => $mapping->{cbQosCMPostPolicyByteOverflow}->{oid}, end => $mapping->{cbQosCMDropByte64}->{oid} }, { oid => $oid_cbQosParentObjectsIndex }, { oid => $oid_cbQosTSCfgEntry, end => $mapping2->{cbQosTSCfgRate64}->{oid} } ]; push @$request_oids, { oid => $self->{oids_label}->{$self->{option_results}->{oid_display}} } if ($self->{option_results}->{oid_filter} ne $self->{option_results}->{oid_display}); $self->{results} = $options{snmp}->get_multiple_table(oids => $request_oids); my %classmap_name = (); foreach (keys %{$self->{results}->{$oid_cbQosConfigIndex}}) { if (defined($self->{results}->{$oid_cbQosCMName}->{$oid_cbQosCMName . '.' . $self->{results}->{$oid_cbQosConfigIndex}->{$_}})) { /(\d+\.\d+)$/; $classmap_name{$1} = $self->{results}->{$oid_cbQosCMName}->{$oid_cbQosCMName . '.' . $self->{results}->{$oid_cbQosConfigIndex}->{$_}}; } } my ($link_queueing, $link_shaping) = ({}, {}); foreach (keys %{$self->{results}->{$oid_cbQosParentObjectsIndex}}) { /(\d+)\.(\d+)$/; my $config_index = $self->{results}->{$oid_cbQosConfigIndex}->{$oid_cbQosConfigIndex . '.' . $1 . '.' . $2}; if (defined($self->{results}->{$oid_cbQosQueueingCfgEntry}->{$mapping3->{cbQosQueueingCfgBandwidth}->{oid} . '.' . $config_index})) { $link_queueing->{$1 . '.' . $self->{results}->{$oid_cbQosParentObjectsIndex}->{$_}} = $config_index; } elsif (defined($self->{results}->{$oid_cbQosTSCfgEntry}->{$mapping2->{cbQosTSCfgRate}->{oid} . '.' . $config_index})) { $link_shaping->{$1 . '.' . $self->{results}->{$oid_cbQosParentObjectsIndex}->{$_}} = $config_index; } } foreach (keys %{$self->{results}->{$oid_cbQosCMStatsEntry}}) { next if (!/$mapping->{cbQosCMPostPolicyByteOverflow}->{oid}\.(\d+)\.(\d+)/); my ($policy_index, $qos_object_index) = ($1, $2); my $class_name = $classmap_name{$policy_index . '.' . $qos_object_index}; my $if_index = $self->{results}->{$oid_cbQosIfIndex}->{$oid_cbQosIfIndex . '.' . $policy_index}; if (!defined($self->{results}->{$self->{oids_label}->{$self->{option_results}->{oid_display}}}->{$self->{oids_label}->{$self->{option_results}->{oid_display}} . '.' . $if_index})) { $self->{output}->output_add(long_msg => "skipping interface index '" . $if_index . "': no display name.", debug => 1); next; } my $interface_display = $self->{results}->{$self->{oids_label}->{$self->{option_results}->{oid_display}}}->{$self->{oids_label}->{$self->{option_results}->{oid_display}} . '.' . $if_index}; if (!defined($self->{results}->{$self->{oids_label}->{$self->{option_results}->{oid_filter}}}->{$self->{oids_label}->{$self->{option_results}->{oid_filter}} . '.' . $if_index})) { $self->{output}->output_add(long_msg => "skipping interface index '" . $if_index . "': no filter name.", debug => 1); next; } my $qos_data = $self->build_qos_information( class_name => $class_name, policy_index => $policy_index, object_index => $qos_object_index, link_queueing => $link_queueing, link_shaping => $link_shaping ); my $interface_filter = $self->{results}->{$self->{oids_label}->{$self->{option_results}->{oid_filter}}}->{$self->{oids_label}->{$self->{option_results}->{oid_filter}} . '.' . $if_index}; my $name = $interface_filter . ':' . $qos_data->{complete_name}; if (defined($self->{option_results}->{filter_source}) && $self->{option_results}->{filter_source} ne '' && $name !~ /$self->{option_results}->{filter_source}/) { $self->{output}->output_add(long_msg => "skipping '" . $name . "': no matching filter source.", debug => 1); next; } # Same hash key but only for disco context if (defined($options{disco})) { $self->{interface_classmap}->{$policy_index . '.' . $qos_object_index} = $name; next; } my $result = $options{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_cbQosCMStatsEntry}, instance => $policy_index . '.' . $qos_object_index); my $traffic_usage = (defined($result->{cbQosCMPostPolicyByte64}) && $result->{cbQosCMPostPolicyByte64} =~ /[1-9]/) ? $result->{cbQosCMPostPolicyByte64} : ( ($result->{cbQosCMPostPolicyByteOverflow} == 4294967295) ? undef : ($result->{cbQosCMPostPolicyByteOverflow} * 4294967295 + $result->{cbQosCMPostPolicyByte}) ); my $drop_usage = (defined($result->{cbQosCMDropByte64}) && $result->{cbQosCMDropByte64} =~ /[1-9]/) ? $result->{cbQosCMDropByte64} : ( ($result->{cbQosCMDropByteOverflow} == 4294967295) ? undef : ($result->{cbQosCMDropByteOverflow} * 4294967295 + $result->{cbQosCMDropByte}) ); my $total = 'unknown'; if (defined($qos_data->{shaping})) { my $result_shaping = $options{snmp}->map_instance(mapping => $mapping2, results => $self->{results}->{$oid_cbQosTSCfgEntry}, instance => $qos_data->{shaping}); $total = defined($result_shaping->{cbQosTSCfgRate64}) ? $result_shaping->{cbQosTSCfgRate64} : $result_shaping->{cbQosTSCfgRate}; } $self->{interface_classmap}->{$policy_index . '.' . $qos_object_index} = { display => $name, traffic_usage => defined($traffic_usage) ? $traffic_usage * 8 : undef, drop_usage => defined($drop_usage) ? $drop_usage * 8 : undef, total => $total }; my @tabname = split /:/, $name; if (defined($tabname[3])){ $class_name = $tabname[3] . '-' . $class_name; } $self->{classmap}->{$name} = { display => $class_name, drop_usage => 0, traffic_usage => 0} if (!defined($self->{classmap}->{$name})); $self->{classmap}->{$name}->{traffic_usage} += defined($traffic_usage) ? $traffic_usage * 8 : 0; $self->{classmap}->{$name}->{drop_usage} += defined($drop_usage) ? $drop_usage * 8 : 0; if (!defined($tabname[3])){ $self->{total}->{traffic_usage} += defined($traffic_usage) ? $traffic_usage * 8 : 0; $self->{total}->{drop_usage} += defined($drop_usage) ? $drop_usage * 8 : 0; } } $self->{cache_name} = 'cisco_qos_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_source}) ? md5_hex($self->{option_results}->{filter_source}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); if (scalar(keys %{$self->{interface_classmap}}) <= 0 && !defined($options{disco})) { $self->{output}->add_option_msg(short_msg => 'Cannot found classmap.'); $self->{output}->option_exit(); } } sub disco_format { my ($self, %options) = @_; $self->{output}->add_disco_format(elements => ['name']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(disco => 1, %options); foreach (keys %{$self->{interface_classmap}}) { $self->{output}->add_disco_entry(name => $self->{interface_classmap}->{$_}); } } 1; __END__ =head1 MODE Check QoS. =over 8 =item B<--filter-source> Filter interface name and class-map (can be a regexp). Example of a source (interfacename:servicepolicy:classmap:...): FastEthernet1:Visioconference =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^(total-traffic)$' =item B<--warning-*> Threshold warning. Can be: 'int-cmap-traffic', 'int-cmap-drop', 'cmap-traffic', 'cmap-drop', 'total-traffic', 'total-drop'. =item B<--critical-*> Threshold critical. Can be: 'int-cmap-traffic', 'int-cmap-drop', 'cmap-traffic', 'cmap-drop', 'total-traffic', 'total-drop'. =item B<--units-traffic> Units of thresholds for the traffic (Default: '%') ('%', 'b/s'). Only for --warning-int-traffic and --critical-int-traffic options. =item B<--oid-filter> Choose OID used to filter interface (default: ifName) (values: ifDesc, ifAlias, ifName). =item B<--oid-display> Choose OID used to display interface (default: ifName) (values: ifDesc, ifAlias, ifName). =back =cut centreon-plugins-20220113/centreon/common/cisco/standard/snmp/mode/sessions.pm000066400000000000000000000257561417000230700273650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::standard::snmp::mode::sessions; 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 => 'connections', type => 0, cb_prefix_output => 'prefix_connections_output', skipped_code => { -10 => 1 } }, { name => 'sessions', type => 0, cb_prefix_output => 'prefix_sessions_output', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{connections} = [ { label => 'connections-current', set => { key_values => [ { name => 'cufwConnGlobalNumActive' } ], output_template => 'current : %s', output_error_template => "current : %s", perfdatas => [ { label => 'connections_current', template => '%d', min => 0 }, ], } }, { label => 'connections-1m', set => { key_values => [ { name => 'cufwConnGlobalConnSetupRate1' } ], output_template => 'average last 1min : %s', output_error_template => "average last 1min : %s", perfdatas => [ { label => 'connections_1m', template => '%d', min => 0 }, ], } }, { label => 'connections-5m', set => { key_values => [ { name => 'cufwConnGlobalConnSetupRate5' } ], output_template => 'average last 5min : %s', output_error_template => "average last 5min : %s", perfdatas => [ { label => 'connections_5m', template => '%d', min => 0 }, ], } }, ]; $self->{maps_counters}->{sessions} = [ { label => 'sessions-total', set => { key_values => [ { name => 'crasNumSessions' } ], output_template => 'total : %s', output_error_template => "total : %s", perfdatas => [ { label => 'sessions_total', template => '%d', min => 0 }, ], } }, { label => 'sessions-email-current', set => { key_values => [ { name => 'crasEmailNumSessions' } ], output_template => 'current email proxy : %s', output_error_template => "current email proxy : %s", perfdatas => [ { label => 'sessions_email_current', template => '%d', min => 0 }, ], } }, { label => 'sessions-email-psec', set => { key_values => [ { name => 'crasEmailCumulateSessions', per_second => 1 } ], output_template => 'email proxy : %.2f/s', output_error_template => "email proxy : %s", perfdatas => [ { label => 'sessions_email_psec', template => '%.2f', min => 0 }, ], } }, { label => 'sessions-ipsec-current', set => { key_values => [ { name => 'crasIPSecNumSessions' } ], output_template => 'current ipsec : %s', output_error_template => "current ipsec : %s", perfdatas => [ { label => 'sessions_ipsec_current', template => '%d', min => 0 }, ], } }, { label => 'sessions-ipsec-psec', set => { key_values => [ { name => 'crasIPSecCumulateSessions', per_second => 1 } ], output_template => 'ipsec : %.2f/s', output_error_template => "ipsec : %s", perfdatas => [ { label => 'sessions_ipsec_psec', template => '%.2f', min => 0 }, ], } }, { label => 'sessions-l2l-current', set => { key_values => [ { name => 'crasL2LNumSessions' } ], output_template => 'current LAN to LAN : %s', output_error_template => "current LAN to LAN : %s", perfdatas => [ { label => 'sessions_l2l_current', template => '%d', min => 0 }, ], } }, { label => 'sessions-l2l-psec', set => { key_values => [ { name => 'crasL2LCumulateSessions', per_second => 1 } ], output_template => 'LAN to LAN : %.2f/s', output_error_template => "LAN to LAN : %s", perfdatas => [ { label => 'sessions_l2l_psec', template => '%.2f', min => 0 }, ], } }, { label => 'sessions-lb-current', set => { key_values => [ { name => 'crasLBNumSessions' } ], output_template => 'current load balancing : %s', output_error_template => "current load balancing : %s", perfdatas => [ { label => 'sessions_lb_current', template => '%d', min => 0 }, ], } }, { label => 'sessions-lb-psec', set => { key_values => [ { name => 'crasLBCumulateSessions', per_second => 1 } ], output_template => 'load balancing : %.2f/s', output_error_template => "load balancing : %s", perfdatas => [ { label => 'sessions_lb_psec', template => '%.2f', min => 0 }, ], } }, { label => 'sessions-svc-current', set => { key_values => [ { name => 'crasSVCNumSessions' } ], output_template => 'current SVC : %s', output_error_template => "current SVC : %s", perfdatas => [ { label => 'sessions_svc_current', template => '%d', min => 0 }, ], } }, { label => 'sessions-svc-psec', set => { key_values => [ { name => 'crasSVCCumulateSessions', per_second => 1 } ], output_template => 'SVC : %.2f/s', output_error_template => "SVC : %s", perfdatas => [ { label => 'sessions_svc_psec', template => '%.2f', min => 0 }, ], } }, { label => 'sessions-webvpn-current', set => { key_values => [ { name => 'crasWebvpnNumSessions' } ], output_template => 'current webvpn : %s', output_error_template => "current webvpn : %s", perfdatas => [ { label => 'sessions_webvpn_current', template => '%d', min => 0 }, ], } }, { label => 'sessions-webvpn-psec', set => { key_values => [ { name => 'crasWebvpnCumulateSessions', per_second => 1 } ], output_template => 'webvpn : %.2f/s', output_error_template => "webvpn : %s", perfdatas => [ { label => 'sessions_webvpn_psec',template => '%.2f', min => 0 }, ], } }, ]; } sub prefix_connections_output { my ($self, %options) = @_; return "Connections "; } sub prefix_sessions_output { my ($self, %options) = @_; return "Sessions "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my %oids_connections = ( cufwConnGlobalNumActive => '.1.3.6.1.4.1.9.9.491.1.1.1.6.0', cufwConnGlobalConnSetupRate1 => '.1.3.6.1.4.1.9.9.491.1.1.1.10.0', cufwConnGlobalConnSetupRate5 => '.1.3.6.1.4.1.9.9.491.1.1.1.11.0', ); my %oids_sessions = ( crasNumSessions => '.1.3.6.1.4.1.9.9.392.1.3.1.0', crasEmailNumSessions => '.1.3.6.1.4.1.9.9.392.1.3.23.0', crasEmailCumulateSessions => '.1.3.6.1.4.1.9.9.392.1.3.24.0', crasIPSecNumSessions => '.1.3.6.1.4.1.9.9.392.1.3.26.0', crasIPSecCumulateSessions => '.1.3.6.1.4.1.9.9.392.1.3.27.0', crasL2LNumSessions => '.1.3.6.1.4.1.9.9.392.1.3.29.0', crasL2LCumulateSessions => '.1.3.6.1.4.1.9.9.392.1.3.30.0', crasLBNumSessions => '.1.3.6.1.4.1.9.9.392.1.3.32.0', crasLBCumulateSessions => '.1.3.6.1.4.1.9.9.392.1.3.33.0', crasSVCNumSessions => '.1.3.6.1.4.1.9.9.392.1.3.35.0', crasSVCCumulateSessions => '.1.3.6.1.4.1.9.9.392.1.3.36.0', crasWebvpnNumSessions => '.1.3.6.1.4.1.9.9.392.1.3.38.0', crasWebvpnCumulateSessions => '.1.3.6.1.4.1.9.9.392.1.3.39.0', ); sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = "cisco_standard_" . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); $self->{connections} = {}; $self->{sessions} = {}; $self->{results} = $options{snmp}->get_leef(oids => [values %oids_connections, values %oids_sessions], nothing_quit => 1); foreach my $name (keys %oids_connections) { next if (!defined($self->{results}->{$oids_connections{$name}}) || $self->{results}->{$oids_connections{$name}} == 0); $self->{connections}->{$name} = $self->{results}->{$oids_connections{$name}}; } foreach my $name (keys %oids_sessions) { next if (!defined($self->{results}->{$oids_sessions{$name}}) || $self->{results}->{$oids_sessions{$name}} == 0); $self->{sessions}->{$name} = $self->{results}->{$oids_sessions{$name}}; } } 1; __END__ =head1 MODE Check sessions. =over 8 =item B<--warning-*> Threshold warning. Can be: 'connections-current', 'connections-1m', 'connections-5m', 'sessions-total', 'sessions-email-current', 'sessions-email-psec', 'sessions-ipsec-current', 'sessions-ipsec-psec', 'sessions-l2l-current', 'sessions-lb-psec' 'sessions-lb-current', 'sessions-lb-psec', 'sessions-svc-current', 'sessions-svc-psec', 'sessions-webvpn-current', 'sessions-webvpn-psec'. =item B<--critical-*> Threshold critical. Can be: 'connections-current', 'connections-1m', 'connections-5m', 'sessions-total', 'sessions-email-current', 'sessions-email-psec', 'sessions-ipsec-current', 'sessions-ipsec-psec', 'sessions-l2l-current', 'sessions-lb-psec' 'sessions-lb-current', 'sessions-lb-psec', 'sessions-svc-current', 'sessions-svc-psec', 'sessions-webvpn-current', 'sessions-webvpn-psec'. =back =cut centreon-plugins-20220113/centreon/common/cisco/standard/snmp/mode/stack.pm000066400000000000000000000240231417000230700266060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::standard::snmp::mode::stack; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_stack_status_output { my ($self, %options) = @_; return sprintf("Stack status is '%s'", $self->{result_values}->{stack_status}); } sub custom_status_output { my ($self, %options) = @_; return sprintf("state is '%s', role is '%s'", $self->{result_values}->{state}, $self->{result_values}->{role}); } sub prefix_global_output { my ($self, %options) = @_; return "Number of members "; } sub prefix_status_output { my ($self, %options) = @_; return "Member '" . $options{instance_value}->{name} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'stack', type => 0 }, { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }, { name => 'members', type => 1, cb_prefix_output => 'prefix_status_output', message_multiple => 'All stack members status are ok' } ]; $self->{maps_counters}->{stack} = [ { label => 'stack-status', type => 2, critical_default => '%{stack_status} =~ /notredundant/', set => { key_values => [ { name => 'stack_status' } ], closure_custom_output => $self->can('custom_stack_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{global} = [ { label => 'waiting', set => { key_values => [ { name => 'waiting' } ], output_template => 'waiting: %d', perfdatas => [ { label => 'waiting', template => '%d', min => 0 } ] } }, { label => 'progressing', set => { key_values => [ { name => 'progressing' } ], output_template => 'progressing: %d', perfdatas => [ { label => 'progressing', template => '%d', min => 0 } ] } }, { label => 'added', set => { key_values => [ { name => 'added' } ], output_template => 'added: %d', perfdatas => [ { label => 'added', template => '%d', min => 0 } ] } }, { label => 'ready', set => { key_values => [ { name => 'ready' } ], output_template => 'ready: %d', perfdatas => [ { label => 'ready', template => '%d', min => 0 } ] } }, { label => 'sdm-mismatch', set => { key_values => [ { name => 'sdmMismatch' } ], output_template => 'SDM mismatch: %d', perfdatas => [ { label => 'sdm_mismatch', template => '%d', min => 0 } ] } }, { label => 'version-mismatch', set => { key_values => [ { name => 'verMismatch' } ], output_template => 'version mismatch: %d', perfdatas => [ { label => 'version_mismatch', template => '%d', min => 0 } ] } }, { label => 'feature-mismatch', set => { key_values => [ { name => 'featureMismatch' } ], output_template => 'feature mismatch: %d', perfdatas => [ { label => 'feature_mismatch', template => '%d', min => 0 } ] } }, { label => 'new-master-init', set => { key_values => [ { name => 'newMasterInit' } ], output_template => 'new master init: %d', perfdatas => [ { label => 'new_master_init', template => '%d', min => 0 } ] } }, { label => 'provisioned', set => { key_values => [ { name => 'provisioned' } ], output_template => 'provisioned: %d', perfdatas => [ { label => 'provisioned', template => '%d', min => 0 } ] } }, { label => 'invalid', set => { key_values => [ { name => 'invalid' } ], output_template => 'invalid: %d', perfdatas => [ { label => 'invalid', template => '%d', min => 0 } ] } }, { label => 'removed', set => { key_values => [ { name => 'removed' } ], output_template => 'removed: %d', perfdatas => [ { label => 'removed', template => '%d', min => 0 } ] } } ]; $self->{maps_counters}->{members} = [ { label => 'status', type => 2, critical_default => '%{state} !~ /ready/ && %{state} !~ /provisioned/', set => { key_values => [ { name => 'name' }, { name => 'role' }, { name => 'state' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } my %map_role = ( 1 => 'master', 2 => 'member', 3 => 'notMember', 4 => 'standby' ); my %map_state = ( 1 => 'waiting', 2 => 'progressing', 3 => 'added', 4 => 'ready', 5 => 'sdmMismatch', 6 => 'verMismatch', 7 => 'featureMismatch', 8 => 'newMasterInit', 9 => 'provisioned', 10 => 'invalid', 11 => 'removed', ); my $mapping = { cswSwitchRole => { oid => '.1.3.6.1.4.1.9.9.500.1.2.1.1.3', map => \%map_role }, cswSwitchState => { oid => '.1.3.6.1.4.1.9.9.500.1.2.1.1.6', map => \%map_state }, }; my $oid_cswSwitchInfoEntry = '.1.3.6.1.4.1.9.9.500.1.2.1.1'; my $oid_cswRingRedundant = '.1.3.6.1.4.1.9.9.500.1.1.3.0'; my $oid_entPhysicalName = '.1.3.6.1.2.1.47.1.1.1.1.7'; sub manage_selection { my ($self, %options) = @_; $self->{global} = { waiting => 0, progressing => 0, added => 0, ready => 0, sdmMismatch => 0, verMismatch => 0, featureMismatch => 0, newMasterInit => 0, provisioned => 0, invalid => 0, removed => 0 }; $self->{members} = {}; my $snmp_result = $options{snmp}->get_leef(oids => [ $oid_cswRingRedundant ], nothing_quit => 1); $self->{stack} = { stack_status => ($snmp_result->{$oid_cswRingRedundant} != 1) ? 'notredundant' : 'redundant', }; $snmp_result = $options{snmp}->get_table( oid => $oid_cswSwitchInfoEntry, start => $mapping->{cswSwitchRole}->{oid}, end => $mapping->{cswSwitchState}->{oid}, nothing_quit => 1 ); foreach my $oid (keys %$snmp_result) { next if($oid !~ /^$mapping->{cswSwitchRole}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); $self->{members}->{$instance} = { name => $instance, role => $result->{cswSwitchRole}, state => $result->{cswSwitchState}, }; $self->{global}->{ $result->{cswSwitchState} }++; } return if (scalar(keys %{$self->{members}}) <= 0); $options{snmp}->load( oids => [ $oid_entPhysicalName ], instances => [ keys %{$self->{members}} ], instance_regexp => '^(.*)$' ); $snmp_result = $options{snmp}->get_leef(); foreach (keys %{$self->{members}}) { if (defined($snmp_result->{ $oid_entPhysicalName . '.' . $_ }) && $snmp_result->{ $oid_entPhysicalName . '.' . $_ } ne '') { $self->{members}->{$_}->{name} = $snmp_result->{ $oid_entPhysicalName . '.' . $_ }; } } } 1; __END__ =head1 MODE Check Cisco Stack (CISCO-STACKWISE-MIB). =over 8 =item B<--warning-*> B<--critical-*> Set thresholds on members count for each states. (Can be: 'waiting', 'progressing', 'added', 'ready', 'sdm-mismatch', 'version-mismatch', 'feature-mismatch', 'new-master-init', 'provisioned', 'invalid', 'removed') =item B<--warning-stack-status> Set warning threshold for stack status (Default: ''). Can used special variables like: %{stack_status} =item B<--critical-stack-status> Set critical threshold for stack status (Default: '%{stack_status} =~ /notredundant/'). Can used special variables like: %{stack_status} =item B<--warning-status> Set warning threshold for members status (Default: ''). Can used special variables like: %{name}, %{role}, %{state} =item B<--critical-status> Set critical threshold for member status (Default: '%{state} !~ /ready/ && %{state} !~ /provisioned/'). Can used special variables like: %{name}, %{role}, %{state} Role can be: 'master', 'member', 'notMember', 'standby'. State can be: 'waiting', 'progressing', 'added', 'ready', 'sdmMismatch', 'verMismatch', 'featureMismatch', 'newMasterInit', 'provisioned', 'invalid', 'removed'. =back =cut centreon-plugins-20220113/centreon/common/cisco/standard/snmp/mode/voicecall.pm000066400000000000000000000124521417000230700274450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::standard::snmp::mode::voicecall; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'gavg', type => 0, cb_prefix_output => 'prefix_gavg_output', message_separator => ' ', skipped_code => { -10 => 1 } }, { name => 'ctype', type => 1, cb_prefix_output => 'prefix_ctype_output', message_multiple => 'All connection types are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{gavg} = [ { label => 'active-1m-average', nlabel => 'calls.active.1m.average.count', set => { key_values => [ { name => 'active_1m_average' } ], output_template => '%.2f (1m)', perfdatas => [ { value => 'active_1m_average', template => '%.2f', min => 0 }, ], } }, { label => 'active-5m-average', nlabel => 'calls.active.5m.average.count', set => { key_values => [ { name => 'active_5m_average' } ], output_template => '%.2f (5m)', perfdatas => [ { value => 'active_5m_average', template => '%.2f', min => 0 }, ], } }, { label => 'active-15m-average', nlabel => 'calls.active.15m.average.count', set => { key_values => [ { name => 'active_15m_average' } ], output_template => '%.2f (15m)', perfdatas => [ { value => 'active_15m_average', template => '%.2f', min => 0 }, ], } }, ]; $self->{maps_counters}->{ctype} = [ { label => 'connection-calls-active', nlabel => 'connection.calls.active.count', set => { key_values => [ { name => 'active_calls' }, { name => 'display' } ], output_template => 'active calls %s', perfdatas => [ { value => 'active_calls', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, ]; } sub prefix_gavg_output { my ($self, %options) = @_; return 'Calls active '; } sub prefix_ctype_output { my ($self, %options) = @_; return "Connection type '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my %map_con_type = ( 1 => 'h323', 2 => 'sip', 3 => 'mgcp', 4 => 'sccp', 5 => 'multicast', 6 => 'cacontrol', 7 => 'telephony', ); my $oid_cvCallVolConnActiveConnection = '.1.3.6.1.4.1.9.9.63.1.3.8.1.1.2'; my $oid_cvActiveCallStatsAvgVal_min = '.1.3.6.1.4.1.9.9.63.1.4.3.3.1.4.2'; my $snmp_result = $options{snmp}->get_multiple_table( oids => [ { oid => $oid_cvCallVolConnActiveConnection }, { oid => $oid_cvActiveCallStatsAvgVal_min } ], nothing_quit => 1 ); $self->{ctype} = {}; foreach (keys %{$snmp_result->{ $oid_cvCallVolConnActiveConnection }}) { /\.(\d+)$/; $self->{ctype}->{$map_con_type{$1}} = { display => $map_con_type{$1}, active_calls => $snmp_result->{ $oid_cvCallVolConnActiveConnection }->{$_}, }; } my %definitions_avg = ( 'active_1m_average' => [1, 1, 1, 0, 0], 'active_5m_average' => [1, 5, 5, 0, 0], 'active_15m_average' => [1, 15, 15, 0, 0], ); foreach my $oid (keys %{$snmp_result->{ $oid_cvActiveCallStatsAvgVal_min }}) { $oid =~ /\.(\d+)$/; my $interval = $1; foreach (values %definitions_avg) { if ($interval >= $_->[0] && $interval <= $_->[1]) { $_->[3]++; $_->[4] += $snmp_result->{ $oid_cvActiveCallStatsAvgVal_min }->{$oid}; } } } $self->{gavg} = {}; foreach (keys %definitions_avg) { next if ($definitions_avg{$_}->[2] != $definitions_avg{$_}->[3]); $self->{gavg}->{$_} = $definitions_avg{$_}->[4] / $definitions_avg{$_}->[2]; } } 1; __END__ =head1 MODE Check call traffic statistics (CISCO-VOICE-DIAL-CONTROL-MIB) =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'active-1m-average', 'active-5m-average', 'active-15m-average', 'connection-calls-active'. =back =cut centreon-plugins-20220113/centreon/common/cisco/standard/snmp/mode/vpc.pm000066400000000000000000000341511417000230700262740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::standard::snmp::mode::vpc; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_keepalive_status_output { my ($self, %options) = @_; return sprintf( 'status: %s', $self->{result_values}->{keepalive_status} ); } sub custom_peer_status_output { my ($self, %options) = @_; return sprintf( 'role: %s', $self->{result_values}->{role} ); } sub custom_peer_status_calc { my ($self, %options) = @_; $self->{result_values}->{role_last} = $options{old_datas}->{$self->{instance} . '_role'}; $self->{result_values}->{role} = $options{new_datas}->{$self->{instance} . '_role'}; if (!defined($options{old_datas}->{$self->{instance} . '_role'})) { $self->{error_msg} = "buffer creation"; return -2; } return 0; } sub custom_link_status_output { my ($self, %options) = @_; return sprintf( 'operational status: %s', $self->{result_values}->{link_status} ); } sub domain_long_output { my ($self, %options) = @_; return "checking vPC domain '" . $options{instance_value}->{domain_id} . "'"; } sub prefix_domain_output { my ($self, %options) = @_; return "vPC domain '" . $options{instance_value}->{domain_id} . "' "; } sub prefix_host_output { my ($self, %options) = @_; return "host link '" . $options{instance_value}->{display} . "' "; } sub prefix_peer_output { my ($self, %options) = @_; return "peer '" . $options{instance_value}->{macaddress} . "' "; } sub prefix_keepalive_output { my ($self, %options) = @_; return 'keepalive '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'domains', type => 3, cb_prefix_output => 'prefix_domain_output', cb_long_output => 'domain_long_output', indent_long_output => ' ', message_multiple => 'All vPC domains are ok', group => [ { name => 'peer', type => 0, cb_prefix_output => 'prefix_peer_output', skipped_code => { -10 => 1 } }, { name => 'keepalive', type => 0, cb_prefix_output => 'prefix_keepalive_output', skipped_code => { -10 => 1 } }, { name => 'hosts', display_long => 1, cb_prefix_output => 'prefix_host_output', message_multiple => 'All host links are ok', type => 1, skipped_code => { -10 => 1 } }, ] } ]; $self->{maps_counters}->{peer} = [ { label => 'peer-status', type => 2, critical_default => '%{role} ne %{role_last}', set => { key_values => [ { name => 'role' }, { name => 'domain_id' } ], closure_custom_calc => $self->can('custom_peer_status_calc'), closure_custom_output => $self->can('custom_peer_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'host-links-up', nlabel => 'vpc.host.links.up.count', display_ok => 0, set => { key_values => [ { name => 'links_up' }, { name => 'links_total' } ], output_template => 'host links up: %s', perfdatas => [ { template => '%s', min => 0, max => 'links_total', label_extra_instance => 1 } ] } }, { label => 'host-links-down', nlabel => 'vpc.host.links.down.count', display_ok => 0, set => { key_values => [ { name => 'links_down' }, { name => 'links_total' } ], output_template => 'host links down: %s', perfdatas => [ { template => '%s', min => 0, max => 'links_total', label_extra_instance => 1 } ] } }, { label => 'host-links-downstar', nlabel => 'vpc.host.links.downstar.count', display_ok => 0, set => { key_values => [ { name => 'links_downstar' }, { name => 'links_total' } ], output_template => 'host links downstar: %s', perfdatas => [ { template => '%s', min => 0, max => 'links_total', label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{keepalive} = [ { label => 'keepalive-status', type => 2, critical_default => '%{keepalive_status} ne "alive"', set => { key_values => [ { name => 'keepalive_status' }, { name => 'domain_id' } ], closure_custom_calc => $self->can('custom_keepalive_status_calc'), closure_custom_output => $self->can('custom_keepalive_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'keepalive-messages-sent', nlabel => 'vpc.keepalive.messages.sent.count', display_ok => 0, set => { key_values => [ { name => 'keepalive_sent', diff => 1 } ], output_template => 'messages sent: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } }, { label => 'keepalive-messages-received', nlabel => 'vpc.keepalive.messages.received.count', display_ok => 0, set => { key_values => [ { name => 'keepalive_received', diff => 1 } ], output_template => 'messages received: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{hosts} = [ { label => 'link-status', type => 2, warning_default => '%{link_status} =~ /downStar/i', critical_default => '%{link_status} eq "down"', set => { key_values => [ { name => 'link_status' }, { name => 'display' } ], closure_custom_output => $self->can('custom_link_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my $mapping_role = { 1 => 'primarySecondary', 2 => 'primary', 3 => 'secondaryPrimary', 4 => 'secondary', 5 => 'noneEstablished' }; my $mapping_keepalive_status = { 1 => 'disabled', 2 => 'alive', 3 => 'peerUnreachable', 4 => 'aliveButDomainIdDismatch', 5 => 'suspendedAsISSU', 6 => 'suspendedAsDestIPUnreachable', 7 => 'suspendedAsVRFUnusable', 8 => 'misconfigured' }; my $mapping_link_status = { 1 => 'down', 2 => 'downStar', 3 => 'up' }; my $mapping = { role => { oid => '.1.3.6.1.4.1.9.9.807.1.2.1.1.2', map => $mapping_role }, # cVpcRoleStatus macaddress => { oid => '.1.3.6.1.4.1.9.9.807.1.2.1.1.5' } # cVpcSystemOperMacAddress }; my $mapping2 = { keepalive_status => { oid => '.1.3.6.1.4.1.9.9.807.1.1.2.1.2', map => $mapping_keepalive_status }, # cVpcPeerKeepAliveStatus keepalive_sent => { oid => '.1.3.6.1.4.1.9.9.807.1.3.1.1.2' }, # cVpcStatsPeerKeepAliveMsgsSent keepalive_received => { oid => '.1.3.6.1.4.1.9.9.807.1.3.1.1.3' } # cVpcStatsPeerKeepAliveMsgsRcved }; my $mapping3 = { if_index => { oid => '.1.3.6.1.4.1.9.9.807.1.4.2.1.3' }, # cVpcStatusHostLinkIfIndex link_status => { oid => '.1.3.6.1.4.1.9.9.807.1.4.2.1.4', map => $mapping_link_status } # cVpcStatusHostLinkStatus }; my $oid_cVpcRoleEntry = '.1.3.6.1.4.1.9.9.807.1.2.1.1'; my $oid_cVpcStatsPeerKeepAliveEntry = '.1.3.6.1.4.1.9.9.807.1.3.1.1'; my $oid_cVpcStatusHostLinkEntry = '.1.3.6.1.4.1.9.9.807.1.4.2.1'; my $oid_ifName = '.1.3.6.1.2.1.31.1.1.1.1'; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_multiple_table( oids => [ { oid => $oid_cVpcRoleEntry, start => $mapping->{role}->{oid}, end => $mapping->{macaddress}->{oid} }, { oid => $oid_cVpcStatusHostLinkEntry, start => $mapping3->{if_index}->{oid}, end => $mapping3->{link_status}->{oid} } ], nothing_quit => 1 ); $self->{domains} = {}; foreach my $oid (keys %{$snmp_result->{$oid_cVpcRoleEntry}}) { next if ($oid !~ /^$mapping->{role}->{oid}\.(.*)$/); my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result->{$oid_cVpcRoleEntry}, instance => $1); my $domain_id = $1; $self->{domains}->{$domain_id} = { domain_id => $domain_id, peer => { domain_id => $domain_id, role => $result->{role}, macaddress => $result->{macaddress}, links_up => 0, links_down => 0, links_downstar => 0, links_total => 0 }, keepalive => {}, hosts => {} }; } my $if_indexes = {}; foreach (keys %{$snmp_result->{$oid_cVpcStatusHostLinkEntry}}) { next if (!/^$mapping3->{link_status}->{oid}\.(\d+)\.(\d+)/); my ($domain_id, $vpc_id) = ($1, $2); next if (!defined($self->{domains}->{$domain_id})); my $result = $options{snmp}->map_instance(mapping => $mapping3, results => $snmp_result->{$oid_cVpcStatusHostLinkEntry}, instance => $domain_id . '.' . $vpc_id); $if_indexes->{ $result->{if_index} } = 1; $self->{domains}->{$domain_id}->{hosts}->{ $result->{if_index} } = { display => $result->{if_index}, link_status => $result->{link_status} }; $self->{domains}->{$domain_id}->{peer}->{links_total}++; $self->{domains}->{$domain_id}->{peer}->{'links_' . lc($result->{link_status})}++; } # get interface name $options{snmp}->load( oids => [ $oid_ifName ], instances => [keys %$if_indexes], instance_regexp => '^(.*)$' ); $snmp_result = $options{snmp}->get_leef(); foreach my $domain_id (keys %{$self->{domains}}) { foreach my $if_index (keys %{$self->{domains}->{$domain_id}->{hosts}}) { next if ( !defined($snmp_result->{ $oid_ifName . '.' . $if_index }) || $snmp_result->{ $oid_ifName . '.' . $if_index } eq '' ); $self->{domains}->{$domain_id}->{hosts}->{$if_index}->{display} = $snmp_result->{ $oid_ifName . '.' . $if_index }; } } # Keepalive part $snmp_result = $options{snmp}->get_multiple_table( oids => [ { oid => $oid_cVpcStatsPeerKeepAliveEntry, start => $mapping2->{keepalive_sent}->{oid}, end => $mapping2->{keepalive_received}->{oid} }, { oid => $mapping2->{keepalive_status}->{oid} } ], return_type => 1 ); foreach (keys %$snmp_result) { next if (!/^$mapping2->{keepalive_status}->{oid}\.(\d+)/); my $domain_id = $1; next if (!defined($self->{domains}->{$domain_id})); my $result = $options{snmp}->map_instance(mapping => $mapping2, results => $snmp_result, instance => $domain_id); $self->{domains}->{$domain_id}->{keepalive} = { domain_id => $domain_id, %$result }; } $self->{cache_name} = 'cisco_standard_' . $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')); } 1; __END__ =head1 MODE Check virtual port-channel (vPC). =over 8 =item B<--unknown-peer-status> Set unknown threshold for status. Can used special variables like: %{role}, %{role_last}, %{domain_id} =item B<--warning-peer-status> Set warning threshold for status. Can used special variables like: %{role}, %{role_last}, %{domain_id} =item B<--critical-peer-status> Set critical threshold for status (Default: '%{role} ne %{role_last}'). Can used special variables like: %{role}, %{role_last}, %{domain_id} =item B<--unknown-keepalive-status> Set unknown threshold for status. Can used special variables like: %{keepalive_status}, %{domain_id} =item B<--warning-keepalive-status> Set warning threshold for status. Can used special variables like: %{keepalive_status}, %{domain_id} =item B<--critical-keepalive-status> Set critical threshold for status (Default: '%{keepalive_status} ne "alive"'). Can used special variables like: %{keepalive_status}, %{domain_id} =item B<--unknown-link-status> Set unknown threshold for status. Can used special variables like: %{link_status}, %{display} =item B<--warning-link-status> Set warning threshold for status (Default: '%{link_status} =~ /downStar/i') Can used special variables like: %{link_status}, %{display} =item B<--critical-link-status> Set critical threshold for status (Default: '%{link_status} eq "down"'). Can used special variables like: %{link_status}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'host-links-up', 'host-links-down', 'host-links-downstar', 'keepalive-messages-sent', 'keepalive-messages-received'. =back =cut centreon-plugins-20220113/centreon/common/cisco/standard/snmp/mode/vss.pm000066400000000000000000000260341417000230700263200ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::standard::snmp::mode::vss; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; return sprintf( 'virtual switching system mode: %s', $self->{result_values}->{mode} ); } sub custom_member_status_output { my ($self, %options) = @_; return sprintf( 'role: %s', $self->{result_values}->{role} ); } sub custom_member_status_calc { my ($self, %options) = @_; $self->{result_values}->{role_last} = $options{old_datas}->{$self->{instance} . '_role'}; $self->{result_values}->{role} = $options{new_datas}->{$self->{instance} . '_role'}; if (!defined($options{old_datas}->{$self->{instance} . '_role'})) { $self->{error_msg} = "buffer creation"; return -2; } return 0; } sub custom_link_status_output { my ($self, %options) = @_; return sprintf( 'operational status: %s', $self->{result_values}->{link_status} ); } sub member_long_output { my ($self, %options) = @_; return "checking member '" . $options{instance_value}->{switch_id} . "'"; } sub prefix_member_output { my ($self, %options) = @_; return "Member '" . $options{instance_value}->{switch_id} . "' "; } sub prefix_vsl_output { my ($self, %options) = @_; return "virtual switch link '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'member', type => 3, cb_prefix_output => 'prefix_member_output', cb_long_output => 'member_long_output', indent_long_output => ' ', message_multiple => 'All members are ok', group => [ { name => 'member_global', type => 0, skipped_code => { -10 => 1 } }, { name => 'vsl', display_long => 1, cb_prefix_output => 'prefix_vsl_output', message_multiple => 'All virtual switch links are ok', type => 1, skipped_code => { -10 => 1 } }, ] } ]; $self->{maps_counters}->{global} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'mode' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold, } }, { label => 'members-total', nlabel => 'vss.members.total.count', display_ok => 0, set => { key_values => [ { name => 'members'} ], output_template => 'total members: %s', perfdatas => [ { template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{member_global} = [ { label => 'member-status', threshold => 0, set => { key_values => [ { name => 'role' }, { name => 'switch_id' } ], closure_custom_calc => $self->can('custom_member_status_calc'), closure_custom_output => $self->can('custom_member_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold, } } ]; $self->{maps_counters}->{vsl} = [ { label => 'link-status', threshold => 0, set => { key_values => [ { name => 'link_status' }, { name => 'display' } ], closure_custom_output => $self->can('custom_link_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } }, { label => 'vsl-ports-operational', nlabel => 'vsl.ports.operational.count', display_ok => 0, set => { key_values => [ { name => 'operational_ports'}, { name => 'display' } ], output_template => 'operational ports: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'unknown-status:s' => { name => 'unknown_status', default => '' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '' }, 'unknown-member-status:s' => { name => 'unknown_member_status', default => '' }, 'warning-member-status:s' => { name => 'warning_member_status', default => '' }, 'critical-member-status:s' => { name => 'critical_member_status', default => '%{role} ne %{role_last}' }, 'unknown-link-status:s' => { name => 'unknown_link_status', default => '' }, 'warning-link-status:s' => { name => 'warning_link_status', default => '' }, 'critical-link-status:s' => { name => 'critical_link_status', default => '%{link_status} eq "down"' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros( macros => [ 'unknown_status', 'warning_status', 'critical_status', 'unknown_member_status', 'warning_member_status', 'critical_member_status', 'unknown_link_status', 'warning_link_status', 'critical_link_status' ] ); } my $mapping_vss_role = { 1 => 'standalone', 2 => 'active', 3 => 'standby' }; my $mapping_vss_mode = { 1 => 'standalone', 2 => 'multiNode' }; my $mapping_vsl_connect_status = { 1 => 'up', 2 => 'down' }; my $mapping = { cvsSwitchMode => { oid => '.1.3.6.1.4.1.9.9.388.1.1.4', map => $mapping_vss_mode } }; my $mapping2 = { cvsChassisSwitchID => { oid => '.1.3.6.1.4.1.9.9.388.1.2.2.1.1' }, cvsChassisRole => { oid => '.1.3.6.1.4.1.9.9.388.1.2.2.1.2', map => $mapping_vss_role } }; my $mapping3 = { cvsVSLCoreSwitchID => { oid => '.1.3.6.1.4.1.9.9.388.1.3.1.1.2' }, cvsVSLConnectOperStatus => { oid => '.1.3.6.1.4.1.9.9.388.1.3.1.1.3', map => $mapping_vsl_connect_status }, cvsVSLOperationalPortCount => { oid => '.1.3.6.1.4.1.9.9.388.1.3.1.1.6' } }; my $oid_cvsGlobalObjects = '.1.3.6.1.4.1.9.9.388.1.1'; my $oid_cvsChassisEntry = '.1.3.6.1.4.1.9.9.388.1.2.2.1'; my $oid_cvsVSLConnectionEntry = '.1.3.6.1.4.1.9.9.388.1.3.1.1'; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_multiple_table( oids => [ { oid => $oid_cvsGlobalObjects, start => $mapping->{cvsSwitchMode}->{oid} }, { oid => $oid_cvsChassisEntry, end => $mapping2->{cvsChassisRole}->{oid} }, { oid => $oid_cvsVSLConnectionEntry, start => $mapping3->{cvsVSLCoreSwitchID}->{oid}, end => $mapping3->{cvsVSLOperationalPortCount}->{oid} } ], nothing_quit => 1 ); my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result->{$oid_cvsGlobalObjects}, instance => '0'); $self->{global} = { mode => $result->{cvsSwitchMode} }; $self->{member} = {}; foreach my $oid (keys %{$snmp_result->{$oid_cvsChassisEntry}}) { next if ($oid !~ /^$mapping2->{cvsChassisSwitchID}->{oid}\.(.*)$/); $result = $options{snmp}->map_instance(mapping => $mapping2, results => $snmp_result->{$oid_cvsChassisEntry}, instance => $1); my $switch_id = $result->{cvsChassisSwitchID}; $self->{member}->{$switch_id} = { switch_id => $switch_id, member_global => { switch_id => $switch_id, role => $result->{cvsChassisRole} }, vsl => {}, }; foreach (keys %{$snmp_result->{$oid_cvsVSLConnectionEntry}}) { next if (!/^$mapping3->{cvsVSLCoreSwitchID}->{oid}\.(.*)/); my $if_index = $1; $result = $options{snmp}->map_instance(mapping => $mapping3, results => $snmp_result->{$oid_cvsVSLConnectionEntry}, instance => $if_index); next if ($result->{cvsVSLCoreSwitchID} != $switch_id); $self->{member}->{$switch_id}->{vsl}->{$if_index} = { display => $if_index, link_status => $result->{cvsVSLConnectOperStatus}, operational_ports => $result->{cvsVSLOperationalPortCount} }; } } $self->{global}->{members} = scalar(keys %{$self->{member}}); $self->{cache_name} = 'cisco_standard_' . $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')); } 1; __END__ =head1 MODE Check virtual switching system. =over 8 =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{mode} =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{mode} =item B<--critical-status> Set critical threshold for status. Can used special variables like: %{mode} =item B<--unknown-member-status> Set unknown threshold for status. Can used special variables like: %{role}, %{role_last}, %{switch_id} =item B<--warning-member-status> Set warning threshold for status. Can used special variables like: %{role}, %{role_last}, %{switch_id} =item B<--critical-member-status> Set critical threshold for status (Default: '%{role} ne %{role_last}'). Can used special variables like: %{role}, %{role_last}, %{switch_id} =item B<--unknown-link-status> Set unknown threshold for status. Can used special variables like: %{link_status}, %{display} =item B<--warning-link-status> Set warning threshold for status. Can used special variables like: %{link_status}, %{display} =item B<--critical-link-status> Set critical threshold for status (Default: '%{link_status} eq "down"'). Can used special variables like: %{link_status}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'members-total', 'vsl-ports-operational'. =back =cut centreon-plugins-20220113/centreon/common/cisco/standard/snmp/mode/wan3g.pm000066400000000000000000000403551417000230700265260ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cisco::standard::snmp::mode::wan3g; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use Digest::MD5 qw(md5_hex); sub custom_connection_status_output { my ($self, %options) = @_; return sprintf( 'connection status: %s', $self->{result_values}->{connection_status} ); } sub custom_sim_status_output { my ($self, %options) = @_; return sprintf( 'sim status: %s', $self->{result_values}->{sim_status} ); } sub custom_modem_status_output { my ($self, %options) = @_; return sprintf( 'modem status: %s [imsi: %s][imei: %s][iccid: %s]', $self->{result_values}->{modem_status}, $self->{result_values}->{imsi}, $self->{result_values}->{imei}, $self->{result_values}->{iccid} ); } sub custom_radio_status_output { my ($self, %options) = @_; return sprintf( 'current band: %s [channel number: %s]', $self->{result_values}->{current_band}, $self->{result_values}->{channel_number} ); } sub custom_network_status_output { my ($self, %options) = @_; return sprintf( 'service status: %s', $self->{result_values}->{service_status} ); } sub modem_long_output { my ($self, %options) = @_; return "checking module '" . $options{instance_value}->{display} . "'"; } sub prefix_modem_output { my ($self, %options) = @_; return "module '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'modem', type => 3, cb_prefix_output => 'prefix_modem_output', cb_long_output => 'modem_long_output', indent_long_output => ' ', message_multiple => 'All cellular modems are ok', group => [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'radio', type => 0, skipped_code => { -10 => 1 } }, { name => 'network', type => 0, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'modem-status', type => 2, unknown_default => '%{modem_status} =~ /unknown/i', warning_default => '%{modem_status} =~ /lowPowerMode/i', critical_default => '%{modem_status} =~ /offLine/i', set => { key_values => [ { name => 'modem_status' }, { name => 'imsi' }, { name => 'imei' }, { name => 'iccid' }, { name => 'display' } ], closure_custom_output => $self->can('custom_modem_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'connection-status', type => 2, unknown_default => '%{connection_status} =~ /unknown/i', critical_default => '%{connection_status} =~ /inactive|idle|disconnected|error/i', set => { key_values => [ { name => 'connection_status' }, { name => 'display' } ], closure_custom_output => $self->can('custom_connection_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'sim-status', type => 2, unknown_default => '%{sim_status} =~ /unknown/i', critical_default => '%{sim_status} !~ /ok|unknown/i', set => { key_values => [ { name => 'sim_status' }, { name => 'display' } ], closure_custom_output => $self->can('custom_sim_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'temperature', nlabel => 'modem.temperature.celsius', display_ok => 0, set => { key_values => [ { name => 'temperature' }, { name => 'display' } ], output_template => 'memory used: %s%s', output_change_bytes => 1, perfdatas => [ { template => '%s', min => 0, unit => 'C', label_extra_instance => 1, instance_use => 'display' } ] } } ]; $self->{maps_counters}->{radio} = [ { label => 'radio-status', type => 2, unknown_default => '%{current_band} =~ /unknown/i', critical_default => '%{current_band} =~ /invalid|none/i', set => { key_values => [ { name => 'current_band' }, { name => 'channel_number' }, { name => 'display' } ], closure_custom_output => $self->can('custom_radio_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'radio-rssi', nlabel => 'modem.radio.rssi.dbm', set => { key_values => [ { name => 'rssi' }, { name => 'display' } ], output_template => 'received signal strength: %s dBm', output_change_bytes => 1, perfdatas => [ { template => '%s', min => 0, unit => 'dBm', label_extra_instance => 1, instance_use => 'display' } ] } } ]; $self->{maps_counters}->{network} = [ { label => 'network-status', type => 2, unknown_default => '%{service_status} =~ /unknown/i', critical_default => '%{service_status} =~ /emergencyOnly|noService/i', set => { key_values => [ { name => 'service_status' }, { name => 'display' } ], closure_custom_output => $self->can('custom_network_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'traffic-in', nlabel => 'modem.traffic.in.bitspersecond', set => { key_values => [ { name => 'traffic_in', per_second => 1 }, { name => 'display' } ], output_template => 'traffic in: %s%s/s', output_change_bytes => 2, perfdatas => [ { template => '%s', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'traffic-out', nlabel => 'modem.traffic.out.bitspersecond', set => { key_values => [ { name => 'traffic_out', per_second => 1 }, { name => 'display' } ], output_template => 'traffic out: %s%s/s', output_change_bytes => 2, perfdatas => [ { template => '%s', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } my $map_current_band = { 1 => 'unknown', 2 => 'invalid', 3 => 'none', 4 => 'gsm850', 5 => 'gsm900', 6 => 'gsm1800', 7 => 'gsm1900', 8 => 'wcdma800', 9 => 'wcdma850', 10 => 'wcdma1900', 11 => 'wcdma2100', 12 => 'lteBand' }; my $map_modem_status = { 1 => 'unknown', 2 => 'offLine', 3 => 'onLine', 4 => 'lowPowerMode' }; my $map_connection_status = { 1 => 'unknown', 2 => 'error', 3 => 'connecting', 4 => 'dormant', 5 => 'connected', 6 => 'disconnected', 7 => 'idle', 8 => 'active', 9 => 'inactive' }; my $map_sim_status = { 1 => 'unknown', 2 => 'ok', 3 => 'notInserted', 4 => 'removed', 5 => 'initFailure', 6 => 'generalFailure', 7 => 'locked', 8 => 'chv1Blocked', 9 => 'chv2Blocked', 10 => 'chv1Rejected', 11 => 'chv2Rejected', 12 => 'mepLocked', 13 => 'networkRejected' }; my $map_service_status = { 1 => 'unknown', 2 => 'noService', 3 => 'normal', 4 => 'emergencyOnly' }; my $mapping = { rssi => { oid => '.1.3.6.1.4.1.9.9.661.1.3.4.1.1.1' }, # c3gCurrentGsmRssi current_band => { oid => '.1.3.6.1.4.1.9.9.661.1.3.4.1.1.3', map => $map_current_band }, # c3gGsmCurrentBand channel_number => { oid => '.1.3.6.1.4.1.9.9.661.1.3.4.1.1.4' }, # c3gGsmChannelNumber imsi => { oid => '.1.3.6.1.4.1.9.9.661.1.3.1.1.1' }, # c3gImsi imei => { oid => '.1.3.6.1.4.1.9.9.661.1.3.1.1.2' }, # c3gImei iccid => { oid => '.1.3.6.1.4.1.9.9.661.1.3.1.1.3' }, # c3gIccId modem_status => { oid => '.1.3.6.1.4.1.9.9.661.1.3.1.1.6', map => $map_modem_status }, # c3gModemStatus temperature => { oid => '.1.3.6.1.4.1.9.9.661.1.1.1.12' }, # c3gModemTemperature connection_status => { oid => '.1.3.6.1.4.1.9.9.661.1.1.1.8', map => $map_connection_status }, # c3gConnectionStatus sim_status => { oid => '.1.3.6.1.4.1.9.9.661.1.3.5.1.1.2', map => $map_sim_status }, # c3gGsmSimStatus service_status => { oid => '.1.3.6.1.4.1.9.9.661.1.3.2.1.2', map => $map_service_status }, # c3gGsmCurrentServiceStatus traffic_out => { oid => '.1.3.6.1.4.1.9.9.661.1.3.2.1.19' }, # c3gGsmTotalByteTransmitted traffic_in => { oid => '.1.3.6.1.4.1.9.9.661.1.3.2.1.20' } # c3gGsmTotalByteReceived }; sub manage_selection { my ($self, %options) = @_; my $oid_entPhysicalName = '.1.3.6.1.2.1.47.1.1.1.1.7'; my $snmp_result = $options{snmp}->get_table( oid => $mapping->{connection_status}->{oid}, nothing_quit => 1 ); my $instances = []; foreach (keys %$snmp_result) { /\.(\d+)$/; push @$instances, $1; } $options{snmp}->load( oids => [ $oid_entPhysicalName ], instances => $instances, instance_regexp => '^(.*)$' ); $snmp_result = $options{snmp}->get_leef(); $self->{modem} = {}; foreach (keys %$snmp_result) { /\.(\d+)$/; my $instance = $1; my $name = $snmp_result->{$_}; 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 module '" . $name . "'.", debug => 1); next; } $self->{modem}->{$instance} = { display => $name, global => { display => $name }, radio => { display => $name }, network => { display => $name } }; } return if (scalar(keys %{$self->{modem}}) <= 0); $options{snmp}->load( oids => [ map($_->{oid}, values(%$mapping)) ], instances => [ keys %{$self->{modem}} ], instance_regexp => '^(.*)$' ); $snmp_result = $options{snmp}->get_leef(); foreach (keys %{$self->{modem}}) { my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $_); $self->{modem}->{$_}->{global}->{modem_status} = $result->{modem_status}; $self->{modem}->{$_}->{global}->{imsi} = $result->{imsi}; $self->{modem}->{$_}->{global}->{imei} = $result->{imei}; $self->{modem}->{$_}->{global}->{iccid} = $result->{iccid}; $self->{modem}->{$_}->{global}->{connection_status} = $result->{connection_status}; $self->{modem}->{$_}->{global}->{sim_status} = $result->{sim_status}; $self->{modem}->{$_}->{global}->{temperature} = $result->{temperature}; $self->{modem}->{$_}->{radio}->{current_band} = $result->{current_band}; $self->{modem}->{$_}->{radio}->{channel_number} = $result->{channel_number}; $self->{modem}->{$_}->{radio}->{rssi} = $result->{rssi}; $self->{modem}->{$_}->{network}->{traffic_in} = $result->{traffic_in}; $self->{modem}->{$_}->{network}->{traffic_out} = $result->{traffic_out}; $self->{modem}->{$_}->{network}->{service_status} = $result->{service_status}; } $self->{cache_name} = 'cisco_standard_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')); } 1; __END__ =head1 MODE Check cellular 3G and 4G LTE WAN. =over 8 =item B<--filter-name> Filter by name (can be a regexp). =item B<--unknown-modem-status> Set unknown threshold for status (Default: '%{modem_status} =~ /unknown/i'). Can used special variables like: %{modem_status}, %{display} =item B<--warning-modem-status> Set warning threshold for status (Default: '%{modem_status} =~ /lowPowerMode/i'). Can used special variables like: %{modem_status}, %{display} =item B<--critical-modem-status> Set critical threshold for status (Default: '%{modem_status} =~ /offLine/i'). Can used special variables like: %{modem_status}, %{display} =item B<--unknown-connection-status> Set unknown threshold for status (Default: '%{connection_status} =~ /unknown/i'). Can used special variables like: %{connection_status}, %{display} =item B<--warning-connection-status> Set warning threshold for status. Can used special variables like: %{connection_status}, %{display} =item B<--critical-connection-status> Set critical threshold for status (Default: '%{connection_status} =~ /inactive|idle|disconnected|error/i'). Can used special variables like: %{connection_status}, %{display} =item B<--unknown-sim-status> Set unknown threshold for status (Default: '%{sim_status} =~ /unknown/i'). Can used special variables like: %{sim_status}, %{display} =item B<--warning-sim-status> Set warning threshold for status. Can used special variables like: %{sim_status}, %{display} =item B<--critical-sim-status> Set critical threshold for status (Default: '%{sim_status} !~ /ok|unknown/i'). Can used special variables like: %{sim_status}, %{display} =item B<--unknown-radio-status> Set unknown threshold for status (Default: '%{current_band} =~ /unknown/i'). Can used special variables like: %{current_band}, %{channel_number}, %{display} =item B<--warning-radio-status> Set warning threshold for status. Can used special variables like: %{current_band}, %{channel_number}, %{display} =item B<--critical-radio-status> Set critical threshold for status (Default: '%{current_band} =~ /invalid|none/i'). Can used special variables like: %{current_band}, %{channel_number}, %{display} =item B<--unknown-network-status> Set unknown threshold for status (Default: '%{service_status} =~ /unknown/i'). Can used special variables like: %{service_status}, %{display} =item B<--warning-network-status> Set warning threshold for status. Can used special variables like: %{service_status}, %{display} =item B<--critical-network-status> Set critical threshold for status (Default: '%{service_status} =~ /emergencyOnly|noService/i'). Can used special variables like: %{service_status}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'temperature', 'traffic-in', 'traffic-out'. =back =cut centreon-plugins-20220113/centreon/common/cps/000077500000000000000000000000001417000230700211265ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/cps/ups/000077500000000000000000000000001417000230700217355ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/cps/ups/snmp/000077500000000000000000000000001417000230700227125ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/cps/ups/snmp/mode/000077500000000000000000000000001417000230700236365ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/cps/ups/snmp/mode/batterystatus.pm000066400000000000000000000140271417000230700271160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cps::ups::snmp::mode::batterystatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); sub custom_status_output { my ($self, %options) = @_; return sprintf('battery status is %s', $self->{result_values}->{status}); } sub custom_load_output { my ($self, %options) = @_; return sprintf("charge remaining: %s%% (%s minutes remaining)", $self->{result_values}->{charge_remain}, $self->{result_values}->{minute_remain} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, message_separator => ' - ', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold, } }, { label => 'charge-remaining', nlabel => 'battery.charge.remaining.percent', set => { key_values => [ { name => 'charge_remain' }, { name => 'minute_remain' } ], closure_custom_output => $self->can('custom_load_output'), perfdatas => [ { value => 'charge_remain', template => '%s', min => 0, max => 100, unit => '%' }, ], } }, { label => 'voltage', nlabel => 'battery.voltage.volt', display_ok => 0, set => { key_values => [ { name => 'voltage', no_value => 0 } ], output_template => 'voltage: %s V', perfdatas => [ { value => 'voltage', template => '%s', unit => 'V' }, ], } }, { label => 'temperature', nlabel => 'battery.temperature.celsius', display_ok => 0, set => { key_values => [ { name => 'temperature', no_value => 0 } ], output_template => 'temperature: %s C', perfdatas => [ { value => 'temperature', template => '%s', unit => 'C' }, ], } }, ]; } 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 => { 'unknown-status:s' => { name => 'unknown_status', default => '%{status} =~ /unknown|notPresent/i' }, 'warning-status:s' => { name => 'warning_status', default => '%{status} =~ /low/i' }, 'critical-status:s' => { name => 'critical_status', default => '' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['unknown_status', 'warning_status', 'critical_status']); } my $map_status = { 1 => 'unknown', 2 => 'normal', 3 => 'low', 4 => 'notPresent' }; my $mapping = { upsBaseBatteryStatus => { oid => '.1.3.6.1.4.1.3808.1.1.1.2.1.1', map => $map_status }, upsAdvanceBatteryCapacity => { oid => '.1.3.6.1.4.1.3808.1.1.1.2.2.1' }, upsAdvanceBatteryVoltage => { oid => '.1.3.6.1.4.1.3808.1.1.1.2.2.2' }, # in dV upsAdvanceBatteryTemperature => { oid => '.1.3.6.1.4.1.3808.1.1.1.2.2.3' }, # in degrees Centigrade upsAdvanceBatteryRunTimeRemaining => { oid => '.1.3.6.1.4.1.3808.1.1.1.2.2.4' }, }; sub manage_selection { my ($self, %options) = @_; my $oid_upsBattery = '.1.3.6.1.4.1.3808.1.1.1.2'; my $snmp_result = $options{snmp}->get_table(oid => $oid_upsBattery, nothing_quit => 1); my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => '0'); $self->{global} = { voltage => (defined($result->{upsAdvanceBatteryVoltage}) && $result->{upsAdvanceBatteryVoltage} =~ /\d/) ? $result->{upsAdvanceBatteryVoltage} * 0.1 : 0, temperature => $result->{upsAdvanceBatteryTemperature}, minute_remain => (defined($result->{upsAdvanceBatteryRunTimeRemaining}) && $result->{upsAdvanceBatteryRunTimeRemaining} =~ /\d/) ? ($result->{upsAdvanceBatteryRunTimeRemaining} / 100 / 60) : 'unknown', charge_remain => (defined($result->{upsAdvanceBatteryCapacity}) && $result->{upsAdvanceBatteryCapacity} =~ /\d/) ? $result->{upsAdvanceBatteryCapacity} : undef, status => $result->{upsBaseBatteryStatus}, }; } 1; __END__ =head1 MODE Check battery status and charge remaining. =over 8 =item B<--unknown-status> Set warning threshold for status (Default: '%{status} =~ /unknown|notPresent/i'). Can used special variables like: %{status} =item B<--warning-status> Set warning threshold for status (Default: '%{status} =~ /low/i'). Can used special variables like: %{status} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{status} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'charge-remaining' (%), 'voltage' (V), 'temperature' (C). =back =cut centreon-plugins-20220113/centreon/common/cps/ups/snmp/mode/inputlines.pm000066400000000000000000000116241417000230700263720ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cps::ups::snmp::mode::inputlines; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); sub custom_status_output { my ($self, %options) = @_; return sprintf("status is '%s'", $self->{result_values}->{status}); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'ilines', type => 0, cb_prefix_output => 'prefix_ilines_output', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{ilines} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold, } }, { label => 'voltage', nlabel => 'lines.input.voltage.volt', set => { key_values => [ { name => 'voltage' } ], output_template => 'Voltage : %.2f V', perfdatas => [ { value => 'voltage', template => '%.2f', unit => 'V' }, ], } }, { label => 'frequence', nlabel => 'lines.input.frequence.hertz', set => { key_values => [ { name => 'frequence' } ], output_template => 'Frequence : %.2f Hz', perfdatas => [ { value => 'frequence', template => '%.2f', min => 0, unit => 'Hz' }, ], } }, ]; } sub prefix_ilines_output { my ($self, %options) = @_; return 'Input '; } 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 => { 'unknown-status:s' => { name => 'unknown_status', default => '' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{status} !~ /normal/' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['unknown_status', 'warning_status', 'critical_status']); } my $map_status = { 1 => 'normal', 2 => 'overVoltage', 3 => 'underVoltage', 4 => 'frequencyFailure', 5 => 'blackout', }; my $mapping = { upsAdvanceInputLineVoltage => { oid => '.1.3.6.1.4.1.3808.1.1.1.3.2.1' }, # in dV upsAdvanceInputFrequency => { oid => '.1.3.6.1.4.1.3808.1.1.1.3.2.4' }, # in dHz upsAdvanceInputStatus => { oid => '.1.3.6.1.4.1.3808.1.1.1.3.2.6', map => $map_status }, }; sub manage_selection { my ($self, %options) = @_; my $oid_upsAdvanceInput = '.1.3.6.1.4.1.3808.1.1.1.3.2'; my $snmp_result = $options{snmp}->get_table(oid => $oid_upsAdvanceInput, nothing_quit => 1); my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => '0'); $self->{ilines} = { frequence => (defined($result->{upsAdvanceInputFrequency}) && $result->{upsAdvanceInputFrequency} =~ /\d/) ? $result->{upsAdvanceInputFrequency} * 0.1 : undef, voltage => (defined($result->{upsAdvanceInputLineVoltage}) && $result->{upsAdvanceInputLineVoltage} =~ /\d/) ? $result->{upsAdvanceInputLineVoltage} * 0.1 : undef, status => $result->{upsAdvanceInputStatus}, }; } 1; __END__ =head1 MODE Check INPUT lines metrics. =over 8 =item B<--unknown-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status} =item B<--critical-status> Set critical threshold for status (Default: '%{status} !~ /normal/'). Can used special variables like: %{status} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'voltage', 'frequence'. =back =cut centreon-plugins-20220113/centreon/common/cps/ups/snmp/mode/outputlines.pm000066400000000000000000000155071417000230700265770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::cps::ups::snmp::mode::outputlines; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); sub custom_status_output { my ($self, %options) = @_; return sprintf("status is '%s'", $self->{result_values}->{status}); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'olines', type => 0, cb_prefix_output => 'prefix_olines_output', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{olines} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold, } }, { label => 'load', nlabel => 'lines.output.load.percentage', set => { key_values => [ { name => 'load' } ], output_template => 'Load : %.2f %%', perfdatas => [ { value => 'load', template => '%.2f', min => 0, max => 100, unit => '%' }, ], } }, { label => 'current', nlabel => 'lines.output.current.ampere', set => { key_values => [ { name => 'current' } ], output_template => 'Current : %.2f A', perfdatas => [ { value => 'current', template => '%.2f', min => 0, unit => 'A' }, ], } }, { label => 'voltage', nlabel => 'lines.output.voltage.volt', set => { key_values => [ { name => 'voltage' } ], output_template => 'Voltage : %.2f V', perfdatas => [ { value => 'voltage', template => '%.2f', unit => 'V' }, ], } }, { label => 'power', nlabel => 'lines.output.power.watt', set => { key_values => [ { name => 'power' } ], output_template => 'Power : %.2f W', perfdatas => [ { value => 'power', template => '%.2f', min => 0, unit => 'W' }, ], } }, { label => 'frequence', nlabel => 'lines.output.frequence.hertz', set => { key_values => [ { name => 'frequence' } ], output_template => 'Frequence : %.2f Hz', perfdatas => [ { value => 'frequence', template => '%.2f', min => 0, unit => 'Hz' }, ], } }, ]; } sub prefix_olines_output { my ($self, %options) = @_; return 'Output '; } 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 => { 'unknown-status:s' => { name => 'unknown_status', default => '%{status} =~ /unknown/i' }, 'warning-status:s' => { name => 'warning_status', default => '%{status} =~ /rebooting|onBattery|onBypass/i' }, 'critical-status:s' => { name => 'critical_status', default => '' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['unknown_status', 'warning_status', 'critical_status']); } my $map_status = { 1 => 'unknown', 2 => 'onLine', 3 => 'onBattery', 4 => 'onBoost', 5 => 'onSleep', 6 => 'off', 7 => 'rebooting', 8 => 'onECO', 9 => 'onBypass', 10 => 'onBuck', 11 => 'onOverload', }; my $mapping = { upsBaseOutputStatus => { oid => '.1.3.6.1.4.1.3808.1.1.1.4.1.1', map => $map_status }, upsAdvanceOutputVoltage => { oid => '.1.3.6.1.4.1.3808.1.1.1.4.2.1' }, # in dV upsAdvanceOutputFrequency => { oid => '.1.3.6.1.4.1.3808.1.1.1.4.2.2' }, # in dHz upsAdvanceOutputLoad => { oid => '.1.3.6.1.4.1.3808.1.1.1.4.2.3' }, # in % upsAdvanceOutputCurrent => { oid => '.1.3.6.1.4.1.3808.1.1.1.4.2.4' }, # in dA upsAdvanceOutputPower => { oid => '.1.3.6.1.4.1.3808.1.1.1.4.2.5' }, # in W }; sub manage_selection { my ($self, %options) = @_; my $oid_upsOutput = '.1.3.6.1.4.1.3808.1.1.1.4'; my $snmp_result = $options{snmp}->get_table(oid => $oid_upsOutput, nothing_quit => 1); my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => '0'); $self->{olines} = { frequence => (defined($result->{upsAdvanceOutputFrequency}) && $result->{upsAdvanceOutputFrequency} =~ /\d/) ? $result->{upsAdvanceOutputFrequency} * 0.1 : undef, voltage => (defined($result->{upsAdvanceOutputVoltage}) && $result->{upsAdvanceOutputVoltage} =~ /\d/) ? $result->{upsAdvanceOutputVoltage} * 0.1 : undef, current => (defined($result->{upsAdvanceOutputCurrent}) && $result->{upsAdvanceOutputCurrent} =~ /\d/) ? $result->{upsAdvanceOutputCurrent} * 0.1 : undef, load => (defined($result->{upsAdvanceOutputLoad}) && $result->{upsAdvanceOutputLoad} =~ /\d/) ? $result->{upsAdvanceOutputLoad} : undef, power => (defined($result->{upsAdvanceOutputPower}) && $result->{upsAdvanceOutputPower} =~ /\d/) ? $result->{upsAdvanceOutputPower} : undef, status => $result->{upsBaseOutputStatus}, }; } 1; __END__ =head1 MODE Check output lines metrics. =over 8 =item B<--unknown-status> Set warning threshold for status (Default: '%{status} =~ /unknown/i'). Can used special variables like: %{status} =item B<--warning-status> Set warning threshold for status (Default: '%{status} =~ /rebooting|onBattery|onBypass/i'). Can used special variables like: %{status} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{status} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'load', 'voltage', 'current', 'power', 'frequence'. =back =cut centreon-plugins-20220113/centreon/common/dell/000077500000000000000000000000001417000230700212615ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/dell/fastpath/000077500000000000000000000000001417000230700230735ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/dell/fastpath/snmp/000077500000000000000000000000001417000230700240505ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/dell/fastpath/snmp/mode/000077500000000000000000000000001417000230700247745ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/dell/fastpath/snmp/mode/components/000077500000000000000000000000001417000230700271615ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/dell/fastpath/snmp/mode/components/fan.pm000066400000000000000000000076211417000230700302710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::dell::fastpath::snmp::mode::components::fan; use strict; use warnings; my %map_fan_status = ( 1 => 'notpresent', 2 => 'operational', 3 => 'failed', 4 => 'powering', 5 => 'nopower', 6 => 'notpowering', 7 => 'incompatible', ); my $mapping = { boxServicesFanItemState => { oid => '.1.3.6.1.4.1.674.10895.5000.2.6132.1.1.43.1.6.1.3', map => \%map_fan_status }, boxServicesFanSpeed => { oid => '.1.3.6.1.4.1.674.10895.5000.2.6132.1.1.43.1.6.1.4' }, }; my $oid_boxServicesFansEntry = '.1.3.6.1.4.1.674.10895.5000.2.6132.1.1.43.1.6.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_boxServicesFansEntry, start => $mapping->{boxServicesFanItemState}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking fans"); $self->{components}->{fan} = {name => 'fans', total => 0, skip => 0}; return if ($self->check_filter(section => 'fan')); my ($exit, $warn, $crit, $checked); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_boxServicesFansEntry}})) { next if ($oid !~ /^$mapping->{boxServicesFanItemState}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_boxServicesFansEntry}, instance => $instance); next if ($self->check_filter(section => 'fan', instance => $instance)); if ($result->{boxServicesFanItemState} =~ /notPresent/i) { $self->absent_problem(section => 'fan', instance => $instance); next; } $self->{components}->{fan}->{total}++; $self->{output}->output_add(long_msg => sprintf("fan '%s' status is '%s' [instance = %s, speed = %s]", $instance, $result->{boxServicesFanItemState}, $instance, defined($result->{boxServicesFanSpeed}) ? $result->{boxServicesFanSpeed} : 'unknown')); $exit = $self->get_severity(label => 'default', section => 'fan', value => $result->{boxServicesFanItemState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Fan '%s' status is '%s'", $instance, $result->{boxServicesFanItemState})); next; } ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'fan', instance => $instance, value => $result->{boxServicesFanSpeed}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Fan '%s' is '%s' rpm", $instance, $result->{boxServicesFanSpeed})); } $self->{output}->perfdata_add( label => 'fan', unit => 'rpm', nlabel => 'hardware.fan.speed.rpm', instances => $instance, value => $result->{boxServicesFanSpeed}, warning => $warn, critical => $crit, min => 0 ); } } 1; centreon-plugins-20220113/centreon/common/dell/fastpath/snmp/mode/components/psu.pm000066400000000000000000000060621417000230700303320ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::dell::fastpath::snmp::mode::components::psu; use strict; use warnings; my %map_status = ( 1 => 'notpresent', 2 => 'operational', 3 => 'failed', 4 => 'powering', 5 => 'nopower', 6 => 'notpowering', 7 => 'incompatible', ); my $mapping = { boxServicesPowSupplyItemState => { oid => '.1.3.6.1.4.1.674.10895.5000.2.6132.1.1.43.1.7.1.3', map => \%map_status }, }; my $oid_boxServicesPowSuppliesEntry = '.1.3.6.1.4.1.674.10895.5000.2.6132.1.1.43.1.7.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_boxServicesPowSuppliesEntry, start => $mapping->{boxServicesPowSupplyItemState}->{oid} }; } 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 ($exit, $warn, $crit, $checked); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_boxServicesPowSuppliesEntry}})) { next if ($oid !~ /^$mapping->{boxServicesPowSupplyItemState}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_boxServicesPowSuppliesEntry}, instance => $instance); next if ($self->check_filter(section => 'psu', instance => $instance)); if ($result->{boxServicesPowSupplyItemState} =~ /notPresent/i) { $self->absent_problem(section => 'psu', instance => $instance); next; } $self->{components}->{psu}->{total}++; $self->{output}->output_add(long_msg => sprintf("power supply '%s' status is '%s' [instance = %s]", $instance, $result->{boxServicesPowSupplyItemState}, $instance)); $exit = $self->get_severity(label => 'default', section => 'psu', value => $result->{boxServicesPowSupplyItemState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Power supply '%s' status is '%s'", $instance, $result->{boxServicesPowSupplyItemState})); next; } } } 1; centreon-plugins-20220113/centreon/common/dell/fastpath/snmp/mode/components/temperature.pm000066400000000000000000000112001417000230700320460ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::dell::fastpath::snmp::mode::components::temperature; use strict; use warnings; my %map_temp_status = ( 0 => 'low', 1 => 'normal', 2 => 'warning', 3 => 'critical', 4 => 'shutdown', 5 => 'notpresent', 6 => 'notoperational', ); my $mapping1 = { boxServicesTempSensorState => { oid => '.1.3.6.1.4.1.674.10895.5000.2.6132.1.1.43.1.8.1.3', map => \%map_temp_status }, boxServicesTempSensorTemperature => { oid => '.1.3.6.1.4.1.674.10895.5000.2.6132.1.1.43.1.8.1.4' }, }; my $mapping2 = { boxServicesTempSensorState => { oid => '.1.3.6.1.4.1.674.10895.5000.2.6132.1.1.43.1.8.1.4', map => \%map_temp_status }, boxServicesTempSensorTemperature => { oid => '.1.3.6.1.4.1.674.10895.5000.2.6132.1.1.43.1.8.1.5' }, }; my $oid_boxServicesTempSensorsEntry = '.1.3.6.1.4.1.674.10895.5000.2.6132.1.1.43.1.8.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_boxServicesTempSensorsEntry }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking temperatures"); $self->{components}->{temperature} = {name => 'temperatures', total => 0, skip => 0}; return if ($self->check_filter(section => 'temperature')); my ($result, $exit, $warn, $crit, $checked); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_boxServicesTempSensorsEntry}})) { next if ($oid !~ /^$mapping2->{boxServicesTempSensorState}->{oid}\.(.*)$/); my $instance = $1; if (defined($self->{results}->{$oid_boxServicesTempSensorsEntry}->{$mapping2->{boxServicesTempSensorTemperature}->{oid} . '.' . $instance})) { $result = $self->{snmp}->map_instance(mapping => $mapping2, results => $self->{results}->{$oid_boxServicesTempSensorsEntry}, instance => $instance); } else { $result = $self->{snmp}->map_instance(mapping => $mapping1, results => $self->{results}->{$oid_boxServicesTempSensorsEntry}, instance => $instance); } next if ($self->check_filter(section => 'temperature', instance => $instance)); if ($result->{boxServicesTempSensorState} =~ /notPresent/i) { $self->absent_problem(section => 'temperature', instance => $instance); next; } $self->{components}->{temperature}->{total}++; $self->{output}->output_add(long_msg => sprintf("temperature '%s' status is '%s' [instance = %s, temperature = %s]", $instance, $result->{boxServicesTempSensorState}, $instance, defined($result->{boxServicesTempSensorTemperature}) ? $result->{boxServicesTempSensorTemperature} : 'unknown')); $exit = $self->get_severity(section => 'temperature', value => $result->{boxServicesTempSensorState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Temperature '%s' status is '%s'", $instance, $result->{boxServicesTempSensorState})); } ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $instance, value => $result->{boxServicesTempSensorTemperature}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Temperature '%s' is '%s' C", $instance, $result->{boxServicesTempSensorTemperature})); } $self->{output}->perfdata_add( label => 'temp', unit => 'C', nlabel => 'hardware.temperature.celsius', instances => $instance, value => $result->{boxServicesTempSensorTemperature}, warning => $warn, critical => $crit, min => 0 ); } } 1; centreon-plugins-20220113/centreon/common/dell/fastpath/snmp/mode/cpu.pm000066400000000000000000000162411417000230700261250ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::dell::fastpath::snmp::mode::cpu; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'warning:s' => { name => 'warning', default => '' }, 'critical:s' => { name => 'critical', default => '' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); ($self->{warn5s}, $self->{warn1m}, $self->{warn5m}) = split /,/, $self->{option_results}->{warning}; ($self->{crit5s}, $self->{crit1m}, $self->{crit5m}) = split /,/, $self->{option_results}->{critical}; if (($self->{perfdata}->threshold_validate(label => 'warn5s', value => $self->{warn5s})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning (5sec) threshold '" . $self->{warn5s} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'warn1m', value => $self->{warn1m})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning (1min) threshold '" . $self->{warn1m} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'warn5m', value => $self->{warn5m})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning (5min) threshold '" . $self->{warn5m} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'crit5s', value => $self->{crit5s})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical (5sec) threshold '" . $self->{crit5s} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'crit1m', value => $self->{crit1m})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical (1min) threshold '" . $self->{crit1m} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'crit5m', value => $self->{crit5m})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical (5min) threshold '" . $self->{crit5m} . "'."); $self->{output}->option_exit(); } } sub run { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; my $oid_agentSwitchCpuProcessTotalUtilization1 = '.1.3.6.1.4.1.674.10895.5000.2.6132.1.1.1.1.4.9.0'; my $oid_agentSwitchCpuProcessTotalUtilization2 = '.1.3.6.1.4.1.674.10895.5000.2.6132.1.1.1.1.4.4.0'; # oid for 6200 series $self->{result} = $self->{snmp}->get_leef(oids => [ $oid_agentSwitchCpuProcessTotalUtilization1, $oid_agentSwitchCpuProcessTotalUtilization2 ], nothing_quit => 1); my $cpu_usage; if ((defined($self->{result}->{$oid_agentSwitchCpuProcessTotalUtilization1})) && ($self->{result}->{$oid_agentSwitchCpuProcessTotalUtilization1} =~ /sec.*(sec|min).*(sec|min)/i)) { $cpu_usage = $self->{result}->{$oid_agentSwitchCpuProcessTotalUtilization1}; } elsif ((defined($self->{result}->{$oid_agentSwitchCpuProcessTotalUtilization2})) && ($self->{result}->{$oid_agentSwitchCpuProcessTotalUtilization2} =~ /sec.*(sec|min).*(sec|min)/i)) { $cpu_usage = $self->{result}->{$oid_agentSwitchCpuProcessTotalUtilization2}; } else { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => sprintf("Can't get CPU information.")); $self->{output}->display(); $self->{output}->exit(); } if ($cpu_usage =~ /^.*\(\s*(\S+)%\).*\(\s*(\S+)%\).*\(\s*(\S+)%\)/) { my $cpu5sec = $1; my $cpu1min = $2; my $cpu5min = $3; my $exit1 = $self->{perfdata}->threshold_check(value => $cpu5sec, threshold => [ { label => 'crit5s', 'exit_litteral' => 'critical' }, { label => 'warn5s', exit_litteral => 'warning' } ]); my $exit2 = $self->{perfdata}->threshold_check(value => $cpu1min, threshold => [ { label => 'crit1m', 'exit_litteral' => 'critical' }, { label => 'warn1m', exit_litteral => 'warning' } ]); my $exit3 = $self->{perfdata}->threshold_check(value => $cpu5min, threshold => [ { label => 'crit5m', 'exit_litteral' => 'critical' }, { label => 'warn5m', exit_litteral => 'warning' } ]); my $exit = $self->{output}->get_most_critical(status => [ $exit1, $exit2, $exit3 ]); $self->{output}->output_add(severity => $exit, short_msg => sprintf("CPU Usage: %.2f%% (5sec), %.2f%% (1min), %.2f%% (5min)", $cpu5sec, $cpu1min, $cpu5min)); $self->{output}->perfdata_add(label => "cpu_5s", unit => '%', value => $cpu5sec, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warn5s'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'crit5s'), min => 0, max => 100); $self->{output}->perfdata_add(label => "cpu_1m", unit => '%', value => $cpu1min, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warn1m'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'crit1m'), min => 0, max => 100); $self->{output}->perfdata_add(label => "cpu_5m", unit => '%', value => $cpu5min, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warn5m'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'crit5m'), min => 0, max => 100); } else { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => sprintf("Can't parse CPU usage.")); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check cpu usage (FASTPATH-SWITCHING-MIB). =over 8 =item B<--warning> Threshold warning in percent (5s,1min,5min). =item B<--critical> Threshold critical in percent (5s,1min,5min). =back =cut centreon-plugins-20220113/centreon/common/dell/fastpath/snmp/mode/environment.pm000066400000000000000000000065771417000230700277150ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::dell::fastpath::snmp::mode::environment; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^(temperature|fan)$'; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { default => [ ['notpresent', 'OK'], ['operational', 'OK'], ['failed', 'CRITICAL'], ['powering', 'WARNING'], ['nopower', 'CRITICAL'], ['notpowering', 'CRITICAL'], ['incompatible', 'CRITICAL'], ], temperature => [ ['low', 'WARNING'], ['normal', 'OK'], ['warning', 'WARNING'], ['critical', 'CRITICAL'], ['shutdown', 'CRITICAL'], ['notpresent', 'OK'], ['notoperational', 'CRITICAL'], ], }; $self->{components_path} = 'centreon::common::dell::fastpath::snmp::mode::components'; $self->{components_module} = ['fan', 'psu', 'temperature']; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } 1; __END__ =head1 MODE Check Hardware (Fans, Power Supplies, Temperature) (FASTPATH-BOXSERVICES-MIB). =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'fan', 'psu', 'temperature'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=fan --filter=psu) Can also exclude specific instance: --filter=fan,1 =item B<--absent-problem> Return an error if an entity is not 'present' (default is skipping) (comma seperated list) Can be specific or global: --absent-problem=psu,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,^(?!(operational)$)' =item B<--warning> Set warning threshold for 'temperature', 'fan' (syntax: type,regexp,threshold) Example: --warning='fan,1.1,5000' =item B<--critical> Set critical threshold for 'temperature', 'fan' (syntax: type,regexp,threshold) Example: --critical='fan,.*,2000' =back =cut centreon-plugins-20220113/centreon/common/dell/fastpath/snmp/mode/memory.pm000066400000000000000000000106651417000230700266520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::dell::fastpath::snmp::mode::memory; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { '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) = @_; $self->{snmp} = $options{snmp}; my $oid_agentSwitchCpuProcessMemFree = '.1.3.6.1.4.1.674.10895.5000.2.6132.1.1.1.1.4.1.0'; # in KB my $oid_agentSwitchCpuProcessMemAvailable = '.1.3.6.1.4.1.674.10895.5000.2.6132.1.1.1.1.4.2.0'; # in KB my $result = $self->{snmp}->get_leef(oids => [$oid_agentSwitchCpuProcessMemFree, $oid_agentSwitchCpuProcessMemAvailable], nothing_quit => 1); my $memory_free = $result->{$oid_agentSwitchCpuProcessMemFree} * 1024; my $memory_available = $result->{$oid_agentSwitchCpuProcessMemAvailable} * 1024; my $memory_used = $memory_available - $memory_free; my $prct_used = ($memory_used / $memory_available) * 100; my $prct_free = ($memory_free / $memory_available) * 100; my $exit = $self->{perfdata}->threshold_check(value => $prct_used, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); my ($memory_used_value, $memory_used_unit) = $self->{perfdata}->change_bytes(value => $memory_used); my ($memory_available_value, $memory_available_unit) = $self->{perfdata}->change_bytes(value => $memory_available); my ($memory_free_value, $memory_free_unit) = $self->{perfdata}->change_bytes(value => $memory_free); $self->{output}->output_add(severity => $exit, short_msg => sprintf("Memory used: %s (%.2f%%), Size: %s, Free: %s (%.2f%%)", $memory_used_value . " " . $memory_used_unit, $prct_used, $memory_available_value . " " . $memory_available_unit, $memory_free_value . " " . $memory_free_unit, $prct_free)); $self->{output}->perfdata_add(label => "used", unit => 'B', value => $memory_used, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning', total => $memory_available, cast_int => 1), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical', total => $memory_available, cast_int => 1), min => 0, max => $memory_available); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check memory usage (FASTPATH-SWITCHING-MIB). =over 8 =item B<--warning> Threshold warning in percent. =item B<--critical> Threshold critical in percent. =back =cut centreon-plugins-20220113/centreon/common/dell/powerconnect3000/000077500000000000000000000000001417000230700242725ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/dell/powerconnect3000/mode/000077500000000000000000000000001417000230700252165ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/dell/powerconnect3000/mode/globalstatus.pm000066400000000000000000000075701417000230700302710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::dell::powerconnect3000::mode::globalstatus; use base qw(centreon::plugins::mode); use strict; use warnings; my %states = ( 3 => ['ok', 'OK'], 4 => ['non critical', 'WARNING'], 5 => ['critical', 'CRITICAL'], ); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; my $oid_productStatusGlobalStatus = '.1.3.6.1.4.1.674.10895.3000.1.2.110.1'; my $oid_productIdentificationDisplayName = '.1.3.6.1.4.1.674.10895.3000.1.2.100.1'; my $oid_productIdentificationBuildNumber = '.1.3.6.1.4.1.674.10895.3000.1.2.100.5'; my $oid_productIdentificationServiceTag = '.1.3.6.1.4.1.674.10895.3000.1.2.100.8.1.4'; my $result = $self->{snmp}->get_multiple_table(oids => [ { oid => $oid_productStatusGlobalStatus, start => $oid_productStatusGlobalStatus }, { oid => $oid_productIdentificationDisplayName, start => $oid_productIdentificationDisplayName }, { oid => $oid_productIdentificationBuildNumber, start => $oid_productIdentificationBuildNumber }, { oid => $oid_productIdentificationServiceTag, start => $oid_productIdentificationServiceTag }, ], nothing_quit => 1 ); my $globalStatus = $result->{$oid_productStatusGlobalStatus}->{$oid_productStatusGlobalStatus . '.0'}; my $displayName = $result->{$oid_productIdentificationDisplayName}->{$oid_productIdentificationDisplayName . '.0'}; my $buildNumber = $result->{$oid_productIdentificationBuildNumber}->{$oid_productIdentificationBuildNumber . '.0'}; my $serviceTag; foreach my $key ($self->{snmp}->oid_lex_sort(keys %{$result->{$oid_productIdentificationServiceTag}})) { next if ($key !~ /^$oid_productIdentificationServiceTag\.(\d+)$/); if (!defined($serviceTag)) { $serviceTag = $result->{$oid_productIdentificationServiceTag}->{$oid_productIdentificationServiceTag . '.' . $1}; } else { $serviceTag .= ',' . $result->{$oid_productIdentificationServiceTag}->{$oid_productIdentificationServiceTag . '.' . $1}; } } $self->{output}->output_add(severity => ${$states{$globalStatus}}[1], short_msg => sprintf("Overall global status is '%s' [Product: %s] [Version: %s] [Service Tag: %s]", ${$states{$globalStatus}}[0], $displayName, $buildNumber, $serviceTag)); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check the overall status of Dell Powerconnect 3000. =over 8 =back =cut centreon-plugins-20220113/centreon/common/emc/000077500000000000000000000000001417000230700211055ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/emc/navisphere/000077500000000000000000000000001417000230700232515ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/emc/navisphere/custom/000077500000000000000000000000001417000230700245635ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/emc/navisphere/custom/custom.pm000066400000000000000000000212601417000230700264340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::emc::navisphere::custom::custom; 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 => { 'remote' => { name => 'remote' }, 'ssh-address:s' => { name => 'ssh_address' }, 'ssh-option:s@' => { name => 'ssh_option' }, 'ssh-path:s' => { name => 'ssh_path' }, 'ssh-command:s' => { name => 'ssh_command', default => 'ssh' }, 'navicli-command:s' => { name => 'navicli_command', default => 'navicli' }, 'navicli-path:s' => { name => 'navicli_path', default => '/opt/Navisphere/bin' }, 'naviseccli-command:s' => { name => 'naviseccli_command', default => 'naviseccli' }, 'naviseccli-path:s' => { name => 'naviseccli_path', default => '/opt/Navisphere/bin' }, 'sudo:s' => { name => 'sudo', }, 'special-arg:s@' => { name => 'special_arg' }, 'hostname:s@' => { name => 'hostname' }, 'secfilepath:s@' => { name => 'secfilepath' }, 'username:s@' => { name => 'username' }, 'password:s@' => { name => 'password' }, 'scope:s@' => { name => 'scope' }, 'timeout:s@' => { name => 'timeout' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'NAVISPHERE OPTIONS', once => 1); $self->{output} = $options{output}; # 1 means we use a file to read $self->{no_navicmd} = 0; $self->{secure} = 0; return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub build_command { my ($self, %options) = @_; if ($self->{scope} !~ /^[012]$/) { $self->{output}->add_option_msg(short_msg => "Wrong scope option '" . $self->{scope} . "'."); $self->{output}->option_exit(); } $self->{cmd} = $self->{option_results}->{navicli_path} . '/' . $self->{option_results}->{navicli_command}; if (defined($self->{username}) || defined($self->{secfilepath})) { $self->{cmd} = $self->{option_results}->{naviseccli_path} . '/' . $self->{option_results}->{naviseccli_command}; $self->{secure} = 1; } if (defined($self->{secfilepath})) { if (!(-x $self->{secfilepath} && -e $self->{secfilepath} . "/SecuredCLISecurityFile.xml" && -e $self->{secfilepath} . "/SecuredCLIXMLEncrypted.key")) { $self->{output}->add_option_msg(short_msg => 'The secfilepath ' . $self->{secfilepath} . ' does not exist or SecuredCLI files are not created.'); $self->{output}->option_exit(); } } elsif (defined($self->{username})) { if (!defined($self->{password})) { $self->{output}->add_option_msg(short_msg => 'Need to specify password option.'); $self->{output}->option_exit(); } } if (! -e $self->{cmd}) { $self->{output}->add_option_msg(short_msg => "Command '" . $self->{cmd} . "' not exist or executable."); $self->{output}->option_exit(); } if (defined($self->{special_arg}) && $self->{special_arg} ne '') { $self->{cmd} .= ' ' . $self->{special_arg}; $self->{no_navicmd} = 1; # It's ok if we use a file. $self->{secure} = 1; return ; } if (!defined($self->{hostname})) { $self->{output}->add_option_msg(short_msg => "Need to specify hostname option."); $self->{output}->option_exit(); } if (defined($self->{secfilepath})) { $self->{cmd} .= " -Secfilepath '" . $self->{secfilepath} . "'"; } elsif (defined($self->{username})) { $self->{cmd} .= " -User '" . $self->{username} . "' -Password '" . $self->{password} . "' -Scope " . $self->{scope}; } $self->{cmd} .= ' -t ' . $self->{timeout}; $self->{cmd} .= ' -h ' . $self->{hostname}; } sub check_options { my ($self, %options) = @_; # return 1 = ok still hostname # return 0 = no hostname left $self->{hostname} = (defined($self->{option_results}->{hostname})) ? shift(@{$self->{option_results}->{hostname}}) : undef; $self->{secfilepath} = (defined($self->{option_results}->{secfilepath})) ? shift(@{$self->{option_results}->{secfilepath}}) : undef; $self->{username} = (defined($self->{option_results}->{username})) ? shift(@{$self->{option_results}->{username}}) : undef; $self->{password} = (defined($self->{option_results}->{password})) ? shift(@{$self->{option_results}->{password}}) : undef; $self->{scope} = (defined($self->{option_results}->{scope})) ? shift(@{$self->{option_results}->{scope}}) : 0; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? shift(@{$self->{option_results}->{timeout}}) : 30; $self->{special_arg} = (defined($self->{option_results}->{special_arg})) ? shift(@{$self->{option_results}->{special_arg}}) : undef; $self->{sudo} = $self->{option_results}->{sudo}; $self->build_command(); if (!defined($self->{hostname}) || scalar(@{$self->{option_results}->{hostname}}) == 0) { return 0; } return 1; } ############## # Specific methods ############## sub execute_command { my ($self, %options) = @_; if ($self->{no_navicmd} == 0) { $self->{cmd} .= ' ' . $options{cmd}; } if (defined($options{secure_only}) && $options{secure_only} == 1 && $self->{secure} != 1) { $self->{output}->add_option_msg(short_msg => "Mode only works with naviseccli."); $self->{output}->option_exit(); } # Need to set timeout over command. $self->{option_results}->{timeout} = $self->{timeout} + 5; return centreon::plugins::misc::execute( output => $self->{output}, options => $self->{option_results}, sudo => $self->{sudo}, command => $self->{cmd}, command_path => undef, command_options => undef ); } 1; __END__ =head1 NAME Navisphere =head1 SYNOPSIS my navisphere manage =head1 NAVISPHERE OPTIONS =over 8 =item B<--remote> Execute command remotely in 'ssh'. =item B<--ssh-address> Specify ssh address target (default: use hostname option) =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<--navicli-path> Specify navicli path (default: '/opt/Navisphere/bin') =item B<--navicli-command> Specify navicli command (default: 'navicli'). =item B<--naviseccli-path> Specify naviseccli path (default: '/opt/Navisphere/bin') =item B<--naviseccli-command> Specify naviseccli command (default: 'naviseccli'). =item B<--sudo> Use 'sudo' to execute the command. =item B<--special-arg> Set a special argument for the command. To be used for set a file. (Need to change command and use 'cat' instead). =item B<--hostname> Emc Clariion/VNX SP Hostname. =item B<--secfilepath> Set directory with security files (username and password not needed. Will use 'naviseccli'). =item B<--username> Username to connect (will use 'naviseccli'). =item B<--password> Password to connect (will use 'naviseccli'). =item B<--scope> User scope to connect (will use 'naviseccli'. Default: '0' (global)). =item B<--timeout> Set timeout for system command (Default: '30'). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/centreon/common/emc/navisphere/mode/000077500000000000000000000000001417000230700241755ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/emc/navisphere/mode/cache.pm000066400000000000000000000175401417000230700256050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::emc::navisphere::mode::cache; use base qw(centreon::plugins::mode); use strict; use warnings; my %states = ( read_cache => [ ['^enabled$' , 'OK'], ['^disabling$' , 'CRITICAL'], ['^disabled$' , 'CRITICAL'], ['^.*$' , 'CRITICAL'], ], write_cache => [ ['^enabled$' , 'OK'], ['^disabled$' , 'CRITICAL'], ['^enabling$' , 'OK'], ['^initializing$' , 'WARNING'], ['^dumping$' , 'CRITICAL'], ['^frozen$' , 'CRITICAL'], ['^.*$' , 'CRITICAL'], ], write_mirror => [ ['^yes$' , 'OK'], ['^.*$' , 'CRITICAL'], ], ); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "cache-command:s" => { name => 'cache_command', default => 'getcache' }, "cache-options:s" => { name => 'cache_options', default => '-pdp -state -mirror' }, "threshold-overload:s@" => { name => 'threshold_overload' }, "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(); } $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 ($label, $filter, $threshold) = ($1, $2, $3); if ($self->{output}->is_litteral_status(status => $threshold) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong threshold-overload status '" . $val . "'."); $self->{output}->option_exit(); } $self->{overload_th}->{$label} = {} if (!defined($self->{overload_th}->{$label})); $self->{overload_th}->{$label}->{$filter} = $threshold; } } sub get_severity { my ($self, %options) = @_; my $status = 'unknown'; foreach my $entry (@{$states{$options{label}}}) { if ($options{value} =~ /${$entry}[0]/i) { $status = ${$entry}[1]; foreach my $filter (keys %{$self->{overload_th}->{$options{label}}}) { if (${$entry}[0] =~ /$filter/i) { $status = $self->{overload_th}->{$options{label}}->{$filter}; last; } } last; } } return $status; } sub run { my ($self, %options) = @_; my $clariion = $options{custom}; #Prct Dirty Cache Pages = 0 #SP Read Cache State Enabled #SP Write Cache State Enabled #Write Cache Mirrored: YES my $response = $clariion->execute_command(cmd => $self->{option_results}->{cache_command} . ' ' . $self->{option_results}->{cache_options}); chomp $response; my ($read_cache_state, $write_cache_state); if ($response !~ /^SP Read Cache State(\s+|:\s+)(.*)/im) { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => 'Cannot find cache informations.'); $self->{output}->display(); $self->{output}->exit(); } $read_cache_state = $2; $response =~ /^SP Write Cache State(\s+|:\s+)(.*)\s*$/im; $write_cache_state = $2; my ($write_cache_mirror, $dirty_prct); if ($response =~ /^Write Cache Mirrored:\s+(.*)\s*$/im) { $write_cache_mirror = $1; } if ($response =~ /^Prct.*?=\s+(\S+)/im) { $dirty_prct = $1; } $self->{output}->output_add(severity => $self->get_severity(value => $read_cache_state, label => 'read_cache'), short_msg => sprintf("Read cache state is '%s'", $read_cache_state)); $self->{output}->output_add(severity => $self->get_severity(value => $write_cache_state, label => 'write_cache'), short_msg => sprintf("Write cache state is '%s'", $write_cache_state)); if (defined($write_cache_mirror)) { $self->{output}->output_add(severity => $self->get_severity(value => $write_cache_mirror, label => 'write_mirror'), short_msg => sprintf("Write cache mirror is '%s'", $write_cache_mirror)); } if (defined($dirty_prct)) { my $exit = $self->{perfdata}->threshold_check(value => $dirty_prct, 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("Dirty Cache Pages is %s %%", $dirty_prct)); } $self->{output}->perfdata_add(label => 'dirty_cache', unit => '%', value => $dirty_prct, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0, max => 100); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check status of the read and write cache. =over 8 =item B<--cache-command> Set cache command (Default: 'getcache'). =item B<--cache-options> Set option for cache command (Default: '-pdp -state -mirror'). =item B<--warning> Threshold warning in percent (for dirty cache). =item B<--critical> Threshold critical in percent (for dirty cache). =item B<--threshold-overload> Set to overload default threshold value. Example: --threshold-overload='read_cache:(enabled)=critical' =back =cut centreon-plugins-20220113/centreon/common/emc/navisphere/mode/controller.pm000066400000000000000000000105131417000230700267160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::emc::navisphere::mode::controller; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); sub custom_busy_calc { my ($self, %options) = @_; my $diff_busy = ($options{new_datas}->{$self->{instance} . '_busy_ticks'} - $options{old_datas}->{$self->{instance} . '_busy_ticks'}); my $total = $diff_busy + ($options{new_datas}->{$self->{instance} . '_idle_ticks'} - $options{old_datas}->{$self->{instance} . '_idle_ticks'}); if ($total == 0) { $self->{error_msg} = "skipped"; return -2; } $self->{result_values}->{busy_prct} = $diff_busy * 100 / $total; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -2 => 1, -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'read-iops', nlabel => 'controller.io.read.usage.iops', set => { key_values => [ { name => 'read', per_second => 1 } ], output_template => 'Read IOPs : %.2f', perfdatas => [ { template => '%.2f', unit => 'iops', min => 0 } ] } }, { label => 'write-iops', nlabel => 'controller.io.write.usage.iops', set => { key_values => [ { name => 'write', per_second => 1 } ], output_template => 'Write IOPs : %.2f', perfdatas => [ { template => '%.2f', unit => 'iops', min => 0 } ] } }, { label => 'busy', nlabel => 'controller.busy.usage.percentage', set => { key_values => [ { name => 'idle_ticks', diff => 1 }, { name => 'busy_ticks', diff => 1 } ], closure_custom_calc => $self->can('custom_busy_calc'), output_template => 'Busy : %.2f %%', output_use => 'busy_prct', threshold_use => 'busy_prct', perfdatas => [ { value => 'busy_prct', template => '%.2f', unit => '%', min => 0, max => 100 } ] } } ]; } sub prefix_global_output { my ($self, %options) = @_; return "Global Controller "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $response = $options{custom}->execute_command(cmd => 'getcontrol -cbt -busy -write -read -idle'); $self->{global} = {}; $self->{global}->{read} = $response =~ /^Total Reads:\s*(\d+)/msi ? $1 : undef; $self->{global}->{write} = $response =~ /^Total Writes:\s*(\d+)/msi ? $1 : undef;; $self->{global}->{idle_ticks} = $response =~ /^Controller idle ticks:\s*(\d+)/msi ? $1 : undef; $self->{global}->{busy_ticks} = $response =~ /^Controller busy ticks:\s*(\d+)/msi ? $1 : undef; $self->{cache_name} = "cache_clariion_" . $options{custom}->{hostname} . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check global controller (busy usage, iops). =over 8 =item B<--warning-*> Threshold warning. Can be: 'busy', 'read-iops', 'write-iops'. =item B<--critical-*> Threshold critical. Can be: 'busy', 'read-iops', 'write-iops'. =back =cut centreon-plugins-20220113/centreon/common/emc/navisphere/mode/disk.pm000066400000000000000000000225141417000230700254710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::emc::navisphere::mode::disk; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use Digest::MD5 qw(md5_hex); my @states = ( ['^enabled$' , 'OK'], ['^binding$' , 'OK'], ['^expanding$' , 'OK'], ['^ready$' , 'OK'], ['^unbound$' , 'OK'], ['^empty$' , 'OK'], ['^hot spare ready$' , 'OK'], ['^powering up$' , 'OK'], ['^requested bypass$', 'WARNING'], ['^equalizing$' , 'WARNING'], ['^formatting$' , 'WARNING'], ['^removed$' , 'WARNING'], ['^unformatted$' , 'WARNING'], ['^failed$' , 'CRITICAL'], ['^off$' , 'CRITICAL'], ['^unsupported$' , 'CRITICAL'], ['^.*$' , 'CRITICAL'], ); sub custom_threshold_check { my ($self, %options) = @_; foreach (@states) { if ($self->{result_values}->{state} =~ /$_->[0]/i) { return $_->[1]; } } return 'ok'; } sub custom_state_output { my ($self, %options) = @_; my $msg = sprintf("state is '%s'", $self->{result_values}->{state}); return $msg; } sub custom_state_calc { my ($self, %options) = @_; $self->{result_values}->{state} = $options{new_datas}->{$self->{instance} . '_state'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub custom_utils_calc { my ($self, %options) = @_; my $diff_busy = $options{new_datas}->{$self->{instance} . '_busy_ticks'} - $options{old_datas}->{$self->{instance} . '_busy_ticks'}; my $diff_idle = $options{new_datas}->{$self->{instance} . '_idle_ticks'} - $options{old_datas}->{$self->{instance} . '_idle_ticks'}; if (($diff_busy + $diff_idle) == 0) { $self->{error_msg} = "wait new values"; return -3; } $self->{result_values}->{utils} = $diff_busy * 100 / ($diff_busy + $diff_idle); $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; 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 => 'state', threshold => 0, set => { key_values => [ { name => 'state' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_state_calc'), closure_custom_output => $self->can('custom_state_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => $self->can('custom_threshold_check'), } }, { label => 'hard-read-errors', set => { key_values => [ { name => 'hard_read_errors', diff => 1 }, { name => 'display' } ], output_template => 'Hard Read Errors : %d', perfdatas => [ { label => 'hard_read_errors', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'hard-write-errors', set => { key_values => [ { name => 'hard_write_errors', diff => 1 }, { name => 'display' } ], output_template => 'Hard Write Errors : %d', perfdatas => [ { label => 'hard_write_errors', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'read-io', set => { key_values => [ { name => 'read_io', per_second => 1 }, { name => 'display' } ], output_template => 'Read I/O : %s %s/s', output_change_bytes => 1, perfdatas => [ { label => 'read_io', template => '%s', min => 0, unit => 'B/s', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'write-io', set => { key_values => [ { name => 'write_io', per_second => 1 }, { name => 'display' } ], output_template => 'Write I/O : %s %s/s', output_change_bytes => 1, perfdatas => [ { label => 'write_io', template => '%s', min => 0, unit => 'B/s', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'utils', set => { key_values => [ { name => 'busy_ticks', diff => 1 }, { name => 'idle_ticks', diff => 1 }, { name => 'display' } ], closure_custom_calc => $self->can('custom_utils_calc'), output_template => 'Utils : %.2f %%', output_use => 'utils', perfdatas => [ { label => 'utils', value => 'utils', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub prefix_disk_output { my ($self, %options) = @_; return "Disk '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-raidgroupid:s' => { name => 'filter_raidgroupid', }, 'filter-disk:s' => { name => 'filter_disk', }, }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{disk} = {}; $self->{cache_name} = "cache_clariion_" . $options{custom}->{hostname} . '_' . $options{custom}->{mode} . '_' . (defined($self->{option_results}->{filter_disk}) ? md5_hex($self->{option_results}->{filter_disk}) : md5_hex('all')); my $response = $options{custom}->execute_command(cmd => 'getdisk -state -bytrd -bytwrt -hw -hr -busyticks -idleticks -rg'); #Bus 1 Enclosure 7 Disk 13 #State: Enabled #Kbytes Read: 1109878030 #Kbytes Written: 0 #Hard Write Errors: 0 #Hard Read Errors: 0 #Busy Ticks: 462350 #Idle Ticks: 388743630 #Raid Group ID: 0 # Add a "\n" for the end. $response .= "\n"; while ($response =~ /^Bus\s+(\S+)\s+Enclosure\s+(\S+)\s+Disk\s+(\S+)(.*?)\n\n/msgi) { my $disk_instance = "$1_$2_$3"; my $values = $4; # First Filters if (defined($self->{option_results}->{filter_disk}) && $self->{option_results}->{filter_disk} ne '' && $disk_instance !~ /$self->{option_results}->{filter_disk}/) { $self->{output}->output_add(long_msg => "skipping disk '" . $disk_instance . "': no matching filter disk", debug => 1); next; } if (defined($self->{option_results}->{filter_raidgroupid}) && $self->{option_results}->{filter_raidgroupid} ne '' && $values =~ /^Raid Group ID:\s+(\S+)/mi && $1 !~ /$self->{option_results}->{filter_raidgroupid}/) { $self->{output}->output_add(long_msg => "skipping disk '" . $disk_instance . "': no matching filter raid group id", debug => 1); next; } my $datas = {}; while ($values =~ /^([^\n]*?):(.*?)\n/msgi) { $datas->{centreon::plugins::misc::trim(lc($1))} = centreon::plugins::misc::trim($2); } $self->{disk}->{$disk_instance} = { display => $disk_instance, state => $datas->{state}, hard_read_errors => $datas->{'hard read errors'}, hard_write_errors => $datas->{'hard write errors'}, read_io => defined($datas->{'kbytes read'}) ? $datas->{'kbytes read'} * 1024 : undef, write_io => defined($datas->{'kbytes write'}) ? $datas->{'kbytes write'} * 1024 : undef, busy_ticks => $datas->{'busy ticks'}, idle_ticks => $datas->{'idle ticks'}, }; } } 1; __END__ =head1 MODE Check the status of the physical disks. =over 8 =item B<--warning-*> Threshold warning. Can be: 'read-errors', 'write-errors', 'read-io', 'write-io', 'utils'. =item B<--critical-*> Threshold critical. Can be: 'read-errors', 'write-errors', 'read-io', 'write-io', 'utils'. =item B<--filter-disk> Filter Disk (regexp can be used). Example: 1_7_14 ([BUS]_[ENCLOSURE]_[DISK]). =item B<--filter-raidgroupid> Filter Raid Group ID (regexp can be used). Example: N/A or a number. =back =cut centreon-plugins-20220113/centreon/common/emc/navisphere/mode/faults.pm000066400000000000000000000037731417000230700260430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::emc::navisphere::mode::faults; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my $clariion = $options{custom}; my $response = $clariion->execute_command(cmd => 'faults -list', secure_only => 1); chomp $response; if ($response =~ /The array is operating normally/msg) { $self->{output}->output_add(severity => 'ok', short_msg => 'The array is operating normally'); } else { $self->{output}->output_add(long_msg => $response); $self->{output}->output_add(severity => 'critical', short_msg => 'Problem detected (see detailed output for more details'); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Detect faults on the array. =over 8 =back =cut centreon-plugins-20220113/centreon/common/emc/navisphere/mode/hbastate.pm000066400000000000000000000152071417000230700263330ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::emc::navisphere::mode::hbastate; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-server:s" => { name => 'filter_server' }, "filter-uid:s" => { name => 'filter_uid' }, "path-status:s@" => { name => 'path_status' }, }); $self->{total_hba} = 0; $self->{total_hba_noskip} = 0; return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{path_status}) || scalar(@{$self->{option_results}->{path_status}}) == 0) { $self->{output}->add_option_msg(short_msg => "Need to set --path-status option."); $self->{output}->option_exit(); } my $i = 0; foreach (@{$self->{option_results}->{path_status}}) { my ($warning, $critical, $filter_uid, $filter_server) = split /,/; if (!defined($filter_uid) && !defined($filter_server)) { $self->{output}->add_option_msg(short_msg => "Need to set a filter in --path-status '" . $_ . "' option."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'warning-' . $i, value => $warning)) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning threshold '" . $warning . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'critical-' . $i, value => $critical)) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical threshold '" . $critical . "'."); $self->{output}->option_exit(); } $i++; } } sub check_hba { my ($self, %options) = @_; my @result = split /Information about each HBA/i, $self->{response}; foreach (@result) { my $hba_infos = $_; # Not in hba section. we move. next if ($hba_infos !~ /^HBA UID:\s*(\S*)/mi); my $hba_uid = $1; $hba_infos =~ /^Server Name:\s*(.*?)\s*$/mi; my $server_name = $1; $self->{total_hba}++; if (defined($self->{option_results}->{filter_server}) && $self->{option_results}->{filter_server} ne '' && $server_name !~ /$self->{option_results}->{filter_server}/) { $self->{output}->output_add(long_msg => "Skipping hba '$hba_uid' server '$server_name'"); next; } if (defined($self->{option_results}->{filter_uid}) && $self->{option_results}->{filter_uid} ne '' && $hba_uid !~ /$self->{option_results}->{filter_uid}/) { $self->{output}->output_add(long_msg => "Skipping hba '$hba_uid' server '$server_name'"); next; } $self->{total_hba_noskip}++; $self->{output}->output_add(long_msg => "Checking hba '$hba_uid' server '$server_name'"); my $not_logged = 0; my $logged = 0; while ($hba_infos =~ /(SP Name:.*?)(\n\n|\Z)/msig) { my $port_infos = $1; # Not in good section next if ($port_infos !~ /HBA Devicename:/mi); $port_infos =~ /SP Name:\s*(.*?)\s*$/mi; my $port_name = $1; $port_infos =~ /SP Port ID:\s*(.*?)\s*$/mi; my $port_id = $1; $port_infos =~ /Logged In:\s*(.*?)\s*$/mi; my $logged_in = $1; if ($logged_in !~ /YES/i) { $not_logged++; } else { $logged++; } $self->{output}->output_add(long_msg => " port [sp name: $port_name] [sp port id: $port_id] logged is $logged_in"); } # Do the checking my $i = -1; foreach (@{$self->{option_results}->{path_status}}) { my ($warning, $critical, $filter_uid, $filter_server) = split /,/; $i++; next if (defined($filter_uid) && $filter_uid ne '' && $hba_uid !~ /$filter_uid/); next if (defined($filter_server) && $filter_server ne '' && $server_name !~ /$filter_server/); my $exit = $self->{perfdata}->threshold_check(value => $logged, threshold => [ { label => 'critical-' . $i, 'exit_litteral' => 'critical' }, { label => 'warning-' . $i, exit_litteral => 'warning' } ]); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => "Path connection problem for hba '$hba_uid' server '$server_name'"); } last; } } } sub run { my ($self, %options) = @_; my $clariion = $options{custom}; $self->{response} = $clariion->execute_command(cmd => 'getall -hba'); chomp $self->{response}; $self->check_hba(); $self->{output}->output_add(severity => 'OK', short_msg => sprintf("All hba states (%s/%s) are ok.", $self->{total_hba_noskip}, $self->{total_hba}) ); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check connection state of servers. =over 8 =item B<--filter-server> Set server to check (not set, means 'all'). =item B<--filter-uid> Set hba uid to check (not set, means 'all'). =item B<--path-status> Set how much path must be connected (Can be multiple). Syntax: [WARNING],[CRITICAL],filter_uid,filter_server Example: ,@0:1,.*,.* - Means all server must have at least two paths connected. =back =cutcentreon-plugins-20220113/centreon/common/emc/navisphere/mode/listluns.pm000066400000000000000000000162001417000230700264070ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::emc::navisphere::mode::listluns; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-lunnumber:s" => { name => 'filter_lunnumber', }, "filter-lunstate:s" => { name => 'filter_lunstate', }, "filter-drivetype:s" => { name => 'filter_drivetype', }, "filter-raidtype:s" => { name => 'filter_raidtype', }, "filter-raidgroupid:s" => { name => 'filter_raidgroupid', }, }); $self->{result} = {}; return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; my $response = $self->{clariion}->execute_command(cmd => 'getlun -uid -state -rg -type -drivetype -capacity'); $| = 1; while ($response =~ /^(LOGICAL UNIT NUMBER.*?\n\n)/imsg) { #LOGICAL UNIT NUMBER 4088 #UID: 60:06:01:60:F8:C0:1E:00:58:68:46:25:C3:14:E1:11 #State: Bound #RAIDGroup ID: 14 #RAID Type: RAID5 #Drive Type: SATAII #LUN Capacity(Megabytes): 2817458 #LUN Capacity(Blocks): 5770154496 #LOGICAL UNIT NUMBER 11 #UID: 60:06:01:60:F8:C0:1E:00:FA:01:AE:2B:27:AF:E3:11 #State: Bound #RAIDGroup ID: N/A #RAID Type: N/A #Drive Type: N/A #LUN Capacity(Megabytes): 6339281 #LUN Capacity(Blocks): 12982847616 my $content = $1; my ($lun_num, $raid_type, $raid_group_id, $drive_type, $state); $lun_num = $1 if ($content =~ /^LOGICAL UNIT NUMBER\s+(\d+)/im); $state = $1 if ($content =~ /^State:\s+(.*)$/im); $raid_type = $1 if ($content =~ /^RAID Type:\s+(.*)$/im); $raid_group_id = $1 if ($content =~ /^RAIDGroup ID:\s+(.*)$/im); $drive_type = $1 if ($content =~ /^Drive Type:\s+(.*)$/im); if (defined($self->{option_results}->{filter_lunnumber}) && $self->{option_results}->{filter_lunnumber} ne '' && $lun_num !~ /$self->{option_results}->{filter_lunnumber}/) { $self->{output}->output_add(long_msg => "Skipping lun '" . $lun_num . "': no matching filter lun number"); next; } if (defined($self->{option_results}->{filter_lunstate}) && $self->{option_results}->{filter_lunstate} ne '' && $state !~ /$self->{option_results}->{filter_lunstate}/) { $self->{output}->output_add(long_msg => "Skipping lun '" . $lun_num . "': no matching filter lun state"); next; } if (defined($self->{option_results}->{filter_drivetype}) && $self->{option_results}->{filter_drivetype} ne '' && $drive_type !~ /$self->{option_results}->{filter_drivetype}/) { $self->{output}->output_add(long_msg => "Skipping lun '" . $lun_num . "': no matching filter lun drive type"); next; } if (defined($self->{option_results}->{filter_raidtype}) && $self->{option_results}->{filter_raidtype} ne '' && $raid_type !~ /$self->{option_results}->{filter_raidtype}/) { $self->{output}->output_add(long_msg => "Skipping lun '" . $lun_num . "': no matching filter lun raid type"); next; } if (defined($self->{option_results}->{filter_raidgroupid}) && $self->{option_results}->{filter_raidgroupid} ne '' && $raid_group_id !~ /$self->{option_results}->{filter_raidgroupid}/) { $self->{output}->output_add(long_msg => "Skipping lun '" . $lun_num . "': no matching filter lun raid group id"); next; } $self->{result}->{$lun_num} = {state => $state, drive_type => $drive_type, raid_type => $raid_type, raid_groupid => $raid_group_id}; } } sub run { my ($self, %options) = @_; $self->{clariion} = $options{custom}; $self->manage_selection(); foreach my $num (sort(keys %{$self->{result}})) { $self->{output}->output_add(long_msg => "'" . $num . "' [state = " . $self->{result}->{$num}->{state} . '] [drive type = ' . $self->{result}->{$num}->{drive_type} . '] [raid type = ' . $self->{result}->{$num}->{raid_type} . '] [raid groupid = ' . $self->{result}->{$num}->{raid_groupid} . ']'); } $self->{output}->output_add(severity => 'OK', short_msg => 'List LUNs:'); $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 => ['number', 'state', 'drive_type', 'raid_type', 'raid_groupid']); } sub disco_show { my ($self, %options) = @_; $self->{clariion} = $options{custom}; $self->manage_selection(); foreach my $num (sort(keys %{$self->{result}})) { $self->{output}->add_disco_entry(number => $num, state => $self->{result}->{$num}->{state}, drive_type => $self->{result}->{$num}->{drive_type}, raid_type => $self->{result}->{$num}->{raid_type}, raid_groupid => $self->{result}->{$num}->{raid_groupid}, ); } } 1; __END__ =head1 MODE List Logical Units (LUNs). =over 8 =item B<--filter-lunnumber> Filter Lun Number (regexp can be used). =item B<--filter-lunstate> Filter Lun State (regexp can be used). Example: Bound, Faulted, Expanding,... =item B<--filter-drivetype> Filter Drive types (regexp can be used). Example: N/A, SATAII, Fibre Channel,... =item B<--filter-raidtype> Filter Raid types (regexp can be used). Example: N/A, Hot Spare, RAID5,... =item B<--filter-raidgroupid> Filter Raid Group ID (regexp can be used). Example: N/A or a number. =back =cut centreon-plugins-20220113/centreon/common/emc/navisphere/mode/portstate.pm000066400000000000000000000110601417000230700265560ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::emc::navisphere::mode::portstate; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "filter-id:s" => { name => 'filter_id' }, }); $self->{total_port} = 0; $self->{total_port_noskip} = 0; return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub check_port { my ($self, %options) = @_; if ($self->{response} =~ /Information about each SPPORT:(.*)/msi) { my $port_infos = $1; while ($port_infos =~ /(SP Name:.*?)(\n\n|\Z)/msig) { my $port_infos = $1; # Not in good section next if ($port_infos !~ /Switch Present:/mi); $port_infos =~ /SP Name:\s*(.*?)\s*$/mi; my $port_name = $1; $port_infos =~ /SP Port ID:\s*(.*?)\s*$/mi; my $port_id = $1; $port_infos =~ /Link Status:\s*(.*?)\s*$/mi; my $link_status = $1; $port_infos =~ /Port Status:\s*(.*?)\s*$/mi; my $port_status = $1; $self->{total_port}++; if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $port_name !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "Skipping SP $port_name port $port_id [link status: $link_status] [port status: $port_status]"); next; } if (defined($self->{option_results}->{filter_id}) && $self->{option_results}->{filter_id} ne '' && $port_id !~ /$self->{option_results}->{filter_id}/) { $self->{output}->output_add(long_msg => "Skipping SP $port_name port $port_id [link status: $link_status] [port status: $port_status]"); next; } $self->{total_port_noskip}++; $self->{output}->output_add(long_msg => "Checking SP $port_name port $port_id [link status: $link_status] [port status: $port_status]"); my ($error, $error_append) = ('', ''); if ($port_status !~ /Online|Enabled/i) { $error = "port status is '" . $port_status . "'"; $error_append = ', '; } if ($link_status !~ /Up/i) { $error .= $error_append . "link status is '" . $link_status . "'"; } if ($error ne '') { $self->{output}->output_add(severity => 'CRITICAL', short_msg => sprintf("SP %s port %s: %s.", $port_name, $port_id, $error) ); } } } } sub run { my ($self, %options) = @_; my $clariion = $options{custom}; $self->{response} = $clariion->execute_command(cmd => 'getall -hba'); chomp $self->{response}; $self->check_port(); $self->{output}->output_add(severity => 'OK', short_msg => sprintf("All ports (%s/%s) are ok.", $self->{total_port_noskip}, $self->{total_port}) ); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check SP port states. =over 8 =item B<--filter-name> Set SP Name to check (not set, means 'all'). =item B<--filter-id> Set SP port ID to check (not set, means 'all'). =back =cutcentreon-plugins-20220113/centreon/common/emc/navisphere/mode/sp.pm000066400000000000000000000066561417000230700251720ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::emc::navisphere::mode::sp; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{cb_hook2} = 'navisphere_execute'; $self->{thresholds} = { battery => [ ['^(Not Ready|Testing|Unknown)$', 'WARNING'], ['^(?!(Present|Valid)$)', 'CRITICAL'], ['.*', 'OK'], ], psu => [ ['^(?!(Present|Valid)$)', 'CRITICAL'], ['.*', 'OK'], ], sp => [ ['^(?!(Present|Valid)$)', 'CRITICAL'], ['.*', 'OK'], ], cable => [ ['^(.*Unknown.*)$' => 'WARNING'], ['^(?!(Present|Valid)$)' => 'CRITICAL'], ['.*', 'OK'], ], cpu => [ ['^(?!(Present|Valid)$)' => 'CRITICAL'], ['.*', 'OK'], ], fan => [ ['^(?!(Present|Valid)$)' => 'CRITICAL'], ['.*', 'OK'], ], io => [ ['^(?!(Present|Valid|Empty)$)' => 'CRITICAL'], ['.*', 'OK'], ], lcc => [ ['^(?!(Present|Valid)$)' => 'CRITICAL'], ['.*', 'OK'], ], dimm => [ ['^(?!(Present|Valid)$)' => 'CRITICAL'], ['.*', 'OK'], ], }; $self->{components_path} = 'centreon::common::emc::navisphere::mode::spcomponents'; $self->{components_module} = ['fan', 'lcc', 'psu', 'battery', 'memory', 'cpu', 'iomodule', 'cable']; } sub navisphere_execute { my ($self, %options) = @_; $self->{response} = $options{custom}->execute_command(cmd => 'getcrus ' . $self->{option_results}->{getcrus_options}); chomp $self->{response}; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_absent => 1, no_performance => 1); bless $self, $class; $options{options}->add_options(arguments => { 'getcrus-options:s' => { name => 'getcrus_options', default => '-all' } }); return $self; } 1; __END__ =head1 MODE Check status of storage processor. =over 8 =item B<--getcrus-options> Set option for 'getcrus' command (Default: '-all'). '-all' option is for some new flare version. =item B<--component> Which component to check (Default: '.*'). Can be: 'fan', 'lcc', 'psu', 'battery', 'memory', 'cpu', 'iomodule', 'cable'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=lcc --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). =back =cut centreon-plugins-20220113/centreon/common/emc/navisphere/mode/spcomponents/000077500000000000000000000000001417000230700267255ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/emc/navisphere/mode/spcomponents/battery.pm000066400000000000000000000042571417000230700307450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::emc::navisphere::mode::spcomponents::battery; use strict; use warnings; sub load { }; sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking batteries"); $self->{components}->{battery} = {name => 'battery', total => 0, skip => 0}; return if ($self->check_filter(section => 'battery')); # SPS means = Standby Power Supply # Enclosure SPE SPS A State: Present while ($self->{response} =~ /^(?:Bus\s+(\d+)\s+){0,1}Enclosure\s+(\S+)\s+(SPS)\s+(\S+)\s+State:\s+(.*)$/mgi) { my ($state, $instance) = ($5, "$2.$3.$4"); if (defined($1)) { $instance = "$1.$2.$3.$4"; } next if ($self->check_filter(section => 'battery', instance => $instance)); $self->{components}->{battery}->{total}++; $self->{output}->output_add(long_msg => sprintf("Battery '%s' state is %s.", $instance, $state) ); my $exit = $self->get_severity(section => 'battery', value => $state); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Battery '%s' state is %s", $instance, $state)); } } } 1; centreon-plugins-20220113/centreon/common/emc/navisphere/mode/spcomponents/cable.pm000066400000000000000000000042031417000230700303300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::emc::navisphere::mode::spcomponents::cable; use strict; use warnings; sub load { }; sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking cables"); $self->{components}->{cable} = {name => 'cables', total => 0, skip => 0}; return if ($self->check_filter(section => 'cable')); # Enclosure SPE SPS A Cabling State: Valid while ($self->{response} =~ /^(?:Bus\s+(\d+)\s+){0,1}Enclosure\s+(\S+)\s+(Power|SPS)\s+(\S+)\s+Cabling\s+State:\s+(.*)$/mgi) { my ($state, $instance) = ($5, "$2.$3.$4"); if (defined($1)) { $instance = "$1.$2.$3.$4"; } next if ($self->check_filter(section => 'cable', instance => $instance)); $self->{components}->{cable}->{total}++; $self->{output}->output_add(long_msg => sprintf("cable '%s' state is %s.", $instance, $state) ); my $exit = $self->get_severity(section => 'cable', value => $state); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("cable '%s' state is %s", $instance, $state)); } } } 1;centreon-plugins-20220113/centreon/common/emc/navisphere/mode/spcomponents/cpu.pm000066400000000000000000000040101417000230700300450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::emc::navisphere::mode::spcomponents::cpu; use strict; use warnings; sub load { }; sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking cpu"); $self->{components}->{cpu} = {name => 'cpus', total => 0, skip => 0}; return if ($self->check_filter(section => 'cpu')); # Enclosure SPE CPU Module A State: Present while ($self->{response} =~ /^Enclosure\s+(\S+)\s+CPU\s+Module\s+(\S+)\s+State:\s+(.*)$/mgi) { my $instance = "$1.$2"; my $state = $3; next if ($self->check_filter(section => 'cpu', instance => $instance)); $self->{components}->{cpu}->{total}++; $self->{output}->output_add(long_msg => sprintf("cpu '%s' state is %s.", $instance, $state) ); my $exit = $self->get_severity(section => 'cpu', value => $state); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("cpu '%s' state is %s", $instance, $state)); } } } 1;centreon-plugins-20220113/centreon/common/emc/navisphere/mode/spcomponents/fan.pm000066400000000000000000000040161417000230700300300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::emc::navisphere::mode::spcomponents::fan; use strict; use warnings; sub load { }; sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking fans"); $self->{components}->{fan} = {name => 'fans', total => 0, skip => 0}; return if ($self->check_filter(section => 'fan')); # Bus 0 Enclosure 0 Fan A State: Present while ($self->{response} =~ /^Bus\s+(\d+)\s+Enclosure\s+(\d+)\s+Fan\s+(\S+)\s+State:\s+(.*)$/mgi) { my $instance = "$1.$2.$3"; my $state = $4; next if ($self->check_filter(section => 'fan', instance => $instance)); $self->{components}->{fan}->{total}++; $self->{output}->output_add(long_msg => sprintf("fan '%s' state is %s.", $instance, $state) ); my $exit = $self->get_severity(section => 'fan', value => $state); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("fan '%s' state is %s", $instance, $state)); } } } 1;centreon-plugins-20220113/centreon/common/emc/navisphere/mode/spcomponents/iomodule.pm000066400000000000000000000040711417000230700311020ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::emc::navisphere::mode::spcomponents::iomodule; use strict; use warnings; sub load { }; sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking I/O modules"); $self->{components}->{io} = {name => 'IO module', total => 0, skip => 0}; return if ($self->check_filter(section => 'io')); # Enclosure SPE SP A I/O Module 0 State: Present while ($self->{response} =~ /^Enclosure\s+(\S+)\s+SP\s+(\S+)\s+I\/O\s+Module\s+(\S+)\s+State:\s+(.*)$/mgi) { my $instance = "$1.$2.$3"; my $state = $4; next if ($self->check_filter(section => 'io', instance => $instance)); $self->{components}->{io}->{total}++; $self->{output}->output_add(long_msg => sprintf("I/O module '%s' state is %s.", $instance, $state) ); my $exit = $self->get_severity(section => 'io', value => $state); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("I/O module '%s' state is %s", $instance, $state)); } } } 1;centreon-plugins-20220113/centreon/common/emc/navisphere/mode/spcomponents/lcc.pm000066400000000000000000000040331417000230700300240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::emc::navisphere::mode::spcomponents::lcc; use strict; use warnings; sub load { }; sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking link control card"); $self->{components}->{lcc} = {name => 'lccs', total => 0, skip => 0}; return if ($self->check_filter(section => 'lcc')); # Bus 1 Enclosure 6 LCC A State: Present while ($self->{response} =~ /^Bus\s+(\d+)\s+Enclosure\s+(\d+)\s+LCC\s+(\S+)\s+State:\s+(.*)$/mgi) { my $instance = "$1.$2.$3"; my $state = $4; next if ($self->check_filter(section => 'lcc', instance => $instance)); $self->{components}->{lcc}->{total}++; $self->{output}->output_add(long_msg => sprintf("lcc '%s' state is %s.", $instance, $state) ); my $exit = $self->get_severity(section => 'lcc', value => $state); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("lcc '%s' state is %s", $instance, $state)); } } } 1;centreon-plugins-20220113/centreon/common/emc/navisphere/mode/spcomponents/memory.pm000066400000000000000000000040251417000230700305740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::emc::navisphere::mode::spcomponents::memory; use strict; use warnings; sub load { }; sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking dimm"); $self->{components}->{dimm} = {name => 'dimm', total => 0, skip => 0}; return if ($self->check_filter(section => 'dimm')); # Enclosure SPE DIMM Module A State: Present while ($self->{response} =~ /^Enclosure\s+(\S+)\s+DIMM\s+Module\s+(\S+)\s+State:\s+(.*)$/mgi) { my $instance = "$1.$2"; my $state = $3; next if ($self->check_filter(section => 'dimm', instance => $instance)); $self->{components}->{dimm}->{total}++; $self->{output}->output_add(long_msg => sprintf("Dimm '%s' state is %s.", $instance, $state) ); my $exit = $self->get_severity(section => 'dimm', value => $state); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("dimm '%s' state is %s", $instance, $state)); } } } 1;centreon-plugins-20220113/centreon/common/emc/navisphere/mode/spcomponents/psu.pm000066400000000000000000000042511417000230700300740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::emc::navisphere::mode::spcomponents::psu; use strict; use warnings; 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')); # Enclosure SPE Power A0 State: Present # Bus 0 Enclosure 0 Power A State: Present while ($self->{response} =~ /^(?:Bus\s+(\d+)\s+){0,1}Enclosure\s+(\S+)\s+(Power)\s+(\S+)\s+State:\s+(.*)$/mgi) { my ($state, $instance) = ($5, "$2.$3.$4"); if (defined($1)) { $instance = "$1.$2.$3.$4"; } next if ($self->check_filter(section => 'psu', instance => $instance)); $self->{components}->{psu}->{total}++; $self->{output}->output_add(long_msg => sprintf("Power Supply '%s' state is %s.", $instance, $state) ); my $exit = $self->get_severity(section => 'psu', value => $state); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Power Supply '%s' state is %s", $instance, $state)); } } } 1;centreon-plugins-20220113/centreon/common/emc/navisphere/mode/spcomponents/sp.pm000066400000000000000000000037241417000230700277130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::emc::navisphere::mode::spcomponents::sp; use strict; use warnings; sub load { }; sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking sp"); $self->{components}->{sp} = {name => 'sp', total => 0, skip => 0}; return if ($self->check_filter(section => 'sp')); # SP A State: Present while ($self->{response} =~ /^SP\s+(\S+)\s+State:\s+(.*)$/mgi) { my $instance = $1; my $state = $2; next if ($self->check_filter(section => 'sp', instance => $instance)); $self->{components}->{sp}->{total}++; $self->{output}->output_add(long_msg => sprintf("sp '%s' state is %s.", $instance, $state) ); my $exit = $self->get_severity(section => 'sp', value => $state); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("sp '%s' state is %s", $instance, $state)); } } } 1;centreon-plugins-20220113/centreon/common/emc/navisphere/mode/spinfo.pm000066400000000000000000000056731417000230700260440ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::emc::navisphere::mode::spinfo; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my $clariion = $options{custom}; my $response = $clariion->execute_command(cmd => 'getagent -ver -rev -prom -model -type -mem -serial -spid'); my $sp_id = 'unknown'; my $sp_agent_rev = 'unknown'; my $sp_flare_rev = 'unknown'; my $sp_prom_rev = 'unknown'; my $sp_model = 'unknown'; my $sp_model_type = 'unknown'; my $sp_memory_total = 'unknown'; my $sp_serial_number = 'unknown'; $sp_id = $1 if ($response =~ /^SP Identifier:\s+(.*)$/im); $sp_agent_rev = $1 if ($response =~ /^Agent Rev:\s+(.*)$/im); $sp_flare_rev = $1 if ($response =~ /^Revision:\s+(.*)$/im); $sp_prom_rev = $1 if ($response =~ /^Prom Rev:\s+(.*)$/im); $sp_model = $1 if ($response =~ /^Model:\s+(.*)$/im); $sp_model_type = $1 if ($response =~ /^Model Type:\s+(.*)$/im); $sp_memory_total = ($1 * 1024 * 1024) if ($response =~ /^SP Memory:\s+(.*)$/im); $sp_serial_number = $1 if ($response =~ /^Serial No:\s+(.*)$/im); my ($memory_value, $memory_unit) = $self->{perfdata}->change_bytes(value => $sp_memory_total); $self->{output}->output_add(severity => 'ok', short_msg => sprintf('[SP ID: %s] [Agent Revision: %s] [FLARE Revision: %s] [PROM Revision: %s] [Model: %s, %s] [Memory: %s %s] [Serial Number: %s]', $sp_id, $sp_agent_rev, $sp_flare_rev, $sp_prom_rev, $sp_model, $sp_model_type, $memory_value, $memory_unit, $sp_serial_number)); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Display informations on the storage processor. =over 8 =back =cut centreon-plugins-20220113/centreon/common/force10/000077500000000000000000000000001417000230700216005ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/force10/snmp/000077500000000000000000000000001417000230700225555ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/force10/snmp/mode/000077500000000000000000000000001417000230700235015ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/force10/snmp/mode/components/000077500000000000000000000000001417000230700256665ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/force10/snmp/mode/components/fan.pm000066400000000000000000000066101417000230700267730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::force10::snmp::mode::components::fan; use strict; use warnings; my $map_status = { 1 => 'up', 2 => 'down', 3 => 'absent' }; my $mapping = { sseries => { status => { oid => '.1.3.6.1.4.1.6027.3.10.1.2.4.1.2', map => $map_status } # chSysFanTrayOperStatus }, mseries => { status => { oid => '.1.3.6.1.4.1.6027.3.19.1.2.3.1.2', map => $map_status } # chSysFanTrayOperStatus }, zseries => { status => { oid => '.1.3.6.1.4.1.6027.3.25.1.2.7.1.2', map => $map_status } # chSysFanTrayOperStatus }, os9 => { status => { oid => '.1.3.6.1.4.1.6027.3.26.1.4.7.1.4', map => $map_status } # dellNetFanTrayOperStatus } }; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping->{sseries}->{status}->{oid} }, { oid => $mapping->{mseries}->{status}->{oid} }, { oid => $mapping->{zseries}->{status}->{oid} }, { oid => $mapping->{os9}->{status}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => 'Checking fans'); $self->{components}->{fan} = { name => 'fans', total => 0, skip => 0 }; return if ($self->check_filter(section => 'fan')); foreach my $name (keys %$mapping) { foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{ $mapping->{$name}->{status}->{oid} }})) { next if ($oid !~ /^$mapping->{$name}->{status}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping->{$name}, results => $self->{results}->{ $mapping->{$name}->{status}->{oid} }, instance => $instance); next if ($result->{status} =~ /absent/i && $self->absent_problem(section => 'fan', instance => $instance)); next if ($self->check_filter(section => 'fan', instance => $instance)); $self->{components}->{fan}->{total}++; $self->{output}->output_add( long_msg => sprintf( "fan '%s' status is '%s' [instance: %s]", $instance, $result->{status}, $instance ) ); my $exit = $self->get_severity(section => 'fan', value => $result->{status}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Fan '%s' status is '%s'", $instance, $result->{status} ) ); } } } } 1; centreon-plugins-20220113/centreon/common/force10/snmp/mode/components/psu.pm000066400000000000000000000071431417000230700270400ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::force10::snmp::mode::components::psu; use strict; use warnings; my $map_status = { 1 => 'up', 2 => 'down', 3 => 'absent' }; my $map_mstatus = { 1 => 'normal', 2 => 'warning', 3 => 'critical', 4 => 'shutdown', 5 => 'notPresent', 6 => 'notFunctioning' }; my $mapping = { sseries => { status => { oid => '.1.3.6.1.4.1.6027.3.10.1.2.3.1.2', map => $map_status } # chSysPowerSupplyOperStatus }, mseries => { status => { oid => '.1.3.6.1.4.1.6027.3.19.1.2.2.1.2', map => $map_mstatus } # chSysPowerSupplyOperStatus }, zseries => { status => { oid => '.1.3.6.1.4.1.6027.3.25.1.2.6.1.2', map => $map_status } # chSysPowerSupplyOperStatus }, os9 => { status => { oid => '.1.3.6.1.4.1.6027.3.26.1.4.6.1.4', map => $map_status } # dellNetPowerSupplyOperStatus } }; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping->{sseries}->{status}->{oid} }, { oid => $mapping->{mseries}->{status}->{oid} }, { oid => $mapping->{zseries}->{status}->{oid} }, { oid => $mapping->{os9}->{status}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => 'Checking power supplies'); $self->{components}->{psu} = { name => 'power supplies', total => 0, skip => 0 }; return if ($self->check_filter(section => 'psu')); foreach my $name (keys %$mapping) { foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{ $mapping->{$name}->{status}->{oid} }})) { next if ($oid !~ /^$mapping->{$name}->{status}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping->{$name}, results => $self->{results}->{ $mapping->{$name}->{status}->{oid} }, instance => $instance); next if ($result->{status} =~ /absent|notPresent/i && $self->absent_problem(section => 'psu', 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' status is '%s' [instance: %s]", $instance, $result->{status}, $instance ) ); my $exit = $self->get_severity(section => 'psu', value => $result->{status}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Power supply '%s' status is '%s'", $instance, $result->{status} ) ); } } } } 1; centreon-plugins-20220113/centreon/common/force10/snmp/mode/components/stack.pm000066400000000000000000000114731417000230700273370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::force10::snmp::mode::components::stack; use strict; use warnings; my $map_unit_status = { 1 => 'ok', 2 => 'unsupported', 3 => 'codeMismatch', 4 => 'configMismatch', 5 => 'unitDown', 6 => 'notPresent' }; my $mapping = { sseries => { status => { oid => '.1.3.6.1.4.1.6027.3.10.1.2.2.1.8', map => $map_unit_status }, # chStackUnitStatus temperature => { oid => '.1.3.6.1.4.1.6027.3.10.1.2.2.1.14' } # chStackUnitTemp }, mseries => { status => { oid => '.1.3.6.1.4.1.6027.3.19.1.2.1.1.8', map => $map_unit_status }, # chStackUnitStatus temperature => { oid => '.1.3.6.1.4.1.6027.3.19.1.2.1.1.14' } # chStackUnitTemp }, os9 => { status => { oid => '.1.3.6.1.4.1.6027.3.26.1.3.4.1.8', map => $map_unit_status }, # dellNetStackUnitStatus temperature => { oid => '.1.3.6.1.4.1.6027.3.26.1.3.4.1.13' } # dellNetStackUnitTemp } }; my $stack_table = { sseries => '.1.3.6.1.4.1.6027.3.10.1.2.2.1', mseries => '.1.3.6.1.4.1.6027.3.19.1.2.1.1', os9 => '.1.3.6.1.4.1.6027.3.26.1.3.4.1' }; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $stack_table->{sseries}, start => $mapping->{sseries}->{status}->{oid}, end => $mapping->{sseries}->{temperature}->{oid} }, { oid => $stack_table->{mseries}, start => $mapping->{mseries}->{status}->{oid}, end => $mapping->{mseries}->{temperature}->{oid} }, { oid => $stack_table->{os9}, start => $mapping->{os9}->{status}->{oid}, end => $mapping->{os9}->{temperature}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => 'Checking stack'); $self->{components}->{stack} = { name => 'stack', total => 0, skip => 0 }; return if ($self->check_filter(section => 'stack')); foreach my $name (keys %$stack_table) { foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{ $stack_table->{$name} }})) { next if ($oid !~ /^$mapping->{$name}->{status}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping->{$name}, results => $self->{results}->{ $stack_table->{$name} }, instance => $instance); next if ($result->{status} =~ /absent/i && $self->absent_problem(section => 'stack', instance => $instance)); next if ($self->check_filter(section => 'stack', instance => $instance)); $self->{components}->{stack}->{total}++; $self->{output}->output_add( long_msg => sprintf( "stack '%s' status is '%s' [instance: %s, temperature: %s]", $instance, $result->{status}, $instance, $result->{temperature} ) ); my $exit = $self->get_severity(section => 'stack', value => $result->{status}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Stack '%s' status is '%s'", $instance, $result->{status} ) ); } my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $instance, value => $result->{temperature}); if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit2, short_msg => sprintf("stack '%s' temperature is %s C", $instance, $result->{temperature}) ); } $self->{output}->perfdata_add( nlabel => 'hardware.stack.temperature.celsius', unit => 'C', instances => $instance, value => $result->{temperature}, warning => $warn, critical => $crit ); } } } 1; centreon-plugins-20220113/centreon/common/force10/snmp/mode/cpu.pm000066400000000000000000000153571417000230700246410ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::force10::snmp::mode::cpu; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_cpu_output { my ($self, %options) = @_; return "CPU '" . $options{instance_value}->{display} . "' usage "; } 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', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{cpu} = [ { label => '5s', nlabel => 'cpu.utilization.5s.percentage', set => { key_values => [ { name => 'cpu_5s' }, { name => 'display' } ], output_template => '%.2f %% (5s)', perfdatas => [ { label => 'cpu_5s', template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => '1m', nlabel => 'cpu.utilization.1m.percentage', set => { key_values => [ { name => 'cpu_1m' }, { name => 'display' } ], output_template => '%.2f %% (1m)', perfdatas => [ { label => 'cpu_1m', template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => '5m', nlabel => 'cpu.utilization.5m.percentage', set => { key_values => [ { name => 'cpu_5m' }, { name => 'display' } ], output_template => '%.2f %% (5m)', perfdatas => [ { label => 'cpu_5m', template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my $mapping = { sseries => { cpu_5s => { oid => '.1.3.6.1.4.1.6027.3.10.1.2.9.1.2' }, # chStackUnitCpuUtil5Sec cpu_1m => { oid => '.1.3.6.1.4.1.6027.3.10.1.2.9.1.3' }, # chStackUnitCpuUtil1Min cpu_5m => { oid => '.1.3.6.1.4.1.6027.3.10.1.2.9.1.4' } # chStackUnitCpuUtil5Min }, mseries => { cpu_5s => { oid => '.1.3.6.1.4.1.6027.3.19.1.2.8.1.2' }, # chStackUnitCpuUtil5Sec cpu_1m => { oid => '.1.3.6.1.4.1.6027.3.19.1.2.8.1.3' }, # chStackUnitCpuUtil1Min cpu_5m => { oid => '.1.3.6.1.4.1.6027.3.19.1.2.8.1.4' } # chStackUnitCpuUtil5Min }, zseries => { cpu_5s => { oid => '.1.3.6.1.4.1.6027.3.25.1.2.3.1.1' }, # chSysCpuUtil5Sec cpu_1m => { oid => '.1.3.6.1.4.1.6027.3.25.1.2.3.1.2' }, # chSysCpuUtil1Min cpu_5m => { oid => '.1.3.6.1.4.1.6027.3.25.1.2.3.1.3' } # chSysCpuUtil5Min }, os9 => { cpu_5s => { oid => '.1.3.6.1.4.1.6027.3.26.1.4.4.1.1' }, # dellNetCpuUtil5Sec cpu_1m => { oid => '.1.3.6.1.4.1.6027.3.26.1.4.4.1.4' }, # dellNetCpuUtil1Min cpu_5m => { oid => '.1.3.6.1.4.1.6027.3.26.1.4.4.1.5' } # dellNetCpuUtil5Min } }; my $map_device_type = { 1 => 'chassis', 2 => 'stack', 3 => 'rpm', 4 => 'supervisor', 5 => 'linecard', 6 => 'port-extender' }; sub load_series { my ($self, %options) = @_; foreach my $oid (keys %{$options{snmp_result}}) { next if ($oid !~ /^$mapping->{ $options{name} }->{cpu_5m}->{oid}\.(.*)/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping->{ $options{name} }, results => $options{snmp_result}, instance => $instance); $self->{cpu}->{$instance} = { display => $instance, %$result }; } } sub load_os9 { my ($self, %options) = @_; foreach my $oid (keys %{$options{snmp_result}}) { next if ($oid !~ /^$mapping->{ $options{name} }->{cpu_5m}->{oid}\.(\d+)\.(\d+)\.(\d+)/); my $name = $map_device_type->{$1} . ':' . $2 . ':' . $3; my $result = $options{snmp}->map_instance(mapping => $mapping->{ $options{name} }, results => $options{snmp_result}, instance => $1 . '.' . $2 . '.' . $3); $self->{cpu}->{$name} = { display => $name, %$result }; } } sub manage_selection { my ($self, %options) = @_; my $oids = { sseries => { oid => '.1.3.6.1.4.1.6027.3.10.1.2.9.1', load => $self->can('load_series') }, mseries => { oid => '.1.3.6.1.4.1.6027.3.19.1.2.8.1', load => $self->can('load_series') }, zseries => { oid => '.1.3.6.1.4.1.6027.3.25.1.2.3.1', load => $self->can('load_series') }, os9 => { oid => '.1.3.6.1.4.1.6027.3.26.1.4.4.1', load => $self->can('load_os9') } }; my $snmp_result = $options{snmp}->get_multiple_table( oids => [ { oid => $oids->{sseries}->{oid}, start => $mapping->{sseries}->{cpu_5s}->{oid}, end => $mapping->{sseries}->{cpu_5m}->{oid} }, { oid => $oids->{mseries}->{oid}, start => $mapping->{mseries}->{cpu_5s}->{oid}, end => $mapping->{mseries}->{cpu_5m}->{oid} }, { oid => $oids->{zseries}->{oid}, end => $mapping->{zseries}->{cpu_5m}->{oid} }, { oid => $oids->{os9}->{oid}, end => $mapping->{os9}->{cpu_5m}->{oid} } ], nothing_quit => 1 ); $self->{cpu} = {}; foreach my $name (keys %$oids) { $oids->{$name}->{load}->( $self, name => $name, snmp => $options{snmp}, snmp_result => $snmp_result->{ $oids->{$name}->{oid} } ); } if (scalar(keys %{$self->{cpu}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No entry found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check cpu usages. =over 8 =item B<--warning-*> Threshold warning. Can be: '5s', '1m', '5m'. =item B<--critical-*> Threshold critical. Can be: '5s', '1m', '5m'. =back =cut centreon-plugins-20220113/centreon/common/force10/snmp/mode/hardware.pm000066400000000000000000000067331417000230700256450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::force10::snmp::mode::hardware; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^(?:temperature)$'; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { fan => [ ['up', 'OK'], ['absent', 'OK'], ['down', 'CRITICAL'] ], psu => [ ['up', 'OK'], ['absent', 'OK'], ['down', 'CRITICAL'], ['normal', 'OK'], ['warning', 'WARNING'], ['critical', 'CRITICAL'], ['shutdown', 'CRITICAL'], ['notPresent', 'OK'], ['notFunctioning', 'CRITICAL'] ], stack => [ ['ok', 'OK'], ['unsupported', 'CRITICAL'], ['codeMismatch', 'CRITICAL'], ['configMismatch', 'WARNING'], ['unitDown', 'CRITICAL'], ['notPresent', 'OK'] ] }; $self->{components_path} = 'centreon::common::force10::snmp::mode::components'; $self->{components_module} = ['fan', 'psu', 'stack']; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } 1; __END__ =head1 MODE Check Hardware (Fan, Power Supply, Temperature). =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'temperature', 'fan', 'psu'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=temperature --filter=psu) Can also exclude specific instance: --filter=fan,1 =item B<--absent-problem> Return an error if an entity is not 'present' (default is skipping) (comma seperated list) Can be specific or global: --absent-problem=fan,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,WARNING,^(?!(up)$)' =item B<--warning> Set warning threshold for temperatures (syntax: type,instance,threshold) Example: --warning='temperature,.*,30' =item B<--critical> Set critical threshold for temperatures (syntax: type,instance,threshold) Example: --critical='temperature,.*,40' =back =cut centreon-plugins-20220113/centreon/common/force10/snmp/mode/memory.pm000066400000000000000000000114331417000230700253510ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::force10::snmp::mode::memory; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_memory_output { my ($self, %options) = @_; return "Memory '" . $options{instance_value}->{display} . "' usage "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'memory', type => 1, cb_prefix_output => 'prefix_memory_output', message_multiple => 'All memory usages are ok' } ]; $self->{maps_counters}->{memory} = [ { label => 'usage', nlabel => 'memory.usage.percentage', set => { key_values => [ { name => 'usage' }, { name => 'display' } ], output_template => '%.2f %%', output_error_template => "%s", perfdatas => [ { label => 'used', template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my $mapping = { sseries => { mem_used => { oid => '.1.3.6.1.4.1.6027.3.10.1.2.9.1.5' } # chStackUnitMemUsageUtil }, mseries => { mem_used => { oid => '.1.3.6.1.4.1.6027.3.19.1.2.8.1.5' } # chStackUnitMemUsageUtil }, zseries => { mem_used => { oid => '.1.3.6.1.4.1.6027.3.25.1.2.3.1.4' } # chSysCpuUtilMemUsage }, os9 => { mem_used => { oid => '.1.3.6.1.4.1.6027.3.26.1.4.4.1.6' } # dellNetCpuUtilMemUsage } }; my $map_device_type = { 1 => 'chassis', 2 => 'stack', 3 => 'rpm', 4 => 'supervisor', 5 => 'linecard', 6 => 'port-extender' }; sub load_series { my ($self, %options) = @_; foreach (keys %{$options{snmp_result}}) { /^$mapping->{ $options{name} }->{mem_used}->{oid}\.(.*)/; my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping->{ $options{name} }, results => $options{snmp_result}, instance => $instance); $self->{memory}->{$instance} = { display => $instance, usage => $result->{mem_used} }; } } sub load_os9 { my ($self, %options) = @_; foreach (keys %{$options{snmp_result}}) { /^$mapping->{ $options{name} }->{mem_used}->{oid}\.(\d+)\.(\d+)\.(\d+)/; my $name = $map_device_type->{$1} . ':' . $2 . ':' . $3; my $result = $options{snmp}->map_instance(mapping => $mapping->{ $options{name} }, results => $options{snmp_result}, instance => $1 . '.' . $2 . '.' . $3); $self->{memory}->{$name} = { display => $name, usage => $result->{mem_used} }; } } sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_multiple_table( oids => [ { oid => $mapping->{sseries}->{mem_used}->{oid} }, { oid => $mapping->{mseries}->{mem_used}->{oid} }, { oid => $mapping->{zseries}->{mem_used}->{oid} }, { oid => $mapping->{os9}->{mem_used}->{oid} } ], nothing_quit => 1 ); my $cb_load = { sseries => $self->can('load_series'), mseries => $self->can('load_series'), zseries => $self->can('load_series'), os9 => $self->can('load_os9') }; $self->{memory} = {}; foreach my $name (keys %$mapping) { $cb_load->{$name}->( $self, name => $name, snmp => $options{snmp}, snmp_result => $snmp_result->{ $mapping->{$name}->{mem_used}->{oid} } ); } if (scalar(keys %{$self->{memory}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No entry found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check memory usages. =over 8 =item B<--warning-usage> Threshold warning (in percent). =item B<--critical-usage> Threshold critical (in percent). =back =cut centreon-plugins-20220113/centreon/common/fortinet/000077500000000000000000000000001417000230700221735ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/fortinet/fortigate/000077500000000000000000000000001417000230700241575ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/fortinet/fortigate/snmp/000077500000000000000000000000001417000230700251345ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/fortinet/fortigate/snmp/mode/000077500000000000000000000000001417000230700260605ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/fortinet/fortigate/snmp/mode/apusage.pm000066400000000000000000000236761417000230700300610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::fortinet::fortigate::snmp::mode::apusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); use Digest::MD5 qw(md5_hex); sub custom_status_output { my ($self, %options) = @_; return 'status: ' . $self->{result_values}->{status} . ' [admin: ' . $self->{result_values}->{admin} . ']'; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'ap', type => 1, cb_prefix_output => 'prefix_ap_output', message_multiple => 'All access points are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{ap} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'admin' }, { name => 'display' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } }, { label => 'in-traffic', nlabel => 'accesspoint.traffic.in.bitspersecond', set => { key_values => [ { name => 'in', per_second => 1 }, { name => 'display' } ], output_change_bytes => 2, output_template => 'traffic in: %s %s/s', perfdatas => [ { label => 'traffic_in', template => '%.2f', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'out-traffic', nlabel => 'accesspoint.traffic.out.bitspersecond', set => { key_values => [ { name => 'out', per_second => 1 }, { name => 'display' } ], output_change_bytes => 2, output_template => 'traffic out: %s %s/s', perfdatas => [ { label => 'traffic_out', template => '%.2f', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'clients', nlabel => 'accesspoint.clients.current.count', set => { key_values => [ { name => 'clients' }, { name => 'display' } ], output_template => 'current client connections: %s', perfdatas => [ { label => 'clients', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'cpu', nlabel => 'accesspoint.cpu.utilization.percentage', set => { key_values => [ { name => 'cpu' }, { name => 'display' } ], output_template => 'cpu usage: %.2f %%', perfdatas => [ { label => 'cpu', template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'memory', nlabel => 'accesspoint.memory.usage.bytes', set => { key_values => [ { name => 'memory' }, { name => 'display' } ], output_template => 'memory usage: %.2f %%', perfdatas => [ { label => 'memory', template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub prefix_ap_output { my ($self, %options) = @_; return "Access point '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'unknown-status:s' => { name => 'unknown_status', default => '' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{admin} eq "enable" and %{status} !~ /online/i' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['unknown_status', 'warning_status', 'critical_status']); } my %map_ap_admin = ( 0 => 'other', 1 => 'discovered', 2 => 'disable', 3 => 'enable', ); my %map_ap_connect_status = ( 0 => 'other', 1 => 'offLine', 2 => 'onLine', 3 => 'downloadingImage', 4 => 'connectedImage', ); my $mapping = { fgWcWtpConfigWtpAdmin => { oid => '.1.3.6.1.4.1.12356.101.14.4.3.1.2', map => \%map_ap_admin }, fgWcWtpConfigWtpName => { oid => '.1.3.6.1.4.1.12356.101.14.4.3.1.3' } }; my $mapping2 = { fgWcWtpSessionConnectionState => { oid => '.1.3.6.1.4.1.12356.101.14.4.4.1.7', map => \%map_ap_connect_status }, fgWcWtpSessionWtpStationCount => { oid => '.1.3.6.1.4.1.12356.101.14.4.4.1.17'}, fgWcWtpSessionWtpByteRxCount => { oid => '.1.3.6.1.4.1.12356.101.14.4.4.1.18' }, fgWcWtpSessionWtpByteTxCount => { oid => '.1.3.6.1.4.1.12356.101.14.4.4.1.19' }, fgWcWtpSessionWtpCpuUsage => { oid => '.1.3.6.1.4.1.12356.101.14.4.4.1.20' }, fgWcWtpSessionWtpMemoryUsage => { oid => '.1.3.6.1.4.1.12356.101.14.4.4.1.21' } }; my $oid_fgWcWtpConfigEntry = '.1.3.6.1.4.1.12356.101.14.4.3.1'; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_table( oid => $oid_fgWcWtpConfigEntry, start => $mapping->{fgWcWtpConfigWtpAdmin}->{oid}, end => $mapping->{fgWcWtpConfigWtpName}->{oid}, nothing_quit => 1 ); $self->{ap} = {}; foreach my $oid (keys %{$snmp_result}) { next if ($oid !~ /^$mapping->{fgWcWtpConfigWtpName}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $result->{fgWcWtpConfigWtpName} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping access point '" . $result->{fgWcWtpConfigWtpName} . "'.", debug => 1); next; } $self->{ap}->{$instance} = { display => $result->{fgWcWtpConfigWtpName}, admin => $result->{fgWcWtpConfigWtpAdmin}, status => 'n/a', }; } if (scalar(keys %{$self->{ap}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No access point found."); $self->{output}->option_exit(); } $options{snmp}->load( oids => [ $mapping2->{fgWcWtpSessionConnectionState}->{oid}, $mapping2->{fgWcWtpSessionWtpStationCount}->{oid}, $mapping2->{fgWcWtpSessionWtpByteRxCount}->{oid}, $mapping2->{fgWcWtpSessionWtpByteTxCount}->{oid}, $mapping2->{fgWcWtpSessionWtpCpuUsage}->{oid}, $mapping2->{fgWcWtpSessionWtpMemoryUsage}->{oid}, ], instances => [keys %{$self->{ap}}], instance_regexp => '^(.*)$' ); $snmp_result = $options{snmp}->get_leef(nothing_quit => 1); foreach (keys %{$self->{ap}}) { my $result = $options{snmp}->map_instance(mapping => $mapping2, results => $snmp_result, instance => $_); $self->{ap}->{$_}->{status} = $result->{fgWcWtpSessionConnectionState}; $self->{ap}->{$_}->{in} = defined($result->{fgWcWtpSessionWtpByteRxCount}) ? ($result->{fgWcWtpSessionWtpByteRxCount} * 8) : undef; $self->{ap}->{$_}->{out} = defined($result->{fgWcWtpSessionWtpByteTxCount}) ? ($result->{fgWcWtpSessionWtpByteTxCount} * 8) : undef; $self->{ap}->{$_}->{clients} = $result->{fgWcWtpSessionWtpStationCount}; $self->{ap}->{$_}->{cpu} = $result->{fgWcWtpSessionWtpCpuUsage}; $self->{ap}->{$_}->{memory} = $result->{fgWcWtpSessionWtpMemoryUsage}; } $self->{cache_name} = 'fortigate_' . $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 access point usage. =over 8 =item B<--warning-*> Threshold warning. Can be: 'in-traffic', 'out-traffic', 'cpu' (%), 'memory' (%), 'clients'. =item B<--critical-*> Threshold critical. Can be: 'in-traffic', 'out-traffic', 'cpu' (%), 'memory' (%), 'clients'. =item B<--filter-name> Filter by access point name (can be a regexp). =item B<--unknown-status> Set warning threshold for status (Default: ''). Can used special variables like: %{admin}, %{status}, %{display} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{admin}, %{status}, %{display} =item B<--critical-status> Set critical threshold for status (Default: '%{admin} eq "enable" and %{status} !~ /online/i''). Can used special variables like: %{admin}, %{status}, %{display} =back =cut centreon-plugins-20220113/centreon/common/fortinet/fortigate/snmp/mode/clusterstatus.pm000066400000000000000000000245721417000230700313550ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::fortinet::fortigate::snmp::mode::clusterstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use Digest::MD5 qw(md5_hex); sub custom_status_output { my ($self, %options) = @_; return sprintf( "status is '%s' [hostname: %s] [role: %s] [checksum: %s]", $self->{result_values}->{sync_status}, $self->{result_values}->{hostname}, $self->{result_values}->{role}, $self->{result_values}->{checksum} ); } sub prefix_global_output { my ($self, %options) = @_; return 'Nodes '; } sub node_long_output { my ($self, %options) = @_; return sprintf( "checking node '%s'", $options{instance_value}->{serial} ); } sub prefix_node_output { my ($self, %options) = @_; return sprintf( "node '%s' ", $options{instance_value}->{serial} ); } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{roleLast} = $options{old_datas}->{$self->{instance} . '_role'}; $self->{result_values}->{role} = $options{new_datas}->{$self->{instance} . '_role'}; if (!defined($options{old_datas}->{$self->{instance} . '_role'})) { $self->{error_msg} = "buffer creation"; return -2; } $self->{result_values}->{sync_status} = $options{new_datas}->{$self->{instance} . '_sync_status'}; $self->{result_values}->{hostname} = $options{new_datas}->{$self->{instance} . '_hostname'}; $self->{result_values}->{checksum} = $options{new_datas}->{$self->{instance} . '_checksum'}; $self->{result_values}->{serial} = $options{new_datas}->{$self->{instance} . '_serial'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }, { name => 'nodes', type => 3, cb_prefix_output => 'prefix_node_output', cb_long_output => 'node_long_output', indent_long_output => ' ', message_multiple => 'All cluster nodes are ok', group => [ { name => 'status', type => 0, skipped_code => { -10 => 1 } }, { name => 'cpu', type => 0, skipped_code => { -10 => 1 } }, { name => 'memory', type => 0, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'total-nodes', nlabel => 'cluster.nodes.count', set => { key_values => [ { name => 'total_nodes' } ], output_template => 'total: %d', perfdatas => [ { template => '%d', min => 0 } ] } }, { label => 'synchronized', nlabel => 'cluster.nodes.synchronized.count', set => { key_values => [ { name => 'synchronized' } ], output_template => 'synchronized: %d', perfdatas => [ { template => '%d', min => 0 } ] } }, { label => 'unsynchronized', nlabel => 'cluster.nodes.unsynchronized.count',set => { key_values => [ { name => 'unsynchronized' } ], output_template => 'unsynchronized: %d', perfdatas => [ { template => '%d', min => 0 } ] } }, { label => 'total-checksums', nlabel => 'cluster.checksums.total.count', display_ok => 0, set => { key_values => [ { name => 'total_checksums' } ], output_template => 'checksums: %d', perfdatas => [ { template => '%d', min => 0 } ] } } ]; $self->{maps_counters}->{status} = [ { label => 'status', type => 2, critical_default => '%{role} ne %{roleLast} or %{sync_status} =~ /unsynchronized/', set => { key_values => [ { name => 'serial' }, { name => 'hostname' }, { name => 'sync_status' }, { name => 'role' }, { name => 'checksum' } ], closure_custom_calc => \&custom_status_calc, closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{cpu} = [ { label => 'cpu-utilization', nlabel => 'node.cpu.utilization.percentage', set => { key_values => [ { name => 'cpu_usage' }, { name => 'serial' } ], output_template => 'cpu usage: %.2f %%', perfdatas => [ { template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1, instance_use => 'serial' } ] } } ]; $self->{maps_counters}->{memory} = [ { label => 'memory-usage', nlabel => 'node.memory.usage.percentage', set => { key_values => [ { name => 'memory_usage' }, { name => 'serial' } ], output_template => 'memory used: %.2f %%', output_change_bytes => 1, perfdatas => [ { template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1, instance_use => 'serial' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'one-node-status:s' => { name => 'one_node_status' } # not used, use --opt-exit instead }); return $self; } my $map_ha_mode = { 1 => 'standalone', 2 => 'activeActive', 3 => 'activePassive' }; my $map_sync_status = { 0 => 'unsynchronized', 1 => 'synchronized' }; my $mapping = { cpuUsage => { oid => '.1.3.6.1.4.1.12356.101.13.2.1.1.3' }, # fgHaStatsCpuUsage memUsage => { oid => '.1.3.6.1.4.1.12356.101.13.2.1.1.4' }, # fgHaStatsMemUsage hostname => { oid => '.1.3.6.1.4.1.12356.101.13.2.1.1.11' }, # fgHaStatsHostname syncStatus => { oid => '.1.3.6.1.4.1.12356.101.13.2.1.1.12', map => $map_sync_status }, # fgHaStatsSyncStatus globalChecksum => { oid => '.1.3.6.1.4.1.12356.101.13.2.1.1.15' }, # fgHaStatsGlobalChecksum masterSerial => { oid => '.1.3.6.1.4.1.12356.101.13.2.1.1.16' } # fgHaStatsMasterSerial }; my $oid_fgHaSystemMode = '.1.3.6.1.4.1.12356.101.13.1.1.0'; sub manage_selection { my ($self, %options) = @_; my $mode = $options{snmp}->get_leef(oids => [ $oid_fgHaSystemMode ], nothing_quit => 1); if ($map_ha_mode->{ $mode->{$oid_fgHaSystemMode} } =~ /standalone/) { $self->{output}->add_option_msg(short_msg => "No cluster configuration (standalone mode)"); $self->{output}->option_exit(); } $self->{output}->output_add(short_msg => 'High-availibility mode: ' . $map_ha_mode->{ $mode->{$oid_fgHaSystemMode} }); my $oid_serial = '.1.3.6.1.4.1.12356.101.13.2.1.1.2'; # fgHaStatsSerial my $snmp_result = $options{snmp}->get_table( oid => $oid_serial, nothing_quit => 1 ); $self->{global} = { synchronized => 0, unsynchronized => 0, total_nodes => 0 }; $self->{nodes} = {}; foreach (keys %$snmp_result) { /^$oid_serial\.(.*)$/; my $instance = $1; $self->{nodes}->{$instance} = { serial => $snmp_result->{$_} }; } return if (scalar(keys %{$self->{nodes}}) <= 0); $options{snmp}->load( oids => [ map($_->{oid}, values(%$mapping)) ], instances => [ map($_, keys(%{$self->{nodes}})) ], instance_regexp => '^(.*)$' ); $snmp_result = $options{snmp}->get_leef(); my $checksums = {}; foreach (keys %{$self->{nodes}}) { my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $_); $checksums->{ $result->{globalChecksum} } = 1; $self->{nodes}->{$_}->{status} = { serial => $self->{nodes}->{$_}->{serial}, hostname => $result->{hostname}, sync_status => $result->{syncStatus}, role => ($result->{masterSerial} eq '' || $result->{masterSerial} =~ /$self->{nodes}->{$_}->{serial}/) ? 'master' : 'slave', checksum => $result->{globalChecksum} }; $self->{nodes}->{$_}->{cpu} = { cpu_usage => $result->{cpuUsage}, serial => $self->{nodes}->{$_}->{serial} }; $self->{nodes}->{$_}->{memory} = { memory_usage => $result->{memUsage}, serial => $self->{nodes}->{$_}->{serial} }; $self->{global}->{ $result->{syncStatus} }++; $self->{global}->{total_nodes}++; } $self->{global}->{total_checksums} = scalar(keys %$checksums); $self->{cache_name} = 'fortinet_fortigate_' . $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')); } 1; __END__ =head1 MODE Check cluster status. =over 8 =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{serial}, %{hostname}, %{sync_status}, %{role}, %{roleLast} =item B<--critical-status> Set critical threshold for status (Default: '%{role} ne %{roleLast} or %{sync_status} =~ /unsynchronized/'). Can used special variables like: %{serial}, %{hostname}, %{sync_status}, %{role}, %{roleLast} =item B<--warning-*> B<--critical-*> Set thresholds. Can be: 'total-nodes', 'synchronized', 'unsynchronized', 'total-checksums', 'cpu-utilization', 'memory-usage'. =back =cut centreon-plugins-20220113/centreon/common/fortinet/fortigate/snmp/mode/cpu.pm000066400000000000000000000142671417000230700272170ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::fortinet::fortigate::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_avg', type => 0 }, { name => 'cpu_core', type => 1, cb_prefix_output => 'prefix_cpu_core_output' }, { name => 'cluster', type => 1, cb_prefix_output => 'prefix_cluster_output' } ]; $self->{maps_counters}->{cpu_avg} = [ { label => 'average', nlabel => 'cpu.utilization.percentage', set => { key_values => [ { name => 'average' } ], output_template => 'CPU(s) average usage is: %.2f %%', perfdatas => [ { label => 'total_cpu_avg', value => 'average', template => '%.2f', min => 0, max => 100, unit => '%' }, ] } } ]; $self->{maps_counters}->{cpu_core} = [ { label => 'core', nlabel => 'core.cpu.utilization.percentage', set => { key_values => [ { name => 'cpu' } ], output_template => 'usage: %.2f %%', perfdatas => [ { value => 'cpu', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 }, ] } } ]; $self->{maps_counters}->{cluster} = [ { label => 'cluster-average', nlabel => 'cluster.cpu.utilization.percentage', display_ok => 0, set => { key_values => [ { name => 'cpu' } ], output_template => 'CPU usage: %.2f %%', perfdatas => [ { value => 'cpu', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 }, ] } } ]; } sub prefix_cluster_output { my ($self, %options) = @_; return "Cluster '" . $options{instance_value}->{display} . "' "; } sub prefix_cpu_core_output { my ($self, %options) = @_; return "CPU '" . $options{instance_value}->{display} . "' "; } 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 => { 'cluster' => { name => 'cluster' }, 'filter-core:s' => { name => 'filter_core' }, }); return $self; } my $oid_fgSysCpuUsage = '.1.3.6.1.4.1.12356.101.4.1.3'; my $oid_fgProcessorUsage = '.1.3.6.1.4.1.12356.101.4.4.2.1.2'; # some not have my $oid_fgHaSystemMode = '.1.3.6.1.4.1.12356.101.13.1.1'; # '.0' to have the mode my $oid_fgHaStatsCpuUsage = '.1.3.6.1.4.1.12356.101.13.2.1.1.3'; my $oid_fgHaStatsHostname = '.1.3.6.1.4.1.12356.101.13.2.1.1.11'; my $maps_ha_mode = { 1 => 'standalone', 2 => 'activeActive', 3 => 'activePassive' }; sub cpu_ha { my ($self, %options) = @_; $self->{cluster} = {}; foreach ($options{snmp}->oid_lex_sort(keys %{$options{snmp_result}->{$oid_fgHaStatsCpuUsage}})) { /\.(\d+)$/; $self->{cluster}->{ $options{snmp_result}->{$oid_fgHaStatsHostname}->{$oid_fgHaStatsHostname . '.' . $1} } = { display => $options{snmp_result}->{$oid_fgHaStatsHostname}->{$oid_fgHaStatsHostname . '.' . $1}, cpu => $options{snmp_result}->{$oid_fgHaStatsCpuUsage}->{$_} }; } } sub manage_selection { my ($self, %options) = @_; my $table_oids = [ { oid => $oid_fgProcessorUsage }, { oid => $oid_fgSysCpuUsage } ]; if (defined($self->{option_results}->{cluster})) { push @$table_oids, { oid => $oid_fgHaSystemMode }, { oid => $oid_fgHaStatsCpuUsage }, { oid => $oid_fgHaStatsHostname }; } my $snmp_result = $options{snmp}->get_multiple_table( oids => $table_oids, nothing_quit => 1 ); my ($cpu, $i) = (0, -1); $self->{cpu_core} = {}; foreach ($options{snmp}->oid_lex_sort(keys %{$snmp_result->{$oid_fgProcessorUsage}})) { $i++; if (defined($self->{option_results}->{filter_core}) && $self->{option_results}->{filter_core} ne '' && $i !~ /$self->{option_results}->{filter_core}/) { $self->{output}->output_add(long_msg => "skipping core cpu '" . $i . "': no matching filter.", debug => 1); next; } $self->{cpu_core}->{$i} = { display => $i, cpu => $snmp_result->{$oid_fgProcessorUsage}->{$_} }; $cpu += $snmp_result->{$oid_fgProcessorUsage}->{$_}; } my $num_core = scalar(keys %{$self->{cpu_core}}); $self->{cpu_avg} = { average => $num_core > 0 ? $cpu / $num_core : $snmp_result->{$oid_fgSysCpuUsage}->{$oid_fgSysCpuUsage . '.0'} }; if (defined($self->{option_results}->{cluster})) { my $ha_mode = $snmp_result->{$oid_fgHaSystemMode}->{$oid_fgHaSystemMode . '.0'}; my $ha_mode_str = defined($maps_ha_mode->{$ha_mode}) ? $maps_ha_mode->{$ha_mode} : 'unknown'; $self->{output}->output_add(long_msg => 'high availabily mode is ' . $ha_mode_str); if ($ha_mode_str =~ /active/) { $self->cpu_ha(snmp => $options{snmp}, snmp_result => $snmp_result); } } } 1; __END__ =head1 MODE Check system cpu usage (FORTINET-FORTIGATE-MIB). =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'core', 'average', 'cluster-average'. =item B<--cluster> Add cluster cpu informations. =item B<--filter-core> Core cpu to monitor (can be a regexp). =back =cut centreon-plugins-20220113/centreon/common/fortinet/fortigate/snmp/mode/disk.pm000066400000000000000000000076501417000230700273600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::fortinet::fortigate::snmp::mode::disk; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { '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 $oid_fgSysDiskUsage = '.1.3.6.1.4.1.12356.101.4.1.6.0'; # in MB my $oid_fgSysDiskCapacity = '.1.3.6.1.4.1.12356.101.4.1.7.0'; # in MB $self->{result} = $options{snmp}->get_leef( oids => [ $oid_fgSysDiskUsage, $oid_fgSysDiskCapacity ], nothing_quit => 1 ); if (!defined($self->{result}->{$oid_fgSysDiskCapacity}) || $self->{result}->{$oid_fgSysDiskCapacity} == 0) { $self->{output}->output_add( severity => 'OK', short_msg => sprintf("No disk present.") ); $self->{output}->display(); $self->{output}->exit(); } my $fgSysDiskUsage = $self->{result}->{$oid_fgSysDiskUsage} * 1024 * 1024; my $fgSysDiskCapacity = $self->{result}->{$oid_fgSysDiskCapacity} * 1024 * 1024; my $prct = $fgSysDiskUsage * 100 / $fgSysDiskCapacity; my $exit = $self->{perfdata}->threshold_check( value => $prct, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ] ); my ($size_value, $size_unit) = $self->{perfdata}->change_bytes(value => $fgSysDiskCapacity); $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Disk Usage: %.2f%% used [Total: %s]", $prct, $size_value . " " . $size_unit ) ); $self->{output}->perfdata_add( label => 'used', unit => 'B', nlabel => 'storage.space.usage.bytes', value => $fgSysDiskUsage, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning', total => $fgSysDiskCapacity, cast_int => 1), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical', total => $fgSysDiskCapacity, cast_int => 1), min => 0, max => $fgSysDiskCapacity ); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check system disk usage (FORTINET-FORTIGATE). =over 8 =item B<--warning> Threshold warning in percent. =item B<--critical> Threshold critical in percent. =back =cut centreon-plugins-20220113/centreon/common/fortinet/fortigate/snmp/mode/hardware.pm000066400000000000000000000144121417000230700302150ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::fortinet::fortigate::snmp::mode::hardware; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^sensors$'; $self->{cb_hook1} = 'get_system_information'; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { sensors => [ ['on', 'CRITICAL'], ['off', 'OK'], ], }; $self->{components_path} = 'centreon::common::fortinet::fortigate::snmp::mode::components'; $self->{components_module} = ['sensors']; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_absent => 1, no_load_components => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub get_system_information { my ($self, %options) = @_; my $oid_sysDescr = '.1.3.6.1.2.1.1.1.0'; my $oid_fgSysVersion = '.1.3.6.1.4.1.12356.101.4.1.1.0'; my $result = $options{snmp}->get_leef(oids => [$oid_sysDescr, $oid_fgSysVersion]);#, nothing_quit => 1); $self->{output}->output_add( long_msg => sprintf( '[System: %s] [Firmware: %s]', $result->{$oid_sysDescr}, defined($result->{$oid_fgSysVersion}) ? $result->{$oid_fgSysVersion} : 'unknown' ) ); } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); } 1; =head1 MODE Check hardware. It's deprecated. Work only for 'FortiGate-5000 Series Chassis'. =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'sensors'. =item B<--add-name-instance> Add literal description for instance value (used in filter, and threshold options). =item B<--filter> Exclude some parts (comma seperated list) Can also exclude specific instance: --filter=sensors,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='sensors,WARNING,off' =item B<--warning> Set warning threshold for 'sensors' (syntax: type,regexp,threshold) Example: --warning='sensors,.*,30' =item B<--critical> Set critical threshold for 'sensors' (syntax: type,regexp,threshold) Example: --critical='sensors,.*,50' =back =cut package centreon::common::fortinet::fortigate::snmp::mode::components::sensors; use strict; use warnings; my %alarm_map = ( 0 => 'off', 1 => 'on', ); my $mapping = { fgHwSensorEntName => { oid => '.1.3.6.1.4.1.12356.101.4.3.2.1.2' }, fgHwSensorEntValue => { oid => '.1.3.6.1.4.1.12356.101.4.3.2.1.3' }, fgHwSensorEntAlarmStatus => { oid => '.1.3.6.1.4.1.12356.101.4.3.2.1.4', map => \%alarm_map }, }; my $oid_fgHwSensorEntry = '.1.3.6.1.4.1.12356.101.4.3.2.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_fgHwSensorEntry }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking sensors"); $self->{components}->{sensors} = {name => 'sensors', total => 0, skip => 0}; return if ($self->check_filter(section => 'sensors')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_fgHwSensorEntry}})) { next if ($oid !~ /^$mapping->{fgHwSensorEntAlarmStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_fgHwSensorEntry}, instance => $instance); my $name = centreon::plugins::misc::trim($result->{fgHwSensorEntName}); next if ($self->check_filter(section => 'sensors', instance => $instance, name => $name)); $self->{components}->{sensors}->{total}++; $self->{output}->output_add( long_msg => sprintf( "sensor '%s' status is '%s' [instance = %s] [value = %s]", $name, $result->{fgHwSensorEntAlarmStatus}, $instance, defined($result->{fgHwSensorEntValue}) ? $result->{fgHwSensorEntValue} : '-' ) ); my $exit = $self->get_severity(section => 'sensors', name => $name, value => $result->{fgHwSensorEntAlarmStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Sensor '%s' status is '%s'", $name, $result->{fgHwSensorEntAlarmStatus}) ); } next if (!defined($result->{fgHwSensorEntValue})); my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'sensors', instance => $instance, name => $name, value => $result->{fgHwSensorEntValue}); if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit2, short_msg => sprintf("Sensor '%s' measure is %s", $name, $result->{fgHwSensorEntValue}) ); } $self->{output}->perfdata_add( nlabel => 'hardware.sensors.measure', instances => $name, value => $result->{fgHwSensorEntValue}, warning => $warn, critical => $crit, ); } } 1; centreon-plugins-20220113/centreon/common/fortinet/fortigate/snmp/mode/interfaces.pm000066400000000000000000000117721417000230700305510ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::fortinet::fortigate::snmp::mode::interfaces; use base qw(snmp_standard::mode::interfaces); use strict; use warnings; sub set_oids_label { my ($self, %options) = @_; $self->SUPER::set_oids_label(%options); $self->{oids_label}->{vdom} = { oid => '.1.3.6.1.4.1.12356.101.7.2.1.1.1', get => 'reload_get_simple', cache => 'reload_cache_vdom_index' }; } sub reload_cache_vdom_index { my ($self, %options) = @_; my $oid_fgVdEntName = '.1.3.6.1.4.1.12356.101.3.2.1.1.2'; my $snmp_result = $self->{snmp}->get_table(oid => $oid_fgVdEntName); my $store_index = defined($options{store_index}) && $options{store_index} == 1 ? 1 : 0; foreach (keys %{$options{result}->{ $self->{oids_label}->{$options{name}}->{oid} }}) { /^$self->{oids_label}->{$options{name}}->{oid}\.(.*)$/; push @{$options{datas}->{all_ids}}, $1 if ($store_index == 1); $options{datas}->{$options{name} . "_" . $1} = $snmp_result->{ $oid_fgVdEntName . '.' . $options{result}->{ $self->{oids_label}->{$options{name}}->{oid} }->{$_} }; } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); 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> Set warning threshold for status. Can used special variables like: %{admstatus}, %{opstatus}, %{duplexstatus}, %{display} =item B<--critical-status> Set critical threshold for status (Default: '%{admstatus} eq "up" and %{opstatus} ne "up"'). Can used special variables like: %{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', 'counter'). =item B<--units-cast> Units of thresholds for communication types (Default: 'percent_delta') ('percent_delta', 'percent', 'delta', '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 interface'). =item B<--name> Allows to use interface name with option --interface instead of interface oid index (Can be a regexp) =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<--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> Choose OID used to filter interface (default: ifName) (values: ifDesc, ifAlias, ifName, IpAddr, Vdom). =item B<--oid-display> Choose OID used to display interface (default: ifName) (values: ifDesc, ifAlias, ifName, IpAddr, Vdom). =item B<--oid-extra-display> Add an OID to display. =item B<--display-transform-src> Regexp src to transform display value. =item B<--display-transform-dst> Regexp dst to transform display value. =item B<--show-cache> Display cache interface datas. =back =cut centreon-plugins-20220113/centreon/common/fortinet/fortigate/snmp/mode/ipsstats.pm000066400000000000000000000221661417000230700302770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::fortinet::fortigate::snmp::mode::ipsstats; 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 => 'domain', type => 1, cb_prefix_output => 'prefix_domain_output', message_multiple => 'All IPS domain statistics are ok' } ]; $self->{maps_counters}->{domain} = [ { label => 'intrusions-detected', nlabel => 'domain.intrusions.detected.count', set => { key_values => [ { name => 'fgIpsIntrusionsDetected', diff => 1 }, { name => 'display' } ], output_template => 'Intrusions detected : %s', perfdatas => [ { label => 'intrusions_detected', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'intrusions-blocked', nlabel => 'domain.intrusions.blocked.count', set => { key_values => [ { name => 'fgIpsIntrusionsBlocked', diff => 1 }, { name => 'display' } ], output_template => 'Intrusions blocked : %s', perfdatas => [ { label => 'intrusions_blocked', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'crit-sev-detections', nlabel => 'domain.intrusions.detected.critical.severity.count', set => { key_values => [ { name => 'fgIpsCritSevDetections', diff => 1 }, { name => 'display' } ], output_template => 'Critical severity intrusions detected : %s', perfdatas => [ { label => 'crit_sev_detections', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'high-sev-detections', nlabel => 'domain.intrusions.detected.high.severity.count', set => { key_values => [ { name => 'fgIpsHighSevDetections', diff => 1 }, { name => 'display' } ], output_template => 'High severity intrusions detected : %s', perfdatas => [ { label => 'high_sev_detections', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'med-sev-detections', nlabel => 'domain.intrusions.detected.medium.severity.count', set => { key_values => [ { name => 'fgIpsMedSevDetections', diff => 1 }, { name => 'display' } ], output_template => 'Medium severity intrusions detected : %s', perfdatas => [ { label => 'med_sev_detections', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'low-sev-detections', nlabel => 'domain.intrusions.detected.low.severity.count', set => { key_values => [ { name => 'fgIpsLowSevDetections', diff => 1 }, { name => 'display' } ], output_template => 'Low severity intrusions detected : %s', perfdatas => [ { label => 'low_sev_detections', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'info-sev-detections', nlabel => 'domain.intrusions.detected.info.severity.count', set => { key_values => [ { name => 'fgIpsInfoSevDetections', diff => 1 }, { name => 'display' } ], output_template => 'Informational severity intrusions detected : %s', perfdatas => [ { label => 'info_sev_detections', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'signature-detections', nlabel => 'domain.intrusions.detected.signature.count', set => { key_values => [ { name => 'fgIpsSignatureDetections', diff => 1 }, { name => 'display' } ], output_template => 'Signature intrusions detected : %s', perfdatas => [ { label => 'signature_detection', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'anomaly-detections', nlabel => 'domain.intrusions.detected.anomaly.count', set => { key_values => [ { name => 'fgIpsAnomalyDetections', diff => 1 }, { name => 'display' } ], output_template => 'Anomaly intrusions detected : %s', perfdatas => [ { label => 'anomaly_detections', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub prefix_domain_output { my ($self, %options) = @_; return "Domain '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } my $mapping = { fgIpsIntrusionsDetected => { oid => '.1.3.6.1.4.1.12356.101.9.2.1.1.1' }, fgIpsIntrusionsBlocked => { oid => '.1.3.6.1.4.1.12356.101.9.2.1.1.2' }, fgIpsCritSevDetections => { oid => '.1.3.6.1.4.1.12356.101.9.2.1.1.3' }, fgIpsHighSevDetections => { oid => '.1.3.6.1.4.1.12356.101.9.2.1.1.4' }, fgIpsMedSevDetections => { oid => '.1.3.6.1.4.1.12356.101.9.2.1.1.5' }, fgIpsLowSevDetections => { oid => '.1.3.6.1.4.1.12356.101.9.2.1.1.6' }, fgIpsInfoSevDetections => { oid => '.1.3.6.1.4.1.12356.101.9.2.1.1.7' }, fgIpsSignatureDetections => { oid => '.1.3.6.1.4.1.12356.101.9.2.1.1.8' }, fgIpsAnomalyDetections => { oid => '.1.3.6.1.4.1.12356.101.9.2.1.1.9' } }; my $oid_fgIpsStatsEntry = '.1.3.6.1.4.1.12356.101.9.2.1.1'; my $oid_fgVdEntName = '.1.3.6.1.4.1.12356.101.3.2.1.1.2'; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_multiple_table( oids => [ { oid => $oid_fgVdEntName }, { oid => $oid_fgIpsStatsEntry } ], nothing_quit => 1 ); $self->{domain} = {}; foreach my $oid (keys %{$snmp_result->{$oid_fgVdEntName}}) { next if ($oid !~ /^$oid_fgVdEntName\.(.*)/); my $instance = $1; if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $snmp_result->{$oid_fgVdEntName}->{$oid} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $snmp_result->{$oid_fgVdEntName}->{$oid} . "': no matching filter."); next; } my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result->{$oid_fgIpsStatsEntry}, instance => $instance); $self->{domain}->{$instance} = $result; $self->{domain}->{$instance}->{display} = $snmp_result->{$oid_fgVdEntName}->{$oid}; } if (scalar(keys %{$self->{domain}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No domain found."); $self->{output}->option_exit(); } $self->{cache_name} = "fortinet_fortigate_" . $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 domain IPS statistics. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'intrusions-detected', 'intrusions-blocked', 'crit-sev-detections', 'high-sev-detections', 'med-sev-detections', 'low-sev-detections', 'info-sev-detections', 'signature-detections', 'anomaly-detections'. =item B<--filter-name> Filter virtual domain name (can be a regexp). =back =cut centreon-plugins-20220113/centreon/common/fortinet/fortigate/snmp/mode/listvirtualdomains.pm000066400000000000000000000074511417000230700323620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::fortinet::fortigate::snmp::mode::listvirtualdomains; use base qw(centreon::plugins::mode); use strict; use warnings; my $oid_fgVdEntName = '.1.3.6.1.4.1.12356.101.3.2.1.1.2'; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'name:s' => { name => 'name' }, 'regexp' => { name => 'use_regexp' } }); $self->{virtualdomain_id_selected} = []; return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{result_names} = $self->{snmp}->get_table(oid => $oid_fgVdEntName, nothing_quit => 1); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{result_names}})) { next if ($oid !~ /\.([0-9]+)$/); my $instance = $1; # Get all without a name if (!defined($self->{option_results}->{name})) { push @{$self->{virtualdomain_id_selected}}, $instance; next; } if (!defined($self->{option_results}->{use_regexp}) && $self->{result_names}->{$oid} ne $self->{option_results}->{name}) { $self->{output}->output_add(long_msg => "Skipping virtualdomain '" . $self->{result_names}->{$oid} . "': no matching filter name"); next; } if (defined($self->{option_results}->{use_regexp}) && $self->{result_names}->{$oid} !~ /$self->{option_results}->{name}/) { $self->{output}->output_add(long_msg => "Skipping virtualdomain '" . $self->{result_names}->{$oid} . "': no matching filter name (regexp)"); next; } push @{$self->{virtualdomain_id_selected}}, $instance; } } sub run { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->manage_selection(); foreach my $instance (sort @{$self->{virtualdomain_id_selected}}) { my $name = $self->{result_names}->{$oid_fgVdEntName . '.' . $instance}; $self->{output}->output_add(long_msg => "'" . $name . "'"); } $self->{output}->output_add( severity => 'OK', short_msg => 'List virtualdomains:' ); $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 $instance (sort @{$self->{virtualdomain_id_selected}}) { my $name = $self->{result_names}->{$oid_fgVdEntName . '.' . $instance}; $self->{output}->add_disco_entry(name => $name); } } 1; __END__ =head1 MODE List filesystems (volumes and aggregates also). =over 8 =item B<--name> Set the virtualdomain name. =item B<--regexp> Allows to use regexp to filter virtualdomain name (with option --name). =back =cut centreon-plugins-20220113/centreon/common/fortinet/fortigate/snmp/mode/memory.pm000066400000000000000000000151141417000230700277300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::fortinet::fortigate::snmp::mode::memory; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_usage_output { my ($self, %options) = @_; return sprintf("memory total: %s %s used: %s %s (%.2f%%) free: %s %s (%.2f%%)", $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}), $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}), $self->{result_values}->{prct_used}, $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}), $self->{result_values}->{prct_free} ); } sub prefix_cluster_output { my ($self, %options) = @_; return "Cluster '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'memory', type => 0 }, { name => 'cluster', type => 1, cb_prefix_output => 'prefix_cluster_output' } ]; $self->{maps_counters}->{memory} = [ { label => 'usage', nlabel => 'memory.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { value => 'used', template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1 }, ] } }, { label => 'usage-free', display_ok => 0, nlabel => 'memory.free.bytes', set => { key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { value => 'free', template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1 }, ] } }, { label => 'usage-prct', display_ok => 0, nlabel => 'memory.usage.percentage', set => { key_values => [ { name => 'prct_used' } ], output_template => 'memory used : %.2f %%', perfdatas => [ { label => 'used_prct', value => 'prct_used', template => '%.2f', min => 0, max => 100, unit => '%' } ] } } ]; $self->{maps_counters}->{cluster} = [ { label => 'cluster-usage-prct', nlabel => 'cluster.memory.usage.percentage', display_ok => 0, set => { key_values => [ { name => 'memory' } ], output_template => 'memory used: %.2f %%', perfdatas => [ { value => 'memory', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 }, ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'cluster' => { name => 'cluster' } }); return $self; } my $oid_fgSystemInfo = '.1.3.6.1.4.1.12356.101.4.1'; my $oid_fgSysMemUsage = '.1.3.6.1.4.1.12356.101.4.1.4'; my $oid_fgSysMemCapacity = '.1.3.6.1.4.1.12356.101.4.1.5'; my $oid_fgHaSystemMode = '.1.3.6.1.4.1.12356.101.13.1.1'; # '.0' to have the mode my $oid_fgHaStatsMemUsage = '.1.3.6.1.4.1.12356.101.13.2.1.1.4'; my $oid_fgHaStatsHostname = '.1.3.6.1.4.1.12356.101.13.2.1.1.11'; my $maps_ha_mode = { 1 => 'standalone', 2 => 'activeActive', 3 => 'activePassive' }; sub memory_ha { my ($self, %options) = @_; $self->{cluster} = {}; foreach ($options{snmp}->oid_lex_sort(keys %{$options{snmp_result}->{$oid_fgHaStatsMemUsage}})) { /\.(\d+)$/; $self->{cluster}->{ $options{snmp_result}->{$oid_fgHaStatsHostname}->{$oid_fgHaStatsHostname . '.' . $1} } = { display => $options{snmp_result}->{$oid_fgHaStatsHostname}->{$oid_fgHaStatsHostname . '.' . $1}, memory => $options{snmp_result}->{$oid_fgHaStatsMemUsage}->{$_} }; } } sub manage_selection { my ($self, %options) = @_; my $table_oids = [ { oid => $oid_fgSystemInfo, start => $oid_fgSysMemUsage, end => $oid_fgSysMemCapacity } ]; if (defined($self->{option_results}->{cluster})) { push @$table_oids, { oid => $oid_fgHaSystemMode }, { oid => $oid_fgHaStatsMemUsage }, { oid => $oid_fgHaStatsHostname }; } my $snmp_result = $options{snmp}->get_multiple_table( oids => $table_oids, nothing_quit => 1 ); $self->{memory} = { prct_used => $snmp_result->{$oid_fgSystemInfo}->{$oid_fgSysMemUsage . '.0'}, total => $snmp_result->{$oid_fgSystemInfo}->{$oid_fgSysMemCapacity . '.0'} * 1024 }; $self->{memory}->{prct_free} = 100 - $self->{memory}->{prct_used}; $self->{memory}->{used} = int(($self->{memory}->{total} * $self->{memory}->{prct_used}) / 100); $self->{memory}->{free} = $self->{memory}->{total} - $self->{memory}->{used}; if (defined($self->{option_results}->{cluster})) { my $ha_mode = $snmp_result->{$oid_fgHaSystemMode}->{$oid_fgHaSystemMode . '.0'}; my $ha_mode_str = defined($maps_ha_mode->{$ha_mode}) ? $maps_ha_mode->{$ha_mode} : 'unknown'; $self->{output}->output_add(long_msg => 'high availabily mode is ' . $ha_mode_str); if ($ha_mode_str =~ /active/) { $self->memory_ha(snmp => $options{snmp}, snmp_result => $snmp_result); } } } 1; __END__ =head1 MODE Check system memory usage (FORTINET-FORTIGATE). =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'usage-free', 'usage-prct', 'cluster-usage-prct'. =item B<--cluster> Add cluster memory informations. =back =cut centreon-plugins-20220113/centreon/common/fortinet/fortigate/snmp/mode/sdwan.pm000066400000000000000000000343101417000230700275330ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::fortinet::fortigate::snmp::mode::sdwan; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use Digest::MD5 qw(md5_hex); sub prefix_traffic_output { my ($self, %options) = @_; return 'traffic '; } sub sdwan_long_output { my ($self, %options) = @_; return sprintf( "checking sd-wan '%s' [vdom: %s] [interface: %s]", $options{instance_value}->{name}, $options{instance_value}->{vdom}, $options{instance_value}->{ifName} ); } sub prefix_sdwan_output { my ($self, %options) = @_; return sprintf( "sd-wan '%s' [vdom: %s] [interface: %s] ", $options{instance_value}->{name}, $options{instance_value}->{vdom}, $options{instance_value}->{ifName} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'sdwan', type => 3, cb_prefix_output => 'prefix_sdwan_output', cb_long_output => 'sdwan_long_output', indent_long_output => ' ', message_multiple => 'All sd-wan links are ok', group => [ { name => 'status', type => 0, skipped_code => { -10 => 1 } }, { name => 'traffic', type => 0, cb_prefix_output => 'prefix_traffic_output', skipped_code => { -10 => 1 } }, { name => 'latency', type => 0, skipped_code => { -10 => 1 } }, { name => 'jitter', type => 0, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{status} = [ { label => 'status', type => 2, critical_default => '%{state} eq "down"', set => { key_values => [ { name => 'state' }, { name => 'vdom' }, { name => 'ifName' }, { name => 'name' }, { name => 'id' } ], output_template => 'state: %s', closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{traffic} = [ { label => 'traffic-in', nlabel => 'sdwan.traffic.in.bitspersecond', set => { key_values => [ { name => 'in', per_second => 1 }, { name => 'vdom' }, { name => 'name' }, { name => 'ifName' } ], output_template => 'in: %s %s/s', output_change_bytes => 2, closure_custom_perfdata => sub { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel}, unit => 'b/s', instances => [$self->{result_values}->{vdom}, $self->{result_values}->{name}, $self->{result_values}->{ifName}], value => sprintf('%.2f', $self->{result_values}->{in}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}), min => 0 ); } } }, { label => 'traffic-out', nlabel => 'sdwan.traffic.out.bitspersecond', set => { key_values => [ { name => 'out', per_second => 1 }, { name => 'vdom' }, { name => 'name' }, { name => 'ifName' } ], output_template => 'out: %s %s/s', output_change_bytes => 2, closure_custom_perfdata => sub { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel}, unit => 'b/s', instances => [$self->{result_values}->{vdom}, $self->{result_values}->{name}, $self->{result_values}->{ifName}], value => sprintf('%.2f', $self->{result_values}->{out}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}), min => 0 ); } } }, { label => 'traffic-bi', nlabel => 'sdwan.traffic.bi.bitspersecond', set => { key_values => [ { name => 'bi', per_second => 1 }, { name => 'vdom' }, { name => 'name' }, { name => 'ifName' } ], output_template => 'bi: %s %s/s', output_change_bytes => 2, closure_custom_perfdata => sub { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel}, unit => 'b/s', instances => [$self->{result_values}->{vdom}, $self->{result_values}->{name}, $self->{result_values}->{ifName}], value => sprintf('%.2f', $self->{result_values}->{bi}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}), min => 0 ); } } } ]; $self->{maps_counters}->{latency} = [ { label => 'latency', nlabel => 'sdwan.latency.milliseconds', set => { key_values => [ { name => 'latency' }, { name => 'vdom' }, { name => 'name' }, { name => 'ifName' } ], output_template => 'latency: %sms', closure_custom_perfdata => sub { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel}, unit => 'ms', instances => [$self->{result_values}->{vdom}, $self->{result_values}->{name}, $self->{result_values}->{ifName}], value => sprintf('%.2f', $self->{result_values}->{latency}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}), min => 0 ); } } } ]; $self->{maps_counters}->{jitter} = [ { label => 'jitter', nlabel => 'sdwan.jitter.milliseconds', set => { key_values => [ { name => 'jitter' }, { name => 'vdom' }, { name => 'name' }, { name => 'ifName' } ], output_template => 'jitter: %sms', closure_custom_perfdata => sub { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel}, unit => 'ms', instances => [$self->{result_values}->{vdom}, $self->{result_values}->{name}, $self->{result_values}->{ifName}], value => sprintf('%.2f', $self->{result_values}->{jitter}), 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 new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-id:s' => { name => 'filter_id' }, 'filter-name:s' => { name => 'filter_name' }, 'filter-vdom:s' => { name => 'filter_vdom' } }); return $self; } my $mapping_status = { 0 => 'up', 1 => 'down' }; my $mapping = { state => { oid => '.1.3.6.1.4.1.12356.101.4.9.2.1.4', map => $mapping_status }, # fgVWLHealthCheckLinkState latency => { oid => '.1.3.6.1.4.1.12356.101.4.9.2.1.5' }, # fgVWLHealthCheckLinkLatency jitter => { oid => '.1.3.6.1.4.1.12356.101.4.9.2.1.6' }, # fgVWLHealthCheckLinkJitter vdom => { oid => '.1.3.6.1.4.1.12356.101.4.9.2.1.10' }, # fgVWLHealthCheckLinkVdom traffic_in => { oid => '.1.3.6.1.4.1.12356.101.4.9.2.1.11' }, # fgVWLHealthCheckLinkBandwidthIn traffic_out => { oid => '.1.3.6.1.4.1.12356.101.4.9.2.1.12' }, # fgVWLHealthCheckLinkBandwidthOut traffic_bi => { oid => '.1.3.6.1.4.1.12356.101.4.9.2.1.13' }, # fgVWLHealthCheckLinkBandwidthBi ifName => { oid => '.1.3.6.1.4.1.12356.101.4.9.2.1.14' } # fgVWLHealthCheckLinkIfName }; sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = 'fortinet_fortigate_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . $self->{mode} . '_' . md5_hex( (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : 'all') . '_' . (defined($self->{option_results}->{filter_id}) ? md5_hex($self->{option_results}->{filter_id}) : 'all') . '_' . (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : 'all') . '_' . (defined($self->{option_results}->{filter_vdom}) ? md5_hex($self->{option_results}->{filter_vdom}) : 'all') ); if ($options{snmp}->is_snmpv1()) { $self->{output}->add_option_msg(short_msg => "Need to use SNMP v2c or v3."); $self->{output}->option_exit(); } my $oid_name = '.1.3.6.1.4.1.12356.101.4.9.2.1.2'; # fgVWLHealthCheckLinkName my $snmp_result = $options{snmp}->get_table( oid => $oid_name, nothing_quit => 1 ); $self->{sdwan} = {}; foreach (keys %$snmp_result) { /^$oid_name\.(.*)$/; my $id = $1; if (defined($self->{option_results}->{filter_id}) && $self->{option_results}->{filter_id} ne '' && $id !~ /$self->{option_results}->{filter_id}/) { $self->{output}->output_add(long_msg => "skipping sd-wan '" . $snmp_result->{$_} . "'.", debug => 1); next; } if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $snmp_result->{$_} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping sd-wan '" . $snmp_result->{$_} . "'.", debug => 1); next; } $self->{sdwan}->{ $id } = { id => $id, name => $snmp_result->{$_} }; } return if (scalar(keys %{$self->{sdwan}}) <= 0); $options{snmp}->load( oids => [ map($_->{oid}, values(%$mapping)) ], instances => [ map($_, keys(%{$self->{sdwan}})) ], instance_regexp => '^(.*)$' ); $snmp_result = $options{snmp}->get_leef(); foreach (keys %{$self->{sdwan}}) { my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $_); if (defined($self->{option_results}->{filter_vdom}) && $self->{option_results}->{filter_vdom} ne '' && $result->{vdom} !~ /$self->{option_results}->{filter_vdom}/) { $self->{output}->output_add(long_msg => "skipping sd-wan '" . $self->{sdwan}->{$_}->{name} . "'.", debug => 1); next; } $self->{sdwan}->{$_}->{vdom} = $result->{vdom}; $self->{sdwan}->{$_}->{ifName} = $result->{ifName}; $self->{sdwan}->{$_}->{status} = { state => $result->{state}, name => $self->{sdwan}->{$_}->{name}, id => $self->{sdwan}->{$_}->{id}, vdom => $result->{vdom}, ifName => $result->{ifName} }; $self->{sdwan}->{$_}->{traffic} = { name => $self->{sdwan}->{$_}->{name}, vdom => $result->{vdom}, ifName => $result->{ifName}, in => $result->{traffic_in} * 1000 * 1000, out => $result->{traffic_out} * 1000 * 1000, bi => $result->{traffic_bi} * 1000 * 1000, }; $self->{sdwan}->{$_}->{jitter} = { name => $self->{sdwan}->{$_}->{name}, vdom => $result->{vdom}, ifName => $result->{ifName}, jitter => $result->{jitter} }; $self->{sdwan}->{$_}->{latency} = { name => $self->{sdwan}->{$_}->{name}, vdom => $result->{vdom}, ifName => $result->{ifName}, latency => $result->{latency} }; } } 1; __END__ =head1 MODE Check sd-wan links. =over 8 =item B<--filter-id> Filter sd-wan links by ID (can be a regexp). =item B<--filter-name> Filter sd-wan links by name (can be a regexp). =item B<--filter-vdom> Filter sd-wan links by vdom name (can be a regexp). =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{state}, %{vdom}, %{id}, %{name}, %{ifName} =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{state}, %{vdom}, %{id}, %{name}, %{ifName} =item B<--critical-status> Set critical threshold for status (Default: '%{state} eq "down"'). Can used special variables like: %{state}, %{vdom}, %{id}, %{name}, %{ifName} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'traffic-in', 'traffic-out', 'traffic-bi', 'latency', 'jitter'. =back =cut centreon-plugins-20220113/centreon/common/fortinet/fortigate/snmp/mode/sessions.pm000066400000000000000000000105251417000230700302670ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::fortinet::fortigate::snmp::mode::sessions; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_average_output { my ($self, %options) = @_; return 'Average session setup rate: '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'average', type => 0, cb_prefix_output => 'prefix_average_output' }, ]; $self->{maps_counters}->{global} = [ { label => 'active', nlabel => 'sessions.active.count', set => { key_values => [ { name => 'active' } ], output_template => 'Current active sessions: %d', perfdatas => [ { label => 'sessions', template => '%d', min => 0 } ] } } ]; $self->{maps_counters}->{average} = [ { label => 'setup-1min', nlabel => 'sessions.setup.1min.count', set => { key_values => [ { name => 'setup_1min' } ], output_template => '%d (1min)', perfdatas => [ { label => 'session_avg_setup1', template => '%d', min => 0 } ] } }, { label => 'setup-10min', nlabel => 'sessions.setup.10min.count', set => { key_values => [ { name => 'setup_10min' } ], output_template => '%d (10min)', perfdatas => [ { label => 'session_avg_setup10', template => '%d', min => 0 } ] } }, { label => 'setup-30min', nlabel => 'sessions.setup.30min.count', set => { key_values => [ { name => 'setup_30min' } ], output_template => '%d (30min)', perfdatas => [ { label => 'session_avg_setup30', template => '%d', min => 0 } ] } }, { label => 'setup-60min', nlabel => 'sessions.setup.60min.count', set => { key_values => [ { name => 'setup_60min' } ], output_template => '%d (60min)', perfdatas => [ { label => 'session_avg_setup60', template => '%d', min => 0 } ] } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $oid_fgSysSesCount = '.1.3.6.1.4.1.12356.101.4.1.8.0'; my $oid_fgSysSesRate1 = '.1.3.6.1.4.1.12356.101.4.1.11.0'; my $oid_fgSysSesRate10 = '.1.3.6.1.4.1.12356.101.4.1.12.0'; my $oid_fgSysSesRate30 = '.1.3.6.1.4.1.12356.101.4.1.13.0'; my $oid_fgSysSesRate60 = '.1.3.6.1.4.1.12356.101.4.1.14.0'; my $result = $options{snmp}->get_leef( oids => [ $oid_fgSysSesCount, $oid_fgSysSesRate1, $oid_fgSysSesRate10, $oid_fgSysSesRate30, $oid_fgSysSesRate60 ], nothing_quit => 1 ); $self->{global} = { active => $result->{$oid_fgSysSesCount} }; $self->{average} = { setup_1min => $result->{$oid_fgSysSesRate1}, setup_10min => $result->{$oid_fgSysSesRate10}, setup_30min => $result->{$oid_fgSysSesRate30}, setup_60min => $result->{$oid_fgSysSesRate60} }; } 1; __END__ =head1 MODE Check sessions (FORTINET-FORTIGATE-MIB). =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'active', 'setup-1min', 'setup-10min', 'setup-30min', 'setup-60min'. =back =cut centreon-plugins-20220113/centreon/common/fortinet/fortigate/snmp/mode/signatures.pm000066400000000000000000000135331417000230700306070ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::fortinet::fortigate::snmp::mode::signatures; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use POSIX qw(mktime floor); sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'av', type => 0, cb_prefix_output => 'prefix_av_output' }, { name => 'avet', type => 0, cb_prefix_output => 'prefix_avet_output' }, { name => 'ips', type => 0, cb_prefix_output => 'prefix_ips_output' }, { name => 'ipset', type => 0, cb_prefix_output => 'prefix_ipset_output' } ]; $self->{maps_counters}->{av} = [ { label => 'av', set => { key_values => [ { name => 'human' }, { name => 'value' } ], threshold_use => 'value', output_template => "last refresh is: '%s'", perfdatas => [ { label => 'av_update', value => 'value', template => '%d', min => 0, unit => 's' } ] } } ]; $self->{maps_counters}->{avet} = [ { label => 'avet', set => { key_values => [ { name => 'human' }, { name => 'value' } ], threshold_use => 'value', output_template => "last refresh is: '%s'", perfdatas => [ { label => 'avet_update', value => 'value', template => '%d', min => 0, unit => 's' } ] } } ]; $self->{maps_counters}->{ips} = [ { label => 'ips', set => { key_values => [ { name => 'human' }, { name => 'value' } ], threshold_use => 'value', output_template => "last refresh is: '%s'", perfdatas => [ { label => 'ips_update', value => 'value', template => '%d', min => 0, unit => 's' } ] } } ]; $self->{maps_counters}->{ipset} = [ { label => 'ipset', set => { key_values => [ { name => 'human' }, { name => 'value' } ], threshold_use => 'value', output_template => "last refresh is: '%s'", perfdatas => [ { label => 'ipset_update', value => 'value', template => '%d', min => 0, unit => 's' } ] } } ]; } sub prefix_av_output { my ($self, %options) = @_; return 'AV Signature '; } sub prefix_avet_output { my ($self, %options) = @_; return 'AV Extended Signature '; } sub prefix_ips_output { my ($self, %options) = @_; return 'IPS Signature '; } sub prefix_ipset_output { my ($self, %options) = @_; return 'IPS Extended Signature '; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub get_epoch_from_signature { my ($self, %options) = @_; $options{date} =~ /\((\d{4})-(\d{2})-(\d{2})\s(\d{2}):(\d{2})\)/; my ($YYYY,$MM,$DD,$hh,$mm)=($1,$2,$3,$4,$5); return mktime (0, $mm, $hh, $DD, $MM - 1, $YYYY - 1900); } sub manage_selection { my ($self, %options) = @_; my $oid_fgSysVersionAv = '.1.3.6.1.4.1.12356.101.4.2.1.0'; my $oid_fgSysVersionIps = '.1.3.6.1.4.1.12356.101.4.2.2.0'; my $oid_fgSysVersionAvEt = '.1.3.6.1.4.1.12356.101.4.2.3.0'; my $oid_fgSysVersionIpsEt = '.1.3.6.1.4.1.12356.101.4.2.4.0'; my $result = $options{snmp}->get_leef(oids => [$oid_fgSysVersionAv, $oid_fgSysVersionIps, $oid_fgSysVersionAvEt, $oid_fgSysVersionIpsEt], nothing_quit => 1); my $av_epoch = $self->get_epoch_from_signature(date => $result->{$oid_fgSysVersionAv}); my $ips_epoch = $self->get_epoch_from_signature(date => $result->{$oid_fgSysVersionIps}); my $avet_epoch = $self->get_epoch_from_signature(date => $result->{$oid_fgSysVersionAvEt}); my $ipset_epoch = $self->get_epoch_from_signature(date => $result->{$oid_fgSysVersionIpsEt}); my $now = time(); my $av_diff = $now - $av_epoch; my $ips_diff = $now - $ips_epoch; my $avet_diff = $now - $avet_epoch; my $ipset_diff = $now - $ipset_epoch; $self->{av} = { human => centreon::plugins::misc::change_seconds(value => $av_diff, start => 'h'), value => $av_diff }; $self->{ips} = { human => centreon::plugins::misc::change_seconds(value => $ips_diff, start => 'h'), value => $ips_diff }; $self->{avet} = { human => centreon::plugins::misc::change_seconds(value => $avet_diff, start => 'h'), value => $avet_diff }; $self->{ipset} = { human => centreon::plugins::misc::change_seconds(value => $ipset_diff, start => 'h'), value => $ipset_diff }; } 1; __END__ =head1 MODE Check last update/refresh of av and ips signatures =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^av$' =item B<--warning-*> B<--critical-*> Thresholds (in seconds). Can be: 'av', 'ips', 'avet', ipset'. =back =cut centreon-plugins-20220113/centreon/common/fortinet/fortigate/snmp/mode/vdomusage.pm000066400000000000000000000434741417000230700304240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::fortinet::fortigate::snmp::mode::vdomusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); use Digest::MD5 qw(md5_hex); sub custom_status_output { my ($self, %options) = @_; return sprintf( "operation mode is '%s'- HA cluster member state is '%s'", $self->{result_values}->{op_mode}, $self->{result_values}->{ha_state} ); } sub custom_license_output { my ($self, %options) = @_; return sprintf( 'number of virtual domains used: %s/%s (%.2f%%)', $self->{result_values}->{used}, $self->{result_values}->{total}, $self->{result_values}->{prct_used} ); } sub custom_traffic_calc { my ($self, %options) = @_; my ($checked, $total_bits) = (0, 0); foreach (keys %{$options{new_datas}}) { if (/$self->{instance}_traffic_$options{extra_options}->{label_ref}_(\d+)/) { my $new_bits = $options{new_datas}->{$_}; next if (!defined($options{old_datas}->{$_})); my $old_bits = $options{old_datas}->{$_}; $checked = 1; my $diff_bits = $new_bits - $old_bits; if ($diff_bits < 0) { $total_bits += $new_bits; } else { $total_bits += $diff_bits; } } } if ($checked == 0) { $self->{error_msg} = 'buffer creation'; return -1; } $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{traffic_per_second} = $total_bits / $options{delta_time}; $self->{result_values}->{label} = $options{extra_options}->{label_ref}; return 0; } sub vdom_long_output { my ($self, %options) = @_; return "checking virtual domain '" . $options{instance_value}->{display} . "'"; } sub prefix_vdom_output { my ($self, %options) = @_; return "virtual domain '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'vdom', type => 3, cb_prefix_output => 'prefix_vdom_output', cb_long_output => 'vdom_long_output', indent_long_output => ' ', message_multiple => 'All virtual domains are ok', group => [ { name => 'vdom_cpu', type => 0, skipped_code => { -10 => 1 } }, { name => 'vdom_memory', type => 0, skipped_code => { -10 => 1 } }, { name => 'vdom_session', type => 0, skipped_code => { -10 => 1 } }, { name => 'vdom_traffic', type => 0, skipped_code => { -10 => 1 } }, { name => 'vdom_policy', type => 0, skipped_code => { -10 => 1 } }, { name => 'vdom_status', type => 0, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'license-usage', nlabel => 'virtualdomains.license.usage.count', set => { key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_license_output'), perfdatas => [ { template => '%d', min => 0, max => 'total' } ] } }, { label => 'license-free', nlabel => 'virtualdomains.license.free.count', display_ok => 0, set => { key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_license_output'), perfdatas => [ { template => '%d', min => 0, max => 'total' } ] } }, { label => 'license-usage-prct', nlabel => 'virtualdomains.license.usage.percentage', display_ok => 0, set => { key_values => [ { name => 'prct_used' }, { name => 'free' }, { name => 'used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_license_output'), perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%' } ] } } ]; $self->{maps_counters}->{vdom_cpu} = [ { label => 'cpu-utilization', nlabel => 'virtualdomain.cpu.utilization.percentage', set => { key_values => [ { name => 'cpu' }, { name => 'display' } ], output_template => 'cpu usage: %.2f%%', perfdatas => [ { template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1, instance_use => 'display' } ] } } ]; $self->{maps_counters}->{vdom_memory} = [ { label => 'memory-usage-prct', nlabel => 'virtualdomain.memory.usage.percentage', set => { key_values => [ { name => 'prct_used' }, { name => 'display' } ], output_template => 'memory used : %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' } ], } } ]; $self->{maps_counters}->{vdom_policy} = [ { label => 'policies-active', nlabel => 'virtualdomain.policies.active.count', set => { key_values => [ { name => 'active_policies' }, { name => 'display' } ], output_template => 'active policies: %d', perfdatas => [ { template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' }, ] } } ]; $self->{maps_counters}->{vdom_session} = [ { label => 'sessions-active', nlabel => 'virtualdomain.sessions.active.count', set => { key_values => [ { name => 'active_sessions' }, { name => 'display' } ], output_template => 'active sessions: %d', perfdatas => [ { template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' }, ] } }, { label => 'sessions-rate', nlabel => 'virtualdomain.sessions.rate.persecond', set => { key_values => [ { name => 'session_rate' }, { name => 'display' } ], output_template => 'session setup rate: %d/s', perfdatas => [ { template => '%d', min => 0, unit => '/s', label_extra_instance => 1, instance_use => 'display' } ] } } ]; $self->{maps_counters}->{vdom_status} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'op_mode' }, { name => 'ha_state' }, { name => 'display' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } } ]; $self->{maps_counters}->{vdom_traffic} = [ { label => 'traffic-in', nlabel => 'virtualdomain.traffic.in.bitspersecond', set => { key_values => [], manual_keys => 1, closure_custom_calc => $self->can('custom_traffic_calc'), closure_custom_calc_extra_options => { label_ref => 'in' }, output_template => 'traffic in: %s%s/s', output_use => 'traffic_per_second', threshold_use => 'traffic_per_second', output_change_bytes => 2, perfdatas => [ { value => 'traffic_per_second', template => '%s', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display' }, ] } }, { label => 'traffic-out', nlabel => 'virtualdomain.traffic.out.bitspersecond', set => { key_values => [], manual_keys => 1, closure_custom_calc => $self->can('custom_traffic_calc'), closure_custom_calc_extra_options => { label_ref => 'out' }, output_template => 'traffic out: %s%s/s', output_use => 'traffic_per_second', threshold_use => 'traffic_per_second', output_change_bytes => 2, perfdatas => [ { value => 'traffic_per_second', template => '%s', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display' }, ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-vdomain:s' => { name => 'filter_vdomain' }, 'add-traffic' => { name => 'add_traffic' }, 'add-policy' => { name => 'add_policy' }, 'policy-cache-time:s' => { name => 'policy_cache_time', default => 60 }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '' } }); $self->{cache_policy} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); $self->{cache_policy}->check_options(%options) if (defined($self->{option_results}->{add_policy})); } my $map_opmode = { 1 => 'nat', 2 => 'transparent' }; my $map_ha = { 1 => 'master', 2 => 'backup', 3 => 'standalone' }; my $mapping = { fgVdNumber => { oid => '.1.3.6.1.4.1.12356.101.3.1.1' }, fgVdMaxVdoms => { oid => '.1.3.6.1.4.1.12356.101.3.1.2' } }; my $mapping_vdom = { fgVdEntOpMode => { oid => '.1.3.6.1.4.1.12356.101.3.2.1.1.3', map => $map_opmode }, fgVdEntHaState => { oid => '.1.3.6.1.4.1.12356.101.3.2.1.1.4', map => $map_ha }, fgVdEntCpuUsage => { oid => '.1.3.6.1.4.1.12356.101.3.2.1.1.5' }, fgVdEntMemUsage => { oid => '.1.3.6.1.4.1.12356.101.3.2.1.1.6' }, fgVdEntSesCount => { oid => '.1.3.6.1.4.1.12356.101.3.2.1.1.7' }, fgVdEntSesRate => { oid => '.1.3.6.1.4.1.12356.101.3.2.1.1.8' } }; my $oid_fgVdEntName = '.1.3.6.1.4.1.12356.101.3.2.1.1.2'; my $oid_fgVdInfo = '.1.3.6.1.4.1.12356.101.3.1'; my $oid_fgIntfEntVdom = '.1.3.6.1.4.1.12356.101.7.2.1.1.1'; sub add_traffic { my ($self, %options) = @_; my $traffic_in32 = '.1.3.6.1.2.1.2.2.1.10'; my $traffic_out32 = '.1.3.6.1.2.1.2.2.1.16'; my $traffic_in64 = '.1.3.6.1.2.1.31.1.1.1.6'; my $traffic_out64 = '.1.3.6.1.2.1.31.1.1.1.10'; my $snmp_result = $options{snmp}->get_table(oid => $oid_fgIntfEntVdom); my $indexes = {}; foreach (keys %$snmp_result) { /\.(\d+)$/; my $ifindex = $1; if (defined($self->{vdom}->{ $snmp_result->{$_} })) { $indexes->{$ifindex} = $snmp_result->{$_}; } } my ($in_oid, $out_oid) = ($traffic_in32, $traffic_out32); if (!$options{snmp}->is_snmpv1()) { ($in_oid, $out_oid) = ($traffic_in64, $traffic_out64); } $options{snmp}->load( oids => [ $in_oid, $out_oid ], instances => [ keys %$indexes ], instance_regexp => '^(.*)$' ); $snmp_result = $options{snmp}->get_leef(); foreach (keys %$indexes) { next if (!defined($snmp_result->{$in_oid . '.' . $_})); $self->{vdom}->{ $indexes->{$_} }->{vdom_traffic} = { display => $self->{vdom}->{ $indexes->{$_} }->{display} } if (!defined($self->{vdom}->{ $indexes->{$_} }->{vdom_traffic})); $self->{vdom}->{ $indexes->{$_} }->{vdom_traffic}->{'traffic_in_' . $_} = $snmp_result->{$in_oid . '.' . $_} * 8; $self->{vdom}->{ $indexes->{$_} }->{vdom_traffic}->{'traffic_out_' . $_} = $snmp_result->{$out_oid . '.' . $_} * 8; } } sub add_policy { my ($self, %options) = @_; my $oid_fgFwPolID = '.1.3.6.1.4.1.12356.101.5.1.2.1.1.1'; my $has_cache_file = $self->{cache_policy}->read(statefile => 'fortinet_fortigate_policy_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port()); my $timestamp_cache = $self->{cache_policy}->get(name => 'last_timestamp'); my $snmp_result = $self->{cache_policy}->get(name => 'snmp_result'); if ($has_cache_file == 0 || !defined($timestamp_cache) || !defined($snmp_result) || ((time() - $timestamp_cache) > (($self->{option_results}->{policy_cache_time}) * 60))) { $snmp_result = $options{snmp}->get_table(oid => $oid_fgFwPolID); $self->{cache_policy}->write(data => { last_timestamp => time(), snmp_result => $snmp_result }); } foreach (keys %$snmp_result) { /^$oid_fgFwPolID\.(\d+)/; $self->{vdom}->{$1}->{vdom_policy}->{active_policies}++ if (defined($self->{vdom}->{$1})); } } sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_multiple_table( oids => [ { oid => $oid_fgVdInfo }, { oid => $oid_fgVdEntName } ], nothing_quit => 1 ); my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result->{$oid_fgVdInfo}, instance => 0); $self->{global} = { used => $result->{fgVdNumber}, total => $result->{fgVdMaxVdoms}, free => $result->{fgVdMaxVdoms} - $result->{fgVdNumber}, prct_used => $result->{fgVdNumber} * 100 / $result->{fgVdMaxVdoms}, prct_free => 100 - ($result->{fgVdNumber} * 100 / $result->{fgVdMaxVdoms}) }; $self->{vdom} = {}; foreach (keys %{$snmp_result->{$oid_fgVdEntName}}) { /\.(\d+)$/; my $instance = $1; my $name = $snmp_result->{$oid_fgVdEntName}->{$_}; if (defined($self->{option_results}->{filter_vdomain}) && $self->{option_results}->{filter_vdomain} ne '' && $name !~ /$self->{option_results}->{filter_vdomain}/) { $self->{output}->output_add(long_msg => "skipping virtual domain '" . $name . "'.", debug => 1); next; } $self->{vdom}->{$instance} = { display => $name, vdom_cpu => { display => $name }, vdom_memory => { display => $name }, vdom_session => { display => $name }, vdom_status => { display => $name } }; $self->{vdom}->{$instance}->{vdom_policy} = { display => $name, active_policies => 0 } if (defined($self->{option_results}->{add_policy})); } return if (scalar(keys %{$self->{vdom}}) <= 0); $options{snmp}->load( oids => [ map($_->{oid}, values(%$mapping_vdom)) ], instances => [ keys %{$self->{vdom}} ], instance_regexp => '^(.*)$' ); $snmp_result = $options{snmp}->get_leef(); foreach (keys %{$self->{vdom}}) { my $result = $options{snmp}->map_instance(mapping => $mapping_vdom, results => $snmp_result, instance => $_); $self->{vdom}->{$_}->{vdom_cpu}->{cpu} = $result->{fgVdEntCpuUsage}; $self->{vdom}->{$_}->{vdom_memory}->{prct_used} = $result->{fgVdEntMemUsage}; $self->{vdom}->{$_}->{vdom_status}->{op_mode} = $result->{fgVdEntOpMode}; $self->{vdom}->{$_}->{vdom_status}->{ha_state} = $result->{fgVdEntHaState}; $self->{vdom}->{$_}->{vdom_session}->{active_sessions} = $result->{fgVdEntSesCount}; $self->{vdom}->{$_}->{vdom_session}->{session_rate} = $result->{fgVdEntSesRate}; } $self->add_traffic(snmp => $options{snmp}) if (defined($self->{option_results}->{add_traffic})); $self->add_policy(snmp => $options{snmp}) if (defined($self->{option_results}->{add_policy})); $self->{cache_name} = 'fortinet_fortigate_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_vdomain}) ? md5_hex($self->{option_results}->{filter_vdomain}) : md5_hex('all')); } 1; __END__ =head1 MODE Check virtual domains. =over 8 =item B<--filter-vdomain> Filter by virtual domain name (can be a regexp). =item B<--add-traffic> Add traffic usage by virtual domain. =item B<--add-policy> Add number of policies by virtual domain. =item B<--policy-cache-time> Time in minutes before reloading cache file (default: 60). =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{op_mode}, %{ha_state} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{op_mode}, %{ha_state} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'cpu-utilization', 'sessions-active', 'session-rate', 'memory-usage-prct', 'license-usage', 'license-free', 'license-usage-prct', 'traffic-in', 'traffic-out', 'policies-active'. =back =cut centreon-plugins-20220113/centreon/common/fortinet/fortigate/snmp/mode/virus.pm000066400000000000000000000135451417000230700275760ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::fortinet::fortigate::snmp::mode::virus; 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 => 'domain', type => 1, cb_prefix_output => 'prefix_domain_output', message_multiple => 'All virtualdomains virus stats are ok' } ]; $self->{maps_counters}->{domain} = [ { label => 'virus-detected', nlabel => 'domain.virus.detected.count', set => { key_values => [ { name => 'fgAvVirusDetected', diff => 1 }, { name => 'display' } ], output_template => 'virus detected: %s', perfdatas => [ { label => 'virus_detected', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'virus-detected-psec', nlabel => 'domain.virus.detected.persecond', display_ok => 0, set => { key_values => [ { name => 'fgAvVirusDetected', per_second => 1 }, { name => 'display' } ], output_template => 'virus detected: %.2f/s', perfdatas => [ { label => 'domain.virus.detected.persecond', template => '%.2f', unit => '/s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'virus-blocked', nlabel => 'domain.virus.blocked.count', set => { key_values => [ { name => 'fgAvVirusBlocked', diff => 1 }, { name => 'display' } ], output_template => 'virus blocked: %s', perfdatas => [ { label => 'virus_blocked', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'virus-blocked-psec', nlabel => 'domain.virus.blocked.persecond', display_ok => 0, set => { key_values => [ { name => 'fgAvVirusBlocked', per_second => 1 }, { name => 'display' } ], output_template => 'virus blocked: %.2f/s', perfdatas => [ { label => 'domain.virus.blocked.persecond', template => '%.2f', unit => '/s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub prefix_domain_output { my ($self, %options) = @_; return "Domain '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } my $mapping = { fgAvVirusDetected => { oid => '.1.3.6.1.4.1.12356.101.8.2.1.1.1' }, fgAvVirusBlocked => { oid => '.1.3.6.1.4.1.12356.101.8.2.1.1.2' }, }; my $oid_fgAvStatsEntry = '.1.3.6.1.4.1.12356.101.8.2.1.1'; my $oid_fgVdEntName = '.1.3.6.1.4.1.12356.101.3.2.1.1.2'; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_multiple_table( oids => [ { oid => $oid_fgVdEntName }, { oid => $oid_fgAvStatsEntry, end => $mapping->{fgAvVirusBlocked}->{oid} } ], nothing_quit => 1 ); $self->{domain} = {}; foreach my $oid (keys %{$snmp_result->{$oid_fgVdEntName}}) { next if ($oid !~ /^$oid_fgVdEntName\.(.*)/); my $instance = $1; if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $snmp_result->{$oid_fgVdEntName}->{$oid} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $snmp_result->{$oid_fgVdEntName}->{$oid} . "': no matching filter."); next; } my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result->{$oid_fgAvStatsEntry}, instance => $instance); $self->{domain}->{$instance} = $result; $self->{domain}->{$instance}->{display} = $snmp_result->{$oid_fgVdEntName}->{$oid}; } if (scalar(keys %{$self->{domain}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'no domain found.'); $self->{output}->option_exit(); } $self->{cache_name} = "fortinet_fortigate_" . $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 virus blocked and detected. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'virus-detected', ''virus-detected-psec', 'virus-blocked', 'virus-blocked-psec'. =item B<--filter-name> Filter virtual domain name (can be a regexp). =back =cut centreon-plugins-20220113/centreon/common/fortinet/fortigate/snmp/mode/vpn.pm000066400000000000000000000256211417000230700272270ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::fortinet::fortigate::snmp::mode::vpn; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_state_output { my ($self, %options) = @_; return sprintf("state is '%s'", $self->{result_values}->{state}); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'vd', type => 3, cb_prefix_output => 'prefix_vd_output', cb_long_output => 'vd_long_output', indent_long_output => ' ', message_multiple => 'All virtual domains are OK', group => [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'vpn', display_long => 1, cb_prefix_output => 'prefix_vpn_output', message_multiple => 'All vpn are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'users', nlabel => 'vpn.users.logged.count', set => { key_values => [ { name => 'users' } ], output_template => 'Logged users: %s', perfdatas => [ { label => 'users', template => '%d', min => 0, unit => 'users', label_extra_instance => 1 } ] } }, { label => 'sessions', nlabel => 'vpn.websessions.active.count', set => { key_values => [ { name => 'sessions' }], output_template => 'Active web sessions: %s', perfdatas => [ { label => 'sessions', template => '%d', min => 0, unit => 'sessions', label_extra_instance => 1 } ] } }, { label => 'tunnels', nlabel => 'vpn.tunnels.active.count', set => { key_values => [ { name => 'tunnels' } ], output_template => 'Active tunnels: %s', perfdatas => [ { label => 'active_tunnels', template => '%d', min => 0, unit => 'tunnels', label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{vpn} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'state' }, { name => 'display' } ], closure_custom_output => \&custom_state_output, closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } }, { label => 'traffic-in', nlabel => 'vpn.traffic.in.bitspersecond', set => { key_values => [ { name => 'traffic_in', per_second => 1 }, { name => 'display' } ], output_template => 'Traffic in: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'traffic_in', template => '%.2f', min => 0, unit => 'b/s', label_extra_instance => 1 } ] } }, { label => 'traffic-out', nlabel => 'vpn.traffic.out.bitspersecond', set => { key_values => [ { name => 'traffic_out', per_second => 1 }, { name => 'display' } ], output_template => 'Traffic out: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'traffic_out', template => '%.2f', min => 0, unit => 'b/s', label_extra_instance => 1 } ] } } ]; } sub prefix_vd_output { my ($self, %options) = @_; return "Virtual domain '" . $options{instance_value}->{display} . "' "; } sub vd_long_output { my ($self, %options) = @_; return "checking virtual domain '" . $options{instance_value}->{display} . "'"; } sub prefix_vpn_output { my ($self, %options) = @_; return "Link '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-vpn:s' => { name => 'filter_vpn' }, 'filter-vdomain:s' => { name => 'filter_vdomain' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{state} eq "down"' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } my $map_status = { 1 => 'down', 2 => 'up' }; my $mapping = { fgVpnTunEntPhase2Name => { oid => '.1.3.6.1.4.1.12356.101.12.2.2.1.3' }, fgVpnTunEntInOctets => { oid => '.1.3.6.1.4.1.12356.101.12.2.2.1.18' }, fgVpnTunEntOutOctets => { oid => '.1.3.6.1.4.1.12356.101.12.2.2.1.19' }, fgVpnTunEntStatus => { oid => '.1.3.6.1.4.1.12356.101.12.2.2.1.20', map => $map_status }, fgVpnTunEntVdom => { oid => '.1.3.6.1.4.1.12356.101.12.2.2.1.21' } }; my $mapping2 = { fgVpnSslStatsLoginUsers => { oid => '.1.3.6.1.4.1.12356.101.12.2.3.1.2' }, fgVpnSslStatsActiveWebSessions => { oid => '.1.3.6.1.4.1.12356.101.12.2.3.1.4' }, fgVpnSslStatsActiveTunnels => { oid => '.1.3.6.1.4.1.12356.101.12.2.3.1.6' } }; my $oid_fgVpnTunTable = '.1.3.6.1.4.1.12356.101.12.2.2.1'; my $oid_fgVpnSslStatsTable = '.1.3.6.1.4.1.12356.101.12.2.3'; my $oid_fgVdEntName = '.1.3.6.1.4.1.12356.101.3.2.1.1.2'; sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = 'fortigate_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_vpn}) ? md5_hex($self->{option_results}->{filter_vpn}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_vdomain}) ? md5_hex($self->{option_results}->{filter_vdomain}) : md5_hex('all')); my $snmp_result = $options{snmp}->get_multiple_table( oids => [ { oid => $oid_fgVdEntName }, { oid => $oid_fgVpnSslStatsTable } ], nothing_quit => 1 ); my $snmp_result2 = $options{snmp}->get_multiple_table( oids => [ { oid => $mapping->{fgVpnTunEntPhase2Name}->{oid} }, { oid => $oid_fgVpnTunTable, start => $mapping->{fgVpnTunEntInOctets}->{oid} } ], return_type => 1 ); $self->{vd} = {}; my $duplicated = {}; foreach my $oid (keys %{$snmp_result->{ $oid_fgVdEntName }}) { $oid =~ /^$oid_fgVdEntName\.(.*)$/; my $vdom_instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping2, results => $snmp_result->{$oid_fgVpnSslStatsTable}, instance => $vdom_instance); my $vdomain_name = $snmp_result->{$oid_fgVdEntName}->{$oid_fgVdEntName . '.' . $vdom_instance}; if (defined($self->{option_results}->{filter_vdomain}) && $self->{option_results}->{filter_vdomain} ne '' && $vdomain_name !~ /$self->{option_results}->{filter_vdomain}/) { $self->{output}->output_add(long_msg => "skipping '" . $vdomain_name . "': no matching filter.", debug => 1); next; } $self->{vd}->{$vdomain_name} = { display => $vdomain_name, global => { users => $result->{fgVpnSslStatsLoginUsers}, tunnels => $result->{fgVpnSslStatsActiveTunnels}, sessions => $result->{fgVpnSslStatsActiveWebSessions} }, vpn => {}, }; foreach (keys %$snmp_result2) { next if (! /^$mapping->{fgVpnTunEntVdom}->{oid}\.(.*)$/ || $snmp_result2->{$_} != $vdom_instance ); my $instance = $1; $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result2, instance => $instance); if (defined($self->{option_results}->{filter_vpn}) && $self->{option_results}->{filter_vpn} ne '' && $result->{fgVpnTunEntPhase2Name} !~ /$self->{option_results}->{filter_vpn}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{fgVpnTunEntPhase2Name} . "': no matching filter.", debug => 1); next; } my $name = $result->{fgVpnTunEntPhase2Name}; $name .= '.' . $instance if (defined($duplicated->{$name})); if (defined($self->{vd}->{$vdomain_name}->{vpn}->{$name})) { $duplicated->{$name} = 1; $self->{vd}->{$vdomain_name}->{vpn}->{$name . '.' . $self->{vd}->{$vdomain_name}->{vpn}->{$name}->{instance}} = $self->{vd}->{$vdomain_name}->{vpn}->{$name}; $self->{vd}->{$vdomain_name}->{vpn}->{$name . '.' . $self->{vd}->{$vdomain_name}->{vpn}->{$name}->{instance}}->{display} = $name . '.' . $self->{vd}->{$vdomain_name}->{vpn}->{$name}->{instance}; delete $self->{vd}->{$vdomain_name}->{vpn}->{$name}; $name = $result->{fgVpnTunEntPhase2Name} . '.' . $instance; } $self->{vd}->{$vdomain_name}->{vpn}->{$name} = { display => $name, instance => $instance, state => $result->{fgVpnTunEntStatus}, traffic_in => $result->{fgVpnTunEntInOctets} * 8, traffic_out => $result->{fgVpnTunEntOutOctets} * 8 }; } } } 1; __END__ =head1 MODE Check Vdomain statistics and VPN state and traffic =over 8 =item B<--filter-*> Filter name with regexp. Can be ('vdomain', 'vpn') =item B<--warning-*> Warning on counters. Can be ('users', 'sessions', 'tunnels', 'traffic-in', 'traffic-out') =item B<--critical-*> Warning on counters. Can be ('users', 'sessions', 'tunnels', 'traffic-in', 'traffic-out') =item B<--warning-status> Set warning threshold for status. Use "%{state}" as a special variable. Useful to be notified when tunnel is up "%{state} eq 'up'" =item B<--critical-status> Set critical threshold for status. Use "%{state}" as a special variable. Useful to be notified when tunnel is up "%{state} eq 'up'" =back =cut centreon-plugins-20220113/centreon/common/foundry/000077500000000000000000000000001417000230700220275ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/foundry/snmp/000077500000000000000000000000001417000230700230045ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/foundry/snmp/mode/000077500000000000000000000000001417000230700237305ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/foundry/snmp/mode/components/000077500000000000000000000000001417000230700261155ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/foundry/snmp/mode/components/board.pm000066400000000000000000000061011417000230700275400ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::foundry::snmp::mode::components::board; use strict; use warnings; my $mapping_board_status = { 0 => 'moduleEmpty', 2 => 'moduleGoingDown', 3 => 'moduleRejected', 4 => 'moduleBad', 8 => 'moduleConfigured', 9 => 'moduleComingUp', 10 => 'moduleRunning' }; my $mapping = { snAgentBrdMainBrdDescription => { oid => '.1.3.6.1.4.1.1991.1.1.2.2.1.1.2' }, snAgentBrdModuleStatus => { oid => '.1.3.6.1.4.1.1991.1.1.2.2.1.1.12', map => $mapping_board_status } }; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping->{snAgentBrdMainBrdDescription}->{oid} }, { oid => $mapping->{snAgentBrdModuleStatus}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => 'checking boards'); $self->{components}->{board} = { name => 'boards', total => 0, skip => 0 }; return if ($self->check_filter(section => 'board')); my $result = { %{$self->{results}->{ $mapping->{snAgentBrdMainBrdDescription}->{oid} }}, %{$self->{results}->{ $mapping->{snAgentBrdModuleStatus}->{oid} }} }; foreach my $oid ($self->{snmp}->oid_lex_sort(keys %$result)) { next if ($oid !~ /^$mapping->{snAgentBrdModuleStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $result, instance => $instance); next if ($self->check_filter(section => 'board', instance => $instance)); $self->{components}->{board}->{total}++; $self->{output}->output_add( long_msg => sprintf( "board '%s' status is '%s' [instance: %s].", $result->{snAgentBrdMainBrdDescription}, $result->{snAgentBrdModuleStatus}, $instance ) ); my $exit = $self->get_severity(section => 'board', value => $result->{snAgentBrdModuleStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "board '%s' status is '%s'", $result->{snAgentBrdMainBrdDescription}, $result->{snAgentBrdModuleStatus} ) ); } } } 1; centreon-plugins-20220113/centreon/common/foundry/snmp/mode/components/fan.pm000066400000000000000000000054331417000230700272240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::foundry::snmp::mode::components::fan; use strict; use warnings; use centreon::common::foundry::snmp::mode::components::resources qw($map_status); my $mapping = { snChasFan2Description => { oid => '.1.3.6.1.4.1.1991.1.1.1.3.2.1.3' }, snChasFan2OperStatus => { oid => '.1.3.6.1.4.1.1991.1.1.1.3.2.1.4', map => $map_status } }; my $oid_snChasFan2Entry = '.1.3.6.1.4.1.1991.1.1.1.3.2.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_snChasFan2Entry, start => $mapping->{snChasFan2Description}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => 'checking fans'); $self->{components}->{fan} = { name => 'fans', total => 0, skip => 0 }; return if ($self->check_filter(section => 'fan')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_snChasFan2Entry}})) { next if ($oid !~ /^$mapping->{snChasFan2OperStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_snChasFan2Entry}, instance => $instance); next if ($self->check_filter(section => 'fan', instance => $instance)); $self->{components}->{fan}->{total}++; $self->{output}->output_add( long_msg => sprintf( "fan '%s' status is '%s' [instance = %s]", $result->{snChasFan2Description}, $result->{snChasFan2OperStatus}, $instance ) ); my $exit = $self->get_severity(label => 'default', section => 'fan', value => $result->{snChasFan2OperStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "fan '%s' status is '%s'", $result->{snChasFan2Description}, $result->{snChasFan2OperStatus} ) ); } } } 1; centreon-plugins-20220113/centreon/common/foundry/snmp/mode/components/psu.pm000066400000000000000000000056641417000230700272750ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::foundry::snmp::mode::components::psu; use strict; use warnings; use centreon::common::foundry::snmp::mode::components::resources qw($map_status); my $mapping = { snChasPwrSupply2Description => { oid => '.1.3.6.1.4.1.1991.1.1.1.2.2.1.3' }, snChasPwrSupply2OperStatus => { oid => '.1.3.6.1.4.1.1991.1.1.1.2.2.1.4', map => $map_status } }; my $oid_snChasPwrSupply2Entry = '.1.3.6.1.4.1.1991.1.1.1.2.2.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_snChasPwrSupply2Entry, start => $mapping->{snChasPwrSupply2Description}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => 'checking power supplies'); $self->{components}->{psu} = { name => 'psu', total => 0, skip => 0 }; return if ($self->check_filter(section => 'psu')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_snChasPwrSupply2Entry}})) { next if ($oid !~ /^$mapping->{snChasPwrSupply2OperStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_snChasPwrSupply2Entry}, 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' status is '%s' [instance: %s].", $result->{snChasPwrSupply2Description}, $result->{snChasPwrSupply2OperStatus}, $instance ) ); my $exit = $self->get_severity(label => 'default', section => 'psu', value => $result->{snChasPwrSupply2OperStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "power supply '%s' status is '%s'", $result->{snChasPwrSupply2Description}, $result->{snChasPwrSupply2OperStatus} ) ); } } } 1; centreon-plugins-20220113/centreon/common/foundry/snmp/mode/components/resources.pm000066400000000000000000000017751417000230700304770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::foundry::snmp::mode::components::resources; use strict; use warnings; use Exporter; our $map_status; our @ISA = qw(Exporter); our @EXPORT_OK = qw($map_status); $map_status = { 1 => 'other', 2 => 'normal', 3 => 'failure' }; 1; centreon-plugins-20220113/centreon/common/foundry/snmp/mode/components/temperature.pm000066400000000000000000000101341417000230700310070ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::foundry::snmp::mode::components::temperature; use strict; use warnings; my $mapping = { snChasActualTemperature => { oid => '.1.3.6.1.4.1.1991.1.1.1.1.18' }, snChasWarningTemperature => { oid => '.1.3.6.1.4.1.1991.1.1.1.1.19' }, snChasShutdownTemperature => { oid => '.1.3.6.1.4.1.1991.1.1.1.1.20' } }; my $oid_snChasGen = '.1.3.6.1.4.1.1991.1.1.1.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_snChasGen, start => $mapping->{snChasActualTemperature}->{oid}, end => $mapping->{snChasShutdownTemperature}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => 'Checking temperatures'); $self->{components}->{temperature} = { name => 'temperatures', total => 0, skip => 0 }; return if ($self->check_filter(section => 'temperature')); my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_snChasGen}, instance => '0'); my ($name, $instance) = ('chassi', 1); next if ($self->check_filter(section => 'temperature', instance => $instance)); $self->{components}->{temperature}->{total}++; $result->{snChasActualTemperature} *= 0.5; $result->{snChasWarningTemperature} *= 0.5; $result->{snChasShutdownTemperature} *= 0.5; $self->{output}->output_add( long_msg => sprintf( "temperature '%s' is %s celsius [instance = %s]", $name, $result->{snChasActualTemperature}, $instance ) ); my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $instance, value => $result->{snChasActualTemperature}); if ($checked == 0) { my $warn_th = defined($result->{snChasWarningTemperature}) ? $result->{snChasWarningTemperature} : ''; my $crit_th = defined($result->{snChasShutdownTemperature}) ? $result->{snChasShutdownTemperature} : ''; $self->{perfdata}->threshold_validate(label => 'warning-temperature-instance-' . $instance, value => $warn_th); $self->{perfdata}->threshold_validate(label => 'critical-temperature-instance-' . $instance, value => $crit_th); $exit = $self->{perfdata}->threshold_check( value => $result->{snChasActualTemperature}, threshold => [ { label => 'critical-temperature-instance-' . $instance, exit_litteral => 'critical' }, { label => 'warning-temperature-instance-' . $instance, exit_litteral => 'warning' } ] ); $warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-temperature-instance-' . $instance); $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-temperature-instance-' . $instance) } if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "temperature '%s' is %s celsius", $name, $result->{snChasActualTemperature} ) ); } $self->{output}->perfdata_add( nlabel => 'hardware.temperature.celsius', unit => 'C', instances => $name, value => $result->{snChasActualTemperature}, warning => $warn, critical => $crit ); } 1; centreon-plugins-20220113/centreon/common/foundry/snmp/mode/cpu.pm000066400000000000000000000073541417000230700250660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::foundry::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 CPUs are ok' } ]; $self->{maps_counters}->{cpu} = [ { label => 'utilization-5s', nlabel => 'cpu.utilization.5s.percentage', set => { key_values => [ { name => 'cpu_5s' }, { name => 'display' } ], output_template => '%.2f %% (5s)', perfdatas => [ { value => 'cpu_5s', template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1 } ] } }, { label => 'utilization-1m', nlabel => 'cpu.utilization.1m.percentage', set => { key_values => [ { name => 'cpu_1m' }, { name => 'display' } ], output_template => '%.2f %% (1m)', perfdatas => [ { value => 'cpu_1m', template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1 } ] } }, { label => 'utilization-5m', nlabel => 'cpu.utilization.5m.percentage', set => { key_values => [ { name => 'cpu_5m' }, { name => 'display' } ], output_template => '%.2f %% (5m)', perfdatas => [ { value => 'cpu_5m', template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1 } ] } } ]; } sub prefix_cpu_output { my ($self, %options) = @_; return "CPU '" . $options{instance_value}->{display} . "' usage: "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $oid_snAgentCpuUtilPercent = '.1.3.6.1.4.1.1991.1.1.2.11.1.1.5'; my $snmp_result = $options{snmp}->get_table(oid => $oid_snAgentCpuUtilPercent, nothing_quit => 1); $self->{cpu} = {}; foreach my $oid (keys %$snmp_result) { next if ($oid !~ /^$oid_snAgentCpuUtilPercent\.(.*?)\.(.*?)\.60/); my $instance = "slot$1:cpu$2"; $self->{cpu}->{$instance} = { display => $instance, cpu_5s => $snmp_result->{ $oid_snAgentCpuUtilPercent . '.' . $1 . '.' . $2 . '.5' }, cpu_1m => $snmp_result->{ $oid_snAgentCpuUtilPercent . '.' . $1 . '.' . $2 . '.60' }, cpu_5m => $snmp_result->{ $oid_snAgentCpuUtilPercent . '.' . $1 . '.' . $2 . '.300' } }; } } 1; __END__ =head1 MODE Check CPU usage. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'utilization-5s', 'utilization-1m', 'utilization-5m'. =back =cut centreon-plugins-20220113/centreon/common/foundry/snmp/mode/hardware.pm000066400000000000000000000060211417000230700260620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::foundry::snmp::mode::hardware; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^(?:temperature)$'; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { default => [ ['other', 'UNKNOWN'], ['normal', 'OK'], ['failure', 'CRITICAL'] ], board => [ ['moduleEmpty', 'OK'], ['moduleGoingDown', 'WARNING'], ['moduleRejected', 'CRITICAL'], ['moduleBad', 'CRITICAL'], ['moduleConfigured', 'OK'], ['moduleComingUp', 'OK'], ['moduleRunning', 'OK'] ] }; $self->{components_path} = 'centreon::common::foundry::snmp::mode::components'; $self->{components_module} = ['board', 'fan', 'psu', 'temperature']; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $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, force_new_perfdata => 1); bless $self, $class; $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: 'board', 'fan', 'temperature', 'psu'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=fan --filter=psu) Can also exclude specific instance: --filter=fan,1.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,fail' =item B<--warning> Set warning threshold for 'temperature' (syntax: type,regexp,threshold) Example: --warning='temperature,.*,30' =item B<--critical> Set critical threshold for 'temperature' (syntax: type,regexp,threshold) Example: --critical='temperature,.*,50' =back =cut centreon-plugins-20220113/centreon/common/foundry/snmp/mode/memory.pm000066400000000000000000000104751417000230700256050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::foundry::snmp::mode::memory; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_usage_output { my ($self, %options) = @_; return sprintf( 'Ram total: %s %s used: %s %s (%.2f%%) free: %s %s (%.2f%%)', $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}), $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}), $self->{result_values}->{prct_used}, $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}), $self->{result_values}->{prct_free} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'memory', type => 0 } ]; $self->{maps_counters}->{memory} = [ { label => 'usage', nlabel => 'memory.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { value => 'used', template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1 } ] } }, { label => 'usage-free', display_ok => 0, nlabel => 'memory.free.bytes', set => { key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { value => 'free', template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1 } ] } }, { label => 'usage-prct', display_ok => 0, nlabel => 'memory.usage.percentage', set => { key_values => [ { name => 'prct_used' } ], output_template => 'Ram used: %.2f %%', perfdatas => [ { value => 'prct_used', template => '%.2f', min => 0, max => 100, unit => '%' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my $mapping = { total => { oid => '.1.3.6.1.4.1.20301.2.5.1.2.12.9.1.1.3' }, # totalMemoryStatsRev free => { oid => '.1.3.6.1.4.1.20301.2.5.1.2.12.9.1.1.4' } # memoryFreeStatsRev }; my $oid_memoryStatsEntry = '.1.3.6.1.4.1.20301.2.5.1.2.12.9.1.1'; sub manage_selection { my ($self, %options) = @_; my $oid_snAgGblDynMemUtil = '.1.3.6.1.4.1.1991.1.1.2.1.53.0'; # % my $oid_snAgGblDynMemTotal = '.1.3.6.1.4.1.1991.1.1.2.1.54.0'; # Bytes my $snmp_result = $options{snmp}->get_leef( oids => [$oid_snAgGblDynMemUtil, $oid_snAgGblDynMemTotal], nothing_quit => 1 ); my $used = $snmp_result->{$oid_snAgGblDynMemUtil} * $snmp_result->{$oid_snAgGblDynMemTotal} / 100; $self->{memory} = { prct_used => $snmp_result->{$oid_snAgGblDynMemUtil}, prct_free => 100 - $snmp_result->{$oid_snAgGblDynMemUtil}, total => $snmp_result->{$oid_snAgGblDynMemTotal}, used => $used, free => $snmp_result->{$oid_snAgGblDynMemTotal} - $used }; } 1; __END__ =head1 MODE Check memory usage. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'usage' (B), 'usage-free' (B), 'usage-prct' (%). =back =cut centreon-plugins-20220113/centreon/common/frogfoot/000077500000000000000000000000001417000230700221665ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/frogfoot/snmp/000077500000000000000000000000001417000230700231435ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/frogfoot/snmp/mode/000077500000000000000000000000001417000230700240675ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/frogfoot/snmp/mode/load.pm000066400000000000000000000065371417000230700253570ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and alarm 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::frogfoot::snmp::mode::load; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_load_output { my ($self, %options) = @_; return 'Load average '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'loadaverage', type => 0, cb_prefix_output => 'prefix_load_output', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{loadaverage} = [ { label => 'load1', nlabel => 'system.loadaverage.1m.count', set => { key_values => [ { name => 'load1' } ], output_template => '%.2f (1m)', perfdatas => [ { template => '%.2f', min => 0 } ] } }, { label => 'load5', nlabel => 'system.loadaverage.5m.count', set => { key_values => [ { name => 'load5' } ], output_template => '%.2f (5m)', perfdatas => [ { template => '%.2f', min => 0 } ] } }, { label => 'load15', nlabel => 'system.loadaverage.15m.count', set => { key_values => [ { name => 'load15' } ], output_template => '%.2f (15m)', perfdatas => [ { template => '%.2f', min => 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 => { }); return $self; } my $mapping = { load_descr => { oid => '.1.3.6.1.4.1.10002.1.1.1.4.2.1.2' }, # loadDescr load_value => { oid => '.1.3.6.1.4.1.10002.1.1.1.4.2.1.3' } # loadValue }; sub manage_selection { my ($self, %options) = @_; my $oid_load_entry = '.1.3.6.1.4.1.10002.1.1.1.4.2.1'; # loadEntry my $snmp_result = $options{snmp}->get_table( oid => $oid_load_entry, start => $mapping->{load_descr}->{oid}, nothing_quit => 1 ); $self->{loadaverage} = {}; foreach (keys %$snmp_result) { next if (! /^$mapping->{load_descr}->{oid}\.(\d+)$/); my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $1); if ($result->{load_descr} =~ /(\d+)/) { $self->{loadaverage}->{'load' . $1} = $result->{load_value}; } } }; 1; __END__ =head1 MODE Check the load average. =over 8 =item B<--warning-*> B<--critical-*> Thresholds where '*' can be: load1, load5, load15 =back =cut centreon-plugins-20220113/centreon/common/frogfoot/snmp/mode/memory.pm000066400000000000000000000076251417000230700257470ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::frogfoot::snmp::mode::memory; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_usage_output { my ($self, %options) = @_; return sprintf( 'Memory total: %s %s used: %s %s (%.2f%%) free: %s %s (%.2f%%)', $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}), $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}), $self->{result_values}->{prct_used}, $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}), $self->{result_values}->{prct_free} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'memory', type => 0, skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{memory} = [ { label => 'usage', nlabel => 'memory.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1 } ] } }, { label => 'usage-free', display_ok => 0, nlabel => 'memory.free.bytes', set => { key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1 } ] } }, { label => 'usage-prct', display_ok => 0, nlabel => 'memory.usage.percentage', set => { key_values => [ { name => 'prct_used' }, { name => 'used' }, { name => 'free' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; return $self; } sub manage_selection { my ($self, %options) = @_; my $oid_memTotal = '.1.3.6.1.4.1.10002.1.1.1.1.1.0'; # KB my $oid_memFree = '.1.3.6.1.4.1.10002.1.1.1.1.2.0'; # KB my $result = $options{snmp}->get_leef(oids => [$oid_memTotal, $oid_memFree], nothing_quit => 1); my $free = $result->{$oid_memFree} * 1024; my $total = $result->{$oid_memTotal} * 1024; my $prct_used = ($total - $free) * 100 / $total; $self->{memory} = { total => $total, used => $total - $free, free => $free, prct_used => $prct_used, prct_free => 100 - $prct_used } } 1; __END__ =head1 MODE Check memory usage. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'usage' (B), 'usage-free' (B), 'usage-prct' (%). =back =cut centreon-plugins-20220113/centreon/common/h3c/000077500000000000000000000000001417000230700210165ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/h3c/snmp/000077500000000000000000000000001417000230700217735ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/h3c/snmp/mode/000077500000000000000000000000001417000230700227175ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/h3c/snmp/mode/components/000077500000000000000000000000001417000230700251045ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/h3c/snmp/mode/components/default.pm000066400000000000000000000064541417000230700270770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::h3c::snmp::mode::components::default; use strict; use warnings; my %map_default_status = ( 1 => 'notSupported', 2 => 'normal', 3 => 'postFailure', 4 => 'entityAbsent', 11 => 'poeError', 21 => 'stackError', 22 => 'stackPortBlocked', 23 => 'stackPortFailed', 31 => 'sfpRecvError', 32 => 'sfpSendError', 33 => 'sfpBothError', 41 => 'fanError', 51 => 'psuError', 61 => 'rpsError', 71 => 'moduleFaulty', 81 => 'sensorError', 91 => 'hardwareFaulty', ); sub check { my ($self, %options) = @_; $self->{output}->output_add(long_msg => "Checking " . $options{component}); $self->{components}->{$options{component}} = {name => $options{component}, total => 0, skip => 0}; return if ($self->check_filter(section => $options{component})); my $mapping = { EntityExtErrorStatus => { oid => $self->{branch} . '.19', map => \%map_default_status }, }; foreach my $instance (sort $self->get_instance_class(class => { $options{component_class} => 1 })) { my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$self->{branch} . '.19'}, instance => $instance); next if (!defined($result->{EntityExtErrorStatus})); next if ($self->check_filter(section => $options{component}, instance => $instance)); if ($result->{EntityExtErrorStatus} =~ /entityAbsent/i) { $self->absent_problem(section => $options{component}, instance => $instance); next; } my $name = ''; $name = $self->get_short_name(instance => $instance) if (defined($self->{short_name}) && $self->{short_name} == 1); $name = $self->get_long_name(instance => $instance) unless (defined($self->{short_name}) && $self->{short_name} == 1 && defined($name) && $name ne ''); $self->{components}->{$options{component}}->{total}++; $self->{output}->output_add(long_msg => sprintf("%s '%s' status is '%s' [instance = %s]", ucfirst($options{component}), $name, $result->{EntityExtErrorStatus}, $instance)); my $exit = $self->get_severity(section => $options{component}, value => $result->{EntityExtErrorStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("%s '%s' status is '%s'", $options{component}, $name, $result->{EntityExtErrorStatus})); } } } 1;centreon-plugins-20220113/centreon/common/h3c/snmp/mode/components/fan.pm000066400000000000000000000054501417000230700262120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::h3c::snmp::mode::components::fan; use strict; use warnings; my %map_fan_status = ( 1 => 'notSupported', 2 => 'normal', 4 => 'entityAbsent', 41 => 'fanError', 91 => 'hardwareFaulty', ); sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking fans"); $self->{components}->{fan} = {name => 'fans', total => 0, skip => 0}; return if ($self->check_filter(section => 'fan')); my $mapping = { EntityExtErrorStatus => { oid => $self->{branch} . '.19', map => \%map_fan_status }, }; foreach my $instance (sort $self->get_instance_class(class => { 7 => 1 })) { my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$self->{branch} . '.19'}, instance => $instance); next if (!defined($result->{EntityExtErrorStatus})); next if ($self->check_filter(section => 'fan', instance => $instance)); if ($result->{EntityExtErrorStatus} =~ /entityAbsent/i) { $self->absent_problem(section => 'fan', instance => $instance); next; } my $name = ''; $name = $self->get_short_name(instance => $instance) if (defined($self->{short_name}) && $self->{short_name} == 1); $name = $self->get_long_name(instance => $instance) unless (defined($self->{short_name}) && $self->{short_name} == 1 && defined($name) && $name ne ''); $self->{components}->{fan}->{total}++; $self->{output}->output_add(long_msg => sprintf("Fan '%s' status is '%s' [instance = %s]", $name, $result->{EntityExtErrorStatus}, $instance)); my $exit = $self->get_severity(section => 'fan', value => $result->{EntityExtErrorStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Fan '%s' status is '%s'", $name, $result->{EntityExtErrorStatus})); } } } 1;centreon-plugins-20220113/centreon/common/h3c/snmp/mode/components/psu.pm000066400000000000000000000055171417000230700262610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::h3c::snmp::mode::components::psu; use strict; use warnings; my %map_psu_status = ( 1 => 'notSupported', 2 => 'normal', 4 => 'entityAbsent', 51 => 'psuError', 91 => 'hardwareFaulty', ); sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking power supplies"); $self->{components}->{psu} = {name => 'power supplies', total => 0, skip => 0}; return if ($self->check_filter(section => 'psu')); my $mapping = { EntityExtErrorStatus => { oid => $self->{branch} . '.19', map => \%map_psu_status }, }; foreach my $instance (sort $self->get_instance_class(class => { 6 => 1 }) ) { my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$self->{branch} . '.19'}, instance => $instance); next if (!defined($result->{EntityExtErrorStatus})); next if ($self->check_filter(section => 'psu', instance => $instance)); if ($result->{EntityExtErrorStatus} =~ /entityAbsent/i) { $self->absent_problem(section => 'psu', instance => $instance); next; } my $name = ''; $name = $self->get_short_name(instance => $instance) if (defined($self->{short_name}) && $self->{short_name} == 1); $name = $self->get_long_name(instance => $instance) unless (defined($self->{short_name}) && $self->{short_name} == 1 && defined($name) && $name ne ''); $self->{components}->{psu}->{total}++; $self->{output}->output_add(long_msg => sprintf("Power supply '%s' status is '%s' [instance = %s]", $name, $result->{EntityExtErrorStatus}, $instance)); my $exit = $self->get_severity(section => 'psu', value => $result->{EntityExtErrorStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Power supply '%s' status is '%s'", $name, $result->{EntityExtErrorStatus})); } } } 1;centreon-plugins-20220113/centreon/common/h3c/snmp/mode/components/sensor.pm000066400000000000000000000130261417000230700267550ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::h3c::snmp::mode::components::sensor; use strict; use warnings; my %map_sensor_status = ( 1 => 'notSupported', 2 => 'normal', 4 => 'entityAbsent', 81 => 'sensorError', 91 => 'hardwareFaulty', ); 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 $mapping = { EntityExtErrorStatus => { oid => $self->{branch} . '.19', map => \%map_sensor_status }, }; my $mapping2 = { EntityExtTemperature => { oid => $self->{branch} . '.12' }, EntityExtTemperatureThreshold => { oid => $self->{branch} . '.13' }, }; my @instances = $self->get_instance_class(class => { 8 => 1 }); return if (scalar(@instances) == 0); $self->{snmp}->load(oids => [$mapping2->{EntityExtTemperature}->{oid}, $mapping2->{EntityExtTemperatureThreshold}->{oid}], instances => [@instances]); my $results = $self->{snmp}->get_leef(); my ($exit, $warn, $crit, $checked); foreach my $instance (sort @instances) { my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$self->{branch} . '.19'}, instance => $instance); my $result2 = $self->{snmp}->map_instance(mapping => $mapping2, results => $results, instance => $instance); next if (!defined($result->{EntityExtErrorStatus})); next if ($self->check_filter(section => 'sensor', instance => $instance)); if ($result->{EntityExtErrorStatus} =~ /entityAbsent/i) { $self->absent_problem(section => 'sensor', instance => $instance); next; } my $name = ''; $name = $self->get_short_name(instance => $instance) if (defined($self->{short_name}) && $self->{short_name} == 1); $name = $self->get_long_name(instance => $instance) unless (defined($self->{short_name}) && $self->{short_name} == 1 && defined($name) && $name ne ''); $self->{components}->{sensor}->{total}++; $self->{output}->output_add(long_msg => sprintf("Sensor '%s' status is '%s' [instance = %s]", $name, $result->{EntityExtErrorStatus}, $instance)); $exit = $self->get_severity(section => 'sensor', value => $result->{EntityExtErrorStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Sensor '%s' status is '%s'", $name, $result->{EntityExtErrorStatus})); } next if (defined($result2->{EntityExtTemperature}) && $result2->{EntityExtTemperature} <= 0); ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $instance, value => $result2->{EntityExtTemperature}); if ($checked == 0 && defined($result2->{EntityExtTemperatureThreshold}) && $result2->{EntityExtTemperatureThreshold} > 0 && $result2->{EntityExtTemperatureThreshold} < 65535) { my $crit_th = '~:' . $result2->{EntityExtTemperatureThreshold}; $self->{perfdata}->threshold_validate(label => 'warning-temperature-instance-' . $instance, value => undef); $self->{perfdata}->threshold_validate(label => 'critical-temperature-instance-' . $instance, value => $crit_th); $exit = $self->{perfdata}->threshold_check(value => $result2->{EntityExtTemperature}, threshold => [ { label => 'critical-temperature-instance-' . $instance, exit_litteral => 'critical' }, { label => 'warning-temperature-instance-' . $instance, exit_litteral => 'warning' } ]); $warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-temperature-instance-' . $instance); $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-temperature-instance-' . $instance); } if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Temperature sensor '%s' is %s degree centigrade", $name, $result2->{EntityExtTemperature})); } $self->{output}->perfdata_add( label => 'temp', unit => 'C', nlabel => 'hardware.sensor.temperature.celsius', instances => $instance, value => $result2->{EntityExtTemperature}, warning => $warn, critical => $crit, ); } } 1; centreon-plugins-20220113/centreon/common/h3c/snmp/mode/cpu.pm000066400000000000000000000154761417000230700240610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::h3c::snmp::mode::cpu; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::statefile; 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', nlabel => 'cpu.utilization.percentage', set => { key_values => [ { name => 'EntityExtCpuUsage' }, { name => 'num' }, ], output_template => ' : %.2f %%', perfdatas => [ { label => 'cpu', value => 'EntityExtCpuUsage', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'num' }, ], } }, ]; } sub prefix_cpu_output { my ($self, %options) = @_; return "CPU '" . $options{instance_value}->{num} . "' Usage "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "reload-cache-time:s" => { name => 'reload_cache_time', default => 180 }, "display-entity-name" => { name => 'display_entity_name' }, }); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{statefile_cache}->check_options(%options); } my $oid_entPhysicalEntry = '.1.3.6.1.2.1.47.1.1.1.1'; my $oid_entPhysicalDescr = '.1.3.6.1.2.1.47.1.1.1.1.2'; my $oid_entPhysicalContainedIn = '.1.3.6.1.2.1.47.1.1.1.1.4'; my $oid_entPhysicalClass = '.1.3.6.1.2.1.47.1.1.1.1.5'; my $oid_entPhysicalName = '.1.3.6.1.2.1.47.1.1.1.1.7'; sub check_cache { my ($self, %options) = @_; $self->{hostname} = $self->{snmp}->get_hostname(); $self->{snmp_port} = $self->{snmp}->get_port(); # init cache file $self->{write_cache} = 0; my $has_cache_file = $self->{statefile_cache}->read(statefile => 'cache_h3c_entity_' . $self->{hostname} . '_' . $self->{snmp_port}); my $timestamp_cache = $self->{statefile_cache}->get(name => 'last_timestamp'); if ($has_cache_file == 0 || !defined($timestamp_cache) || ((time() - $timestamp_cache) > (($self->{option_results}->{reload_cache_time}) * 60))) { push @{$self->{snmp_request}}, { oid => $oid_entPhysicalEntry, start => $oid_entPhysicalDescr, end => $oid_entPhysicalName }; $self->{write_cache} = 1; } } sub write_cache { my ($self, %options) = @_; if ($self->{write_cache} == 1) { my $datas = {}; $datas->{last_timestamp} = time(); $datas->{oids} = $self->{results}->{$oid_entPhysicalEntry}; $self->{statefile_cache}->write(data => $datas); } else { $self->{results}->{$oid_entPhysicalEntry} = $self->{statefile_cache}->get(name => 'oids'); } } sub get_long_name { my ($self, %options) = @_; my @names = ($self->{results}->{$oid_entPhysicalEntry}->{$oid_entPhysicalDescr . '.' . $options{instance}}); my %loop = ($options{instance} => 1); my $child = $self->{results}->{$oid_entPhysicalEntry}->{$oid_entPhysicalContainedIn . '.' . $options{instance}}; while (1) { last if (!defined($child) || defined($loop{$child}) || !defined($self->{results}->{$oid_entPhysicalEntry}->{$oid_entPhysicalDescr . '.' . $child})); unshift @names, $self->{results}->{$oid_entPhysicalEntry}->{$oid_entPhysicalDescr . '.' . $child}; $loop{$child} = 1; $child = $self->{results}->{$oid_entPhysicalEntry}->{$oid_entPhysicalContainedIn . '.' . $child}; } return join(' > ', @names); } sub manage_selection { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; my $oid_h3cEntityExtCpuUsage = '.1.3.6.1.4.1.2011.10.2.6.1.1.1.1.6'; my $oid_hh3cEntityExtCpuUsage = '.1.3.6.1.4.1.25506.2.6.1.1.1.1.6'; $self->{snmp_request} = [ { oid => $oid_h3cEntityExtCpuUsage }, { oid => $oid_hh3cEntityExtCpuUsage }, ]; $self->check_cache() if (defined($self->{option_results}->{display_entity_name})); $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{snmp_request}, nothing_quit => 1); $self->write_cache() if (defined($self->{option_results}->{display_entity_name})); $self->{branch} = $oid_hh3cEntityExtCpuUsage; if (defined($self->{results}->{$oid_h3cEntityExtCpuUsage}) && scalar(keys %{$self->{results}->{$oid_h3cEntityExtCpuUsage}}) > 0) { $self->{branch} = $oid_h3cEntityExtCpuUsage; } my $mapping = { EntityExtCpuUsage => { oid => $self->{branch} }, }; $self->{cpu} = {}; foreach my $oid (keys %{$self->{results}->{$self->{branch}}}) { $oid =~ /^$mapping->{EntityExtCpuUsage}->{oid}\.(.*)$/; my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$self->{branch}}, instance => $instance); if (defined($result->{EntityExtCpuUsage}) && $result->{EntityExtCpuUsage} > 0) { my $name = '-'; if (defined($self->{option_results}->{display_entity_name})) { $name = $self->get_long_name(instance => $instance); } $self->{cpu}->{$instance} = { num => $instance, name => $name, %$result}; } } if (scalar(keys %{$self->{cpu}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No entry found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check CPU usages. =over 8 =item B<--warning-usage> Threshold warning. =item B<--critical-usage> Threshold critical. =item B<--reload-cache-time> Time in seconds before reloading cache file (default: 180). =item B<--display-entity-name> Display entity name of the component. A cache file will be used. =back =cut centreon-plugins-20220113/centreon/common/h3c/snmp/mode/hardware.pm000066400000000000000000000265031417000230700250600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::h3c::snmp::mode::hardware; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; use centreon::plugins::statefile; sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^(temperature)$'; $self->{cb_hook1} = 'init_cache'; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { psu => [ ['notSupported', 'WARNING'], ['normal', 'OK'], ['entityAbsent', 'OK'], ['psuError', 'CRITICAL'], ['hardwareFaulty', 'CRITICAL'], ], fan => [ ['notSupported', 'WARNING'], ['normal', 'OK'], ['entityAbsent', 'OK'], ['fanError', 'CRITICAL'], ['hardwareFaulty', 'CRITICAL'], ], sensor => [ ['notSupported', 'WARNING'], ['normal', 'OK'], ['entityAbsent', 'OK'], ['sensorError', 'CRITICAL'], ['hardwareFaulty', 'CRITICAL'], ], other => [ ['notSupported', 'WARNING'], ['normal', 'OK'], ['entityAbsent', 'OK'], ['hardwareFaulty', 'CRITICAL'], ], unknown => [ ['notSupported', 'WARNING'], ['normal', 'OK'], ['entityAbsent', 'OK'], ['hardwareFaulty', 'CRITICAL'], ], chassis => [ ['notSupported', 'WARNING'], ['normal', 'OK'], ['entityAbsent', 'OK'], ['hardwareFaulty', 'CRITICAL'], ], backplane => [ ['notSupported', 'WARNING'], ['normal', 'OK'], ['entityAbsent', 'OK'], ['hardwareFaulty', 'CRITICAL'], ], container => [ ['notSupported', 'WARNING'], ['normal', 'OK'], ['entityAbsent', 'OK'], ['hardwareFaulty', 'CRITICAL'], ], module => [ ['notSupported', 'WARNING'], ['normal', 'OK'], ['entityAbsent', 'OK'], ['hardwareFaulty', 'CRITICAL'], ], port => [ ['notSupported', 'WARNING'], ['normal', 'OK'], ['entityAbsent', 'OK'], ['hardwareFaulty', 'CRITICAL'], ], stack => [ ['notSupported', 'WARNING'], ['normal', 'OK'], ['entityAbsent', 'OK'], ['hardwareFaulty', 'CRITICAL'], ], cpu => [ ['notSupported', 'WARNING'], ['normal', 'OK'], ['entityAbsent', 'OK'], ['hardwareFaulty', 'CRITICAL'], ], }; $self->{components_path} = 'centreon::common::h3c::snmp::mode::components'; $self->{components_module} = ['chassis', 'backplane', 'container', 'psu', 'fan', 'sensor', 'module', 'port', 'stack', 'cpu', 'other', 'unknown']; $self->{mapping_name} = { 1 => 'other', 2 => 'unknown', 3 => 'chassis', 4 => 'backplane', 5 => 'container', 6 => 'psu', 7 => 'fan', 8 => 'sensor', 9 => 'module', 10 => 'port', 11 => 'stack', 12 => 'cpu' }; $self->{mapping_component} = { 1 => 'default', 2 => 'default', 3 => 'default', 4 => 'default', 5 => 'default', 6 => 'psu', 7 => 'fan', 8 => 'sensor', 9 => 'default', 10 => 'default', 11 => 'default', 12 => 'default' }; } my $oid_hh3cEntityExtStateEntry = '.1.3.6.1.4.1.25506.2.6.1.1.1.1'; my $oid_h3cEntityExtStateEntry = '.1.3.6.1.4.1.2011.10.2.6.1.1.1.1'; my $oid_h3cEntityExtErrorStatus = '.1.3.6.1.4.1.2011.10.2.6.1.1.1.1.19'; my $oid_hh3cEntityExtErrorStatus = '.1.3.6.1.4.1.25506.2.6.1.1.1.1.19'; sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); $self->write_cache(); $self->{branch} = $oid_hh3cEntityExtStateEntry; if (defined($self->{results}->{$oid_h3cEntityExtErrorStatus}) && scalar(keys %{$self->{results}->{$oid_h3cEntityExtErrorStatus}}) > 0) { $self->{branch} = $oid_h3cEntityExtStateEntry; } } sub init_cache { my ($self, %options) = @_; $self->{request} = [ { oid => $oid_h3cEntityExtErrorStatus }, { oid => $oid_hh3cEntityExtErrorStatus }, ]; $self->check_cache(%options); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "reload-cache-time:s" => { name => 'reload_cache_time', default => 180 }, "short-name" => { name => 'short_name' }, }); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{short_name} = (defined($self->{option_results}->{short_name})) ? 1 : 0; $self->{statefile_cache}->check_options(%options); } my $oid_entPhysicalEntry = '.1.3.6.1.2.1.47.1.1.1.1'; my $oid_entPhysicalDescr = '.1.3.6.1.2.1.47.1.1.1.1.2'; my $oid_entPhysicalContainedIn = '.1.3.6.1.2.1.47.1.1.1.1.4'; my $oid_entPhysicalClass = '.1.3.6.1.2.1.47.1.1.1.1.5'; my $oid_entPhysicalName = '.1.3.6.1.2.1.47.1.1.1.1.7'; sub check_cache { my ($self, %options) = @_; $self->{hostname} = $options{snmp}->get_hostname(); $self->{snmp_port} = $options{snmp}->get_port(); # init cache file $self->{write_cache} = 0; my $has_cache_file = $self->{statefile_cache}->read(statefile => 'cache_h3c_entity_' . $self->{hostname} . '_' . $self->{snmp_port}); my $timestamp_cache = $self->{statefile_cache}->get(name => 'last_timestamp'); if ($has_cache_file == 0 || !defined($timestamp_cache) || ((time() - $timestamp_cache) > (($self->{option_results}->{reload_cache_time}) * 60)) && $self->{option_results}->{reload_cache_time} != '-1') { push @{$self->{request}}, { oid => $oid_entPhysicalEntry, start => $oid_entPhysicalDescr, end => $oid_entPhysicalName }; $self->{write_cache} = 1; } } sub write_cache { my ($self, %options) = @_; if ($self->{write_cache} == 1) { my $datas = {}; $datas->{last_timestamp} = time(); $datas->{oids} = $self->{results}->{$oid_entPhysicalEntry}; $self->{statefile_cache}->write(data => $datas); } else { $self->{results}->{$oid_entPhysicalEntry} = $self->{statefile_cache}->get(name => 'oids'); } } sub get_short_name { my ($self, %options) = @_; return $self->{results}->{$oid_entPhysicalEntry}->{$oid_entPhysicalName . '.' . $options{instance}}; } sub get_long_name { my ($self, %options) = @_; my @names = ($self->{results}->{$oid_entPhysicalEntry}->{$oid_entPhysicalDescr . '.' . $options{instance}}); my %loop = ($options{instance} => 1); my $child = $self->{results}->{$oid_entPhysicalEntry}->{$oid_entPhysicalContainedIn . '.' . $options{instance}}; while (1) { last if (!defined($child) || defined($loop{$child}) || !defined($self->{results}->{$oid_entPhysicalEntry}->{$oid_entPhysicalDescr . '.' . $child})); unshift @names, $self->{results}->{$oid_entPhysicalEntry}->{$oid_entPhysicalDescr . '.' . $child}; $loop{$child} = 1; $child = $self->{results}->{$oid_entPhysicalEntry}->{$oid_entPhysicalContainedIn . '.' . $child}; } return join(' > ', @names); } sub get_instance_class { my ($self, %options) = @_; my @instances = (); foreach (keys %{$self->{results}->{$oid_entPhysicalEntry}}) { if (/^$oid_entPhysicalClass\.(\d+)/ && defined($options{class}->{$self->{results}->{$oid_entPhysicalEntry}->{$_}})) { push @instances, $1; } } return @instances; } sub load_components { my ($self, %options) = @_; foreach (keys %{$self->{mapping_name}}) { if ($self->{mapping_name}->{$_} =~ /$self->{option_results}->{component}/) { my $mod_name = $self->{components_path} . "::" . $self->{mapping_component}->{$_}; centreon::plugins::misc::mymodule_load(output => $self->{output}, module => $mod_name, error_msg => "Cannot load module '$mod_name'."); $self->{loaded} = 1; } } } sub exec_components { my ($self, %options) = @_; foreach (keys %{$self->{mapping_name}}) { if ($self->{mapping_name}->{$_} =~ /$self->{option_results}->{component}/) { my $mod_name = $self->{components_path} . "::" . $self->{mapping_component}->{$_}; my $func = $mod_name->can('check'); $func->($self, component => $self->{mapping_name}->{$_}, component_class => $_); } } } 1; __END__ =head1 MODE Check Hardware (Fans, Power Supplies, Module,...). =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'fan', 'psu', 'other', 'unknown', 'sensor', 'chassis', 'backplane', 'container', 'module', 'port', 'stack', 'cpu'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=fan --filter=psu) Can also exclude specific instance: --filter=fan,101 =item B<--absent-problem> Return an error if an entity is not 'present' (default is skipping) (comma seperated list) Can be specific or global: --absent-problem=psu#44# =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,^(?!(normal)$)' =item B<--warning> Set warning threshold for 'temperature' (syntax: type,regexp,threshold) Example: --warning='temperature,.*,40' =item B<--critical> Set critical threshold for 'temperature' (syntax: type,regexp,threshold) Example: --critical='temperature,.*,45' =item B<--warning-count-*> Set warning threshold for component count. Can be: 'fan', 'psu', 'other', 'unknown', 'sensor', 'chassis', 'backplane', 'container', 'module', 'port', 'stack', 'cpu'. =item B<--critical-count-*> Set critical threshold for component count. Can be: 'fan', 'psu', 'other', 'unknown', 'sensor', 'chassis', 'backplane', 'container', 'module', 'port', 'stack', 'cpu'. =item B<--reload-cache-time> Time in seconds before reloading cache file (Default: 180). Use '-1' to disable cache reload. =back =cut centreon-plugins-20220113/centreon/common/h3c/snmp/mode/memory.pm000066400000000000000000000262471417000230700246000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::h3c::snmp::mode::memory; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::statefile; sub custom_usage_perfdata { my ($self, %options) = @_; if ($self->{result_values}->{total} == 4294967295) { $self->{output}->perfdata_add( label => 'used', unit => '%', nlabel => 'memory.usage.percentage', instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, value => $self->{result_values}->{prct_used}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}), min => 0, max => 100 ); } else { $self->{output}->perfdata_add( label => 'used', unit => 'B', nlabel => $self->{nlabel}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, value => int($self->{result_values}->{used}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), min => 0, max => $self->{result_values}->{total} ); } } sub custom_usage_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check(value => $self->{result_values}->{prct_used}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ]); return $exit; } sub custom_usage_output { my ($self, %options) = @_; my $msg; if ($self->{result_values}->{total} == 4294967295) { $msg = sprintf("Used: %.2f%% Free: %.2f%%", $self->{result_values}->{prct_used}, $self->{result_values}->{prct_free}); } else { 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}); $msg = sprintf("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} . '_total'} * $options{new_datas}->{$self->{instance} . '_used_prct'} / 100; $self->{result_values}->{free} = $options{new_datas}->{$self->{instance} . '_total'} - $self->{result_values}->{used}; $self->{result_values}->{prct_free} = 100 - $options{new_datas}->{$self->{instance} . '_used_prct'}; $self->{result_values}->{prct_used} = $options{new_datas}->{$self->{instance} . '_used_prct'}; 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 memory usages are ok' } ]; $self->{maps_counters}->{memory} = [ { label => 'usage', nlabel => 'memory.usage.bytes', set => { key_values => [ { name => 'display' }, { name => 'used_prct' }, { 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 prefix_memory_output { my ($self, %options) = @_; return "Memory '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "reload-cache-time:s" => { name => 'reload_cache_time', default => 180 }, "display-entity-name" => { name => 'display_entity_name' }, }); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{statefile_cache}->check_options(%options); } my $oid_entPhysicalEntry = '.1.3.6.1.2.1.47.1.1.1.1'; my $oid_entPhysicalDescr = '.1.3.6.1.2.1.47.1.1.1.1.2'; my $oid_entPhysicalContainedIn = '.1.3.6.1.2.1.47.1.1.1.1.4'; my $oid_entPhysicalClass = '.1.3.6.1.2.1.47.1.1.1.1.5'; my $oid_entPhysicalName = '.1.3.6.1.2.1.47.1.1.1.1.7'; sub check_cache { my ($self, %options) = @_; $self->{hostname} = $self->{snmp}->get_hostname(); $self->{snmp_port} = $self->{snmp}->get_port(); # init cache file $self->{write_cache} = 0; my $has_cache_file = $self->{statefile_cache}->read(statefile => 'cache_h3c_entity_' . $self->{hostname} . '_' . $self->{snmp_port}); my $timestamp_cache = $self->{statefile_cache}->get(name => 'last_timestamp'); if ($has_cache_file == 0 || !defined($timestamp_cache) || ((time() - $timestamp_cache) > (($self->{option_results}->{reload_cache_time}) * 60))) { push @{$self->{snmp_request}}, { oid => $oid_entPhysicalEntry, start => $oid_entPhysicalDescr, end => $oid_entPhysicalName }; $self->{write_cache} = 1; } } sub write_cache { my ($self, %options) = @_; if ($self->{write_cache} == 1) { my $datas = {}; $datas->{last_timestamp} = time(); $datas->{oids} = $self->{results}->{$oid_entPhysicalEntry}; $self->{statefile_cache}->write(data => $datas); } else { $self->{results}->{$oid_entPhysicalEntry} = $self->{statefile_cache}->get(name => 'oids'); } } sub get_long_name { my ($self, %options) = @_; my @names = ($self->{results}->{$oid_entPhysicalEntry}->{$oid_entPhysicalDescr . '.' . $options{instance}}); my %loop = ($options{instance} => 1); my $child = $self->{results}->{$oid_entPhysicalEntry}->{$oid_entPhysicalContainedIn . '.' . $options{instance}}; while (1) { last if (!defined($child) || defined($loop{$child}) || !defined($self->{results}->{$oid_entPhysicalEntry}->{$oid_entPhysicalDescr . '.' . $child})); unshift @names, $self->{results}->{$oid_entPhysicalEntry}->{$oid_entPhysicalDescr . '.' . $child}; $loop{$child} = 1; $child = $self->{results}->{$oid_entPhysicalEntry}->{$oid_entPhysicalContainedIn . '.' . $child}; } return join(' > ', @names); } sub manage_selection { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; my $oid_h3cEntityExtStateEntry = '.1.3.6.1.4.1.2011.10.2.6.1.1.1.1'; my $oid_hh3cEntityExtStateEntry = '.1.3.6.1.4.1.25506.2.6.1.1.1.1'; my $oid_hh3cEntityExtMemUsage = '.1.3.6.1.4.1.25506.2.6.1.1.1.1.8'; my $oid_hh3cEntityExtMemSize = '.1.3.6.1.4.1.25506.2.6.1.1.1.1.10'; my $oid_h3cEntityExtMemUsage = '.1.3.6.1.4.1.2011.10.2.6.1.1.1.1.8'; my $oid_h3cEntityExtMemSize = '.1.3.6.1.4.1.2011.10.2.6.1.1.1.1.10'; $self->{snmp_request} = [ { oid => $oid_hh3cEntityExtMemUsage }, { oid => $oid_hh3cEntityExtMemSize }, { oid => $oid_h3cEntityExtMemUsage }, { oid => $oid_h3cEntityExtMemSize }, ]; $self->check_cache() if (defined($self->{option_results}->{display_entity_name})); $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{snmp_request}, nothing_quit => 1); $self->write_cache() if (defined($self->{option_results}->{display_entity_name})); $self->{branch} = $oid_hh3cEntityExtStateEntry; if (defined($self->{results}->{$oid_h3cEntityExtMemUsage}) && scalar(keys %{$self->{results}->{$oid_h3cEntityExtMemUsage}}) > 0) { $self->{branch} = $oid_h3cEntityExtStateEntry; } my $mapping = { EntityExtMemUsage => { oid => $self->{branch} . '.8' }, }; my $mapping2 = { EntityExtMemSize => { oid => $self->{branch} . '.10' }, }; $self->{memory} = {}; foreach my $oid (keys %{$self->{results}->{$self->{branch} . '.8'}}) { next if ($oid !~ /^$self->{branch}\.8\.(\d+)/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$self->{branch} . '.8'}, instance => $instance); my $result2 = $self->{snmp}->map_instance(mapping => $mapping2, results => $self->{results}->{$self->{branch} . '.10'}, instance => $instance); if (defined($result2->{EntityExtMemSize}) && $result2->{EntityExtMemSize} > 0) { my $name = '-'; if (defined($self->{option_results}->{display_entity_name})) { $name = $self->get_long_name(instance => $instance); } $self->{memory}->{$instance} = { display => $instance, name => $name, used_prct => $result->{EntityExtMemUsage}, total => $result2->{EntityExtMemSize} }; } } if (scalar(keys %{$self->{memory}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No entry found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check memory usages. =over 8 =item B<--warning-usage> Threshold warning (in percent). =item B<--critical-usage> Threshold critical (in percent). =item B<--reload-cache-time> Time in seconds before reloading cache file (default: 180). =item B<--display-entity-name> Display entity name of the component. A cache file will be used. =back =cut centreon-plugins-20220113/centreon/common/ibm/000077500000000000000000000000001417000230700211105ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/ibm/nos/000077500000000000000000000000001417000230700217075ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/ibm/nos/snmp/000077500000000000000000000000001417000230700226645ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/ibm/nos/snmp/mode/000077500000000000000000000000001417000230700236105ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/ibm/nos/snmp/mode/components/000077500000000000000000000000001417000230700257755ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/ibm/nos/snmp/mode/components/faultled.pm000066400000000000000000000040521417000230700301340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::ibm::nos::snmp::mode::components::faultled; use strict; use warnings; my %map_faultled_states = ( 1 => 'on', 2 => 'off' ); sub load {} sub check_faultled { my ($self, %options) = @_; $self->{components}->{faultled}->{total}++; $self->{output}->output_add(long_msg => sprintf( "Fault LED state is %s", $options{value} ) ); my $exit = $self->get_severity(section => 'faultled', value => $options{value}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Fault LED state is %s", $options{value} ) ); } } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => 'checking fault LED'); $self->{components}->{faultled} = { name => 'faultled', total => 0, skip => 0 }; return if ($self->check_filter(section => 'faultled')); my $oid_mmspFaultLED = '.1.3.6.1.4.1.26543.2.5.1.3.10.12.0'; my $results = $self->{snmp}->get_leef(oids => [$oid_mmspFaultLED]); return if (!defined($results->{$oid_mmspFaultLED})); check_faultled($self, value => $map_faultled_states{$results->{$oid_mmspFaultLED}}); } 1; centreon-plugins-20220113/centreon/common/ibm/nos/snmp/mode/components/temperature.pm000066400000000000000000000075511417000230700307000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::ibm::nos::snmp::mode::components::temperature; use strict; use warnings; sub load {} sub check { my ($self) = @_; $self->{output}->output_add(long_msg => 'checking temperatures'); $self->{components}->{temperature} = { name => 'temperatures', total => 0, skip => 0 }; return if ($self->check_filter(section => 'temperature')); my $oid_hwTemperatureWarn = '.1.3.6.1.4.1.26543.2.5.1.3.1.22.0'; my $oid_hwTemperatureShut = '.1.3.6.1.4.1.26543.2.5.1.3.1.23.0'; my $results = $self->{snmp}->get_leef(oids => [$oid_hwTemperatureWarn, $oid_hwTemperatureShut]); return if (!defined($results->{$oid_hwTemperatureWarn})); my $instance = 'system'; # .1.3.6.1.4.1.20301.2.5.1.3.1.41.1.1.20.1 = STRING: "44 C (Warn at 66 C / Recover at 61 C)" # .1.3.6.1.4.1.20301.2.5.1.3.1.41.1.1.21.1 = STRING: "44 C (Shutdown at 72 C / Recover at 67 C)" $results->{$oid_hwTemperatureWarn} =~ /^([.0-9]+)\s*C\s*\(Warn(?:ing)?\s*at\s*([.0-9]+)\s*C/i; my ($temperature, $warning_mib) = ($1, $2); $results->{$oid_hwTemperatureShut} =~ /^([.0-9]+)\s*C\s*\(Shutdown\s*at\s*([.0-9]+)\s*C/i; $temperature = $1 if ($1 > $temperature); my $critical_mib = ($warning_mib + $2) / 2; if ($warning_mib == $critical_mib) { #seen on some chassis ! $warning_mib -= 10; $critical_mib -= 5; } $self->{components}->{temperature}->{total}++; $self->{output}->output_add(long_msg => sprintf( "temperature '%s' is %.1f C [instance: %s]", $instance, $temperature, $instance ) ); my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $instance, value => $temperature); if ($checked == 0) { $self->{perfdata}->threshold_validate(label => 'warning-temperature-instance-' . $instance, value => $warning_mib); $self->{perfdata}->threshold_validate(label => 'critical-temperature-instance-' . $instance, value => $critical_mib); $warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-temperature-instance-' . $instance); $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-temperature-instance-' . $instance); $exit = $self->{perfdata}->threshold_check( value => $temperature, threshold => [ { label => 'critical-temperature-instance-' . $instance, exit_litteral => 'critical' }, { label => 'warning-temperature-instance-' . $instance, exit_litteral => 'warning' } ] ); } if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Temperature '%s' is %.1f C", $instance, $temperature ) ); } $self->{output}->perfdata_add( unit => 'C', nlabel => 'hardware.temperature.celsius', instances => 'system', value => $temperature, warning => $warn, critical => $crit ); } 1; centreon-plugins-20220113/centreon/common/ibm/nos/snmp/mode/cpu.pm000066400000000000000000000054771417000230700247520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::ibm::nos::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 => 0, cb_prefix_output => 'prefix_message_output', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{cpu} = [ { label => 'average-1m', nlabel => 'cpu.utilization.1m.percentage', set => { key_values => [ { name => 'average_1m' } ], output_template => '%.2f %% (1m)', perfdatas => [ { value => 'average_1m', template => '%.2f', min => 0, max => 100, unit => '%' } ] } }, { label => 'average-5m', nlabel => 'cpu.utilization.5m.percentage', set => { key_values => [ { name => 'average_5m' } ], output_template => '%.2f %% (5m)', perfdatas => [ { value => 'average_5m', template => '%.2f', min => 0, max => 100, unit => '%' } ] } } ]; } sub prefix_message_output { my ($self, %options) = @_; return "CPU average usage: "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; return $self; } sub manage_selection { my ($self, %options) = @_; my $oid_mpCpuStatsUtil1Minute = '.1.3.6.1.4.1.26543.2.5.1.2.2.3.0'; my $oid_mpCpuStatsUtil5Minutes = '.1.3.6.1.4.1.26543.2.5.1.2.2.6.0'; my $result = $options{snmp}->get_leef(oids => [$oid_mpCpuStatsUtil1Minute, $oid_mpCpuStatsUtil5Minutes], nothing_quit => 1); $self->{cpu} = { average_1m => $result->{$oid_mpCpuStatsUtil1Minute}, average_5m => $result->{$oid_mpCpuStatsUtil5Minutes} } } 1; __END__ =head1 MODE Check CPU usage (over the last minute). =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'average-1m' (%), 'average-5m' (%). =back =cut centreon-plugins-20220113/centreon/common/ibm/nos/snmp/mode/disk.pm000066400000000000000000000042251417000230700251030ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::ibm::nos::snmp::mode::disk; use base qw(snmp_standard::mode::storage); use strict; use warnings; sub default_storage_type { my ($self, %options) = @_; return '^(?!(hrStorageRam)$)'; } sub prefix_storage_output { my ($self, %options) = @_; return "Disk '" . $options{instance_value}->{display} . "' "; } 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 disks. =over 8 =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. =item B<--storage> Set the storage (number expected) ex: 1, 2,... (empty means 'check all storage'). =item B<--name> Allows to use storage name with option --storage instead of storage oid index. =item B<--regexp> Allows to use regexp to filter storage (with option --name). =item B<--regexp-isensitive> Allows to use regexp non case-sensitive (with --regexp). =item B<--reload-cache-time> Time in minutes before reloading cache file (default: 180). =item B<--show-cache> Display cache storage datas. =item B<--filter-storage-type> Filter storage types with a regexp (Default: '^(?!(hrStorageRam)$)'). =back =cut centreon-plugins-20220113/centreon/common/ibm/nos/snmp/mode/environment.pm000066400000000000000000000046251417000230700265210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::ibm::nos::snmp::mode::environment; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^(?:temperature)$'; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { 'faultled' => [ ['on', 'CRITICAL'], ['off', 'OK'] ] }; $self->{components_path} = 'centreon::common::ibm::nos::snmp::mode::components'; $self->{components_module} = ['faultled', 'temperature']; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } 1; __END__ =head1 MODE Check hardware. =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'faultled', 'temperature'. =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,status,regexp) It used before default thresholds (order stays). Example: --threshold-overload='faulted,WARNING,on' =item B<--warning> Set warning threshold for temperatures (syntax: type,regexp,threshold) Example: --warning='temperature,.*,30' =item B<--critical> Set critical threshold for temperatures (syntax: type,regexp,threshold) Example: --critical='temperature,.*,40' =back =cut centreon-plugins-20220113/centreon/common/ibm/nos/snmp/mode/memory.pm000066400000000000000000000077271417000230700254730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::ibm::nos::snmp::mode::memory; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_usage_output { my ($self, %options) = @_; return sprintf( 'Ram Total: %s %s Used: %s %s (%.2f%%) Free: %s %s (%.2f%%)', $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}), $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}), $self->{result_values}->{prct_used}, $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}), $self->{result_values}->{prct_free} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'memory', type => 0, skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{memory} = [ { label => 'usage', nlabel => 'memory.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { value => 'used', template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1 } ] } }, { label => 'usage-free', display_ok => 0, nlabel => 'memory.free.bytes', set => { key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { value => 'free', template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1 } ] } }, { label => 'usage-prct', display_ok => 0, nlabel => 'memory.usage.percentage', set => { key_values => [ { name => 'prct_used' } ], output_template => 'Ram Used : %.2f %%', perfdatas => [ { value => 'prct_used', template => '%.2f', min => 0, max => 100, unit => '%' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; return $self; } sub manage_selection { my ($self, %options) = @_; my $oid_totalMemoryStats = '.1.3.6.1.4.1.26543.2.5.1.2.12.1.0'; # in bytes my $oid_memoryFreeStats = '.1.3.6.1.4.1.26543.2.5.1.2.12.2.0'; # in bytes my $result = $options{snmp}->get_leef(oids => [$oid_totalMemoryStats, $oid_memoryFreeStats], nothing_quit => 1); my $free = $result->{$oid_memoryFreeStats}; my $total = $result->{$oid_totalMemoryStats}; my $prct_used = ($total - $free) * 100 / $total; $self->{memory} = { total => $total, used => $total - $free, free => $free, prct_used => $prct_used, prct_free => 100 - $prct_used } } 1; __END__ =head1 MODE Check memory usage. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'usage' (B), 'usage-free' (B), 'usage-prct' (%). =back =cut centreon-plugins-20220113/centreon/common/ibm/tapelibrary/000077500000000000000000000000001417000230700234265ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/ibm/tapelibrary/snmp/000077500000000000000000000000001417000230700244035ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/ibm/tapelibrary/snmp/mode/000077500000000000000000000000001417000230700253275ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/ibm/tapelibrary/snmp/mode/components/000077500000000000000000000000001417000230700275145ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/ibm/tapelibrary/snmp/mode/components/changer.pm000066400000000000000000000054161417000230700314670ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::ibm::tapelibrary::snmp::mode::components::changer; use strict; use warnings; use centreon::common::ibm::tapelibrary::snmp::mode::components::resources qw($map_operational); my $mapping = { changerDevice_OperationalStatus => { oid => '.1.3.6.1.4.1.14851.3.1.11.2.1.9', map => $map_operational }, }; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping->{changerDevice_OperationalStatus}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking changers"); $self->{components}->{changer} = {name => 'changers', total => 0, skip => 0}; return if ($self->check_filter(section => 'changer')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$mapping->{changerDevice_OperationalStatus}->{oid}}})) { $oid =~ /^$mapping->{changerDevice_OperationalStatus}->{oid}\.(.*)$/; my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$mapping->{changerDevice_OperationalStatus}->{oid}}, instance => $instance); next if ($self->check_filter(section => 'changer', instance => $instance)); $self->{components}->{changer}->{total}++; $self->{output}->output_add(long_msg => sprintf("changer '%s' status is '%s' [instance: %s].", $instance, $result->{changerDevice_OperationalStatus}, $instance )); my $exit = $self->get_severity(label => 'operational', section => 'changer', value => $result->{changerDevice_OperationalStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("changer '%s' status is '%s'", $instance, $result->{changerDevice_OperationalStatus})); } } } 1;centreon-plugins-20220113/centreon/common/ibm/tapelibrary/snmp/mode/components/chassis.pm000066400000000000000000000053571417000230700315210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::ibm::tapelibrary::snmp::mode::components::chassis; use strict; use warnings; use centreon::common::ibm::tapelibrary::snmp::mode::components::resources qw($map_operational); my $mapping = { subChassis_OperationalStatus => { oid => '.1.3.6.1.4.1.14851.3.1.4.10.1.10', map => $map_operational }, }; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping->{subChassis_OperationalStatus}->{oid} }; } 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')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$mapping->{subChassis_OperationalStatus}->{oid}}})) { $oid =~ /^$mapping->{subChassis_OperationalStatus}->{oid}\.(.*)$/; my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$mapping->{subChassis_OperationalStatus}->{oid}}, instance => $instance); next if ($self->check_filter(section => 'chassis', instance => $instance)); $self->{components}->{chassis}->{total}++; $self->{output}->output_add(long_msg => sprintf("chassis '%s' status is '%s' [instance: %s].", $instance, $result->{subChassis_OperationalStatus}, $instance )); my $exit = $self->get_severity(label => 'operational', section => 'chassis', value => $result->{subChassis_OperationalStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("chassis '%s' status is '%s'", $instance, $result->{subChassis_OperationalStatus})); } } } 1;centreon-plugins-20220113/centreon/common/ibm/tapelibrary/snmp/mode/components/drive.pm000066400000000000000000000057241417000230700311730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::ibm::tapelibrary::snmp::mode::components::drive; use strict; use warnings; use centreon::common::ibm::tapelibrary::snmp::mode::components::resources qw($map_operational); my $mapping = { mediaAccessDevice_Name => { oid => '.1.3.6.1.4.1.14851.3.1.6.2.1.3' }, mediaAccessDevice_OperationalStatus => { oid => '.1.3.6.1.4.1.14851.3.1.6.2.1.11', map => $map_operational }, }; my $oid_mediaAccessDeviceEntry = '.1.3.6.1.4.1.14851.3.1.6.2.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_mediaAccessDeviceEntry }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking drives"); $self->{components}->{drive} = {name => 'drives', total => 0, skip => 0}; return if ($self->check_filter(section => 'drive')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_mediaAccessDeviceEntry}})) { next if ($oid !~ /^$mapping->{mediaAccessDevice_OperationalStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_mediaAccessDeviceEntry}, instance => $instance); next if ($self->check_filter(section => 'drive', instance => $instance)); $self->{components}->{drive}->{total}++; $result->{mediaAccessDevice_Name} =~ s/\s+/ /g; $self->{output}->output_add(long_msg => sprintf("drive '%s' status is '%s' [instance: %s].", $result->{mediaAccessDevice_Name}, $result->{mediaAccessDevice_OperationalStatus}, $instance )); my $exit = $self->get_severity(label => 'operational', section => 'drive', value => $result->{mediaAccessDevice_OperationalStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("drive '%s' status is '%s'", $result->{mediaAccessDevice_Name}, $result->{mediaAccessDevice_OperationalStatus})); } } } 1;centreon-plugins-20220113/centreon/common/ibm/tapelibrary/snmp/mode/components/psu.pm000066400000000000000000000062071417000230700306660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::ibm::tapelibrary::snmp::mode::components::psu; use strict; use warnings; use centreon::common::ibm::tapelibrary::snmp::mode::components::resources qw($map_status); my $mapping = { chassis_PS1Status => { oid => '.1.3.6.1.4.1.2.6.257.1.3.2.1.3', map => $map_status }, chassis_PS2Status => { oid => '.1.3.6.1.4.1.2.6.257.1.3.2.1.4', map => $map_status }, chassis_SerialNumber => { oid => '.1.3.6.1.4.1.2.6.257.1.3.2.1.9' }, }; my $oid_frameConfigEntry = '.1.3.6.1.4.1.2.6.257.1.3.2.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_frameConfigEntry }; } sub check_psu { my ($self, %options) = @_; return if ($self->check_filter(section => 'psu', instance => $options{instance})); $self->{components}->{psu}->{total}++; $self->{output}->output_add(long_msg => sprintf("psu '%s' status is '%s' [instance: %s, chassis: %s].", $options{instance}, $options{status}, $options{instance}, $options{serial} )); my $exit = $self->get_severity(label => 'status', section => 'psu', value => $options{status}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("psu '%s' status is '%s'", $options{instance}, $options{status})); } } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking power supplies"); $self->{components}->{psu} = {name => 'psu', total => 0, skip => 0}; return if ($self->check_filter(section => 'psu')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_frameConfigEntry}})) { next if ($oid !~ /^$mapping->{chassis_SerialNumber}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_frameConfigEntry}, instance => $instance); check_psu($self, status => $result->{chassis_PS1Status}, instance => $instance . '.1', serial => $result->{chassis_SerialNumber}); check_psu($self, status => $result->{chassis_PS2Status}, instance => $instance . '.2', serial => $result->{chassis_SerialNumber}); } } 1;centreon-plugins-20220113/centreon/common/ibm/tapelibrary/snmp/mode/components/resources.pm000066400000000000000000000031011417000230700320570ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::ibm::tapelibrary::snmp::mode::components::resources; use strict; use warnings; use Exporter; our $map_operational; our $map_status; our @ISA = qw(Exporter); our @EXPORT_OK = qw($map_operational $map_status); $map_status = { 1 => 'notinstalled', 2 => 'ok', 3 => 'notok', }; $map_operational = { 0 => 'unknown', 1 => 'other', 2 => 'ok', 3 => 'degraded', 4 => 'stressed', 5 => 'predictiveFailure', 6 => 'error', 7 => 'non-RecoverableError', 8 => 'starting', 9 => 'stopping', 10 => 'stopped', 11 => 'inService', 12 => 'noContact', 13 => 'lostCommunication', 14 => 'aborted', 15 => 'dormant', 16 => 'supportingEntityInError', 17 => 'completed', 18 => 'powerMode', 19 => 'dMTFReserved', 32768 => 'vendorReserved', }; 1;centreon-plugins-20220113/centreon/common/ibm/tapelibrary/snmp/mode/hardware.pm000066400000000000000000000062001417000230700274600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::ibm::tapelibrary::snmp::mode::hardware; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { status => [ ['notinstalled', 'OK'], ['notok', 'CRITICAL'], ['ok', 'OK'], ], operational => [ ['unknown', 'UNKNOWN'], ['other', 'UNKNOWN'], ['ok', 'OK'], ['degraded', 'WARNING'], ['stressed', 'WARNING'], ['predictiveFailure', 'WARNING'], ['error', 'CRITICAL'], ['non-RecoverableError', 'CRITICAL'], ['starting', 'OK'], ['stopping', 'OK'], ['stopped', 'OK'], ['inService', 'CRITICAL'], ['noContact', 'WARNING'], ['lostCommunication', 'WARNING'], ['aborted', 'OK'], ['dormant', 'OK'], ['supportingEntityInError', 'CRITICAL'], ['completed', 'OK'], ['powerMode', 'OK'], ], }; $self->{components_path} = 'centreon::common::ibm::tapelibrary::snmp::mode::components'; $self->{components_module} = ['chassis', 'drive', 'changer', 'psu']; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $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, no_performance => 1); bless $self, $class; $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: 'chassis', 'drive', 'changer', 'psu'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=drive) Can also exclude specific instance: --filter=drive,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='chassis,CRITICAL,degraded' =back =cut centreon-plugins-20220113/centreon/common/ingrian/000077500000000000000000000000001417000230700217705ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/ingrian/snmp/000077500000000000000000000000001417000230700227455ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/ingrian/snmp/mode/000077500000000000000000000000001417000230700236715ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/ingrian/snmp/mode/connections.pm000066400000000000000000000072211417000230700265530ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::ingrian::snmp::mode::connections; 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 => 'global', type => 0, message_separator => ' - ' } ]; $self->{maps_counters}->{global} = [ { label => 'total', set => { key_values => [ { name => 'naeTotalTotalConnections', diff => 1 } ], output_template => 'Total Connections : %s', perfdatas => [ { label => 'total', value => 'naeTotalTotalConnections', template => '%s', min => 0 }, ], } }, { label => 'ssl', set => { key_values => [ { name => 'naeTotalSSLConnections', diff => 1 } ], output_template => 'Total SSL Connections : %s', perfdatas => [ { label => 'total_ssl', value => 'naeTotalSSLConnections', template => '%s', min => 0 }, ], } }, { label => 'non-ssl', set => { key_values => [ { name => 'naeTotalNonSSLConnections', diff => 1 } ], output_template => 'Total non-SSL Connections : %s', perfdatas => [ { label => 'total_non_ssl', value => 'naeTotalNonSSLConnections', template => '%s', min => 0 }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my $mapping = { naeTotalTotalConnections => { oid => '.1.3.6.1.4.1.5595.3.5.1.4' }, naeTotalNonSSLConnections => { oid => '.1.3.6.1.4.1.5595.3.5.1.5.4' }, naeTotalSSLConnections => { oid => '.1.3.6.1.4.1.5595.3.5.1.6.4' }, }; my $oid_naeConnectionStats = '.1.3.6.1.4.1.5595.3.5'; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_table(oid => $oid_naeConnectionStats, nothing_quit => 1); my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => '0'); $self->{global} = { %$result }; $self->{cache_name} = "ingrian_" . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check connections. =over 8 =item B<--warning-*> Threshold warning. Can be: 'total', 'ssl', 'non-ssl'. =item B<--critical-*> Threshold critical. Can be: 'total', 'ssl', 'non-ssl'. =back =cut centreon-plugins-20220113/centreon/common/ingrian/snmp/mode/cpu.pm000066400000000000000000000101711417000230700250160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::ingrian::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, cb_init => 'skip_global', }, { name => 'cpu', type => 1, cb_prefix_output => 'prefix_cpu_output', message_multiple => 'All CPU usages are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'total', set => { key_values => [ { name => 'total' } ], output_template => 'Total CPU Usage : %.2f %%', perfdatas => [ { label => 'total_cpu_avg', value => 'total', template => '%.2f', min => 0, max => 100, unit => '%' }, ], } }, ]; $self->{maps_counters}->{cpu} = [ { label => 'usage', set => { key_values => [ { name => 'usage' }, { name => 'display' }, ], output_template => 'Usage : %.2f %%', perfdatas => [ { label => 'cpu', value => 'usage', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub skip_global { my ($self, %options) = @_; scalar(keys %{$self->{cpu}}) > 1 ? return(0) : return(1); } 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; $options{options}->add_options(arguments => { }); return $self; } my $mapping = { naeSystemCPUDescr => { oid => '.1.3.6.1.4.1.5595.3.2.4.1.2' }, naeSystemCPUUtilization => { oid => '.1.3.6.1.4.1.5595.3.2.4.1.3' }, }; sub manage_selection { my ($self, %options) = @_; my $oid_naeSystemStatCPUEntry = '.1.3.6.1.4.1.5595.3.2.4.1'; my $oid_naeSystemStatCPU = '.1.3.6.1.4.1.5595.3.2.2'; # without .0 my $snmp_result = $options{snmp}->get_multiple_table(oids => [ { oid => $oid_naeSystemStatCPU }, { oid => $oid_naeSystemStatCPUEntry }, ], nothing_quit => 1); $self->{cpu} = {}; foreach my $oid (keys %{$snmp_result->{$oid_naeSystemStatCPUEntry}}) { next if ($oid !~ /^$mapping->{naeSystemCPUUtilization}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result->{$oid_naeSystemStatCPUEntry}, instance => $instance); $self->{cpu}->{$instance} = { display => $instance - 1, usage => $result->{naeSystemCPUUtilization} }; } $self->{global} = { total => $snmp_result->{$oid_naeSystemStatCPU}->{$oid_naeSystemStatCPU . '.0'} }; } 1; __END__ =head1 MODE Check CPU usages. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^total$' =item B<--warning-*> Threshold warning. Can be: 'total', 'usage'. =item B<--critical-*> Threshold critical. Can be: 'total', 'usage'. =back =cut centreon-plugins-20220113/centreon/common/ingrian/snmp/mode/disk.pm000066400000000000000000000060721417000230700251660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::ingrian::snmp::mode::disk; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'disk', type => 1, cb_prefix_output => 'prefix_disk_output', message_multiple => 'All disk usages are ok' } ]; $self->{maps_counters}->{disk} = [ { label => 'usage', set => { key_values => [ { name => 'used' }, { name => 'display' } ], output_template => 'Used : %.2f %%', perfdatas => [ { label => 'used', value => 'used', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub prefix_disk_output { my ($self, %options) = @_; return "Disk '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my $mapping = { naeSystemDiskDescr => { oid => '.1.3.6.1.4.1.5595.3.2.7.1.2' }, naeSystemDiskUtilization => { oid => '.1.3.6.1.4.1.5595.3.2.7.1.3' }, }; my $oid_naeSystemStatDiskEntry = '.1.3.6.1.4.1.5595.3.2.7.1'; sub manage_selection { my ($self, %options) = @_; $self->{disk} = {}; my $snmp_result = $options{snmp}->get_table(oid => $oid_naeSystemStatDiskEntry, nothing_quit => 1); foreach my $oid (keys %{$snmp_result}) { next if ($oid !~ /^$mapping->{naeSystemDiskUtilization}->{oid}\.(.*)/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); $self->{disk}->{$instance} = { display => $result->{naeSystemDiskDescr}, used => $result->{naeSystemDiskUtilization}}; } } 1; __END__ =head1 MODE Check disk usages. =over 8 =item B<--warning-usage> Threshold warning (in percent). =item B<--critical-usage> Threshold critical (in percent). =back =cut centreon-plugins-20220113/centreon/common/ingrian/snmp/mode/memory.pm000066400000000000000000000114661417000230700255470ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::ingrian::snmp::mode::memory; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_usage_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add(label => 'used', unit => 'B', value => $self->{result_values}->{used}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}, total => $self->{result_values}->{total}, cast_int => 1), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}, total => $self->{result_values}->{total}, cast_int => 1), min => 0, max => $self->{result_values}->{total}); } sub custom_usage_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check(value => $self->{result_values}->{prct_used}, 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("Memory 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}->{total} = $options{new_datas}->{$self->{instance} . '_total'}; $self->{result_values}->{prct_used} = $options{new_datas}->{$self->{instance} . '_prct_used'}; $self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used}; $self->{result_values}->{used} = $self->{result_values}->{total} * $self->{result_values}->{prct_used} / 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 => 'memory', type => 0 } ]; $self->{maps_counters}->{memory} = [ { label => 'usage', set => { key_values => [ { name => 'prct_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; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $oid_naeSystemStatUsedMem = '.1.3.6.1.4.1.5595.3.2.5.0'; my $oid_naeSystemStatTotalMem = '.1.3.6.1.4.1.5595.3.2.6.0'; # in Bytes my $snmp_result = $options{snmp}->get_leef(oids => [$oid_naeSystemStatUsedMem, $oid_naeSystemStatTotalMem], nothing_quit => 1); $self->{memory} = { prct_used => $snmp_result->{$oid_naeSystemStatUsedMem}, total => $snmp_result->{$oid_naeSystemStatTotalMem} }; } 1; __END__ =head1 MODE Check memory usages. =over 8 =item B<--warning-usage> Threshold warning (in percent). =item B<--critical-usage> Threshold critical (in percent). =back =cut centreon-plugins-20220113/centreon/common/ingrian/snmp/mode/requeststats.pm000066400000000000000000000117751417000230700270110ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::ingrian::snmp::mode::requeststats; 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 => 'rq', type => 1, cb_prefix_output => 'prefix_disk_output', message_multiple => 'All request statistics are ok' } ]; $self->{maps_counters}->{rq} = [ { label => 'success', set => { key_values => [ { name => 'success', diff => 1 }, { name => 'display' } ], output_template => 'Success : %s', perfdatas => [ { label => 'success', value => 'success', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'fail', set => { key_values => [ { name => 'fail', diff => 1 }, { name => 'display' } ], output_template => 'Fail : %s', perfdatas => [ { label => 'fail', value => 'fail', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub prefix_disk_output { my ($self, %options) = @_; return "'" . $options{instance_value}->{display} . "' requests "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, }); return $self; } my @map = ( { label => 'Total', suffix => 1 }, { label => 'KeyGen', suffix => 2 }, { label => 'KeyInfo', suffix => 3 }, { label => 'KeyDel', suffix => 4 }, { label => 'KeyQuery', suffix => 5 }, { label => 'KeyImport', suffix => 6 }, { label => 'KeyExport', suffix => 7 }, { label => 'RandomGen', suffix => 8 }, { label => 'Cryptographic', suffix => 9 }, { label => 'Authenticate', suffix => 10 }, { label => 'KeyModify', suffix => 11 }, { label => 'KeyClone', suffix => 12 }, { label => 'CertificateExport', suffix => 13 }, { label => 'KeyVersionGenerate', suffix => 14 }, { label => 'KeyVersionModify', suffix => 15 }, { label => 'KeyCertificateExport', suffix => 16 }, { label => 'RecordEvent', suffix => 17 }, { label => 'PublicKeyExport', suffix => 18 }, { label => 'CAExport', suffix => 19 }, ); my $oid_naeServerStats = '.1.3.6.1.4.1.5595.3.3'; sub manage_selection { my ($self, %options) = @_; $self->{rq} = {}; my $snmp_result = $options{snmp}->get_table(oid => $oid_naeServerStats, nothing_quit => 1); foreach (@map) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $_->{label} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $_->{label} . "': no matching filter.", debug => 1); next; } $self->{rq}->{$_->{suffix}} = { display => $_->{label}, success => $snmp_result->{$oid_naeServerStats . '.' . $_->{suffix} . '.3.0'}, fail => $snmp_result->{$oid_naeServerStats . '.' . $_->{suffix} . '.4.0'} }; } $self->{cache_name} = "ingrian_" . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')); } 1; __END__ =head1 MODE Check request statistics. =over 8 =item B<--filter-name> Filter by name (can be a regexp). =item B<--warning-*> Threshold warning. Can be: 'success', 'fail'. =item B<--critical-*> Threshold critical. Can be: 'success', 'fail'. =back =cut centreon-plugins-20220113/centreon/common/jvm/000077500000000000000000000000001417000230700211355ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/jvm/mode/000077500000000000000000000000001417000230700220615ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/jvm/mode/classcount.pm000066400000000000000000000066011417000230700246000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::jvm::mode::classcount; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); sub prefix_global_output { my ($self, %options) = @_; return 'Class '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'current', nlabel => 'class.loaded.current.count', set => { key_values => [ { name => 'LoadedClassCount' } ], output_template => 'current: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'loaded', nlabel => 'class.loaded.count', set => { key_values => [ { name => 'TotalLoadedClassCount', diff => 1 } ], output_template => 'loaded: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'unloaded', nlabel => 'class.unloaded.count', set => { key_values => [ { name => 'UnloadedClassCount', diff => 1 } ], output_template => 'unloaded: %s', perfdatas => [ { template => '%s', min => 0 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub manage_selection { my ($self, %options) = @_; my $mbean = 'java.lang:type=ClassLoading'; my $request = [ { mbean => $mbean, attributes => [ { name => 'UnloadedClassCount' }, { name => 'LoadedClassCount' }, { name => 'TotalLoadedClassCount' } ] }, ]; my $result = $options{custom}->get_attributes(request => $request, nothing_quit => 1); $self->{global} = $result->{$mbean}; $self->{cache_name} = 'jvm_standard_' . $self->{mode} . '_' . md5_hex($options{custom}->get_connection_info()) . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check Java Class Loading Mbean. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='current' =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'unloaded', 'loaded', 'current'. =back =cut centreon-plugins-20220113/centreon/common/jvm/mode/cpuload.pm000066400000000000000000000064271417000230700240570ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::jvm::mode::cpuload; 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 => ' - ', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'system', nlabel => 'system.cpu.load.percentage', set => { key_values => [ { name => 'system_load' } ], output_template => 'system cpu load: %.2f%%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%' } ] } }, { label => 'process', nlabel => 'process.cpu.load.percentage', set => { key_values => [ { name => 'process_load' } ], output_template => 'process cpu load: %.2f%%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{request} = [ { mbean => 'java.lang:type=OperatingSystem', attributes => [ { name => 'SystemCpuLoad' }, { name => 'ProcessCpuLoad' } ] } ]; my $result = $options{custom}->get_attributes(request => $self->{request}, nothing_quit => 1); $self->{global} = { system_load => $result->{'java.lang:type=OperatingSystem'}->{SystemCpuLoad} * 100, process_load => $result->{'java.lang:type=OperatingSystem'}->{ProcessCpuLoad} * 100 }; } 1; __END__ =head1 MODE Check JVM SystemCpuLoad and ProcessCpuLoad (From 0 to 1 where 1 means 100% of CPU ressources are in use, here we * by 100 for convenience). WARN : Probably not work for java -version < 7. Example: perl centreon_plugins.pl --plugin=apps::tomcat::jmx::plugin --custommode=jolokia --url=http://10.30.2.22:8080/jolokia --mode=cpu-load --warning-system 50 --critical-system 75 --warning-process 60 --critical-process 80 =over 8 =item B<--warning-system> Threshold warning of System cpuload =item B<--critical-system> Threshold critical of System cpuload =item B<--warning-process> Threshold warning of Process cpuload =item B<--critical-process> Threshold critical of Process cpuload =back =cut centreon-plugins-20220113/centreon/common/jvm/mode/fdusage.pm000066400000000000000000000102751417000230700240420ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::jvm::mode::fdusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_usage_output { my ($self, %options) = @_; return sprintf( "File descriptor usage total: %s used: %s (%.2f%%) free: %s (%.2f%%)", $self->{result_values}->{total}, $self->{result_values}->{used}, $self->{result_values}->{prct_used}, $self->{result_values}->{free}, $self->{result_values}->{prct_free} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 } ]; $self->{maps_counters}->{global} = [ { label => 'usage', nlabel => 'fd.opened.usage.count', set => { key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', cast_int => 1 }, ] } }, { label => 'usage-free', display_ok => 0, nlabel => 'fd.opened.free.count', set => { key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', cast_int => 1 } ] } }, { label => 'usage-prct', display_ok => 0, nlabel => 'fd.opened.usage.percentage', set => { key_values => [ { name => 'prct_used' }, { name => 'used' }, { name => 'free' }, { name => 'prct_free' }, { name => 'total' } ], output_template => 'Used : %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{request} = [ { mbean => 'java.lang:type=OperatingSystem', attributes => [ { name => 'MaxFileDescriptorCount' }, { name => 'OpenFileDescriptorCount' } ] } ]; my $result = $options{custom}->get_attributes(request => $self->{request}, nothing_quit => 1); $self->{global} = { used => $result->{'java.lang:type=OperatingSystem'}->{OpenFileDescriptorCount}, free => $result->{'java.lang:type=OperatingSystem'}->{MaxFileDescriptorCount} - $result->{'java.lang:type=OperatingSystem'}->{OpenFileDescriptorCount}, total => $result->{'java.lang:type=OperatingSystem'}->{MaxFileDescriptorCount} }; $self->{global}->{prct_used} = $self->{global}->{used} / $self->{global}->{total} * 100; $self->{global}->{prct_free} = 100 - $self->{global}->{prct_used}; } 1; __END__ =head1 MODE Check number/percentage of file descriptors Example: perl centreon_plugins.pl --plugin=apps::tomcat::jmx::plugin --custommode=jolokia --url=http://10.30.2.22:8080/jolokia-war --mode=fd-usage --warning 60 --critical 75 =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'usage', 'usage-free', 'usage-prct' (%). =back =cut centreon-plugins-20220113/centreon/common/jvm/mode/gcusage.pm000066400000000000000000000100111417000230700240260ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::jvm::mode::gcusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); sub prefix_gc_output { my ($self, %options) = @_; return "Garbage collector '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'gc', type => 1, cb_prefix_output => 'prefix_gc_output', message_multiple => 'All garbage collectors are ok' } ]; $self->{maps_counters}->{gc} = [ { label => 'time', nlabel => 'gc.collection.time.elapsed.milliseconds', set => { key_values => [ { name => 'time', diff => 1 }, { name => 'display' } ], output_template => 'collection time: %s ms', perfdatas => [ { template => '%s', unit => 'ms', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'count', nlabel => 'gc.collection.count', set => { key_values => [ { name => 'count', diff => 1 }, { name => 'display' } ], output_template => 'collection count: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{request} = [ { mbean => "java.lang:type=GarbageCollector,name=*", attributes => [ { name => 'CollectionCount' }, { name => 'CollectionTime' } ] } ]; $self->{gc} = {}; my $result = $options{custom}->get_attributes(request => $self->{request}, nothing_quit => 1); foreach my $key (keys %$result) { $key =~ /name=(.*?)(?:,|$)/; my $name = $1; $self->{gc}->{$name} = { display => $name, time => $result->{$key}->{CollectionTime}, count => $result->{$key}->{CollectionCount} } } if (scalar(keys %{$self->{gc}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No garbage collector found.'); $self->{output}->option_exit(); } $self->{cache_name} = 'jvm_standard_' . $self->{mode} . '_' . md5_hex($options{custom}->get_connection_info()) . '_' . (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 garbage collectors. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^count$' =item B<--filter-name> Filter garbage collector name (can be a regexp). =item B<--warning-*> Threshold warning. Can be: 'count', 'time' (ms). =item B<--critical-*> Threshold critical. Can be: 'count', 'time' (ms). =back =cut centreon-plugins-20220113/centreon/common/jvm/mode/loadaverage.pm000066400000000000000000000050351417000230700246740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::jvm::mode::loadaverage; 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 } ]; $self->{maps_counters}->{global} = [ { label => 'load1', nlabel => 'system.load.1m.count', set => { key_values => [ { name => 'load' } ], output_template => 'System load average: %.2f (1m)', perfdatas => [ { template => '%.2f', min => 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 => {}); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{request} = [ { mbean => "java.lang:type=OperatingSystem", attributes => [ { name => 'SystemLoadAverage' } ] } ]; my $result = $options{custom}->get_attributes(request => $self->{request}, nothing_quit => 1); my $load = $result->{'java.lang:type=OperatingSystem'}->{SystemLoadAverage}; if ($load == -1) { $self->{output}->add_option_msg(short_msg => 'System load average is not set'); $self->{output}->option_exit(); } $self->{global} = { load => $load }; } 1; __END__ =head1 MODE Check system load average Example: perl centreon_plugins.pl --plugin=apps::tomcat::jmx::plugin --custommode=jolokia --url=http://10.30.2.22:8080/jolokia-war --mode=load-average --warning 2 --critical 3 =over 8 =item B<--warning-load1> Warning threshold for loadaverage =item B<--critical-load1> Critical threshold for loadaverage =back =cut centreon-plugins-20220113/centreon/common/jvm/mode/memory.pm000066400000000000000000000160101417000230700237250ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::jvm::mode::memory; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_usage_perfdata { my ($self, %options) = @_; my $use_th = 1; $use_th = 0 if ($self->{instance_mode}->{option_results}->{units} eq '%' && $self->{result_values}->{max} <= 0); my $value_perf = $self->{result_values}->{used}; my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%' && $self->{result_values}->{max} > 0) { $total_options{total} = $self->{result_values}->{max}; $total_options{cast_int} = 1; } $self->{output}->perfdata_add( nlabel => $self->{nlabel}, unit => 'B', value => $value_perf, warning => $use_th == 1 ? $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, %total_options) : undef, critical => $use_th == 1 ? $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, %total_options) : undef, min => 0, max => $self->{result_values}->{max} > 0 ? $self->{result_values}->{max} : undef ); } sub custom_usage_threshold { my ($self, %options) = @_; # Cannot use percent without total return 'ok' if ($self->{result_values}->{max} <= 0 && $self->{instance_mode}->{option_results}->{units} eq '%'); my ($exit, $threshold_value); $threshold_value = $self->{result_values}->{used}; if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; } $exit = $self->{perfdata}->threshold_check( value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_usage_output { my ($self, %options) = @_; my $msg; my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); if ($self->{result_values}->{max} > 0) { my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{max}); my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{max} - $self->{result_values}->{used}); $msg = sprintf( "%s Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", $self->{result_values}->{label}, $total_size_value . " " . $total_size_unit, $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}, $total_free_value . " " . $total_free_unit, 100 - $self->{result_values}->{prct_used} ); } else { $msg = sprintf( "%s Used: %s", $self->{result_values}->{label}, $total_used_value . " " . $total_used_unit ); } return $msg; } sub custom_usage_calc { my ($self, %options) = @_; $self->{result_values}->{label} = $options{new_datas}->{$self->{label} . '_label'}; $self->{result_values}->{max} = $options{new_datas}->{$self->{instance} . '_max'}; $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_used'}; if ($self->{result_values}->{max} > 0) { $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{max}; } return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'heap', type => 0 }, { name => 'nonheap', type => 0 } ]; $self->{maps_counters}->{heap} = [ { label => 'heap', nlabel => 'memory.heap.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'max' }, { name => 'label' } ], 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') } }, ]; $self->{maps_counters}->{nonheap} = [ { label => 'nonheap', nlabel => 'memory.nonheap.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'max' }, { name => 'label' } ], 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, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'units:s' => { name => 'units', default => '%' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{request} = [ { mbean => 'java.lang:type=Memory' } ]; my $result = $options{custom}->get_attributes(request => $self->{request}, nothing_quit => 1); $self->{heap} = { label => 'HeapMemory', used => $result->{'java.lang:type=Memory'}->{HeapMemoryUsage}->{used}, max => $result->{'java.lang:type=Memory'}->{HeapMemoryUsage}->{max} }; $self->{nonheap} = { label => 'NonHeapMemoryUsage', used => $result->{'java.lang:type=Memory'}->{NonHeapMemoryUsage}->{used}, max => $result->{'java.lang:type=Memory'}->{NonHeapMemoryUsage}->{max} }; } 1; __END__ =head1 MODE Check Java Heap and NonHeap Memory usage (Mbean java.lang:type=Memory). Example: perl centreon_plugins.pl --plugin=apps::tomcat::jmx::plugin --custommode=jolokia --url=http://10.30.2.22:8080/jolokia-war --mode=memory --warning-heap 60 --critical-heap 75 --warning-nonheap 65 --critical-nonheap 75 =over 8 =item B<--warning-heap> Threshold warning of Heap memory usage =item B<--critical-heap> Threshold critical of Heap memory usage =item B<--warning-nonheap> Threshold warning of NonHeap memory usage =item B<--critical-nonheap> Threshold critical of NonHeap memory usage =item B<--units> Units of thresholds (Default: '%') ('%', 'B'). =back =cut centreon-plugins-20220113/centreon/common/jvm/mode/memorydetailed.pm000066400000000000000000000253421417000230700254310ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::jvm::mode::memorydetailed; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my %mapping_memory = ( 'Eden Space' => 'eden', 'Par Eden Space' => 'eden', 'PS Eden Space' => 'eden', 'Survivor Space' => 'survivor', 'Par Survivor Space' => 'survivor', 'PS Survivor Space' => 'survivor', 'CMS Perm Gen' => 'permanent', 'PS Perm Gen' => 'permanent', 'Perm Gen' => 'permanent', 'Metaspace' => 'permanent', 'JIT data cache' => 'permanent', 'Code Cache' => 'code', 'JIT Code Cache' => 'code', 'CMS Old Gen' => 'tenured', 'PS Old Gen' => 'tenured', 'Tenured Gen' => 'tenured' ); sub custom_usage_perfdata { my ($self, %options) = @_; my $use_th = 1; $use_th = 0 if ($self->{instance_mode}->{option_results}->{units} eq '%' && $self->{result_values}->{max} <= 0); my $value_perf = $self->{result_values}->{used}; my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%' && $self->{result_values}->{max} > 0) { $total_options{total} = $self->{result_values}->{max}; $total_options{cast_int} = 1; } $self->{output}->perfdata_add( nlabel => $self->{nlabel}, unit => 'B', value => $value_perf, warning => $use_th == 1 ? $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, %total_options) : undef, critical => $use_th == 1 ? $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, %total_options) : undef, min => 0, max => $self->{result_values}->{max} > 0 ? $self->{result_values}->{max} : undef ); } sub custom_usage_threshold { my ($self, %options) = @_; # Cannot use percent without total return 'ok' if ($self->{result_values}->{max} <= 0 && $self->{instance_mode}->{option_results}->{units} eq '%'); my ($exit, $threshold_value); $threshold_value = $self->{result_values}->{used}; if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; } $exit = $self->{perfdata}->threshold_check( value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_usage_output { my ($self, %options) = @_; my $msg; my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); if ($self->{result_values}->{max} > 0) { my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{max}); my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{max} - $self->{result_values}->{used}); $msg = sprintf( "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, 100 - $self->{result_values}->{prct_used} ); } else { $msg = sprintf("Used: %s", $total_used_value . " " . $total_used_unit); } return $msg; } sub custom_usage_calc { my ($self, %options) = @_; if ($mapping_memory{$options{new_datas}->{$self->{instance} . '_display'}} ne $self->{label}) { return -12; } $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{max} = $options{new_datas}->{$self->{instance} . '_max'}; $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_used'}; if ($self->{result_values}->{max} > 0) { $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{max}; } return 0; } sub prefix_mem_output { my ($self, %options) = @_; return "Memory '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'mem', type => 1, cb_prefix_output => 'prefix_mem_output', message_multiple => 'All memories within bounds', skipped_code => { -12 => 1 } } ]; $self->{maps_counters}->{mem} = [ { label => 'eden', nlabel => 'memory.eden.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'max' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_output => $self->can('custom_usage_output'), closure_custom_threshold_check => $self->can('custom_usage_threshold'), closure_custom_perfdata => $self->can('custom_usage_perfdata') } }, { label => 'tenured', nlabel => 'memory.tenured.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'max' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_output => $self->can('custom_usage_output'), closure_custom_threshold_check => $self->can('custom_usage_threshold'), closure_custom_perfdata => $self->can('custom_usage_perfdata') } }, { label => 'survivor', nlabel => 'memory.survivor.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'max' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_output => $self->can('custom_usage_output'), closure_custom_threshold_check => $self->can('custom_usage_threshold'), closure_custom_perfdata => $self->can('custom_usage_perfdata') } }, { label => 'permanent', nlabel => 'memory.permanent.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'max' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_output => $self->can('custom_usage_output'), closure_custom_threshold_check => $self->can('custom_usage_threshold'), closure_custom_perfdata => $self->can('custom_usage_perfdata') } }, { label => 'code', nlabel => 'memory.code.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'max' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_output => $self->can('custom_usage_output'), closure_custom_threshold_check => $self->can('custom_usage_threshold'), closure_custom_perfdata => $self->can('custom_usage_perfdata') } } ]; } 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 => { 'units:s' => { name => 'units', default => '%' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{request} = [ { mbean => 'java.lang:type=MemoryPool,name=*', attributes => [ { name => 'Usage' } ] } ]; my $result = $options{custom}->get_attributes(request => $self->{request}, nothing_quit => 1); $self->{mem} = {}; foreach my $key (keys %$result) { $key =~ /(?:[:,])name=(.*?)(?:,|$)/; my $memtype = $1; if (!defined($mapping_memory{$memtype})) { $self->{output}->output_add(long_msg => "unknown memory type: " . $memtype, debug => 1); next; } $self->{mem}->{$memtype} = { display => $memtype, used => $result->{'java.lang:name=' . $memtype . ',type=MemoryPool'}->{Usage}->{used}, max => $result->{'java.lang:name=' . $memtype . ',type=MemoryPool'}->{Usage}->{max} }; } } 1; __END__ =head1 MODE Check JVM Memory Pools : Eden Space (heap) (-eden) : The pool from which memory is initially allocated for most objects. Survivor Space (heap) (-survivor) : The pool containing objects that have survived the garbage collection of the Eden space. Tenured Generation (heap) (-tenured) : The pool containing objects that have existed for some time in the survivor space. Permanent Generation (non-heap) (-permanent) : The pool containing all the reflective data of the virtual machine itself, such as class and method objects. Code Cache (non-heap) (-code) : The HotSpot Java VM also includes a code cache, containing memory that is used for compilation and storage of native code. Example: perl centreon_plugins.pl --plugin=apps::tomcat::jmx::plugin --custommode=jolokia --url=http://10.30.2.22:00/jolokia-war --mode=memory-detailed --warning-eden 60 --critical-eden 75 --warning-survivor 65 --critical-survivor 75 =over 8 =item B<--warning-eden> Threshold warning of Heap 'Eden Space' memory usage =item B<--critical-eden> Threshold critical of Heap 'Survivor Space' memory usage =item B<--warning-tenured> Threshold warning of Heap 'Tenured Generation' memory usage =item B<--critical-tenured> Threshold critical of Heap 'Tenured Generation' memory usage =item B<--warning-survivor> Threshold warning of Heap 'Survivor Space' memory usage =item B<--critical-survivor> Threshold critical of Heap 'Survivor Space' memory usage =item B<--warning-permanent> Threshold warning of NonHeap 'Permanent Generation' memory usage =item B<--critical-permanent> Threshold critical of NonHeap 'Permanent Generation' memory usage =item B<--warning-code> Threshold warning of NonHeap 'Code Cache' memory usage =item B<--critical-code> Threshold critical of NonHeap 'Code Cache' memory usage =item B<--units> Units of thresholds (Default: '%') ('%', 'B'). =back =cut centreon-plugins-20220113/centreon/common/jvm/mode/threads.pm000066400000000000000000000064501417000230700240560ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::jvm::mode::threads; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); sub prefix_global_output { my ($self, %options) = @_; return 'Threads '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'active', nlabel => 'threads.active.count', set => { key_values => [ { name => 'ThreadCount' } ], output_template => 'active: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'started', nlabel => 'threads.started.count', set => { key_values => [ { name => 'TotalStartedThreadCount', diff => 1 } ], output_template => 'started: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'daemon', nlabel => 'threads.daemon.count', set => { key_values => [ { name => 'DaemonThreadCount' } ], output_template => 'daemon: %s', perfdatas => [ { template => '%s', min => 0 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $mbean = 'java.lang:type=Threading'; my $request = [ { mbean => $mbean, attributes => [ { name => 'TotalStartedThreadCount' }, { name => 'ThreadCount' }, { name => 'DaemonThreadCount' } ] }, ]; my $result = $options{custom}->get_attributes(request => $request, nothing_quit => 1); $self->{global} = $result->{$mbean}; $self->{cache_name} = 'jvm_standard_' . $self->{mode} . '_' . md5_hex($options{custom}->get_connection_info()) . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check threads. =over 8 =item B<--warning-*> Threshold warning. Can be: 'active', 'started', 'daemon'. =item B<--critical-*> Threshold critical. Can be: 'active', 'started', 'daemon'. =back =cut centreon-plugins-20220113/centreon/common/microsoft/000077500000000000000000000000001417000230700223465ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/microsoft/skype/000077500000000000000000000000001417000230700235015ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/microsoft/skype/mssql/000077500000000000000000000000001417000230700246405ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/microsoft/skype/mssql/mode/000077500000000000000000000000001417000230700255645ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/microsoft/skype/mssql/mode/appsharingqoe.pm000066400000000000000000000132731417000230700307710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::microsoft::skype::mssql::mode::appsharingqoe; 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, skipped_code => { -10 => 1 } }, { name => 'count', type => 0 }, ]; $self->{maps_counters}->{global} = [ { label => 'spoiled-tile-prct-total-avg', set => { key_values => [ { name => 'SpoiledTilePercentTotal' } ], output_template => 'Average Spoiled Tiles: %.2f%%', perfdatas => [ { label => 'spoiled_tile_prct_total_avg', value => 'SpoiledTilePercentTotal', template => '%.2f', unit => '%', min => 0, max => 100 }, ], } }, { label => 'rdp-tile-processing-latency-avg', set => { key_values => [ { name => 'RDPTileProcessingLatencyAverage' } ], output_template => 'Average RDP Tiles Processing Latency: %.2f ms', perfdatas => [ { label => 'rdp_tile_processing_latency_avg', value => 'RDPTileProcessingLatencyAverage', template => '%.2f', unit => 'ms', min => 0 }, ], } }, { label => 'relative-one-way-average', set => { key_values => [ { name => 'RelativeOneWayAverage' } ], output_template => 'Average Amount of One-way Latency: %.2f ms', perfdatas => [ { label => 'relative_one_way_average', value => 'RelativeOneWayAverage', template => '%.2f', unit => 'ms', min => 0 }, ], } }, ]; $self->{maps_counters}->{count} = [ { label => 'stream-count', set => { key_values => [ { name => 'TotalStreams' } ], output_template => 'Streams Count: %.2f/s', perfdatas => [ { label => 'stream_count', value => 'TotalStreams', template => '%.2f', unit => 'streams/s', min => 0 }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "timeframe:s" => { name => 'timeframe', default => '900' }, "filter-counters:s" => { name => 'filter_counters', default => '' }, }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{sql} = $options{sql}; $self->{sql}->connect(); my $query = "SELECT AVG(SpoiledTilePercentTotal) AS SpoiledTilePercentTotal, AVG(RDPTileProcessingLatencyAverage) AS RDPTileProcessingLatencyAverage, AVG(RelativeOneWayAverage) AS RelativeOneWayAverage, COUNT(*) AS TotalStreams FROM [QoEMetrics].[dbo].AppSharingStream WHERE ConferenceDateTime > (DATEADD(SECOND,-" . $self->{option_results}->{timeframe} . ",SYSUTCDATETIME())) AND ConferenceDateTime < SYSUTCDATETIME()"; $self->{sql}->query(query => $query); my $results = $self->{sql}->fetchrow_hashref; $self->{global} = { SpoiledTilePercentTotal => (defined($results->{SpoiledTilePercentTotal})) ? $results->{SpoiledTilePercentTotal} : 0, RDPTileProcessingLatencyAverage => (defined($results->{RDPTileProcessingLatencyAverage})) ? $results->{RDPTileProcessingLatencyAverage} : 0, RelativeOneWayAverage => (defined($results->{RelativeOneWayAverage})) ? $results->{RelativeOneWayAverage} : 0, }; $self->{count}->{TotalStreams} = $results->{TotalStreams} / $self->{option_results}->{timeframe}; } 1; __END__ =head1 MODE Check app sharing QoE metrics from SQL Server (Lync 2013, Skype 2015). MS Recommandations : SpoiledTilePercentTotal (Total percentage of the content that did not reach the viewer but was instead discarded and overwritten by fresh content) > 36 RDPTileProcessingLatencyAverage (Average processing time for remote desktop protocol (RDP) tiles. A higher total equates to a longer delay in the viewing experience) > 400 RelativeOneWayAverage (Average amount of one-way latency. Relative one-way latency measures the delay between the client and the server) > 1.75 =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). =item B<--timeframe> Set the timeframe to query in seconds (Default: 900) =item B<--warning-*> Set warning thresholds. Can be : 'spoiled-tile-prct-total-avg', 'rdp-tile-processing-latency-avg', 'relative-one-way-average' =item B<--critical-*> Set critical thresholds. Can be : 'spoiled-tile-prct-total-avg', 'rdp-tile-processing-latency-avg', 'relative-one-way-average' =back =cut centreon-plugins-20220113/centreon/common/microsoft/skype/mssql/mode/audioqoe.pm000066400000000000000000000154331417000230700277360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::microsoft::skype::mssql::mode::audioqoe; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'jitter', type => 0, cb_prefix_output => 'prefix_jitter_output', skipped_code => { -10 => 1 } }, { name => 'packet', type => 0, cb_prefix_output => 'prefix_packet_output', skipped_code => { -10 => 1 } }, { name => 'count', type => 0 }, ]; $self->{maps_counters}->{jitter} = [ { label => 'jitter-avg', set => { key_values => [ { name => 'JitterAvg' } ], output_template => 'Average: %d ms', perfdatas => [ { label => 'jitter_avg', value => 'JitterAvg', template => '%d', unit => 'ms', min => 0 }, ], } }, { label => 'jitter-min', set => { key_values => [ { name => 'JitterMin' } ], output_template => 'Min: %d ms', perfdatas => [ { label => 'jitter_min', value => 'JitterMin', template => '%d', unit => 'ms', min => 0 }, ], } }, { label => 'jitter-max', set => { key_values => [ { name => 'JitterMax' } ], output_template => 'Max: %d ms', perfdatas => [ { label => 'jitter_max', value => 'JitterMax', template => '%d', unit => 'ms', min => 0 }, ], } }, ]; $self->{maps_counters}->{packet} = [ { label => 'loss-avg', set => { key_values => [ { name => 'PacketLossAvg' } ], output_template => 'Average: %.2f%%', perfdatas => [ { label => 'pckt_loss_avg', value => 'PacketLossAvg', template => '%.2f', unit => '%', min => 0, max => 100 }, ], } }, { label => 'loss-min', set => { key_values => [ { name => 'PacketLossMin' } ], output_template => 'Min: %.2f%%', perfdatas => [ { label => 'pckt_loss_min', value => 'PacketLossMin', template => '%.2f', unit => '%', min => 0, max => 100 }, ], } }, { label => 'loss-max', set => { key_values => [ { name => 'PacketLossMax' } ], output_template => 'Max: %.2f%%', perfdatas => [ { label => 'pckt_loss_max', value => 'PacketLossMax', template => '%.2f', unit => '%', min => 0, max => 100 }, ], } }, ]; $self->{maps_counters}->{count} = [ { label => 'stream-count', set => { key_values => [ { name => 'TotalStreams' } ], output_template => 'Streams Count: %.2f/s', perfdatas => [ { label => 'stream_count', value => 'TotalStreams', template => '%.2f', unit => 'streams/s', min => 0 }, ], } }, ]; } sub prefix_jitter_output { my ($self, %options) = @_; return "Jitter "; } sub prefix_packet_output { my ($self, %options) = @_; return "Packets Loss "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "timeframe:s" => { name => 'timeframe', default => '900' }, "filter-counters:s" => { name => 'filter_counters', default => '' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; $self->{sql} = $options{sql}; $self->{sql}->connect(); my $query = "SELECT MIN(CAST(JitterInterArrival AS BIGINT)) AS JitterMin, MAX(CAST(JitterInterArrival AS BIGINT)) AS JitterMax, AVG(CAST(JitterInterArrival AS BIGINT)) AS JitterAvg, MIN(PacketLossRate) AS PacketLossMin, MAX(PacketLossRate) AS PacketLossMax, AVG(PacketLossRate) AS PacketLossAvg, COUNT(*) AS TotalStreams FROM [QoEMetrics].[dbo].AudioStream WHERE ConferenceDateTime > (DATEADD(SECOND,-" . $self->{option_results}->{timeframe} . ",SYSUTCDATETIME())) AND ConferenceDateTime < SYSUTCDATETIME()"; $self->{sql}->query(query => $query); my $results = $self->{sql}->fetchrow_hashref; $self->{jitter} = { JitterMin => (defined($results->{JitterMin})) ? $results->{JitterMin} : 0, JitterMax => (defined($results->{JitterMax})) ? $results->{JitterMax} : 0, JitterAvg => (defined($results->{JitterAvg})) ? $results->{JitterAvg} : 0, }; $self->{packet} = { PacketLossMin => (defined($results->{PacketLossMin})) ? $results->{PacketLossMin} : 0, PacketLossMax => (defined($results->{PacketLossMax})) ? $results->{PacketLossMax} : 0, PacketLossAvg => (defined($results->{PacketLossAvg})) ? $results->{PacketLossAvg} : 0, }; $self->{count}->{TotalStreams} = $results->{TotalStreams} / $self->{option_results}->{timeframe}; } 1; __END__ =head1 MODE Check audio stream QoE metrics from SQL Server (Lync 2013, Skype 2015). =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). =item B<--timeframe> Set the timeframe to query in seconds (Default: 900) =item B<--warning-*> Set warning thresholds. Can be : 'jitter-min', 'jitter-max', 'jitter-avg', 'loss-min', 'loss-max', 'loss-avg' =item B<--critical-*> Set critical thresholds. Can be : 'jitter-min', 'jitter-max', 'jitter-avg', 'loss-min', 'loss-max', 'loss-avg' =back =cut centreon-plugins-20220113/centreon/common/microsoft/skype/mssql/mode/poorcalls.pm000066400000000000000000000101341417000230700301170ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::microsoft::skype::mssql::mode::poorcalls; 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 }, { name => 'uri', type => 1, cb_prefix_output => 'prefix_uri_output', message_multiple => 'All users are ok' }, ]; $self->{maps_counters}->{global} = [ { label => 'global', set => { key_values => [ { name => 'count' } ], output_template => 'Poor Calls: %d', perfdatas => [ { label => 'poor_calls', value => 'count', template => '%d', unit => 'calls', min => 0 }, ], } }, ]; $self->{maps_counters}->{uri} = [ { label => 'user', set => { key_values => [ { name => 'count' }, { name => 'display' } ], output_template => 'poor calls count: %d', } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "lookback:s" => { name => 'lookback', default => '65' }, # not used "timeframe:s" => { name => 'timeframe', default => '900' }, "filter-user:s" => { name => 'filter_user' }, "filter-counters:s" => { name => 'filter_counters', default => '' }, }); return $self; } sub prefix_uri_output { my ($self, %options) = @_; return "User '" . $options{instance_value}->{display} . "' "; } sub manage_selection { my ($self, %options) = @_; $self->{sql} = $options{sql}; $self->{sql}->connect(); my $query = "SELECT URI, LastPoorCallTime FROM [QoEMetrics].[dbo].[User] WHERE LastPoorCallTime > (DATEADD(SECOND,-" . $self->{option_results}->{timeframe} . ",SYSUTCDATETIME())) AND LastPoorCallTime < SYSUTCDATETIME()"; $self->{sql}->query(query => $query); $self->{global}->{count} = 0; while (my $row = $self->{sql}->fetchrow_hashref()) { if (defined($self->{option_results}->{filter_user}) && $self->{option_results}->{filter_user} ne '' && $row->{URI} !~ /$self->{option_results}->{filter_user}/) { $self->{output}->output_add(long_msg => "Skipping '" . $row->{URI} . "': no matching filter.", debug => 1); next; } $self->{global}->{count}++; $self->{uri}->{$row->{URI}} = { count => 0, display => $row->{URI} } if (!defined($self->{uri}->{$row->{URI}})); $self->{uri}->{$row->{URI}}->{count}++; } } 1; __END__ =head1 MODE Check poor calls from SQL Server (Lync 2013, Skype 2015). =over 8 =item B<--filter-user> Filter user name (can be a regexp) =item B<--filter-counters> Only display some counters (regexp can be used). =item B<--timeframe> Set the timeframe to query in seconds (Default: 900) =item B<--warning-global> Set warning threshold for number of poor calls. =item B<--critical-global> Set critical threshold for number of poor calls. =back =cut centreon-plugins-20220113/centreon/common/microsoft/skype/mssql/mode/sessionstypes.pm000066400000000000000000000136431417000230700310640ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::microsoft::skype::mssql::mode::sessionstypes; 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 }, ]; $self->{maps_counters}->{global} = [ { label => 'instant-messaging', set => { key_values => [ { name => 'instant_messaging' } ], output_template => 'Instant Messaging: %d', perfdatas => [ { label => 'instant_messaging', value => 'instant_messaging', template => '%d', unit => 'sessions', min => 0 }, ], } }, { label => 'audio', set => { key_values => [ { name => 'audio' } ], output_template => 'Audio: %d', perfdatas => [ { label => 'audio', value => 'audio', template => '%d', unit => 'sessions', min => 0 }, ], } }, { label => 'video', set => { key_values => [ { name => 'video' } ], output_template => 'Video: %d', perfdatas => [ { label => 'video', value => 'video', template => '%d', unit => 'sessions', min => 0 }, ], } }, { label => 'file-transfer', set => { key_values => [ { name => 'file_transfer' } ], output_template => 'File Transfer: %d', perfdatas => [ { label => 'file_transfer', value => 'file_transfer', template => '%d', unit => 'sessions', min => 0 }, ], } }, { label => 'remote-assistance', set => { key_values => [ { name => 'remote_assistance' } ], output_template => 'Remote Assistance: %d', perfdatas => [ { label => 'remote_assistance', value => 'remote_assistance', template => '%d', unit => 'sessions', min => 0 }, ], } }, { label => 'app-sharing', set => { key_values => [ { name => 'app_sharing' } ], output_template => 'App Sharing: %d', perfdatas => [ { label => 'app_sharing', value => 'app_sharing', template => '%d', unit => 'sessions', min => 0 }, ], } }, { label => 'app-invite', set => { key_values => [ { name => 'app_invite' } ], output_template => 'App Invite: %d', perfdatas => [ { label => 'app_invite', value => 'app_invite', template => '%d', unit => 'sessions', min => 0 }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "lookback:s" => { name => 'lookback', default => '5' }, # not used "timeframe:s" => { name => 'timeframe', default => '900' }, "filter-counters:s" => { name => 'filter_counters', default => '' }, }); return $self; } my %mapping_types = ( 1 => 'instant_messaging', 2 => 'file_transfer', 4 => 'remote_assistance', 8 => 'app_sharing', 16 => 'audio', 32 => 'video', 64 => 'app_invite', ); sub manage_selection { my ($self, %options) = @_; $self->{sql} = $options{sql}; $self->{sql}->connect(); $self->{global} = { instant_messaging => 0, file_transfer => 0, remote_assistance => 0, app_sharing => 0, app_sharing => 0, video => 0, app_invite => 0 }; my $query = "SELECT * FROM [LcsCDR].[dbo].[SessionDetails] s LEFT OUTER JOIN [LcsCDR].[dbo].[Users] u1 ON s.User1Id = u1.UserId LEFT OUTER JOIN [LcsCDR].[dbo].[Users] u2 ON s.User2Id = u2.UserId WHERE s.SessionIdTime > (DATEADD(SECOND,-" . $self->{option_results}->{timeframe} . ",SYSUTCDATETIME())) AND s.SessionIdTime < SYSUTCDATETIME()"; $self->{sql}->query(query => $query); while (my $row = $self->{sql}->fetchrow_hashref()) { next if (!defined($mapping_types{$row->{MediaTypes}})); $self->{global}->{$mapping_types{$row->{MediaTypes}}}++; } } 1; __END__ =head1 MODE Check number of sessions ordered by type. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). =item B<--timeframe> Set the timeframe to query in seconds (Default: 900) =item B<--warning-*> Set warning threshold. Can be : 'instant-messaging', 'app-sharing', 'audio', 'video', 'app-invite', 'remote-assistance' =item B<--critical-*> Set critical threshold. Can be : 'instant-messaging', 'app-sharing', 'audio', 'video', 'app-invite', 'remote-assistance' =back =cut centreon-plugins-20220113/centreon/common/microsoft/skype/mssql/mode/videoqoe.pm000066400000000000000000000144461417000230700277460ustar00rootroot00000000000000package centreon::common::microsoft::skype::mssql::mode::videoqoe; 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, skipped_code => { -10 => 1 } }, { name => 'count', type => 0 }, ]; $self->{maps_counters}->{global} = [ { label => 'packet-loss', set => { key_values => [ { name => 'VideoPacketLossRate' } ], output_template => 'Packet Loss Rate: %.2f%%', perfdatas => [ { label => 'video_pckt_loss_rate', value => 'VideoPacketLossRate', template => '%.2f', unit => '%', min => 0, max => 100 }, ], } }, { label => 'post-fecplr', set => { key_values => [ { name => 'VideoPostFECPLR' } ], output_template => 'Packet Loss Rate After Correction: %.2f%%', perfdatas => [ { label => 'video_post_fecplr', value => 'VideoPostFECPLR', template => '%.2f', unit => '%', min => 0, max => 100 }, ], } }, { label => 'local-frame-loss', set => { key_values => [ { name => 'VideoLocalFrameLossPercentageAvg' } ], output_template => 'Video Frame Loss: %.2f%%', perfdatas => [ { label => 'video_frame_loss_prct_avg', value => 'VideoLocalFrameLossPercentageAvg', template => '%.2f', unit => '%', min => 0, max => 100 }, ], } }, { label => 'recv-frame', set => { key_values => [ { name => 'RecvFrameRateAverage' } ], output_template => 'Receiver Frame Rate: %.2f/s', perfdatas => [ { label => 'rcv_frame_rate_avg', value => 'RecvFrameRateAverage', template => '%.2f', unit => 'frames/s', min => 0 }, ], } }, { label => 'inbound-frame', set => { key_values => [ { name => 'InboundVideoFrameRateAvg' } ], output_template => 'Inbound Video Frame Rate: %.2f%%', perfdatas => [ { label => 'inbound_video_frame_rate_avg', value => 'InboundVideoFrameRateAvg', template => '%.2f', unit => '%', min => 0, max => 100 }, ], } }, { label => 'outbound-frame', set => { key_values => [ { name => 'OutboundVideoFrameRateAvg' } ], output_template => 'Outbound Video Frame Rate: %.2f%%', perfdatas => [ { label => 'outbound_video_frame_rate_avg', value => 'OutboundVideoFrameRateAvg', template => '%.2f', unit => '%', min => 0, max => 100 }, ], } }, ]; $self->{maps_counters}->{count} = [ { label => 'stream-count', set => { key_values => [ { name => 'TotalStreams' } ], output_template => 'Streams Count: %.2f/s', perfdatas => [ { label => 'stream_count', value => 'TotalStreams', template => '%.2f', unit => 'streams/s', min => 0 }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "timeframe:s" => { name => 'timeframe', default => '900' }, "filter-counters:s" => { name => 'filter_counters', default => '' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; $self->{sql} = $options{sql}; $self->{sql}->connect(); my $query = "SELECT AVG(VideoPostFECPLR) AS VideoPostFECPLR, AVG(VideoLocalFrameLossPercentageAvg) AS VideoLocalFrameLossPercentageAvg, AVG(RecvFrameRateAverage) AS RecvFrameRateAverage, AVG(VideoPacketLossRate) AS VideoPacketLossRate, AVG(InboundVideoFrameRateAvg) AS InboundVideoFrameRateAvg, AVG(OutboundVideoFrameRateAvg) AS OutboundVideoFrameRateAvg, COUNT(*) AS TotalStreams FROM [QoEMetrics].[dbo].VideoStream WHERE ConferenceDateTime > (DATEADD(SECOND,-" . $self->{option_results}->{timeframe} . ",SYSUTCDATETIME())) AND ConferenceDateTime < SYSUTCDATETIME()"; $self->{sql}->query(query => $query); my $results = $self->{sql}->fetchrow_hashref; $self->{global} = { VideoPostFECPLR => (defined($results->{VideoPostFECPLR})) ? $results->{VideoPostFECPLR} : 0, VideoLocalFrameLossPercentageAvg => (defined($results->{VideoLocalFrameLossPercentageAvg})) ? $results->{VideoLocalFrameLossPercentageAvg} : 0, RecvFrameRateAverage => (defined($results->{RecvFrameRateAverage})) ? $results->{RecvFrameRateAverage} : 0, VideoPacketLossRate => (defined($results->{VideoPacketLossRate})) ? $results->{VideoPacketLossRate} : 0, InboundVideoFrameRateAvg => (defined($results->{InboundVideoFrameRateAvg})) ? $results->{InboundVideoFrameRateAvg} : 0, OutboundVideoFrameRateAvg => (defined($results->{OutboundVideoFrameRateAvg})) ? $results->{OutboundVideoFrameRateAvg} : 0, }; $self->{count}->{TotalStreams} = $results->{TotalStreams} / $self->{option_results}->{timeframe}; } 1; __END__ =head1 MODE Check video stream QoE from SQL Server (Lync 2013, Skype 2015). =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). =item B<--timeframe> Set the timeframe to query in seconds (Default: 900) =item B<--warning-*> Set warning thresholds. Can be : 'recv-frame', 'local-frame-loss', 'post-fecplr', 'packet-loss', 'inboud-frame', 'outbound-frame' =item B<--critical-*> Set critical thresholds. Can be : 'recv-frame', 'local-frame-loss', 'post-fecplr', packet-loss', 'inboud-frame', 'outbound-frame' =back =cut centreon-plugins-20220113/centreon/common/monitoring/000077500000000000000000000000001417000230700225265ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/monitoring/openmetrics/000077500000000000000000000000001417000230700250565ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/monitoring/openmetrics/custom/000077500000000000000000000000001417000230700263705ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/monitoring/openmetrics/custom/file.pm000066400000000000000000000101371417000230700276470ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::monitoring::openmetrics::custom::file; use strict; use warnings; use centreon::plugins::misc; use Digest::MD5 qw(md5_hex); 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 => { 'hostname:s' => { name => 'hostname' }, '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 => 10 }, 'sudo' => { name => 'sudo' }, 'command:s' => { name => 'command', default => 'cat' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'FILE OPTIONS', once => 1); $self->{output} = $options{output}; return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; if (defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '') { $self->{option_results}->{remote} = 1; } return 0; } sub get_uuid { my ($self, %options) = @_; return md5_hex( ((defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '') ? $self->{option_results}->{hostname} : 'none') . '_' . ((defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne '') ? $self->{option_results}->{command_options} : 'none') ); } sub scrape { my ($self, %options) = @_; return 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}, ); } 1; __END__ =head1 NAME Openmetrics file =head1 SYNOPSIS Openmetrics file custom mode =head1 FILE OPTIONS =over 8 =item B<--hostname> Endpoint hostname (If 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: 'cat'). =item B<--command-path> Command path. =item B<--command-options> Command options). =item B<--timeout> Set SSH timeout (Default: 10). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/centreon/common/monitoring/openmetrics/custom/web.pm000066400000000000000000000117711417000230700275120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::monitoring::openmetrics::custom::web; use strict; use warnings; use centreon::plugins::http; use Digest::MD5 qw(md5_hex); 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 => { 'hostname:s@' => { name => 'hostname' }, 'port:s@' => { name => 'port' }, 'proto:s@' => { name => 'proto' }, 'urlpath:s@' => { name => 'url_path' }, 'username:s@' => { name => 'username' }, 'password:s@' => { name => 'password' }, 'timeout:s@' => { name => 'timeout' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'WEB OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? shift(@{$self->{option_results}->{hostname}}) : undef; $self->{port} = (defined($self->{option_results}->{port})) ? shift(@{$self->{option_results}->{port}}) : 80; $self->{proto} = (defined($self->{option_results}->{proto})) ? shift(@{$self->{option_results}->{proto}}) : 'http'; $self->{url_path} = (defined($self->{option_results}->{url_path})) ? shift(@{$self->{option_results}->{url_path}}) : '/metrics'; $self->{username} = (defined($self->{option_results}->{username})) ? shift(@{$self->{option_results}->{username}}) : ''; $self->{password} = (defined($self->{option_results}->{password})) ? shift(@{$self->{option_results}->{password}}) : ''; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? shift(@{$self->{option_results}->{timeout}}) : 10; if (!defined($self->{hostname})) { $self->{output}->add_option_msg(short_msg => "Need to specify hostname option."); $self->{output}->option_exit(); } if (!defined($self->{hostname}) || scalar(@{$self->{option_results}->{hostname}}) == 0) { return 0; } return 1; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{url_path} = $self->{url_path}; $self->{option_results}->{timeout} = $self->{timeout}; if (defined($self->{username}) && $self->{username} ne '') { $self->{option_results}->{credentials} = 1; $self->{option_results}->{basic} = 1; $self->{option_results}->{username} = $self->{username}; $self->{option_results}->{password} = $self->{password}; } } sub get_uuid { my ($self, %options) = @_; return md5_hex( ((defined($self->{hostname}) && $self->{hostname} ne '') ? $self->{hostname} : 'none') . '_' . ((defined($self->{port}) && $self->{port} ne '') ? $self->{port} : 'none') ); } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->set_options(%{$self->{option_results}}); } sub scrape { my ($self, %options) = @_; $self->settings(); return $self->{http}->request(critical_status => '', warning_status => ''); } 1; __END__ =head1 NAME Openmetrics web =head1 SYNOPSIS Openmetrics web custom mode =head1 WEB OPTIONS =over 8 =item B<--hostname> Endpoint hostname. =item B<--port> Port used (Default: 80) =item B<--proto> Specify https if needed (Default: 'http') =item B<--urlpath> URL to scrape metrics from (Default: '/metrics'). =item B<--username> Endpoint username. =item B<--password> Endpoint password. =item B<--timeout> Set HTTP timeout (Default: 10). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/centreon/common/monitoring/openmetrics/scrape.pm000066400000000000000000000036761417000230700267050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::monitoring::openmetrics::scrape; use strict; use warnings; use centreon::plugins::misc; sub parse { my (%options) = @_; my $result; my $response = $options{custom}->scrape; foreach my $line (split /\n/, $response) { $result->{metrics}->{$1}->{type} = $2 if ($line =~ /^#\sTYPE\s(\w+)\s(.*)$/); $result->{metrics}->{$1}->{help} = $2 if ($line =~ /^#\sHELP\s(\w+)\s(.*)$/); next if ($line !~ /^[\d\/\s]*([\w.]+)(.*)?\s([\d.+-e]+)$/); my ($metric, $dimensions, $value) = ($1, $2, $3); $dimensions =~ s/[{}]//g; $dimensions =~ s/"/'/g; $dimensions =~ s/$options{strip_chars}//g if (defined($options{strip_chars})); my %dimensions = (); foreach (split /,/, $dimensions) { my ($key, $value) = split /=/; $dimensions{$key} = $value; } push @{$result->{metrics}->{$metric}->{data}}, { value => centreon::plugins::misc::expand_exponential(value => $value), dimensions => \%dimensions, dimensions_string => $dimensions }; } return $result->{metrics}; } 1; __END__ =head1 MODE Scrape metrics. =over 8 =back =cut centreon-plugins-20220113/centreon/common/polycom/000077500000000000000000000000001417000230700220235ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/polycom/endpoint/000077500000000000000000000000001417000230700236435ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/polycom/endpoint/snmp/000077500000000000000000000000001417000230700246205ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/polycom/endpoint/snmp/mode/000077500000000000000000000000001417000230700255445ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/polycom/endpoint/snmp/mode/components/000077500000000000000000000000001417000230700277315ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/polycom/endpoint/snmp/mode/components/board.pm000066400000000000000000000047651417000230700313720ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::polycom::endpoint::snmp::mode::components::board; use strict; use warnings; use centreon::common::polycom::endpoint::snmp::mode::components::resources qw($map_status); my $mapping = { hardwareUcBoardStatus => { oid => '.1.3.6.1.4.1.13885.101.1.3.12.1', map => $map_status }, }; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping->{hardwareUcBoardStatus}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "checking boards"); $self->{components}->{board} = {name => 'board', total => 0, skip => 0}; return if ($self->check_filter(section => 'board')); return if (!defined($self->{results}->{ $mapping->{hardwareUcBoardStatus}->{oid} }) || scalar(keys %{$self->{results}->{ $mapping->{hardwareUcBoardStatus}->{oid} }}) <= 0); my $instance = '0'; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{ $mapping->{hardwareUcBoardStatus}->{oid} }, instance => $instance); return if ($self->check_filter(section => 'board', instance => $instance)); $self->{components}->{board}->{total}++; $self->{output}->output_add( long_msg => sprintf( 'overall boards status is %s [instance: %s]', $result->{hardwareUcBoardStatus}, $instance ) ); my $exit = $self->get_severity(section => 'board', label => 'default', value => $result->{hardwareUcBoardStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf('Overall boards status is %s', $result->{hardwareUcBoardStatus} ) ); } } 1; centreon-plugins-20220113/centreon/common/polycom/endpoint/snmp/mode/components/camera.pm000066400000000000000000000056571417000230700315340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::polycom::endpoint::snmp::mode::components::camera; use strict; use warnings; use centreon::common::polycom::endpoint::snmp::mode::components::resources qw($map_status); my $mapping = { hardwareCameraCamerasName => { oid => '.1.3.6.1.4.1.13885.101.1.3.6.2.1.2' }, hardwareCameraCamerasStatus => { oid => '.1.3.6.1.4.1.13885.101.1.3.6.2.1.3', map => $map_status }, }; my $oid_hardwareCameraCamerasEntry = '.1.3.6.1.4.1.13885.101.1.3.6.2.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_hardwareCameraCamerasEntry }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "checking cameras"); $self->{components}->{camera} = {name => 'cameras', total => 0, skip => 0}; return if ($self->check_filter(section => 'camera')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_hardwareCameraCamerasEntry}})) { next if ($oid !~ /^$mapping->{hardwareCameraCamerasStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_hardwareCameraCamerasEntry}, instance => $instance); next if ($self->check_filter(section => 'camera', instance => $instance)); $self->{components}->{camera}->{total}++; $self->{output}->output_add( long_msg => sprintf( "camera '%s' status is '%s' [instance = %s]", $result->{hardwareCameraCamerasName}, $result->{hardwareCameraCamerasStatus}, $instance, ) ); my $exit = $self->get_severity(label => 'default', section => 'camera', instance => $instance, value => $result->{hardwareCameraCamerasStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Camera '%s' status is '%s'", $result->{hardwareCameraCamerasName}, $result->{hardwareCameraCamerasStatus} ) ); } } } 1; centreon-plugins-20220113/centreon/common/polycom/endpoint/snmp/mode/components/global.pm000066400000000000000000000047711417000230700315400ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::polycom::endpoint::snmp::mode::components::global; use strict; use warnings; use centreon::common::polycom::endpoint::snmp::mode::components::resources qw($map_status); my $mapping = { hardwareOverallStatus => { oid => '.1.3.6.1.4.1.13885.101.1.3.1', map => $map_status }, }; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping->{hardwareOverallStatus}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "checking global"); $self->{components}->{global} = {name => 'global', total => 0, skip => 0}; return if ($self->check_filter(section => 'global')); return if (!defined($self->{results}->{ $mapping->{hardwareOverallStatus}->{oid} }) || scalar(keys %{$self->{results}->{ $mapping->{hardwareOverallStatus}->{oid} }}) <= 0); my $instance = '0'; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{ $mapping->{hardwareOverallStatus}->{oid} }, instance => $instance); return if ($self->check_filter(section => 'global', instance => $instance)); $self->{components}->{global}->{total}++; $self->{output}->output_add( long_msg => sprintf( 'overall global status is %s [instance: %s]', $result->{hardwareOverallStatus}, $instance ) ); my $exit = $self->get_severity(section => 'global', label => 'default', value => $result->{hardwareOverallStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf('Overall global status is %s', $result->{hardwareOverallStatus} ) ); } } 1; centreon-plugins-20220113/centreon/common/polycom/endpoint/snmp/mode/components/microphone.pm000066400000000000000000000060671417000230700324430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::polycom::endpoint::snmp::mode::components::microphone; use strict; use warnings; use centreon::common::polycom::endpoint::snmp::mode::components::resources qw($map_status); my $mapping = { hardwareMicrophoneMicrophonesName => { oid => '.1.3.6.1.4.1.13885.101.1.3.5.2.1.2' }, hardwareMicrophoneMicrophonesStatus => { oid => '.1.3.6.1.4.1.13885.101.1.3.5.2.1.3', map => $map_status }, }; my $oid_hardwareMicrophoneMicrophonesEntry = '.1.3.6.1.4.1.13885.101.1.3.5.2.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_hardwareMicrophoneMicrophonesEntry }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "checking microphones"); $self->{components}->{microphone} = {name => 'microphones', total => 0, skip => 0}; return if ($self->check_filter(section => 'microphone')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_hardwareMicrophoneMicrophonesEntry}})) { next if ($oid !~ /^$mapping->{hardwareMicrophoneMicrophonesStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_hardwareMicrophoneMicrophonesEntry}, instance => $instance); next if ($self->check_filter(section => 'microphone', instance => $instance)); $self->{components}->{microphone}->{total}++; $self->{output}->output_add( long_msg => sprintf( "microphone '%s' status is '%s' [instance = %s]", $result->{hardwareMicrophoneMicrophonesName}, $result->{hardwareMicrophoneMicrophonesStatus}, $instance, ) ); my $exit = $self->get_severity(label => 'default', section => 'microphone', instance => $instance, value => $result->{hardwareMicrophoneMicrophonesStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Microphone '%s' status is '%s'", $result->{hardwareMicrophoneMicrophonesName}, $result->{hardwareMicrophoneMicrophonesStatus} ) ); } } } 1; centreon-plugins-20220113/centreon/common/polycom/endpoint/snmp/mode/components/nic.pm000066400000000000000000000055141417000230700310450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::polycom::endpoint::snmp::mode::components::nic; use strict; use warnings; use centreon::common::polycom::endpoint::snmp::mode::components::resources qw($map_status); my $mapping = { hardwareNICNICsName => { oid => '.1.3.6.1.4.1.13885.101.1.3.10.2.1.2' }, hardwareNICNICsStatus => { oid => '.1.3.6.1.4.1.13885.101.1.3.10.2.1.6', map => $map_status }, }; my $oid_hardwareNICNICsEntry = '.1.3.6.1.4.1.13885.101.1.3.10.2.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_hardwareNICNICsEntry }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "checking nics"); $self->{components}->{nic} = {name => 'nics', total => 0, skip => 0}; return if ($self->check_filter(section => 'nic')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_hardwareNICNICsEntry}})) { next if ($oid !~ /^$mapping->{hardwareNICNICsStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_hardwareNICNICsEntry}, instance => $instance); next if ($self->check_filter(section => 'nic', instance => $instance)); $self->{components}->{nic}->{total}++; $self->{output}->output_add( long_msg => sprintf( "nic '%s' status is '%s' [instance = %s]", $result->{hardwareNICNICsName}, $result->{hardwareNICNICsStatus}, $instance, ) ); my $exit = $self->get_severity(label => 'default', section => 'nic', instance => $instance, value => $result->{hardwareNICNICsStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Nic '%s' status is '%s'", $result->{hardwareNICNICsName}, $result->{hardwareNICNICsStatus} ) ); } } } 1; centreon-plugins-20220113/centreon/common/polycom/endpoint/snmp/mode/components/ptc.pm000066400000000000000000000047641417000230700310700ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::polycom::endpoint::snmp::mode::components::ptc; use strict; use warnings; use centreon::common::polycom::endpoint::snmp::mode::components::resources qw($map_status); my $mapping = { hardwarePTCStatus => { oid => '.1.3.6.1.4.1.13885.101.1.3.11.1', map => $map_status }, }; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping->{hardwarePTCStatus}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "checking polycom touch control"); $self->{components}->{ptc} = {name => 'ptc', total => 0, skip => 0}; return if ($self->check_filter(section => 'ptc')); return if (!defined($self->{results}->{ $mapping->{hardwarePTCStatus}->{oid} }) || scalar(keys %{$self->{results}->{ $mapping->{hardwarePTCStatus}->{oid} }}) <= 0); my $instance = '0'; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{ $mapping->{hardwarePTCStatus}->{oid} }, instance => $instance); return if ($self->check_filter(section => 'ptc', instance => $instance)); $self->{components}->{ptc}->{total}++; $self->{output}->output_add( long_msg => sprintf( 'overall polycom touch control status is %s [instance: %s]', $result->{hardwarePTCStatus}, $instance ) ); my $exit = $self->get_severity(section => 'ptc', label => 'default', value => $result->{hardwarePTCStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf('Overall polycom touch control status is %s', $result->{hardwarePTCStatus} ) ); } } 1; centreon-plugins-20220113/centreon/common/polycom/endpoint/snmp/mode/components/resources.pm000066400000000000000000000020061417000230700322770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::polycom::endpoint::snmp::mode::components::resources; use strict; use warnings; use Exporter; our $map_status; our @ISA = qw(Exporter); our @EXPORT_OK = qw($map_status); $map_status = { 1 => 'disabled', 2 => 'ok', 3 => 'failed', }; 1; centreon-plugins-20220113/centreon/common/polycom/endpoint/snmp/mode/hardware.pm000066400000000000000000000047211417000230700277030ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::polycom::endpoint::snmp::mode::hardware; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { default => [ ['ok', 'OK'], ['disabled', 'OK'], ['failed', 'CRITICAL'], ], }; $self->{components_path} = 'centreon::common::polycom::endpoint::snmp::mode::components'; $self->{components_module} = ['global', 'microphone', 'camera', 'nic', 'ptc', 'board']; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_performance => 1, no_absent => 1, force_new_perfdata => 1); bless $self, $class; $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: 'global', 'microphone', 'camera', 'nic', 'ptc', 'board'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=camera) Can also exclude specific instance: --filter=camera,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='camera,WARNING,disabled' =back =cut centreon-plugins-20220113/centreon/common/polycom/endpoint/snmp/mode/videoconferencing.pm000066400000000000000000000044361417000230700316000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::polycom::endpoint::snmp::mode::videoconferencing; 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 }, ]; $self->{maps_counters}->{global} = [ { label => 'conferences-active', nlabel => 'videoconferencing.conferences.active.count', set => { key_values => [ { name => 'NumberActiveConferences' } ], output_template => 'Current Conferences : %s', perfdatas => [ { label => 'conferences_active', value => 'NumberActiveConferences', template => '%d', min => 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 => {}); return $self; } sub manage_selection { my ($self, %options) = @_; my $oid_conferenceNumberActiveConferences = '.1.3.6.1.4.1.13885.101.1.5.1.0'; my $results = $options{snmp}->get_leef(oids => [$oid_conferenceNumberActiveConferences], nothing_quit => 1); $self->{global} = { NumberActiveConferences => $results->{$oid_conferenceNumberActiveConferences} }; } 1; __END__ =head1 MODE Check video conferencing usage. =over 8 =item B<--warning-conferences-active> Threshold warning. =item B<--critical-conferences-active> Threshold critical. =back =cut centreon-plugins-20220113/centreon/common/powershell/000077500000000000000000000000001417000230700225255ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/powershell/dell/000077500000000000000000000000001417000230700234455ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/powershell/dell/compellent/000077500000000000000000000000001417000230700256075ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/powershell/dell/compellent/hbausage.pm000066400000000000000000000065671417000230700277420ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::dell::compellent::hbausage; use strict; use warnings; sub get_powershell { my (%options) = @_; my $ps = ' $culture = new-object "System.Globalization.CultureInfo" "en-us" [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture $ProgressPreference = "SilentlyContinue" $ErrorActionPreference = "Stop" $scuser = "' . $options{cem_user} . '" $scpass = ConvertTo-SecureString "' . $options{cem_password} . '" -AsPlainText -Force $schost = "' . $options{cem_host} . '" $scport = "' . $options{cem_port} . '" $connName = "EMDefault" Function display_hba_information { $conn = Connect-DellApiConnection -HostName $schost -Port $scport -User $scuser -password $scpass -Save $connName '; if (defined($options{filter_sc}) && $options{filter_sc} ne '') { $ps .= '$storageCenters = Get-DellStorageCenter -ConnectionName $connName -Name "' . $options{filter_sc} . '" '; } else { $ps .= '$storageCenters = Get-DellStorageCenter -ConnectionName $connName '; } $ps .= ' $historical = New-DellHistoricalFilter -FilterTime "Other" -StartTime "' . $options{start_time} . '" -EndTime "' . $options{end_time} . '" foreach ($sc in $storageCenters) { $hbaList = Get-DellScServerHba -ConnectionName $connName -StorageCenter $sc foreach ($hba in $hbaList) { $usageList = Get-DellScServerHbaHistoricalIoUsage -ConnectionName $connName -Instance $hba -HistoricalFilter $historical write-host ("[sc={0}]" -f $hba.ScName) -NoNewline write-host ("[name={0}]" -f $hba.Name) -NoNewline $attrs = @{ReadKbPerSecond = 0; WriteKbPerSecond = 0; ReadIops = 0; WriteIops = 0; ReadLatency = 0; WriteLatency = 0; } $count = 0 foreach ($usage in $usageList) { foreach ($item in $($attrs.GetEnumerator() | sort -Property Key)) { $attrs[$item.Key] += ($usage | Select -ExpandProperty $item.Key) } $count++ } foreach ($item in $attrs.GetEnumerator() | sort -Property Key) { write-host ("[{0}={1}]" -f $item.Key, ($item.Value / $count)) -NoNewline } write-host } } } Try { Import-Module "' . $options{sdk_path_dll} . '" display_hba_information } Catch { Write-Host $Error[0].Exception $ret = Remove-DellSavedApiConnection -Name $connName exit 1 } $ret = Remove-DellSavedApiConnection -Name $connName exit 0 '; return $ps; } 1; __END__ =head1 DESCRIPTION Method to get compellent hba informations. =cut centreon-plugins-20220113/centreon/common/powershell/dell/compellent/volumeusage.pm000066400000000000000000000101201417000230700304730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::dell::compellent::volumeusage; use strict; use warnings; sub get_powershell { my (%options) = @_; my $ps = ' $culture = new-object "System.Globalization.CultureInfo" "en-us" [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture $ProgressPreference = "SilentlyContinue" $ErrorActionPreference = "Stop" $scuser = "' . $options{cem_user} . '" $scpass = ConvertTo-SecureString "' . $options{cem_password} . '" -AsPlainText -Force $schost = "' . $options{cem_host} . '" $scport = "' . $options{cem_port} . '" $connName = "EMDefault" Function display_volume_information { $conn = Connect-DellApiConnection -HostName $schost -Port $scport -User $scuser -password $scpass -Save $connName '; if (defined($options{filter_sc}) && $options{filter_sc} ne '') { $ps .= '$storageCenters = Get-DellStorageCenter -ConnectionName $connName -Name "' . $options{filter_sc} . '" '; } else { $ps .= '$storageCenters = Get-DellStorageCenter -ConnectionName $connName '; } $ps .= ' foreach ($sc in $storageCenters) { $volumeList = Get-DellScVolume -ConnectionName $connName -StorageCenter $sc foreach ($vol in $volumeList) { '; if (defined($options{filter_vol}) && $options{filter_vol} ne '') { $ps .= 'if (-Not ($vol -match "' . $options{filter_vol} . '")) { continue } '; } $ps .= '$volusage = Get-DellScVolumeStorageUsageAssociation -ConnectionName $connName -Instance $vol $usage = Get-DellScVolumeStorageUsage -ConnectionName $connName -Instance $volusage write-host ("[sc={0}]" -f $sc.Name) -NoNewline write-host ("[volume={0}]" -f $usage.Name) -NoNewline write-host ("[configuredSpace={0}]" -f $usage.ConfiguredSpace.GetByteSize()) -NoNewline write-host ("[freeSpace={0}]" -f $usage.FreeSpace.GetByteSize()) -NoNewline write-host ("[activeSpace={0}]" -f $usage.ActiveSpace.GetByteSize()) -NoNewline write-host ("[raidOverhead={0}]" -f $usage.RaidOverhead.GetByteSize()) -NoNewline write-host ("[totalDiskSpace={0}]" -f $usage.TotalDiskSpace.GetByteSize()) -NoNewline write-host ("[replaySpace={0}]" -f $usage.replaySpace.GetByteSize()) } '; if (defined($options{filter_vol}) && $options{filter_vol} ne '') { $ps .= 'continue '; } $ps .= '$diskList = Get-DellScDisk -ConnectionName $connName -StorageCenter $sc foreach ($disk in $diskList) { $diskusage = Get-DellScDiskStorageUsageAssociation -ConnectionName $connName -Instance $disk $usage = Get-DellScDiskStorageUsage -ConnectionName $connName -Instance $diskusage write-host ("[sc={0}]" -f $sc.Name) -NoNewline write-host ("[disk={0}]" -f $disk.Name) -NoNewline write-host ("[spare={0}]" -f $disk.Spare) -NoNewline write-host ("[allocatedSpace={0}]" -f $usage.AllocatedSpace.GetByteSize()) } } } Try { Import-Module "' . $options{sdk_path_dll} . '" display_volume_information } Catch { Write-Host $Error[0].Exception $ret = Remove-DellSavedApiConnection -Name $connName exit 1 } $ret = Remove-DellSavedApiConnection -Name $connName exit 0 '; return $ps; } 1; __END__ =head1 DESCRIPTION Method to get compellent volume informations. =cut centreon-plugins-20220113/centreon/common/powershell/exchange/000077500000000000000000000000001417000230700243075ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/powershell/exchange/activesyncmailbox.pm000066400000000000000000000102321417000230700303670ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::exchange::activesyncmailbox; use strict; use warnings; use centreon::plugins::misc; use centreon::common::powershell::exchange::powershell; sub get_powershell { my (%options) = @_; my $no_trust_ssl = (defined($options{no_trust_ssl})) ? '' : '-TrustAnySSLCertificate'; my $ps = centreon::common::powershell::exchange::powershell::powershell_init(%options); $ps .= ' try { $ErrorActionPreference = "Stop" $username = "' . $options{mailbox} . '" $password = "' . $options{password} . '" $secstr = New-Object -TypeName System.Security.SecureString $password.ToCharArray() | ForEach-Object {$secstr.AppendChar($_)} $cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $secstr $results = Test-ActiveSyncConnectivity -MailboxCredential $cred ' . $no_trust_ssl . ' } catch { Write-Host $Error[0].Exception exit 1 } Foreach ($result in $results) { Write-Host "[scenario=" $result.Scenario "][result=" $result.Result "][latency=" $result.Latency.TotalMilliseconds "][[error=" $Result.Error "]]" } exit 0 '; return $ps; } sub check { my ($self, %options) = @_; # options: stdout # Following output: #[scenario= Options ][result= Failure ][latency= 52,00 ][[error=...]] $self->{output}->output_add( severity => 'OK', short_msg => "ActiveSync to '" . $options{mailbox} . "' is ok." ); my $checked = 0; $self->{output}->output_add(long_msg => $options{stdout}); while ($options{stdout} =~ /\[scenario=(.*?)\]\[result=(.*?)\]\[latency=(.*?)\]\[\[error=(.*?)\]\]/msg) { $self->{data} = {}; ($self->{data}->{scenario}, $self->{data}->{result}, $self->{data}->{latency}, $self->{data}->{error}) = ($self->{output}->decode($1), centreon::plugins::misc::trim($2), centreon::plugins::misc::trim($3), centreon::plugins::misc::trim($4)); $checked++; my $status = 'ok'; if (defined($self->{option_results}->{critical}) && $self->{option_results}->{critical} ne '' && $self->{output}->test_eval(test => $self->{option_results}->{critical}, values => $self->{data})) { $status = 'critical'; } elsif (defined($self->{option_results}->{warning}) && $self->{option_results}->{warning} ne '' && $self->{output}->test_eval(test => $self->{option_results}->{warning}, values => $self->{data})) { $status = 'warning'; } if (!$self->{output}->is_status(value => $status, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $status, short_msg => sprintf( "ActiveSync scenario '%s' to '%s' is '%s'", $self->{data}->{scenario}, $options{mailbox}, $self->{data}->{result} ) ); } if ($self->{data}->{latency} =~ /^(\d+)/) { $self->{output}->perfdata_add( label => $self->{data}->{scenario}, unit => 's', value => sprintf("%.3f", $1 / 1000), min => 0 ); } } if ($checked == 0) { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => 'Cannot find informations' ); } } 1; __END__ =head1 DESCRIPTION Method to check Exchange activesync on a specific mailbox. =cut centreon-plugins-20220113/centreon/common/powershell/exchange/databases.pm000066400000000000000000000074671417000230700266120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::exchange::databases; use strict; use warnings; use centreon::common::powershell::exchange::powershell; use centreon::common::powershell::functions; sub get_powershell { my (%options) = @_; # options: no_mailflow, no_mapi my $no_mailflow = (defined($options{no_mailflow})) ? 1 : 0; my $no_mapi = (defined($options{no_mapi})) ? 1 : 0; my $no_copystatus = (defined($options{no_copystatus})) ? 1 : 0; my $ps = centreon::common::powershell::exchange::powershell::powershell_init(%options); $ps .= centreon::common::powershell::functions::escape_jsonstring(%options); $ps .= centreon::common::powershell::functions::convert_to_json(%options); $ps .= ' # Check to make sure all databases are mounted try { $ErrorActionPreference = "Stop" '; if (defined($options{filter_database})) { $ps .= ' $MountedDB = Get-MailboxDatabase -Identity "' . $options{filter_database} . '" -Status '; } else { $ps .= ' $MountedDB = Get-MailboxDatabase -Status '; } $ps .= ' } catch { Write-Host $Error[0].Exception exit 1 } $items = New-Object System.Collections.Generic.List[Hashtable]; Foreach ($DB in $MountedDB) { $item = @{} '; if (defined($options{filter_server}) && $options{filter_server} ne '') { $ps .= ' if (!($DB.Server.Name -match "' . $options{filter_server} . '")) { continue } '; } $ps .= ' $item.database = $DB.Name $item.server = $DB.Server.Name $item.mounted = $DB.Mounted $item.size = $DB.DatabaseSize.ToBytes().ToString() $item.asize = $DB.AvailableNewMailboxSpace.ToBytes().ToString() '; if (defined($options{filter_database_test}) && $options{filter_database_test} ne '') { $ps .= ' if (!($DB.Name -match "' . $options{filter_database_test} . '")) { continue } '; } $ps .= ' If ($DB.Mounted -eq $true) { '; if ($no_mapi == 0) { $ps .= ' # Test Mapi Connectivity $MapiResult = test-mapiconnectivity -Database $DB.Name $item.mapi_result = $MapiResult.Result.Value.value__ '; } if ($no_mailflow == 0) { $ps .= ' # Test Mailflow $MailflowResult = Test-mailflow -Targetdatabase $DB.Name $item.mailflow_result = $MailflowResult.testmailflowresult $item.mailflow_latency = $MailflowResult.MessageLatencyTime.TotalMilliseconds '; } if ($no_copystatus == 0) { $ps .= ' # Test CopyStatus $tmp_name = $DB.Name + "\" + $DB.Server $CopyStatusResult = Get-MailboxDatabaseCopyStatus -Identity $tmp_name $item.copystatus_indexstate = $CopyStatusResult.ContentIndexState.value__ $item.copystatus_content_index_error_message = $CopyStatusResult.ContentIndexErrorMessage '; } $ps .= ' } $items.Add($item) } $jsonString = $items | ConvertTo-JSON-20 -forceArray $true Write-Host $jsonString exit 0 '; return $ps; } 1; __END__ =head1 DESCRIPTION Method to check Exchange databases. =cut centreon-plugins-20220113/centreon/common/powershell/exchange/imapmailbox.pm000066400000000000000000000100001417000230700271360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::exchange::imapmailbox; use strict; use warnings; use centreon::plugins::misc; use centreon::common::powershell::exchange::powershell; sub get_powershell { my (%options) = @_; my $ps = centreon::common::powershell::exchange::powershell::powershell_init(%options); $ps .= ' try { $ErrorActionPreference = "Stop" $username = "' . $options{mailbox} . '" $password = "' . $options{password} . '" $secstr = New-Object -TypeName System.Security.SecureString $password.ToCharArray() | ForEach-Object {$secstr.AppendChar($_)} $cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $secstr $results = Test-ImapConnectivity -MailboxCredential $cred } catch { Write-Host $Error[0].Exception exit 1 } Foreach ($result in $results) { Write-Host "[scenario=" $result.Scenario "][result=" $result.Result "][latency=" $result.Latency.TotalMilliseconds "][[error=" $Result.Error "]]" } exit 0 '; return $ps; } sub check { my ($self, %options) = @_; # Following output: #[scenario= Options ][result= Failure ][latency= 52,00 ][[error=...]] $self->{output}->output_add( severity => 'OK', short_msg => "Imap to '" . $options{mailbox} . "' is ok." ); my $checked = 0; $self->{output}->output_add(long_msg => $options{stdout}); while ($options{stdout} =~ /\[scenario=(.*?)\]\[result=(.*?)\]\[latency=(.*?)\]\[\[error=(.*?)\]\]/msg) { $self->{data} = {}; ($self->{data}->{scenario}, $self->{data}->{result}, $self->{data}->{latency}, $self->{data}->{error}) = ($self->{output}->decode($1), centreon::plugins::misc::trim($2), centreon::plugins::misc::trim($3), centreon::plugins::misc::trim($4)); $checked++; my $status = 'ok'; if (defined($self->{option_results}->{critical}) && $self->{option_results}->{critical} ne '' && $self->{output}->test_eval(test => $self->{option_results}->{critical}, values => $self->{data})) { $status = 'critical'; } elsif (defined($self->{option_results}->{warning}) && $self->{option_results}->{warning} ne '' && $self->{output}->test_eval(test => $self->{option_results}->{warning}, values => $self->{data})) { $status = 'warning'; } if (!$self->{output}->is_status(value => $status, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $status, short_msg => sprintf( "Imap scenario '%s' to '%s' is '%s'", $self->{data}->{scenario}, $options{mailbox}, $self->{data}->{result} ) ); } if ($self->{data}->{latency} =~ /^(\d+)/) { $self->{output}->perfdata_add( label => $self->{data}->{scenario}, unit => 's', value => sprintf("%.3f", $1 / 1000), min => 0 ); } } if ($checked == 0) { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => 'Cannot find informations' ); } } 1; __END__ =head1 DESCRIPTION Method to check Exchange 2010 on a specific mailbox. =cut centreon-plugins-20220113/centreon/common/powershell/exchange/listdatabases.pm000066400000000000000000000043261417000230700274750ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::exchange::listdatabases; use strict; use warnings; use centreon::plugins::misc; use centreon::common::powershell::exchange::powershell; use centreon::common::powershell::functions; sub get_powershell { my (%options) = @_; my $ps = centreon::common::powershell::exchange::powershell::powershell_init(%options); $ps .= centreon::common::powershell::functions::escape_jsonstring(%options); $ps .= centreon::common::powershell::functions::convert_to_json(%options); $ps .= ' # Check to make sure all databases are mounted try { $ErrorActionPreference = "Stop" '; if (defined($options{filter_database})) { $ps .= ' $MountedDB = Get-MailboxDatabase -Identity "' . $options{filter_database} . '" -Status '; } else { $ps .= ' $MountedDB = Get-MailboxDatabase -Status '; } $ps .= ' } catch { Write-Host $Error[0].Exception exit 1 } $items = New-Object System.Collections.Generic.List[Hashtable]; Foreach ($DB in $MountedDB) { $item = @{} $item.name = $DB.Name $item.server = $DB.Server.Name $item.mounted = $DB.Mounted $item.size = $DB.DatabaseSize.ToBytes().ToString() $item.asize = $DB.AvailableNewMailboxSpace.ToBytes().ToString() $items.Add($item) '; $ps .= ' } $jsonString = $items | ConvertTo-JSON-20 -forceArray $true Write-Host $jsonString exit 0 '; return $ps; } 1; __END__ =head1 DESCRIPTION Method to list Exchange databases. =cut centreon-plugins-20220113/centreon/common/powershell/exchange/mailboxes.pm000066400000000000000000000175631417000230700266440ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::exchange::mailboxes; use strict; use warnings; use centreon::common::powershell::exchange::powershell; use centreon::common::powershell::functions; sub get_powershell { my (%options) = @_; my $ps = centreon::common::powershell::exchange::powershell::powershell_init(%options); $ps .= centreon::common::powershell::functions::escape_jsonstring(%options); $ps .= centreon::common::powershell::functions::convert_to_json(%options); my $extra_matches = ''; if (defined($options{ps_match_server}) && $options{ps_match_server} ne '') { $extra_matches .= ' | ?{$_.ServerName -match "' . $options{ps_match_server} . '"}'; } if (defined($options{ps_match_database}) && $options{ps_match_database} ne '') { $extra_matches .= ' | ?{$_.Database -match "' . $options{ps_match_database} . '"}'; } $ps .= ' try { $ErrorActionPreference = "Stop" '; if (defined($options{ps_database}) && $options{ps_database} ne '') { $ps .= ' $mailboxes = Get-Mailbox -ResultSize unlimited -WarningAction SilentlyContinue -Database "' . $options{ps_database} . '" $folder_mailboxes = Get-Mailbox -PublicFolder:$true -ResultSize unlimited -WarningAction SilentlyContinue -Database "' . $options{ps_database} . '" ' . $extra_matches .' '; } elsif (defined($options{ps_server}) && $options{ps_server} ne '') { $ps .= ' $mailboxes = Get-Mailbox -ResultSize unlimited -WarningAction SilentlyContinue -Server "' . $options{ps_server} . '" $folder_mailboxes = Get-Mailbox -PublicFolder:$true -ResultSize unlimited -WarningAction SilentlyContinue -Server "' . $options{ps_server} . '" ' . $extra_matches .' '; } else { $ps .= ' $mailboxes = Get-Mailbox -ResultSize unlimited -WarningAction SilentlyContinue ' . $extra_matches . ' $folder_mailboxes = Get-Mailbox -PublicFolder:$true -ResultSize unlimited -WarningAction SilentlyContinue ' . $extra_matches . ' '; } $ps .= ' $result = @{} $result.users = @{ total = 0; over_quota = 0; warning_quota = 0; unlimited = 0; over_quota_details = New-Object System.Collections.Generic.List[Hashtable]; warning_quota_details = New-Object System.Collections.Generic.List[Hashtable]; unlimited_details = New-Object System.Collections.Generic.List[Hashtable] } $result.public_folders = @{ total = 0; over_quota = 0; warning_quota = 0; unlimited = 0; over_quota_details = New-Object System.Collections.Generic.List[Hashtable]; warning_quota_details = New-Object System.Collections.Generic.List[Hashtable]; unlimited_details = New-Object System.Collections.Generic.List[Hashtable] } $result.group_by_databases = @{} foreach ($mailbox in $mailboxes) { $item = @{} $detail = @{ database = $mailbox.Database.Name; server_name = $mailbox.ServerName; name = $mailbox.Name } if (-not $result.group_by_databases[$mailbox.Database]) { $result.group_by_databases[$mailbox.Database] = 0 } $result.group_by_databases[$mailbox.Database]++ $result.users.total++ if (($null -eq $mailbox.ProhibitSendReceiveQuota -or $mailbox.ProhibitSendReceiveQuota.IsUnlimited -eq $true) -or ($null -eq $mailbox.ProhibitSendQuota -or $mailbox.ProhibitSendQuota.IsUnlimited -eq $true)) { $result.users.unlimited++ $result.users.unlimited_details.Add($detail) } if ($mailbox.ProhibitSendReceiveQuota -ne "unlimited" -or $mailbox.ProhibitSendQuota -ne "unlimited") { $stat = get-mailboxStatistics -Identity $mailbox.Identity -ErrorAction SilentlyContinue if ($stat) { $size_bytes = $stat.TotalItemSize.Value.ToBytes() if ($null -ne $mailbox.ProhibitSendQuota -and -not $mailbox.ProhibitSendQuota.IsUnlimited) { if ($size_bytes > $mailbox.ProhibitSendQuota.Value.ToBytes()) { $result.users.over_quota++ $result.users.over_quota_details.Add($detail) } } elseif ($null -ne $mailbox.ProhibitSendReceiveQuota -and -not ($mailbox.ProhibitSendReceiveQuota.IsUnlimited)) { if ($size_bytes > $mailbox.ProhibitSendReceiveQuota.Value.ToBytes()) { $result.users.over_quota++ $result.users.over_quota_details.Add($detail) } } elseif ($null -ne $mailbox.issueWarningQuota -and -not ($mailbox.issueWarningQuota.IsUnlimited)) { if ($size_bytes > $mailbox.issueWarningQuota.Value.ToBytes()) { $result.users.warning_quota++ $result.users.warning_quota_details.Add($detail) } } } } } foreach ($mailbox in $folder_mailboxes) { $item = @{} $detail = @{ database = $mailbox.Database.Name; server_name = $mailbox.ServerName; name = $mailbox.Name } $result.public_folders.total++ if (($null -eq $mailbox.ProhibitSendReceiveQuota -or $mailbox.ProhibitSendReceiveQuota.IsUnlimited -eq $true) -or ($null -eq $mailbox.ProhibitSendQuota -or $mailbox.ProhibitSendQuota.IsUnlimited -eq $true)) { $result.public_folders.unlimited++ $result.public_folders.unlimited_details.Add($detail) } if ($mailbox.ProhibitSendReceiveQuota -ne "unlimited" -or $mailbox.ProhibitSendQuota -ne "unlimited") { $stat = get-mailboxStatistics -Identity $mailbox.Identity -ErrorAction SilentlyContinue if ($stat) { $size_bytes = $stat.TotalItemSize.Value.ToBytes() if ($null -ne $mailbox.ProhibitSendQuota -and -not ($mailbox.ProhibitSendQuota.IsUnlimited)) { if ($size_bytes > $mailbox.ProhibitSendQuota.Value.ToBytes()) { $result.public_folders.over_quota++ $result.public_folders.over_quota_details.Add($detail) } } elseif ($null -ne $mailbox.ProhibitSendReceiveQuota -and -not ($mailbox.ProhibitSendReceiveQuota.IsUnlimited)) { if ($size_bytes > $mailbox.ProhibitSendReceiveQuota.Value.ToBytes()) { $result.public_folders.over_quota++ $result.public_folders.over_quota_details.Add($detail) } } elseif ($null -ne $mailbox.issueWarningQuota -and -not ($mailbox.issueWarningQuota.IsUnlimited)) { if ($size_bytes > $mailbox.issueWarningQuota.Value.ToBytes()) { $result.public_folders.warning_quota++ $result.public_folders.warning_quota_details.Add($detail) } } } } } $jsonString = $result | ConvertTo-JSON-20 Write-Host $jsonString exit 0 } catch { Write-Host $Error[0].Exception exit 1 } '; return $ps; } 1; __END__ =head1 DESCRIPTION Method to check Exchange mailboxes. =cut centreon-plugins-20220113/centreon/common/powershell/exchange/mapimailbox.pm000066400000000000000000000066201417000230700271530ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::exchange::mapimailbox; use strict; use warnings; use centreon::plugins::misc; use centreon::common::powershell::exchange::powershell; sub get_powershell { my (%options) = @_; my $ps = centreon::common::powershell::exchange::powershell::powershell_init(%options); $ps .= ' try { $ErrorActionPreference = "Stop" $mapi = test-mapiconnectivity -Identity "' . $options{mailbox} . '" } catch { Write-Host $Error[0].Exception exit 1 } Write-Host "[name=" $mapi.Database "][server=" $mapi.Server "][result=" $mapi.Result "][error=" $mapi.Error "]" exit 0 '; return $ps; } sub check { my ($self, %options) = @_; # Following output: #[name= Mailbox Database 0975194476 ][server= SRVI-WIN-TEST ][result= Success ][error=...] if ($options{stdout} !~ /^\[name=(.*?)\]\[server=(.*?)\]\[result=(.*?)\]\[error=(.*)\]$/) { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => 'Cannot find informations' ); return ; } $self->{data} = {}; ($self->{data}->{database}, $self->{data}->{server}, $self->{data}->{result}, $self->{data}->{error}) = (centreon::plugins::misc::trim($1), centreon::plugins::misc::trim($2), centreon::plugins::misc::trim($3), centreon::plugins::misc::trim($4)); $self->{output}->output_add( severity => 'OK', short_msg => "MAPI connection to '" . $options{mailbox} . "' is '" . $self->{data}->{result} . "'." ); $self->{output}->output_add( long_msg => sprintf( "Database: %s, Server: %s\nError: %s", $self->{data}->{database}, $self->{data}->{server}, $self->{data}->{error} ) ); my $status = 'ok'; if (defined($self->{option_results}->{critical}) && $self->{option_results}->{critical} ne '' && $self->{output}->test_eval(test => $self->{option_results}->{critical}, values => $self->{data})) { $status = 'critical'; } elsif (defined($self->{option_results}->{warning}) && $self->{option_results}->{warning} ne '' && $self->{output}->test_eval(test => $self->{option_results}->{warning}, values => $self->{data})) { $status = 'warning'; } if (!$self->{output}->is_status(value => $status, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $status, short_msg => sprintf( "MAPI connection to '%s' is '%s'", $options{mailbox}, $self->{data}->{result} ) ); } } 1; __END__ =head1 DESCRIPTION Method to check Exchange mapi connection on a specific mailbox. =cut centreon-plugins-20220113/centreon/common/powershell/exchange/outlookwebservices.pm000066400000000000000000000075721417000230700306160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::exchange::outlookwebservices; use strict; use warnings; use centreon::plugins::misc; use centreon::common::powershell::exchange::powershell; sub get_powershell { my (%options) = @_; my $ps = centreon::common::powershell::exchange::powershell::powershell_init(%options); $ps .= ' try { $ErrorActionPreference = "Stop" '; if (defined($options{password}) && $options{password} ne '') { $ps .= ' $username = "' . $options{mailbox} . '" $password = "' . $options{password} . '" $secstr = New-Object -TypeName System.Security.SecureString $password.ToCharArray() | ForEach-Object {$secstr.AppendChar($_)} $cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $secstr $results = Test-OutlookWebServices -WarningAction:SilentlyContinue -MailboxCredential $cred '; } else { $ps .= ' $results = Test-OutlookWebServices -WarningAction:SilentlyContinue -Identity "' . $options{mailbox} . '" '; } $ps .= ' } catch { Write-Host $Error[0].Exception exit 1 } Foreach ($result in $results) { Write-Host "[id=" $result.Id "][type=" $result.Type "][[message=" $result.Message "]]" } exit 0 '; return $ps; } sub check { my ($self, %options) = @_; # Following output: #[id= XXXX ][type= Success][[message=...]] $self->{output}->output_add( severity => 'OK', short_msg => sprintf("Outlook webservices to '%s' are ok.", $options{mailbox}) ); my $checked = 0; $self->{output}->output_add(long_msg => $options{stdout}); while ($options{stdout} =~ /\[id=(.*?)\]\[type=(.*?)\]\[\[message=(.*?)\]\]/msg) { $self->{data} = {}; ($self->{data}->{id}, $self->{data}->{type}, $self->{data}->{message}) = (centreon::plugins::misc::trim($1), centreon::plugins::misc::trim($2), $self->{output}->decode($3)); $checked++; my $status = 'ok'; if (defined($self->{option_results}->{critical}) && $self->{option_results}->{critical} ne '' && $self->{output}->test_eval(test => $self->{option_results}->{critical}, values => $self->{data})) { $status = 'critical'; } elsif (defined($self->{option_results}->{warning}) && $self->{option_results}->{warning} ne '' && $self->{output}->test_eval(test => $self->{option_results}->{warning}, values => $self->{data})) { $status = 'warning'; } if (!$self->{output}->is_status(value => $status, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $status, short_msg => sprintf( "Check id '%s' status is '%s' [message: %s]", $self->{data}->{id}, $self->{data}->{type}, $self->{data}->{message} ) ); } } if ($checked == 0) { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => 'Cannot find informations' ); } } 1; __END__ =head1 DESCRIPTION Method to check Exchange outlook autodiscovery webservices. =cut centreon-plugins-20220113/centreon/common/powershell/exchange/owamailbox.pm000066400000000000000000000105071417000230700270120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::exchange::owamailbox; use strict; use warnings; use centreon::plugins::misc; use centreon::common::powershell::exchange::powershell; sub get_powershell { my (%options) = @_; my $no_trust_ssl = (defined($options{no_trust_ssl})) ? '' : '-TrustAnySSLCertificate'; my $ps = centreon::common::powershell::exchange::powershell::powershell_init(%options); $ps .= ' try { $ErrorActionPreference = "Stop" $username = "' . $options{mailbox} . '" $password = "' . $options{password} . '" $secstr = New-Object -TypeName System.Security.SecureString $password.ToCharArray() | ForEach-Object {$secstr.AppendChar($_)} $cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username,$secstr $results = Test-OwaConnectivity -WarningAction:SilentlyContinue -Url:' . $options{url} . ' -MailboxCredential:$cred ' . $no_trust_ssl . ' } catch { Write-Host $Error[0].Exception exit 1 } Foreach ($result in $results) { Write-Host "[url=" $result.Url "][scenario=" $result.Scenario "][result=" $result.Result "][latency=" $result.Latency.TotalMilliseconds "][[error=" $Result.Error "]]" } exit 0 '; return $ps; } sub check { my ($self, %options) = @_; # Following output: #[url= http://xxxx/ ][scenario= Options ][result= Ignored ][latency= ][[error=...]] $self->{output}->output_add( severity => 'OK', short_msg => "OWA to '" . $options{mailbox} . "' is ok." ); my $checked = 0; $self->{output}->output_add(long_msg => $options{stdout}); while ($options{stdout} =~ /\[url=(.*?)\]\[scenario=(.*?)\]\[result=(.*?)\]\[latency=(.*?)\]\[\[error=(.*?)\]\]/msg) { $self->{data} = {}; ($self->{data}->{url}, $self->{data}->{scenario}, $self->{data}->{result}, $self->{data}->{latency}, $self->{data}->{error}) = ($self->{output}->decode($1), $self->{output}->decode($2), centreon::plugins::misc::trim($3), centreon::plugins::misc::trim($4), centreon::plugins::misc::trim($5)); $checked++; my $status = 'ok'; if (defined($self->{option_results}->{critical}) && $self->{option_results}->{critical} ne '' && $self->{output}->test_eval(test => $self->{option_results}->{critical}, values => $self->{data})) { $status = 'critical'; } elsif (defined($self->{option_results}->{warning}) && $self->{option_results}->{warning} ne '' && $self->{output}->test_eval(test => $self->{option_results}->{warning}, values => $self->{data})) { $status = 'warning'; } if (!$self->{output}->is_status(value => $status, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $status, short_msg => sprintf( "OWA scenario '%s' to '%s' is '%s' [url: %s]", $self->{data}->{scenario}, $options{mailbox}, $self->{data}->{result}, $self->{data}->{url} ) ); } if ($self->{data}->{latency} =~ /^(\d+)/) { $self->{output}->perfdata_add( label => $self->{data}->{url} . '_' . $self->{data}->{scenario}, unit => 's', value => sprintf("%.3f", $1 / 1000), min => 0 ); } } if ($checked == 0) { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => 'Cannot find informations' ); } } 1; __END__ =head1 DESCRIPTION Method to check Exchange owa connection on a specific mailbox. =cut centreon-plugins-20220113/centreon/common/powershell/exchange/powershell.pm000066400000000000000000000076761417000230700270510ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::exchange::powershell; use strict; use warnings; use centreon::plugins::misc; # Generate Scipt to Load exchange extensions #--remote-host --remote-user --remote-password sub powershell_init { my (%options) = @_; my $ps = ' $culture = new-object "System.Globalization.CultureInfo" "en-us" [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture '; if (!defined($options{remote_host})) { $ps.=' If (@(Get-PSSnapin -Registered | Where-Object {$_.Name -Match "Microsoft.Exchange.Management.PowerShell.E"} ).count -gt 0) { If (@(Get-PSSnapin | Where-Object {$_.Name -Match "Microsoft.Exchange.Management.PowerShell.E"} ).count -eq 0) { Try { Get-PSSnapin -Registered | Where-Object {$_.Name -Match "Microsoft.Exchange.Management.PowerShell.E"} | Add-PSSnapin -ErrorAction STOP } Catch { Write-Host $Error[0].Exception exit 1 } } } else { Write-Host "Snap-In no present or not registered" exit 1 } $ProgressPreference = "SilentlyContinue" '; } else { # Find exchange installation path my $exchangepath; if (defined($ENV{ExchangeInstallPath})) { # Windows Variable $exchangepath = $ENV{ExchangeInstallPath}; } else { # No ENV -> look into registry (access via cygwin ssh session) my $filename = "/proc/registry/HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Session Manager/Environment/ExchangeInstallPath"; if (-e $filename) { open FILE, "$filename" or die "Couldn't open file: $!"; $exchangepath = ; $exchangepath =~ s/[\r|\n|\0].*//g; close FILE; } } # No installation found if (!defined($exchangepath)) { print '$ENV{ExchangeInstallPath} is undefined. Please install PowerShell extensions for Exchange.'; exit 1 } $ps .= ' # Open a session to the exchange try { $ErrorActionPreference = "Stop" . "'.$exchangepath.'\bin\RemoteExchange.ps1" } catch { Write-Host $Error[0].Exception exit 1 } try { $ErrorActionPreference = "Stop"'; if (defined($options{remote_user}) && defined($options{remote_password})) { # Replace / to \ $options{remote_user}=~ s/\//\\/g; $ps .= ' $username = "'.centreon::plugins::misc::powershell_escape($options{remote_user}) . '" $password = ConvertTo-SecureString "' . centreon::plugins::misc::powershell_escape($options{remote_password}) . '" -AsPlainText -Force $UserCredential = new-object -typename System.Management.Automation.PSCredential -argumentlist $username,$password Connect-ExchangeServer -ServerFqdn "'. centreon::plugins::misc::powershell_escape($options{remote_host}) .'" -UserName $UserCredential '; } else { $ps .= ' Connect-ExchangeServer -ServerFqdn "'. centreon::plugins::misc::powershell_escape($options{remote_host}) .'" '; } $ps .= ' } catch { Write-Host $Error[0].Exception exit 1 } '; } return $ps; } 1; __END__ =head1 DESCRIPTION Powershell commands =cut centreon-plugins-20220113/centreon/common/powershell/exchange/queues.pm000066400000000000000000000040071417000230700261550ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::exchange::queues; use strict; use warnings; use centreon::common::powershell::exchange::powershell; use centreon::common::powershell::functions; sub get_powershell { my (%options) = @_; my $ps = centreon::common::powershell::exchange::powershell::powershell_init(%options); $ps .= centreon::common::powershell::functions::escape_jsonstring(%options); $ps .= centreon::common::powershell::functions::convert_to_json(%options); $ps .= ' try { $ErrorActionPreference = "Stop" $results = Get-Queue } catch { Write-Host $Error[0].Exception exit 1 } $items = New-Object System.Collections.Generic.List[Hashtable]; Foreach ($result in $results) { $item = @{} $item.identity = $result.Identity.ToString().Replace("\\", "/") $item.nexthopdomain = $result.NextHopDomain $item.delivery_type = $result.DeliveryType.value__ $item.status = $result.Status.value__ $item.is_valid = $result.IsValid $item.message_count = $result.MessageCount $item.last_error = $result.LastError $items.Add($item) } $jsonString = $items | ConvertTo-JSON-20 -forceArray $true Write-Host $jsonString exit 0 '; return $ps; } 1; __END__ =head1 DESCRIPTION Method to check Exchange queues. =cut centreon-plugins-20220113/centreon/common/powershell/exchange/replicationhealth.pm000066400000000000000000000070041417000230700303450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::exchange::replicationhealth; use strict; use warnings; use centreon::plugins::misc; use centreon::common::powershell::exchange::powershell; sub get_powershell { my (%options) = @_; my $ps = centreon::common::powershell::exchange::powershell::powershell_init(%options); $ps .= ' try { $ErrorActionPreference = "Stop" $results = Test-ReplicationHealth } catch { Write-Host $Error[0].Exception exit 1 } Foreach ($result in $results) { Write-Host "[server=" $result.Server "][check=" $result.Check "][result=" $result.Result "][isvalid=" $result.IsValid "][[error=" $result.Error "]]" } exit 0 '; return $ps; } sub check { my ($self, %options) = @_; # Following output: #[Server= XXXX ][check= ReplayService][result= Passed ][isvalid= Yes][[error=...]] $self->{output}->output_add( severity => 'OK', short_msg => "All replication health tests are ok." ); my $checked = 0; $self->{output}->output_add(long_msg => $options{stdout}); while ($options{stdout} =~ /\[server=(.*?)\]\[check=(.*?)\]\[result=(.*?)\]\[isvalid=(.*?)\]\[\[error=(.*?)\]\]/msg) { $self->{data} = {}; ($self->{data}->{server}, $self->{data}->{check}, $self->{data}->{result}, $self->{data}->{isvalid}, $self->{data}->{error}) = ($self->{output}->decode($1), centreon::plugins::misc::trim($2), centreon::plugins::misc::trim($3), centreon::plugins::misc::trim($4), centreon::plugins::misc::trim($5)); $checked++; my $status = 'ok'; if (defined($self->{option_results}->{critical}) && $self->{option_results}->{critical} ne '' && $self->{output}->test_eval(test => $self->{option_results}->{critical}, values => $self->{data})) { $status = 'critical'; } elsif (defined($self->{option_results}->{warning}) && $self->{option_results}->{warning} ne '' && $self->{output}->test_eval(test => $self->{option_results}->{warning}, values => $self->{data})) { $status = 'warning'; } if (!$self->{output}->is_status(value => $status, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $status, short_msg => sprintf( "Replication test '%s' status on '%s' is '%s' [error: %s]", $self->{data}->{check}, $self->{data}->{server}, $self->{data}->{result}, $self->{data}->{error} ) ); } } if ($checked == 0) { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => 'Cannot find informations' ); } } 1; __END__ =head1 DESCRIPTION Method to check Exchange queues. =cut centreon-plugins-20220113/centreon/common/powershell/exchange/services.pm000066400000000000000000000073021417000230700264720ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::exchange::services; use strict; use warnings; use centreon::plugins::misc; use centreon::common::powershell::exchange::powershell; sub get_powershell { my (%options) = @_; my $ps = centreon::common::powershell::exchange::powershell::powershell_init(%options); $ps .= ' try { $ErrorActionPreference = "Stop" $results = Test-ServiceHealth } catch { Write-Host $Error[0].Exception exit 1 } Foreach ($result in $results) { $servicesrunning = [String]::join(",", $result.ServicesRunning) $servicesnotrunning = [String]::join(",", $result.ServicesNotRunning) Write-Host "[role=" $result.Role "][requiredservicesrunning=" $result.RequiredServicesRunning "][servicesrunning=" $servicesrunning "][servicesnotrunning=" $servicesnotrunning "]" } exit 0 '; return $ps; } sub check { my ($self, %options) = @_; # Following output: #[role= Mailbox Server Role ][requiredservicesrunning= True ][servicesrunning= IISAdmin,MSExchangeADTopology,MSExchangeSA,... ][servicesnotrunning= ] $self->{output}->output_add( severity => 'OK', short_msg => "All role services are ok." ); my $checked = 0; $self->{output}->output_add(long_msg => $options{stdout}); while ($options{stdout} =~ /\[role=(.*?)\]\[requiredservicesrunning=(.*?)\]\[servicesrunning=(.*?)\]\[servicesnotrunning=(.*?)\]/msg) { $self->{data} = {}; ($self->{data}->{role}, $self->{data}->{requiredservicesrunning}, $self->{data}->{servicesrunning}, $self->{data}->{servicesnotrunning}) = ($self->{output}->decode($1), centreon::plugins::misc::trim($2), centreon::plugins::misc::trim($3), centreon::plugins::misc::trim($4)); $checked++; my $status = 'ok'; if (defined($self->{option_results}->{critical}) && $self->{option_results}->{critical} ne '' && $self->{output}->test_eval(test => $self->{option_results}->{critical}, values => $self->{data})) { $status = 'critical'; } elsif (defined($self->{option_results}->{warning}) && $self->{option_results}->{warning} ne '' && $self->{output}->test_eval(test => $self->{option_results}->{warning}, values => $self->{data})) { $status = 'warning'; } if (!$self->{output}->is_status(value => $status, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $status, short_msg => sprintf( "Role '%s' services problem [services not running: %s]", $self->{data}->{role}, $self->{data}->{servicesnotrunning} ) ); } } if ($checked == 0) { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => 'Cannot find informations' ); } } 1; __END__ =head1 DESCRIPTION Method to check Exchange services running or not running. =cut centreon-plugins-20220113/centreon/common/powershell/functions.pm000066400000000000000000000066551417000230700251070ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::functions; use strict; use warnings; sub escape_jsonstring { my (%options) = @_; my $ps = q{ function Escape-JSONString($str) { if ($str -eq $null) {return ""} $str = $str.ToString().Replace('\\','\\\\').Replace('"','\"').Replace("`n",'\n').Replace("`r",'\r').Replace("`t",'\t') return $str; } }; return $ps; } sub convert_to_json { my (%options) = @_; my $ps = q{ function ConvertTo-JSON-20($maxDepth = 4,$forceArray = $false) { begin { $data = @() } process{ $data += $_ } end{ if ($data.length -eq 1 -and $forceArray -eq $false) { $value = $data[0] } else { $value = $data } if ($value -eq $null) { return "null" } $dataType = $value.GetType().Name switch -regex ($dataType) { 'String' { return "`"{0}`"" -f (Escape-JSONString $value ) } '(System\.)?DateTime' {return "`"{0:yyyy-MM-dd}T{0:HH:mm:ss}`"" -f $value} 'Int16|Int32|Double' {return "$value"} 'Boolean' {return "$value".ToLower()} '(System\.)?Object\[\]' { # array if ($maxDepth -le 0){return "`"$value`""} $jsonResult = '' foreach($elem in $value){ #if ($elem -eq $null) {continue} if ($jsonResult.Length -gt 0) {$jsonResult +=','} $jsonResult += ($elem | ConvertTo-JSON-20 -maxDepth ($maxDepth -1)) } return "[" + $jsonResult + "]" } '(System\.)?Hashtable' { # hashtable $jsonResult = '' foreach($key in $value.Keys){ if ($jsonResult.Length -gt 0) {$jsonResult +=','} $jsonResult += @" "{0}":{1} "@ -f $key , ($value[$key] | ConvertTo-JSON-20 -maxDepth ($maxDepth -1) ) } return "{" + $jsonResult + "}" } default { #object if ($maxDepth -le 0){return "`"{0}`"" -f (Escape-JSONString $value)} return "{" + (($value | Get-Member -MemberType *property | % { @" "{0}":{1} "@ -f $_.Name , ($value.($_.Name) | ConvertTo-JSON-20 -maxDepth ($maxDepth -1) ) }) -join ',') + "}" } } } } }; return $ps; } 1; __END__ =head1 DESCRIPTION Powershell common functions. =cut centreon-plugins-20220113/centreon/common/powershell/hyperv/000077500000000000000000000000001417000230700240425ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/powershell/hyperv/2012/000077500000000000000000000000001417000230700244265ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/powershell/hyperv/2012/listnodevms.pm000066400000000000000000000037761417000230700273500ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::hyperv::2012::listnodevms; use strict; use warnings; use centreon::common::powershell::functions; sub get_powershell { my (%options) = @_; my $ps = ' $culture = new-object "System.Globalization.CultureInfo" "en-us" [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture '; $ps .= centreon::common::powershell::functions::escape_jsonstring(%options); $ps .= centreon::common::powershell::functions::convert_to_json(%options); $ps .= ' $ProgressPreference = "SilentlyContinue" Try { $ErrorActionPreference = "Stop" $vms = Get-VM $items = New-Object System.Collections.Generic.List[Hashtable]; Foreach ($vm in $vms) { $item = @{} $note = $vm.Notes -replace "\r","" $note = $note -replace "\n"," - " $item.name = $vm.VMName $item.state = $vm.State.value__ $item.status = $vm.Status $item.note = $note $item.is_clustered = $vm.IsClustered $items.Add($item) } $jsonString = $items | ConvertTo-JSON-20 -forceArray $true Write-Host $jsonString } Catch { Write-Host $Error[0].Exception exit 1 } exit 0 '; return $ps; } 1; __END__ =head1 DESCRIPTION Method to get hyper-v informations. =cut centreon-plugins-20220113/centreon/common/powershell/hyperv/2012/nodeintegrationservice.pm000066400000000000000000000053751417000230700315500ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::hyperv::2012::nodeintegrationservice; use strict; use warnings; use centreon::common::powershell::functions; sub get_powershell { my (%options) = @_; my $ps = ' $culture = new-object "System.Globalization.CultureInfo" "en-us" [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture '; $ps .= centreon::common::powershell::functions::escape_jsonstring(%options); $ps .= centreon::common::powershell::functions::convert_to_json(%options); $ps .= ' $ProgressPreference = "SilentlyContinue" Try { $ErrorActionPreference = "Stop" $vms = Get-VM $items = New-Object System.Collections.Generic.List[Hashtable]; Foreach ($vm in $vms) { $item = @{} $note = $vm.Notes -replace "\r","" $note = $note -replace "\n"," - " $item.name = $vm.VMName $item.state = $vm.State.value__ $item.integration_services_state = $vm.IntegrationServicesState $item.integration_services_version = $null if ($null -ne $vm.IntegrationServicesVersion) { $item.integration_services_version = $vm.IntegrationServicesVersion.toString() } $item.note = $note $services = New-Object System.Collections.Generic.List[Hashtable]; Foreach ($service in $vm.VMIntegrationService) { $item_service = @{} $item_service.service = $service.Name $item_service.enabled = $service.Enabled $item_service.primary_operational_status = $service.PrimaryOperationalStatus.value__ $item_service.secondary_operational_status = $service.SecondaryOperationalStatus.value__ $services.Add($item_service) } $item.services = $services $items.Add($item) } $jsonString = $items | ConvertTo-JSON-20 -forceArray $true Write-Host $jsonString } Catch { Write-Host $Error[0].Exception exit 1 } exit 0 '; return $ps; } 1; __END__ =head1 DESCRIPTION Method to get hyper-v informations. =cut centreon-plugins-20220113/centreon/common/powershell/hyperv/2012/nodereplication.pm000066400000000000000000000035651417000230700301540ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::hyperv::2012::nodereplication; use strict; use warnings; use centreon::common::powershell::functions; sub get_powershell { my (%options) = @_; my $ps = ' $culture = new-object "System.Globalization.CultureInfo" "en-us" [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture '; $ps .= centreon::common::powershell::functions::escape_jsonstring(%options); $ps .= centreon::common::powershell::functions::convert_to_json(%options); $ps .= ' $ProgressPreference = "SilentlyContinue" Try { $ErrorActionPreference = "Stop" $vms = Get-VMReplication $items = New-Object System.Collections.Generic.List[Hashtable]; Foreach ($vm in $vms) { $item = @{} $item.name = $vm.Name $item.state = $vm.State.value__ $item.health = $vm.Health.value__ $items.Add($item) } $jsonString = $items | ConvertTo-JSON-20 -forceArray $true Write-Host $jsonString } Catch { Write-Host $Error[0].Exception exit 1 } exit 0 '; return $ps; } 1; __END__ =head1 DESCRIPTION Method to get hyper-v informations. =cut centreon-plugins-20220113/centreon/common/powershell/hyperv/2012/nodesnapshot.pm000066400000000000000000000061471417000230700275010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::hyperv::2012::nodesnapshot; use strict; use warnings; use centreon::common::powershell::functions; sub get_powershell { my (%options) = @_; my $ps = ' $culture = new-object "System.Globalization.CultureInfo" "en-us" [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture '; $ps .= centreon::common::powershell::functions::escape_jsonstring(%options); $ps .= centreon::common::powershell::functions::convert_to_json(%options); $ps .= ' $ProgressPreference = "SilentlyContinue" Try { $ErrorActionPreference = "Stop" $vms = Get-VM if ($vms.Length -gt 0) { $snapshots = Get-VMSnapshot -VMName * } $items = New-Object System.Collections.Generic.List[Hashtable]; Foreach ($vm in $vms) { $item = @{} $note = $vm.Notes -replace "\r","" $note = $note -replace "\n"," - " $item.note = $note $item.name = $vm.VMName $item.state = $vm.State.value__ $checkpoints = New-Object System.Collections.Generic.List[Hashtable]; Foreach ($snap in $snapshots) { if ($snap.VMName -eq $vm.VMName) { $checkpoint = @{} $checkpoint.type = "snapshot" $checkpoint.creation_time = (get-date -date $snap.CreationTime.ToUniversalTime() -UFormat ' . "'%s'" . ') $checkpoints.Add($checkpoint) } } 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") { $checkpoint = @{} $parent = Get-Item $VHD.ParentPath $checkpoint.type = "backing" $checkpoint.creation_time = (get-date -date $parent.LastWriteTime.ToUniversalTime() -UFormat ' . "'%s'" . ') $checkpoints.Add($checkpoint) } } } $item.checkpoints = $checkpoints $items.Add($item) } $jsonString = $items | ConvertTo-JSON-20 -forceArray $true Write-Host $jsonString } Catch { Write-Host $Error[0].Exception exit 1 } exit 0 '; return $ps; } 1; __END__ =head1 DESCRIPTION Method to get hyper-v informations. =cut centreon-plugins-20220113/centreon/common/powershell/hyperv/2012/nodevmstatus.pm000066400000000000000000000044021417000230700275200ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::hyperv::2012::nodevmstatus; use strict; use warnings; use centreon::common::powershell::functions; sub get_powershell { my (%options) = @_; my $ps = ' $culture = new-object "System.Globalization.CultureInfo" "en-us" [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture '; $ps .= centreon::common::powershell::functions::escape_jsonstring(%options); $ps .= centreon::common::powershell::functions::convert_to_json(%options); $ps .= ' $ProgressPreference = "SilentlyContinue" Try { $ErrorActionPreference = "Stop" $vms = Get-VM $node_is_clustered = 0 Try { If (@(Get-ClusterNode -ea Ignore).Count -ne 0) { $node_is_clustered = 1 } } Catch { } $items = New-Object System.Collections.Generic.List[Hashtable]; Foreach ($vm in $vms) { $item = @{} $note = $vm.Notes -replace "\r","" $note = $note -replace "\n"," - " $item.name = $vm.VMName $item.state = $vm.State.value__ $item.status = $vm.Status $item.note = $note $item.is_clustered = $vm.IsClustered if ($node_is_clustered -eq 0) { $item.is_clustered = $false } $items.Add($item) } $jsonString = $items | ConvertTo-JSON-20 -forceArray $true Write-Host $jsonString } Catch { Write-Host $Error[0].Exception exit 1 } exit 0 '; return $ps; } 1; __END__ =head1 DESCRIPTION Method to get hyper-v informations. =cut centreon-plugins-20220113/centreon/common/powershell/hyperv/2012/scvmmdiscovery.pm000066400000000000000000000071121417000230700300420ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::hyperv::2012::scvmmdiscovery; use strict; use warnings; use centreon::common::powershell::functions; sub get_powershell { my (%options) = @_; my $hostname = '$env:computername'; if (defined($options{scvmm_hostname}) && $options{scvmm_hostname} ne '') { $hostname = '"' . $options{scvmm_hostname} . '"'; } my $ps = ' $culture = new-object "System.Globalization.CultureInfo" "en-us" [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture '; $ps .= centreon::common::powershell::functions::escape_jsonstring(%options); $ps .= centreon::common::powershell::functions::convert_to_json(%options); $ps .= ' $ProgressPreference = "SilentlyContinue" Try { $ErrorActionPreference = "Stop" Import-Module -Name "virtualmachinemanager" $username = "' . $options{scvmm_username} . '" $password = ConvertTo-SecureString "' . $options{scvmm_password} . '" -AsPlainText -Force $UserCredential = new-object -typename System.Management.Automation.PSCredential -argumentlist $username,$password $connection = Get-VMMServer -ComputerName ' . $hostname . ' -TCPPort ' . $options{scvmm_port} . ' -Credential $UserCredential $vms = Get-SCVirtualMachine -VMMServer $connection $items = New-Object System.Collections.Generic.List[Hashtable]; Foreach ($vm in $vms) { $item = @{} $item.type = "vm" $item.vmId = $vm.VMId $item.name = $vm.Name $desc = $vm.Description -replace "\r","" $item.description = $desc $item.operatingSystem = $vm.OperatingSystem.ToString() $item.status = $vm.Status.value__ $item.hostGroupPath = $vm.HostGroupPath $item.enabled = $vm.enabled $item.computerName = $vm.ComputerName $item.tag = $vm.Tag $item.vmHostId = $vm.VMHost.ID.Guid $ipv4Addresses = @() if ($vm.Status -eq "Running") { Foreach ($adapter in $vm.VirtualNetworkAdapters) { $ipv4Addresses += $adapter.IPv4Addresses } } $item.ipv4Addresses = $ipv4Addresses $items.Add($item) } $vmhosts = Get-SCVmHost -VMMServer $connection Foreach ($vmhost in $vmhosts) { $item = @{} $item.type = "host" $item.id = $vmhost.ID.Guid $item.name = $vmhost.Name $desc = $host.Description -replace "\r","" $item.description = $desc $item.FQDN = $vmhost.FQDN $item.clusterName = $vmhost.HostCluster.Name $item.operatingSystem = $vmhost.OperatingSystem.Name $items.Add($item) } $jsonString = $items | ConvertTo-JSON-20 -forceArray $true Write-Host $jsonString } Catch { Write-Host $Error[0].Exception exit 1 } exit 0 '; return $ps; } 1; __END__ =head1 DESCRIPTION Method to get hyper-v informations. =cut centreon-plugins-20220113/centreon/common/powershell/hyperv/2012/scvmmintegrationservice.pm000066400000000000000000000060451417000230700317430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::hyperv::2012::scvmmintegrationservice; use strict; use warnings; use centreon::common::powershell::functions; sub get_powershell { my (%options) = @_; my $hostname = '$env:computername'; if (defined($options{scvmm_hostname}) && $options{scvmm_hostname} ne '') { $hostname = '"' . $options{scvmm_hostname} . '"'; } my $ps = ' $culture = new-object "System.Globalization.CultureInfo" "en-us" [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture '; $ps .= centreon::common::powershell::functions::escape_jsonstring(%options); $ps .= centreon::common::powershell::functions::convert_to_json(%options); $ps .= ' $ProgressPreference = "SilentlyContinue" Try { $ErrorActionPreference = "Stop" Import-Module -Name "virtualmachinemanager" $username = "' . $options{scvmm_username} . '" $password = ConvertTo-SecureString "' . $options{scvmm_password} . '" -AsPlainText -Force $UserCredential = new-object -typename System.Management.Automation.PSCredential -argumentlist $username,$password $connection = Get-VMMServer -ComputerName ' . $hostname . ' -TCPPort ' . $options{scvmm_port} . ' -Credential $UserCredential $vms = Get-SCVirtualMachine -VMMServer $connection $items = New-Object System.Collections.Generic.List[Hashtable]; Foreach ($vm in $vms) { $item = @{} $desc = $vm.description -replace "\r","" $desc = $desc -replace "\n"," - " $item.name = $vm.Name $item.status = $vm.Status.value__ $item.description = $desc $item.cloud = $vm.Cloud $item.host_group_path = $vm.HostGroupPath $item.vm_addition = $vm.VMAddition $item.operating_system_shutdown_enabled = $vm.OperatingSystemShutdownEnabled $item.time_synchronization_enabled = $vm.TimeSynchronizationEnabled $item.data_exchange_enabled = $vm.DataExchangeEnabled $item.heartbeat_enabled = $vm.HeartbeatEnabled $item.backup_enabled = $vm.BackupEnabled $items.Add($item) } $jsonString = $items | ConvertTo-JSON-20 -forceArray $true Write-Host $jsonString } Catch { Write-Host $Error[0].Exception exit 1 } exit 0 '; return $ps; } 1; __END__ =head1 DESCRIPTION Method to get hyper-v informations. =cut centreon-plugins-20220113/centreon/common/powershell/hyperv/2012/scvmmsnapshot.pm000066400000000000000000000061241417000230700276740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::hyperv::2012::scvmmsnapshot; use strict; use warnings; use centreon::common::powershell::functions; sub get_powershell { my (%options) = @_; my $hostname = '$env:computername'; if (defined($options{scvmm_hostname}) && $options{scvmm_hostname} ne '') { $hostname = '"' . $options{scvmm_hostname} . '"'; } my $ps = ' $culture = new-object "System.Globalization.CultureInfo" "en-us" [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture '; $ps .= centreon::common::powershell::functions::escape_jsonstring(%options); $ps .= centreon::common::powershell::functions::convert_to_json(%options); $ps .= ' $ProgressPreference = "SilentlyContinue" Try { $ErrorActionPreference = "Stop" Import-Module -Name "virtualmachinemanager" $username = "' . $options{scvmm_username} . '" $password = ConvertTo-SecureString "' . $options{scvmm_password} . '" -AsPlainText -Force $UserCredential = new-object -typename System.Management.Automation.PSCredential -argumentlist $username,$password $connection = Get-VMMServer -ComputerName ' . $hostname . ' -TCPPort ' . $options{scvmm_port} . ' -Credential $UserCredential $vms = Get-SCVirtualMachine -VMMServer $connection $items = New-Object System.Collections.Generic.List[Hashtable]; Foreach ($vm in $vms) { $item = @{} $checkpoints = Get-SCVMCheckpoint -VMMServer $connection -Vm $vm $desc = $vm.description -replace "\r","" $desc = $desc -replace "\n"," - " $item.name = $vm.Name $item.description = $desc $item.status = $vm.Status.value__ $item.host_group_path = $vm.HostGroupPath $chkpt_list = New-Object System.Collections.Generic.List[Hashtable]; foreach ($checkpoint in $checkpoints) { $chkpt = @{} $chkpt.type = "backing" $chkpt.added_time = (get-date -date $checkpoint.AddedTime.ToUniversalTime() -UFormat ' . "'%s'" . ') $chkpt_list.Add($chkpt) } $item.checkpoints = $chkpt_list $items.Add($item) } $jsonString = $items | ConvertTo-JSON-20 -forceArray $true Write-Host $jsonString } Catch { Write-Host $Error[0].Exception exit 1 } exit 0 '; return $ps; } 1; __END__ =head1 DESCRIPTION Method to get hyper-v informations. =cut centreon-plugins-20220113/centreon/common/powershell/hyperv/2012/scvmmvmstatus.pm000066400000000000000000000052501417000230700277220ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::hyperv::2012::scvmmvmstatus; use strict; use warnings; use centreon::common::powershell::functions; sub get_powershell { my (%options) = @_; my $hostname = '$env:computername'; if (defined($options{scvmm_hostname}) && $options{scvmm_hostname} ne '') { $hostname = '"' . $options{scvmm_hostname} . '"'; } my $ps = ' $culture = new-object "System.Globalization.CultureInfo" "en-us" [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture '; $ps .= centreon::common::powershell::functions::escape_jsonstring(%options); $ps .= centreon::common::powershell::functions::convert_to_json(%options); $ps .= ' $ProgressPreference = "SilentlyContinue" Try { $ErrorActionPreference = "Stop" Import-Module -Name "virtualmachinemanager" $username = "' . $options{scvmm_username} . '" $password = ConvertTo-SecureString "' . $options{scvmm_password} . '" -AsPlainText -Force $UserCredential = new-object -typename System.Management.Automation.PSCredential -argumentlist $username,$password $connection = Get-VMMServer -ComputerName ' . $hostname . ' -TCPPort ' . $options{scvmm_port} . ' -Credential $UserCredential $vms = Get-SCVirtualMachine -VMMServer $connection $items = New-Object System.Collections.Generic.List[Hashtable]; Foreach ($vm in $vms) { $item = @{} $desc = $vm.description -replace "\r","" $desc = $desc -replace "\n"," - " $item.name = $vm.Name $item.description = $desc $item.status = $vm.Status.value__ $item.cloud = $vm.Cloud $item.host_group_path = $vm.HostGroupPath $items.Add($item) } $jsonString = $items | ConvertTo-JSON-20 -forceArray $true Write-Host $jsonString } Catch { Write-Host $Error[0].Exception exit 1 } exit 0 '; return $ps; } 1; __END__ =head1 DESCRIPTION Method to get hyper-v informations. =cut centreon-plugins-20220113/centreon/common/powershell/sccm/000077500000000000000000000000001417000230700234525ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/powershell/sccm/databasereplicationstatus.pm000066400000000000000000000102601417000230700312510ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::sccm::databasereplicationstatus; use strict; use warnings; use centreon::common::powershell::functions; sub get_powershell { my (%options) = @_; my $ps = ' $culture = new-object "System.Globalization.CultureInfo" "en-us" [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture '; $ps .= centreon::common::powershell::functions::escape_jsonstring(%options); $ps .= centreon::common::powershell::functions::convert_to_json(%options); $ps .= ' $ProgressPreference = "SilentlyContinue" Try { $ErrorActionPreference = "Stop" $modulePath = ${env:SMS_ADMIN_UI_PATH} $modulePath = $modulePath.Substring(0, $modulePath.lastIndexOf("\")) $module = $modulePath + "\ConfigurationManager.psd1" Import-Module $module $providers = Get-PSProvider | Where {$_.Name -match "CMSite" } if ($null -eq $providers -or $providers.Count -eq 0) { $providers = New-Object System.Collections.Generic.List[Hashtable]; $item = @{} $item.Name = "AdminUI.PS.Provider\CMSite" $items.Add($item) } $returnArray = @() foreach ($provider in $providers) { New-PSDrive -Name SCCMDrive -PSProvider $provider.Name -Root $env:COMPUTERNAME -Description "SCCM Site" | Out-Null CD "SCCMDrive:\" $CMObject = Get-CMDatabaseReplicationStatus CD "C:\" Remove-PSDrive -Name SCCMDrive $returnObject = New-Object -TypeName PSObject Add-Member -InputObject $returnObject -MemberType NoteProperty -Name "providerName" -Value $provider.Name Add-Member -InputObject $returnObject -MemberType NoteProperty -Name "LinkStatus" -Value $CMObject.LinkStatus Add-Member -InputObject $returnObject -MemberType NoteProperty -Name "Site1" -Value $CMObject.Site1 Add-Member -InputObject $returnObject -MemberType NoteProperty -Name "SiteName1" -Value $CMObject.SiteName1 Add-Member -InputObject $returnObject -MemberType NoteProperty -Name "SiteType1" -Value $CMObject.SiteType1 Add-Member -InputObject $returnObject -MemberType NoteProperty -Name "Site1Status" -Value $CMObject.Site1Status Add-Member -InputObject $returnObject -MemberType NoteProperty -Name "Site2" -Value $CMObject.Site2 Add-Member -InputObject $returnObject -MemberType NoteProperty -Name "SiteName2" -Value $CMObject.SiteName2 Add-Member -InputObject $returnObject -MemberType NoteProperty -Name "SiteType2" -Value $CMObject.SiteType2 Add-Member -InputObject $returnObject -MemberType NoteProperty -Name "Site2Status" -Value $CMObject.Site2Status Add-Member -InputObject $returnObject -MemberType NoteProperty -Name "Site1ToSite2GlobalState" -Value $CMObject.Site1ToSite2GlobalState Add-Member -InputObject $returnObject -MemberType NoteProperty -Name "Site1ToSite2GlobalSyncTime" -Value $CMObject.Site1ToSite2GlobalSyncTime Add-Member -InputObject $returnObject -MemberType NoteProperty -Name "Site2ToSite1GlobalState" -Value $CMObject.Site2ToSite1GlobalState Add-Member -InputObject $returnObject -MemberType NoteProperty -Name "Site2ToSite1GlobalSyncTime" -Value $CMObject.Site2ToSite1GlobalSyncTime $returnArray += $returnObject } $returnArray | ConvertTo-JSON-20 -forceArray $true } Catch { Write-Host $Error[0].Exception exit 1 } exit 0 '; return $ps; } 1; __END__ =head1 DESCRIPTION Method to get SCCM database replication informations. =cut centreon-plugins-20220113/centreon/common/powershell/sccm/sitestatus.pm000066400000000000000000000064501417000230700262250ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::sccm::sitestatus; use strict; use warnings; use centreon::common::powershell::functions; sub get_powershell { my (%options) = @_; my $ps = ' $culture = new-object "System.Globalization.CultureInfo" "en-us" [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture '; $ps .= centreon::common::powershell::functions::escape_jsonstring(%options); $ps .= centreon::common::powershell::functions::convert_to_json(%options); $ps .= ' $ProgressPreference = "SilentlyContinue" Try { $ErrorActionPreference = "Stop" $modulePath = ${env:SMS_ADMIN_UI_PATH} $modulePath = $modulePath.Substring(0, $modulePath.lastIndexOf("\")) $module = $modulePath + "\ConfigurationManager.psd1" Import-Module $module $returnArray = @() $providers = Get-PSProvider | Where {$_.Name -match "CMSite" } if ($null -eq $providers -or $providers.Count -eq 0) { $providers = New-Object System.Collections.Generic.List[Hashtable]; $item = @{} $item.Name = "AdminUI.PS.Provider\CMSite" $items.Add($item) } foreach ($provider in $providers) { New-PSDrive -Name SCCMDrive -PSProvider $provider.Name -Root $env:COMPUTERNAME -Description "SCCM Site" | Out-Null CD "SCCMDrive:\" $CMObject = Get-CMSite CD "C:\" Remove-PSDrive -Name SCCMDrive Foreach ($site in $CMObject) { $returnObject = New-Object -TypeName PSObject Add-Member -InputObject $returnObject -MemberType NoteProperty -Name "providerName" -Value $provider.Name Add-Member -InputObject $returnObject -MemberType NoteProperty -Name "SiteCode" -Value $site.SiteCode Add-Member -InputObject $returnObject -MemberType NoteProperty -Name "SiteName" -Value $site.SiteName Add-Member -InputObject $returnObject -MemberType NoteProperty -Name "Type" -Value $site.Type Add-Member -InputObject $returnObject -MemberType NoteProperty -Name "Mode" -Value $site.Mode Add-Member -InputObject $returnObject -MemberType NoteProperty -Name "Status" -Value $site.Status Add-Member -InputObject $returnObject -MemberType NoteProperty -Name "SecondarySiteCMUpdateStatus" -Value $site.SecondarySiteCMUpdateStatus $returnArray += $returnObject } } $returnArray | ConvertTo-JSON-20 -forceArray $true } Catch { Write-Host $Error[0].Exception exit 1 } exit 0 '; return $ps; } 1; __END__ =head1 DESCRIPTION Method to get SCCM database replication informations. =cut centreon-plugins-20220113/centreon/common/powershell/veeam/000077500000000000000000000000001417000230700236225ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/powershell/veeam/functions.pm000066400000000000000000000035571417000230700262020ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::veeam::functions; use strict; use warnings; sub powershell_init { my (%options) = @_; my $ps = ' $register_snaps=Get-PSSnapin -Registered $all_snaps=Get-PSSnapin $load_snaps=@("VeeamPSSnapin") $registered=0 foreach ($snap_name in $load_snaps) { if (@($register_snaps | Where-Object {$_.Name -Match $snap_name} ).count -gt 0) { if (@($all_snaps | Where-Object {$_.Name -Match $snap_name} ).count -eq 0) { Try { $register_snaps | Where-Object {$_.Name -Match $snap_name} | Add-PSSnapin -ErrorAction STOP $registered=1 } Catch { Write-Host $Error[0].Exception exit 1 } } } } if ($registered -eq 0) { if (@(Get-Module | Where-Object {$_.Name -Match "Veeam.Backup.PowerShell"} ).count -eq 0) { Try { Import-Module -DisableNameChecking -Name "Veeam.Backup.PowerShell" } Catch { Write-Host $Error[0].Exception exit 1 } } } '; return $ps; } 1; __END__ =head1 DESCRIPTION Powershell commands =cut centreon-plugins-20220113/centreon/common/powershell/veeam/jobstatus.pm000066400000000000000000000047531417000230700262070ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::veeam::jobstatus; use strict; use warnings; use centreon::common::powershell::functions; use centreon::common::powershell::veeam::functions; sub get_powershell { my (%options) = @_; my $ps = ' $ProgressPreference = "SilentlyContinue" $WarningPreference = "SilentlyContinue" $culture = new-object "System.Globalization.CultureInfo" "en-us" [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture '; $ps .= centreon::common::powershell::functions::escape_jsonstring(%options); $ps .= centreon::common::powershell::functions::convert_to_json(%options); $ps .= centreon::common::powershell::veeam::functions::powershell_init(); $ps .= ' Try { $ErrorActionPreference = "Stop" $items = New-Object System.Collections.Generic.List[Hashtable]; $jobs = Get-VBRJob foreach ($job in $jobs) { $item = @{} $item.name = $job.Name $item.type = $job.JobType.value__ $item.isRunning = $job.isRunning $item.result = -10 $item.creationTimeUTC = "" $item.endTimeUTC = "" $lastsession = $job.findlastsession() if ($lastsession) { $item.result = $lastsession.Result.value__ $item.creationTimeUTC = (get-date -date $lastsession.creationTime.ToUniversalTime() -Uformat ' . "'%s'" . ') $item.endTimeUTC = (get-date -date $lastsession.EndTime.ToUniversalTime() -Uformat ' . "'%s'" . ') } $items.Add($item) } $jsonString = $items | ConvertTo-JSON-20 -forceArray $true Write-Host $jsonString } Catch { Write-Host $Error[0].Exception exit 1 } exit 0 '; return $ps; } 1; __END__ =head1 DESCRIPTION Method to get veeam job status informations. =cut centreon-plugins-20220113/centreon/common/powershell/veeam/licenses.pm000066400000000000000000000051511417000230700257670ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::veeam::licenses; use strict; use warnings; use centreon::common::powershell::functions; use centreon::common::powershell::veeam::functions; sub get_powershell { my (%options) = @_; my $ps = ' $ProgressPreference = "SilentlyContinue" $WarningPreference = "SilentlyContinue" $culture = new-object "System.Globalization.CultureInfo" "en-us" [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture '; $ps .= centreon::common::powershell::functions::escape_jsonstring(%options); $ps .= centreon::common::powershell::functions::convert_to_json(%options); $ps .= centreon::common::powershell::veeam::functions::powershell_init(); $ps .= ' Try { $ErrorActionPreference = "Stop" $items = New-Object System.Collections.Generic.List[Hashtable]; $licenses = Get-VBRInstalledLicense foreach ($license in $licenses) { $item = @{ licensed_to = $license.LicensedTo; type = $license.Type.value__; status = $license.Status.value__; expiration_time = $null; licensed_instances = $null; used_instances = $null } if ($null -ne $license.InstanceLicenseSummary) { $item.licensed_instances = $license.InstanceLicenseSummary.LicensedInstancesNumber $item.used_instances = $license.InstanceLicenseSummary.UsedInstancesNumber } if ($null -ne $license.ExpirationDate) { $item.expiration_time = (get-date -date $license.ExpirationDate.ToUniversalTime() -UFormat ' . "'%s'" . ') } $items.Add($item) } $jsonString = $items | ConvertTo-JSON-20 -forceArray $true Write-Host $jsonString } Catch { Write-Host $Error[0].Exception exit 1 } exit 0 '; return $ps; } 1; __END__ =head1 DESCRIPTION Method to get veeam licenses informations. =cut centreon-plugins-20220113/centreon/common/powershell/veeam/listjobs.pm000066400000000000000000000037431417000230700260200ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::veeam::listjobs; use strict; use warnings; use centreon::common::powershell::functions; use centreon::common::powershell::veeam::functions; sub get_powershell { my (%options) = @_; my $ps = ' $ProgressPreference = "SilentlyContinue" $WarningPreference = "SilentlyContinue" $culture = new-object "System.Globalization.CultureInfo" "en-us" [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture '; $ps .= centreon::common::powershell::functions::escape_jsonstring(%options); $ps .= centreon::common::powershell::functions::convert_to_json(%options); $ps .= centreon::common::powershell::veeam::functions::powershell_init(); $ps .= ' Try { $ErrorActionPreference = "Stop" $items = New-Object System.Collections.Generic.List[Hashtable]; $jobs = Get-VBRJob foreach ($job in $jobs) { $item = @{ name = $job.Name; type = $job.JobType.value__ } $items.Add($item) } $jsonString = $items | ConvertTo-JSON-20 -forceArray $true Write-Host $jsonString } Catch { Write-Host $Error[0].Exception exit 1 } exit 0 '; return $ps; } 1; __END__ =head1 DESCRIPTION Method to get veeam jobs. =cut centreon-plugins-20220113/centreon/common/powershell/veeam/tapejobs.pm000066400000000000000000000042021417000230700257650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::veeam::tapejobs; use strict; use warnings; use centreon::common::powershell::functions; use centreon::common::powershell::veeam::functions; sub get_powershell { my (%options) = @_; my $ps = ' $ProgressPreference = "SilentlyContinue" $WarningPreference = "SilentlyContinue" $culture = new-object "System.Globalization.CultureInfo" "en-us" [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture '; $ps .= centreon::common::powershell::functions::escape_jsonstring(%options); $ps .= centreon::common::powershell::functions::convert_to_json(%options); $ps .= centreon::common::powershell::veeam::functions::powershell_init(); $ps .= ' Try { $ErrorActionPreference = "Stop" $items = New-Object System.Collections.Generic.List[Hashtable]; $jobs = Get-VBRtapeJob foreach ($job in $jobs) { $item = @{ name = $job.Name; enabled = $job.Enabled; type = $job.Type.value__; lastResult = $job.LastResult.value__; lastState = $job.LastState.value__ } $items.Add($item) } $jsonString = $items | ConvertTo-JSON-20 -forceArray $true Write-Host $jsonString } Catch { Write-Host $Error[0].Exception exit 1 } exit 0 '; return $ps; } 1; __END__ =head1 DESCRIPTION Method to get veeam tape job status informations. =cut centreon-plugins-20220113/centreon/common/powershell/windows/000077500000000000000000000000001417000230700242175ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/powershell/windows/liststorages.pm000066400000000000000000000042611417000230700273030ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::windows::liststorages; use strict; use warnings; use centreon::common::powershell::functions; sub get_powershell { my (%options) = @_; my $ps = ' $culture = new-object "System.Globalization.CultureInfo" "en-us" [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture '; $ps .= centreon::common::powershell::functions::escape_jsonstring(%options); $ps .= centreon::common::powershell::functions::convert_to_json(%options); $ps .= ' $ProgressPreference = "SilentlyContinue" Try { $ErrorActionPreference = "Stop" $disks = Get-CimInstance Win32_LogicalDisk $items = New-Object System.Collections.Generic.List[Hashtable]; Foreach ($disk in $disks) { $item = @{ name = $disk.DeviceID; type = $disk.DriveType; providername = $disk.ProviderName; desc = $disk.VolumeName; size = $null; freespace = $null; } if ($disk.Size -ne $null) { $item.size = $disk.Size.toString() } if ($disk.FreeSpace -ne $null) { $item.freespace = $disk.FreeSpace.toString() } $items.Add($item) } $jsonString = $items | ConvertTo-JSON-20 -forceArray $true Write-Host $jsonString } Catch { Write-Host $Error[0].Exception exit 1 } exit 0 '; return $ps; } 1; __END__ =head1 DESCRIPTION Method to list Windows Disks. =cut centreon-plugins-20220113/centreon/common/powershell/windows/pendingreboot.pm000066400000000000000000000116171417000230700274220ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::windows::pendingreboot; use strict; use warnings; use centreon::common::powershell::functions; sub get_powershell { my (%options) = @_; my $ps = ' $culture = new-object "System.Globalization.CultureInfo" "en-us" [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture '; $ps .= centreon::common::powershell::functions::escape_jsonstring(%options); $ps .= centreon::common::powershell::functions::convert_to_json(%options); $ps .= ' $ProgressPreference = "SilentlyContinue" Try { $ErrorActionPreference = "Stop" $ComputerName = "$env:COMPUTERNAME" $CompPendRen,$PendFileRename,$Pending,$SCCM = $false,$false,$false,$false ## Setting CBSRebootPend to null since not all versions of Windows has this value $CBSRebootPend = $null ## Making registry connection to the local/remote computer $HKLM = [UInt32] "0x80000002" $WMI_Reg = [WMIClass] "\\\\$ComputerName\\root\\default:StdRegProv" $RegSubKeysCBS = $WMI_Reg.EnumKey($HKLM,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Component Based Servicing\\") If ($RegSubKeysCBS.ReturnValue -eq 0) { $CBSRebootPend = $RegSubKeysCBS.sNames -contains "RebootPending" } ## Query WUAU from the registry $RegWUAURebootReq = $WMI_Reg.EnumKey($HKLM,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\Auto Update\\") $WUAURebootReq = $RegWUAURebootReq.sNames -contains "RebootRequired" ## Query PendingFileRenameOperations from the registry $RegSubKeySM = $WMI_Reg.GetMultiStringValue($HKLM,"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\","PendingFileRenameOperations") $RegValuePFRO = $RegSubKeySM.sValue ## Query ComputerName and ActiveComputerName from the registry $ActCompNm = $WMI_Reg.GetStringValue($HKLM,"SYSTEM\\CurrentControlSet\\Control\\ComputerName\\ActiveComputerName\\","ComputerName") $CompNm = $WMI_Reg.GetStringValue($HKLM,"SYSTEM\\CurrentControlSet\\Control\\ComputerName\\ComputerName\\","ComputerName") If ($ActCompNm -ne $CompNm) { $CompPendRen = $true } ## If PendingFileRenameOperations has a value set $RegValuePFRO variable to $true If ($RegValuePFRO) { $PendFileRename = $true } ## Determine SCCM 2012 Client Reboot Pending Status ## To avoid nested "if" statements and unneeded WMI calls to determine if the CCM_ClientUtilities class exist, setting EA = 0 $CCMClientSDK = $null $CCMSplat = @{ NameSpace="ROOT\\ccm\\ClientSDK" Class="CCM_ClientUtilities" Name="DetermineIfRebootPending" ComputerName=$ComputerName ErrorAction="Stop" } ## Try CCMClientSDK Try { $CCMClientSDK = Invoke-WmiMethod @CCMSplat } Catch [System.UnauthorizedAccessException] { $CcmStatus = Get-Service -Name CcmExec -ComputerName $ComputerName -ErrorAction SilentlyContinue If ($CcmStatus.Status -ne "Running") { Write-Warning "$ComputerName`: Error - CcmExec service is not running." $CCMClientSDK = $null } } Catch { $CCMClientSDK = $null } If ($CCMClientSDK) { If ($CCMClientSDK.ReturnValue -ne 0) { Write-Warning "Error: DetermineIfRebootPending returned error code $($CCMClientSDK.ReturnValue)" } If ($CCMClientSDK.IsHardRebootPending -or $CCMClientSDK.RebootPending) { $SCCM = $true } } Else { $SCCM = $null } $WindowsVersion = (Get-WmiObject -class Win32_OperatingSystem).Caption; $item = @{ WindowsVersion = $WindowsVersion; CBServicing = $CBSRebootPend; WindowsUpdate = $WUAURebootReq; CCMClientSDK = $SCCM; PendComputerRename = $CompPendRen; PendFileRename = $PendFileRename; RebootPending = ($CompPendRen -or $CBSRebootPend -or $WUAURebootReq -or $SCCM -or $PendFileRename) } $jsonString = $item | ConvertTo-JSON-20 Write-Host $jsonString } Catch { Write-Host $Error[0].Exception exit 1 } exit 0 '; return $ps; } 1; __END__ =head1 DESCRIPTION Method to get pending reboot informations. =cut centreon-plugins-20220113/centreon/common/powershell/wsus/000077500000000000000000000000001417000230700235265ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/powershell/wsus/computersstatus.pm000066400000000000000000000057151417000230700273610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::wsus::computersstatus; use strict; use warnings; use centreon::common::powershell::functions; sub get_powershell { my (%options) = @_; my $ps = ' $culture = new-object "System.Globalization.CultureInfo" "en-us" [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture '; $ps .= centreon::common::powershell::functions::escape_jsonstring(%options); $ps .= centreon::common::powershell::functions::convert_to_json(%options); $ps .= ' $wsusServer = "' . $options{wsus_server} . '" $useSsl = ' . $options{use_ssl} . ' $wsusPort = ' . $options{wsus_port} . ' $notUpdatedSince = ' . $options{not_updated_since} . ' Try { [void][reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration") } Catch { Write-Host $Error[0].Exception exit 1 } $ProgressPreference = "SilentlyContinue" Try { $ErrorActionPreference = "Stop" $wsusObject = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($wsusServer, $useSsl, $wsusPort) $wsusStatus = $wsusObject.GetStatus() $notUpdatedSinceTimespan = new-object TimeSpan($notUpdatedSince, 0, 0, 0) $computersNotContactedSinceCount = $wsusObject.GetComputersNotContactedSinceCount([DateTime]::UtcNow.Subtract($notUpdatedSinceTimespan)) $computerTargetScope = new-object Microsoft.UpdateServices.Administration.ComputerTargetScope $unassignedComputersCount = $wsusObject.GetComputerTargetGroup([Microsoft.UpdateServices.Administration.ComputerTargetGroupId]::UnassignedComputers).GetComputerTargets().Count $item = @{ ComputerTargetsNeedingUpdatesCount = $wsusStatus.ComputerTargetsNeedingUpdatesCount; ComputerTargetsWithUpdateErrorsCount = $wsusStatus.ComputerTargetsWithUpdateErrorsCount; ComputersUpToDateCount = $wsusStatus.ComputersUpToDateCount; ComputersNotContactedSinceCount = $computersNotContactedSinceCount; UnassignedComputersCount = $unassignedComputersCount } $jsonString = $item | ConvertTo-JSON-20 Write-Host $jsonString } Catch { Write-Host $Error[0].Exception exit 1 } exit 0 '; return $ps; } 1; __END__ =head1 DESCRIPTION Method to get WSUS computers informations. =cut centreon-plugins-20220113/centreon/common/powershell/wsus/serverstatistics.pm000066400000000000000000000050751417000230700275140ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::wsus::serverstatistics; use strict; use warnings; use centreon::common::powershell::functions; sub get_powershell { my (%options) = @_; my $ps = ' $culture = new-object "System.Globalization.CultureInfo" "en-us" [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture '; $ps .= centreon::common::powershell::functions::escape_jsonstring(%options); $ps .= centreon::common::powershell::functions::convert_to_json(%options); $ps .= ' $wsusServer = "' . $options{wsus_server} . '" $useSsl = ' . $options{use_ssl} . ' $wsusPort = ' . $options{wsus_port} . ' Try { [void][reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration") } Catch { Write-Host $Error[0].Exception exit 1 } $ProgressPreference = "SilentlyContinue" Try { $ErrorActionPreference = "Stop" $wsusObject = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($wsusServer, $useSsl, $wsusPort) $wsusStatus = $wsusObject.GetStatus() $item = @{ ComputerTargetCount = $wsusStatus.ComputerTargetCount; CustomComputerTargetGroupCount = $wsusStatus.CustomComputerTargetGroupCount; UpdateCount = $wsusStatus.UpdateCount; ApprovedUpdateCount = $wsusStatus.ApprovedUpdateCount; DeclinedUpdateCount = $wsusStatus.DeclinedUpdateCount; NotApprovedUpdateCount = $wsusStatus.NotApprovedUpdateCount; UpdatesWithStaleUpdateApprovalsCount = $wsusStatus.UpdatesWithStaleUpdateApprovalsCount; ExpiredUpdateCount = $wsusStatus.ExpiredUpdateCount } $jsonString = $item | ConvertTo-JSON-20 Write-Host $jsonString } Catch { Write-Host $Error[0].Exception exit 1 } exit 0 '; return $ps; } 1; __END__ =head1 DESCRIPTION Method to get WSUS server statistics. =cut centreon-plugins-20220113/centreon/common/powershell/wsus/synchronisationstatus.pm000066400000000000000000000050731417000230700305670ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::wsus::synchronisationstatus; use strict; use warnings; use centreon::common::powershell::functions; sub get_powershell { my (%options) = @_; my $ps = ' $culture = new-object "System.Globalization.CultureInfo" "en-us" [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture '; $ps .= centreon::common::powershell::functions::escape_jsonstring(%options); $ps .= centreon::common::powershell::functions::convert_to_json(%options); $ps .= ' $wsusServer = "' . $options{wsus_server} . '" $useSsl = ' . $options{use_ssl} . ' $wsusPort = ' . $options{wsus_port} . ' Try { [void][reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration") } Catch { Write-Host $Error[0].Exception exit 1 } $ProgressPreference = "SilentlyContinue" Try { $ErrorActionPreference = "Stop" $wsusObject = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($wsusServer, $useSsl, $wsusPort) $syncStatus = $wsusObject.GetSubscription().GetSynchronizationStatus() $syncProgress = $wsusObject.GetSubscription().GetSynchronizationProgress() $lastSync = $wsusObject.GetSubscription().GetLastSynchronizationInfo() $item = @{ SynchronizationStatus = $syncStatus.ToString(); TotalItems = $syncProgress.TotalItems; ProcessedItems = $syncProgress.ProcessedItems; LastSynchronizationResult = $lastSync.Result.ToString(); LastSynchronizationStartTime = $lastSync.StartTime; LastSynchronizationEndTime = $lastSync.EndTime } $jsonString = $item | ConvertTo-JSON-20 Write-Host $jsonString } Catch { Write-Host $Error[0].Exception exit 1 } exit 0 '; return $ps; } 1; __END__ =head1 DESCRIPTION Method to get WSUS synchronisation informations. =cut centreon-plugins-20220113/centreon/common/powershell/wsus/updatesstatus.pm000066400000000000000000000046241417000230700270030ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::powershell::wsus::updatesstatus; use strict; use warnings; use centreon::common::powershell::functions; sub get_powershell { my (%options) = @_; my $ps = ' $culture = new-object "System.Globalization.CultureInfo" "en-us" [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture '; $ps .= centreon::common::powershell::functions::escape_jsonstring(%options); $ps .= centreon::common::powershell::functions::convert_to_json(%options); $ps .= ' $wsusServer = "' . $options{wsus_server} . '" $useSsl = ' . $options{use_ssl} . ' $wsusPort = ' . $options{wsus_port} . ' Try { [void][reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration") } Catch { Write-Host $Error[0].Exception exit 1 } $ProgressPreference = "SilentlyContinue" Try { $ErrorActionPreference = "Stop" $wsusObject = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($wsusServer, $useSsl, $wsusPort) $wsusStatus = $wsusObject.GetStatus() $item = @{ UpdatesWithClientErrorsCount = $wsusStatus.UpdatesWithClientErrorsCount; UpdatesWithServerErrorsCount = $wsusStatus.UpdatesWithServerErrorsCount; UpdatesNeedingFilesCount = $wsusStatus.UpdatesNeedingFilesCount; UpdatesNeededByComputersCount = $wsusStatus.UpdatesNeededByComputersCount; UpdatesUpToDateCount = $wsusStatus.UpdatesUpToDateCount } $jsonString = $item | ConvertTo-JSON-20 Write-Host $jsonString } Catch { Write-Host $Error[0].Exception exit 1 } exit 0 '; return $ps; } 1; __END__ =head1 DESCRIPTION Method to get WSUS updates informations. =cut centreon-plugins-20220113/centreon/common/protocols/000077500000000000000000000000001417000230700223655ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/protocols/actuator/000077500000000000000000000000001417000230700242075ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/protocols/actuator/custom/000077500000000000000000000000001417000230700255215ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/protocols/actuator/custom/centreonmap.pm000066400000000000000000000225471417000230700304040ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Authors : Roman Morandell - ivertix # package centreon::common::protocols::actuator::custom::centreonmap; use strict; use warnings; use centreon::plugins::http; use centreon::plugins::statefile; use JSON::XS; use Digest::MD5 qw(md5_hex); 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'url-path:s' => { name => 'url_path' }, 'api-username:s' => { name => 'api_username' }, 'api-password:s' => { name => 'api_password' }, 'client-version:s' => { name => 'client_version' }, 'timeout:s' => { name => 'timeout' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); $self->{cache} = centreon::plugins::statefile->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'http'; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 8080; $self->{url_path} = (defined($self->{option_results}->{url_path})) ? $self->{option_results}->{url_path} : '/centreon-studio/api/beta'; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : ''; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : ''; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 30; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300' ; $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; $self->{client_version} = (defined($self->{option_results}->{client_version})) ? $self->{option_results}->{client_version} : '21.04.0'; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify hostname option.'); $self->{output}->option_exit(); } if ($self->{api_username} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-username option."); $self->{output}->option_exit(); } if ($self->{api_password} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-password option."); $self->{output}->option_exit(); } $self->{cache}->check_options(option_results => $self->{option_results}); return 0; } sub get_connection_infos { my ($self, %options) = @_; return $self->{hostname} . '_' . $self->{http}->get_port(); } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub get_port { my ($self, %options) = @_; return $self->{port}; } sub json_decode { my ($self, %options) = @_; my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($options{content}); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } return $decoded; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->add_header(key => 'X-Client-Version', value => $self->{client_version}); $self->{http}->set_options(%{$self->{option_results}}); } sub clean_session { my ($self, %options) = @_; my $datas = {}; $options{statefile}->write(data => $datas); $self->{studio_session} = undef; } sub get_session { my ($self, %options) = @_; my $has_cache_file = $options{statefile}->read(statefile => 'centreonmap_session_' . md5_hex($self->{option_results}->{hostname}) . '_' . md5_hex($self->{option_results}->{api_username})); my $studio_session = $options{statefile}->get(name => 'studio_session'); if ($has_cache_file == 0 || !defined($studio_session)) { my $login = { login => $self->{api_username}, password => $self->{api_password} }; my $post_json = JSON::XS->new->utf8->encode($login); my ($content) = $self->{http}->request( method => 'POST', url_path => $self->{url_path} . '/authentication', header => ['Content-type: application/json'], query_form_post => $post_json, warning_status => '', unknown_status => '', critical_status => '' ); if ($self->{http}->get_code() != 200) { $self->{output}->add_option_msg(short_msg => "Authentication error [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded = $self->json_decode(content => $content); if (!defined($decoded->{studioSession})) { $self->{output}->add_option_msg(short_msg => 'Cannot studio session'); $self->{output}->option_exit(); } $studio_session = $decoded->{studioSession}; $options{statefile}->write(data => { studio_session => $studio_session }); } $self->{studio_session} = $studio_session; } sub request_api { my ($self, %options) = @_; $self->settings(); if (!defined($self->{studio_session})) { $self->get_session(statefile => $self->{cache}); } my $content = $self->{http}->request( url_path => $self->{url_path} . '/actuator' . $options{endpoint}, get_param => $options{get_param}, header => [ 'studio-session: ' . $self->{studio_session} ], warning_status => '', unknown_status => '', critical_status => '' ); # Maybe there is an issue with the token. So we retry. if ($self->{http}->get_code() < 200 || $self->{http}->get_code() >= 300) { $self->clean_session(statefile => $self->{cache}); $self->get_session(statefile => $self->{cache}); $content = $self->{http}->request( url_path => $self->{url_path} . '/actuator' . $options{endpoint}, get_param => $options{get_param}, header => [ 'studio-session: ' . $self->{studio_session} ], unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status} ); } my $decoded = $self->json_decode(content => $content); if (!defined($decoded)) { $self->{output}->add_option_msg(short_msg => 'Error while retrieving data (add --debug option for detailed message)'); $self->{output}->option_exit(); } return $decoded; } 1; __END__ =head1 NAME Centreon Map API =head1 SYNOPSIS Centreon Map API =head1 REST API OPTIONS =over 8 =item B<--hostname> API hostname. =item B<--url-path> API url path (Default: '/centreon-studio/api/beta') =item B<--port> API port (Default: 8080) =item B<--proto> Specify https if needed (Default: 'http') =item B<--api-username> Set API username =item B<--api-password> Set API password =item B<--timeout> Set HTTP timeout =item B<--client-version> Set the client version (Default: '21.04.0') =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/centreon/common/protocols/actuator/custom/standard.pm000066400000000000000000000151141417000230700276610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::protocols::actuator::custom::standard; use strict; use warnings; use centreon::plugins::http; use JSON::XS; 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 => { 'api-username:s' => { name => 'api_username' }, 'api-password:s' => { name => 'api_password' }, 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'timeout:s' => { name => 'timeout' }, 'unknown-http-status:s' => { name => 'unknown_http_status' }, 'warning-http-status:s' => { name => 'warning_http_status' }, 'critical-http-status:s' => { name => 'critical_http_status' }, 'url-path:s' => { name => 'url_path' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 8080; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'http'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 30; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : ''; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : ''; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300'; $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; $self->{url_path} = (defined($self->{option_results}->{url_path})) ? $self->{option_results}->{url_path} : '/actuator'; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --hostname option.'); $self->{output}->option_exit(); } return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; if (defined($self->{api_username}) && $self->{api_username} ne '') { $self->{option_results}->{credentials} = 1; $self->{option_results}->{basic} = 1; $self->{option_results}->{username} = $self->{api_username}; $self->{option_results}->{password} = $self->{api_password}; } } sub settings { my ($self, %options) = @_; return if (defined($self->{settings_done})); $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->set_options(%{$self->{option_results}}); $self->{settings_done} = 1; } sub get_connection_infos { my ($self, %options) = @_; return $self->{hostname} . '_' . $self->{http}->get_port(); } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub request_api { my ($self, %options) = @_; $self->settings(); my $content = $self->{http}->request( url_path => $self->{url_path} . $options{endpoint}, get_param => $options{get_param}, unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status}, cookies_file => '' ); if (!defined($content) || $content eq '') { $self->{output}->add_option_msg(short_msg => "API returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } return $decoded; } 1; __END__ =head1 NAME Spring Boot Actuator Rest API =head1 REST API OPTIONS Spring Boot Actuator Rest API =over 8 =item B<--hostname> Hostname. =item B<--port> Port used (Default: 8080) =item B<--proto> Specify https if needed (Default: 'http') =item B<--api-username> Specify username for authentication (basic auth) =item B<--api-password> Specify password for authentication (basic auth) =item B<--timeout> Set timeout in seconds (Default: 30) =item B<--url-path> API url path (Default: '/actuator') =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/centreon/common/protocols/jmx/000077500000000000000000000000001417000230700231635ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/protocols/jmx/custom/000077500000000000000000000000001417000230700244755ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/protocols/jmx/custom/jolokia.pm000066400000000000000000000304471417000230700264730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::protocols::jmx::custom::jolokia; use strict; use warnings; use JMX::Jmx4Perl; use JMX::Jmx4Perl::Alias; use JMX::Jmx4Perl::Request; use JMX::Jmx4Perl::Util; sub new { my ($class, %options) = @_; my $self = {}; bless $self, $class; # $options{options} = options object # $options{output} = output object # $options{exit_value} = integer # $options{noptions} = integer 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 => { 'url:s@' => { name => 'url' }, 'timeout:s@' => { name => 'timeout' }, 'username:s@' => { name => 'username' }, 'password:s@' => { name => 'password' }, 'proxy-url:s@' => { name => 'proxy_url' }, 'proxy-username:s@' => { name => 'proxy_username' }, 'proxy-password:s@' => { name => 'proxy_password' }, 'target-url:s@' => { name => 'target_url' }, 'target-username:s@' => { name => 'target_username' }, 'target-password:s@' => { name => 'target_password' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'JOLOKIA OPTIONS', once => 1); $self->{output} = $options{output}; $self->{jmx4perl} = undef; return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; foreach (('url', 'timeout', 'username', 'password', 'proxy_url', 'proxy_username', 'proxy_password', 'target_url', 'target_username', 'target_password')) { $self->{$_} = (defined($self->{option_results}->{$_})) ? shift(@{$self->{option_results}->{$_}}) : undef; } $self->{connect_params} = {}; if (!defined($self->{url}) || $self->{url} eq '') { $self->{output}->add_option_msg(short_msg => "Please set option --url."); $self->{output}->option_exit(); } if (defined($self->{timeout}) && $self->{timeout} =~ /^\d+$/ && $self->{timeout} > 0) { $self->{timeout} = $self->{timeout}; } else { $self->{timeout} = 30; } $self->{connect_params}->{url} = $self->{url}; $self->{connect_params}->{timeout} = $self->{timeout}; if (defined($self->{username}) && $self->{username} ne '') { $self->{connect_params}->{user} = $self->{username}; $self->{connect_params}->{password} = $self->{password}; } if (defined($self->{proxy_url}) && $self->{proxy_url} ne '') { $self->{connect_params}->{proxy} = { url => $self->{proxy_url} }; if (defined($self->{proxy_username}) && $self->{proxy_username} ne '') { $self->{connect_params}->{proxy}->{'proxy-user'} = $self->{proxy_username}; $self->{connect_params}->{proxy}->{'proxy-password'} = $self->{proxy_password}; } } if (defined($self->{target_url}) && $self->{target_url} ne '') { $self->{connect_params}->{target} = { url => $self->{target_url}, user => undef, password => undef }; if (defined($self->{target_username}) && $self->{target_username} ne '') { $self->{connect_params}->{target}->{user} = $self->{target_username}; $self->{connect_params}->{target}->{password} = $self->{target_password}; } } if (!defined($self->{url}) || scalar(@{$self->{option_results}->{url}}) == 0) { return 0; } return 1; } sub get_connection_info { my ($self, %options) = @_; my $connection_info = $self->{url}; $connection_info .= '_' . $self->{proxy_url} if (defined($self->{proxy_url})); return $connection_info; } sub connect { my ($self, %options) = @_; $self->{jmx4perl} = new JMX::Jmx4Perl($self->{connect_params}); } sub _add_request { my ($self, %options) = @_; my $request = JMX::Jmx4Perl::Request->new( READ, $options{object}, $options{attribute} ); if (!$request->is_mbean_pattern($options{object})) { $request->{path} = $options{path}; } return $request; } sub check_error { my ($self, %options) = @_; # 500-599 an error. 400 is an attribute not present my $status = $options{response}->status(); if ($status >= 500 || $status == 401 || $status == 403 || $status == 408) { $self->{output}->add_option_msg(short_msg => "protocol issue: " . $options{response}->error_text()); $self->{output}->option_exit(); } } sub get_attributes { my ($self, %options) = @_; my $nothing_quit = defined($options{nothing_quit}) && $options{nothing_quit} == 1 ? 1 : 0; #$options{request} = [ # { mbean => 'java.lang:name=*,type=MemoryPool', attributes => [ { name => 'CollectionUsage', path => 'committed' }, { name => 'Name', path => undef }, # { name => 'NonHeapMemoryUsagePlop', path => undef } ] }, # { mbean => 'java.lang:type=Memory', attributes => [ { name => 'NonHeapMemoryUsage' } ] }, # { mbean => 'java.lang:type=Memory', attributes => [ { name => 'HeapMemoryUsage', path => 'committed' } ] }, # { mbean => 'java.lang:type=Memory', attributes => [] }, #]; if (!defined($self->{jmx4perl})) { $self->connect(); } my @requests = (); for (my $i = 0; defined($options{request}) && $i < scalar(@{$options{request}}); $i++) { my $object = $options{request}->[$i]->{mbean}; for (my $j = 0; defined($options{request}->[$i]->{attributes}) && $j < scalar(@{$options{request}->[$i]->{attributes}}) ; $j++) { push @requests, $self->_add_request(object => $object, attribute => $options{request}->[$i]->{attributes}->[$j]->{name}, path => $options{request}->[$i]->{attributes}->[$j]->{path}); } if (!defined($options{request}->[$i]->{attributes}) || scalar(@{$options{request}->[$i]->{attributes}}) == 0) { push @requests, $self->_add_request(object => $object, path => $options{request}->[$i]->{path}); } } my $response = {}; my @responses = $self->{jmx4perl}->request(@requests); for (my $i = 0, my $pos = 0; defined($options{request}) && $i < scalar(@{$options{request}}); $i++) { for (my $j = 0; defined($options{request}->[$i]->{attributes}) && defined($responses[$pos]) && $j < scalar(@{$options{request}->[$i]->{attributes}}); $j++, $pos++) { if ($responses[$pos]->is_error()) { $self->check_error(response => $responses[$pos]); next; } my $mbean = $responses[$pos]->{request}->{mbean}; my $attribute = $responses[$pos]->{request}->{attribute}; my $value = $responses[$pos]->{value}; if ($requests[$pos]->is_mbean_pattern()) { foreach (keys %{$responses[$pos]->{value}}) { $response->{$_} = {} if (!defined($response->{$_})); $response->{$_}->{$attribute} = $responses[$pos]->{value}->{$_}->{$attribute}; } } else { $response->{$mbean} = {} if (!defined($response->{$mbean})); $response->{$mbean}->{$attribute} = $value; } } if (!defined($options{request}->[$i]->{attributes}) || scalar(@{$options{request}->[$i]->{attributes}}) == 0) { if ($responses[$pos]->is_error()) { $self->check_error(response => $responses[$pos]); } else { my $mbean = $responses[$pos]->{request}->{mbean}; $response->{$mbean} = {} if (!defined($response->{$mbean})); foreach (keys %{$responses[$pos]->{value}}) { $response->{$mbean}->{$_} = $responses[$pos]->{value}->{$_}; } } $pos++; } } if ($nothing_quit == 1 && scalar(keys %{$response}) == 0) { $self->{output}->add_option_msg(short_msg => "JMX Request: Cant get a single value."); $self->{output}->option_exit(); } return $response; } sub list_attributes { my ($self, %options) = @_; my $max_depth = defined($options{max_depth}) ? $options{max_depth} : 5; my $max_objects = defined($options{max_objects}) ? $options{max_objects} : 100; my $max_collection_size = defined($options{max_collection_size}) ? $options{max_collection_size} : 50; my $pattern = defined($options{mbean_pattern}) ? $options{mbean_pattern} : '*:*'; my $color = 1; eval { local $SIG{__DIE__} = 'IGNORE'; require Term::ANSIColor; }; if ($@) { $color = 0; } if (!defined($self->{jmx4perl})) { $self->connect(); } my $mbeans = $self->{jmx4perl}->search($pattern); print "List attributes:\n"; for my $mbean (@$mbeans) { my $request = JMX::Jmx4Perl::Request->new( READ, $mbean, undef, { maxDepth => $max_depth, maxObjects => $max_objects, maxCollectionSize => $max_collection_size, ignoreErrors => 1 } ); my $response = $self->{jmx4perl}->request($request); if ($response->is_error) { print "ERROR: " . $response->error_text . "\n"; print JMX::Jmx4Perl::Util->dump_value($response, { format => 'DATA' }); } else { my $values = $response->value; if (keys %$values) { for my $a (keys %$values) { print Term::ANSIColor::color('red on_yellow') if ($color == 1); print "$mbean -- $a"; print Term::ANSIColor::color('reset') if ($color == 1); my $val = $values->{$a}; if (JMX::Jmx4Perl::Util->is_object_to_dump($val)) { my $v = JMX::Jmx4Perl::Util->dump_value($val, { format => 'DATA' }); $v =~ s/^\s*//; print " = " . $v; } else { my $scal = JMX::Jmx4Perl::Util->dump_scalar($val); if (defined($scal)) { print " = " . $scal . "\n"; } else { print " = undef\n"; } } } } } } } 1; __END__ =head1 NAME JOlokia connector library =head1 SYNOPSIS my jolokia connector =head1 JOLOKIA OPTIONS =over 8 =item B<--url> Url where the jolokia agent is deployed (required). Example: http://localhost:8080/jolokia =item B<--timeout> Timeout in seconds for HTTP requests (Defaults: 30 seconds) =item B<--username> Credentials to use for the HTTP request =item B<--password> Credentials to use for the HTTP request =item B<--proxy-url> Optional HTTP proxy to use. =item B<--proxy-username> Credentials to use for the proxy =item B<--proxy-password> Credentials to use for the proxy =item B<--target-url> Target to use (if you use jolokia agent as a proxy in --url option). =item B<--target-username> Credentials to use for the target =item B<--target-password> Credentials to use for the target =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/centreon/common/protocols/ldap/000077500000000000000000000000001417000230700233055ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/protocols/ldap/lib/000077500000000000000000000000001417000230700240535ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/protocols/ldap/lib/ldap.pm000066400000000000000000000065471417000230700253450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::protocols::ldap::lib::ldap; use strict; use warnings; use Net::LDAP; sub quit { my (%options) = @_; if (defined($options{ldap_handle})) { $options{ldap_handle}->unbind(); } } sub search { my (%options) = @_; my %ldap_search_options = (); $ldap_search_options{base} = $options{search_base}; $ldap_search_options{filter} = $options{search_filter}; my $attrs; foreach my $option (@{$options{ldap_search_options}}) { next if ($option !~ /^\s*(.+?)\s*=(.+)$/); if ($1 eq 'attrs') { $attrs = [] if (!defined($attrs)); push @$attrs, $2; } else { $ldap_search_options{$1} = $2; } } $ldap_search_options{attrs} = $attrs if (defined($attrs)); my $search_result = $options{ldap_handle}->search(%ldap_search_options); if ($search_result->code) { return ($search_result, 1, 'Search operation error: ' . $search_result->error); } return ($search_result, 0); } sub connect { my (%options) = @_; my %ldap_connect_options = (); my %ldap_bind_options = (); $ldap_connect_options{timeout} = $options{timeout} if (defined($options{timeout})); foreach my $option (@{$options{ldap_connect_options}}) { next if ($option !~ /^(.+?)=(.+)$/); $ldap_connect_options{$1} = $2; } my $ldap_handle = Net::LDAP->new($options{hostname}, %ldap_connect_options); if (!defined($ldap_handle)) { return (undef, 1, 'Unable to connect to LDAP: ' . $@); } # TLS Process if (defined($options{use_tls})) { my %ldap_starttls_options = (); foreach my $option (@{$options{ldap_starttls_options}}) { next if ($option !~ /^(.+?)=(.+)$/); $ldap_starttls_options{$1} = $2; } my $tls_result = $ldap_handle->start_tls(%ldap_starttls_options); if ($tls_result->code) { return ($ldap_handle, 1, 'Start TLS operation error: ' . $tls_result->error); } } # Bind process my $username; if (defined($options{username}) && $options{username} ne '') { $ldap_bind_options{password} = $options{password}; $username = $options{username}; } foreach my $option (@{$options{ldap_bind_options}}) { next if ($option !~ /^(.+?)=(.+)$/); $ldap_bind_options{$1} = $2; } my $bind_result = $ldap_handle->bind($username, %ldap_bind_options); if ($bind_result->code) { return ($ldap_handle, 1, 'Bind operation error: ' . $bind_result->error); } return ($ldap_handle, 0); } 1; centreon-plugins-20220113/centreon/common/protocols/modbus/000077500000000000000000000000001417000230700236565ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/protocols/modbus/custom/000077500000000000000000000000001417000230700251705ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/protocols/modbus/custom/api.pm000066400000000000000000000164441417000230700263100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package 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}; 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 {} 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 centreon-plugins-20220113/centreon/common/protocols/sql/000077500000000000000000000000001417000230700231645ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/protocols/sql/mode/000077500000000000000000000000001417000230700241105ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/protocols/sql/mode/collection.pm000066400000000000000000001475241417000230700266160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::protocols::sql::mode::collection; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use JSON::XS; use Safe; use centreon::plugins::statefile; use Digest::MD5 qw(md5_hex); use Time::HiRes qw(gettimeofday tv_interval); sub custom_select_threshold { my ($self, %options) = @_; my $status = 'ok'; our $expand = $self->{result_values}->{expand}; if (defined($self->{result_values}->{config}->{critical}) && $self->{result_values}->{config}->{critical} && $self->{instance_mode}->{safe}->reval($self->{result_values}->{config}->{critical})) { $status = 'critical'; } elsif (defined($self->{result_values}->{config}->{warning}) && $self->{result_values}->{config}->{warning} ne '' && $self->{instance_mode}->{safe}->reval($self->{result_values}->{config}->{warning})) { $status = 'warning'; } elsif (defined($self->{result_values}->{config}->{unknown}) && $self->{result_values}->{config}->{unknown} && $self->{instance_mode}->reval($self->{result_values}->{config}->{unknown})) { $status = 'unknown'; } if ($@) { $self->{output}->add_option_msg(short_msg => 'Unsafe code evaluation: ' . $@); $self->{output}->option_exit(); } $self->{result_values}->{last_status} = $status; return $status; } sub custom_select_perfdata { my ($self, %options) = @_; return if (!defined($self->{result_values}->{config}->{perfdatas})); foreach (@{$self->{result_values}->{config}->{perfdatas}}) { next if (!defined($_->{value}) || $_->{value} !~ /^\d+(?:\.\d+)?$/); $self->{output}->perfdata_add(%$_); } } sub custom_select_output { my ($self, %options) = @_; return '' if ( $self->{result_values}->{last_status} eq 'ok' && defined($self->{result_values}->{config}->{formatting}) && defined($self->{result_values}->{config}->{formatting}->{display_ok}) && $self->{result_values}->{config}->{formatting}->{display_ok} =~ /^false|0$/ ); my $format; if (defined($self->{result_values}->{config}->{ 'formatting_' . $self->{result_values}->{last_status} })) { $format = $self->{result_values}->{config}->{ 'formatting_' . $self->{result_values}->{last_status} }; } elsif (defined($self->{result_values}->{config}->{formatting})) { $format = $self->{result_values}->{config}->{formatting}; } if (defined($format)) { return sprintf( $format->{printf_msg}, @{$format->{printf_var}} ); } # without formatting: [name: xxxxxx][test: xxxx][test2: xxx][mytable.plcRead: xxx][mytable.plcWrite: xxx] my $output = ''; foreach (sort keys %{$self->{result_values}->{expand}}) { next if (/^(?:constants|builtin)\./); $output .= '[' . $_ . ': ' . (defined($self->{result_values}->{expand}->{$_}) ? $self->{result_values}->{expand}->{$_} : '') . ']'; } return $output; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'selections', type => 1, message_multiple => 'All selections are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{selections} = [ { label => 'select', threshold => 0, set => { key_values => [ { name => 'expand' }, { name => 'config' } ], closure_custom_output => $self->can('custom_select_output'), closure_custom_perfdata => $self->can('custom_select_perfdata'), closure_custom_threshold_check => $self->can('custom_select_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 => { 'config:s' => { name => 'config' }, 'filter-selection:s%' => { name => 'filter_selection' }, 'constant:s%' => { name => 'constant' } }); $self->{safe} = Safe->new(); $self->{safe}->share('$expand'); $self->{safe_func} = Safe->new(); $self->{safe_func}->share('$assign_var'); $self->{builtin} = {}; $self->{sql_cache} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{config})) { $self->{output}->add_option_msg(short_msg => 'Please set config option'); $self->{output}->option_exit(); } $self->{sql_cache}->check_options(option_results => $self->{option_results}); } sub read_config { my ($self, %options) = @_; my $content; if ($self->{option_results}->{config} =~ /\n/m || ! -f "$self->{option_results}->{config}") { $content = $self->{option_results}->{config}; } else { $content = do { local $/ = undef; if (!open my $fh, '<', $self->{option_results}->{config}) { $self->{output}->add_option_msg(short_msg => "Could not open file $self->{option_results}->{config} : $!"); $self->{output}->option_exit(); } <$fh>; }; } eval { $self->{config} = JSON::XS->new->decode($content); }; if ($@) { $self->{output}->output_add(long_msg => "json config error: $@", debug => 1); $self->{output}->add_option_msg(short_msg => 'Cannot decode json config'); $self->{output}->option_exit(); } } sub get_map_value { my ($self, %options) = @_; return undef if ( !defined($self->{config}->{mapping}) || !defined($self->{config}->{mapping}->{ $options{map} }) ); return '' if (!defined($self->{config}->{mapping}->{ $options{map} }->{ $options{value} })); return $self->{config}->{mapping}->{ $options{map} }->{ $options{value} }; } 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}->option_exit(); } if ($options{name} !~ /^[a-zA-Z0-9_]+$/) { $self->{output}->add_option_msg(short_msg => 'incorrect name attribute: ' . $options{name}); $self->{output}->option_exit(); } } sub collect_sql_tables { my ($self, %options) = @_; return if (!defined($self->{config}->{sql}->{tables})); foreach my $table (@{$self->{config}->{sql}->{tables}}) { $self->validate_name(name => $table->{name}, section => "[sql > tables]"); if (!defined($table->{query}) || $table->{query} eq '') { $self->{output}->add_option_msg(short_msg => "query attribute is missing [sql > tables > $table->{name}]"); $self->{output}->option_exit(); } # substitute constants $self->{expand} = $self->set_constants(); $table->{query} = $self->substitute_string(value => $table->{query}); my $timing0 = [gettimeofday]; $options{sql}->query(query => $table->{query}); $self->add_builtin(name => 'sqlExecutionTime.' . $table->{name}, value => tv_interval($timing0, [gettimeofday])); $self->{sql_collected}->{tables}->{ $table->{name} } = {}; my $i = 0; while (my $entry = $options{sql}->fetchrow_hashref()) { my $instance = $i; if (defined($table->{instances})) { $instance = ''; my $append = ''; foreach (@{$table->{instances}}) { if (!defined($entry->{$_})) { $self->{output}->add_option_msg(short_msg => "cannot get instance '$_' in result [sql > tables > $table->{name}]"); $self->{output}->option_exit(); } $instance .= $append . $entry->{$_}; $append = ':'; } } if (defined($table->{entries})) { foreach (@{$table->{entries}}) { if (!defined($_->{id}) || !defined($entry->{ $_->{id} })) { $self->{output}->add_option_msg(short_msg => "id attribute is missing or wrong [sql > tables > $table->{name} > entries]"); $self->{output}->option_exit(); } if (defined($_->{map}) && $_->{map} ne '') { if (!defined($self->{config}->{mapping}) || !defined($self->{config}->{mapping}->{ $_->{map} })) { $self->{output}->add_option_msg(short_msg => "unknown map attribute [sql > tables > $table->{name} > $_->{id}]: $_->{map}"); $self->{output}->option_exit(); } $entry->{ $_->{id} } = $self->{config}->{mapping}->{ $_->{map} }->{ $entry->{ $_->{id} } }; } if (defined($_->{sampling}) && $_->{sampling} == 1) { $self->{sql_collected_sampling}->{tables}->{ $table->{name} } = {} if (!defined($self->{sql_collected_sampling}->{tables}->{ $table->{name} })); $self->{sql_collected_sampling}->{tables}->{ $table->{name} }->{$instance}->{ $_->{id} } = $entry->{ $_->{id} }; } } } $self->{sql_collected}->{tables}->{ $table->{name} }->{$instance} = $entry; $i++; } } } sub is_sql_cache_enabled { my ($self, %options) = @_; return 0 if ( !defined($self->{config}->{sql}->{cache}) || !defined($self->{config}->{sql}->{cache}->{enable}) || $self->{config}->{sql}->{cache}->{enable} !~ /^true|1$/i ); return 1; } sub use_sql_cache { my ($self, %options) = @_; return 0 if ($self->is_sql_cache_enabled() == 0); my $has_cache_file = $self->{sql_cache}->read( statefile => 'cache_sql_collection_' . $options{sql}->get_unique_id4save() . '_' . md5_hex($self->{option_results}->{config}) ); $self->{sql_collected} = $self->{sql_cache}->get(name => 'sql_collected'); my $reload = defined($self->{config}->{sql}->{cache}->{reload}) && $self->{config}->{sql}->{cache}->{reload} =~ /(\d+)/ ? $self->{config}->{sql}->{cache}->{reload} : 30; return 0 if ( $has_cache_file == 0 || !defined($self->{sql_collected}) || ((time() - $self->{sql_collected}->{epoch}) > ($reload * 60)) ); return 1; } sub save_sql_cache { my ($self, %options) = @_; return 0 if ($self->is_sql_cache_enabled() == 0); $self->{sql_cache}->write(data => { sql_collected => $self->{sql_collected} }); } sub collect_sql_sampling { my ($self, %options) = @_; return if ($self->{sql_collected}->{sampling} == 0); my $has_cache_file = $self->{sql_cache}->read( statefile => 'cache_sql_collection_sampling_' . $options{sql}->get_unique_id4save() . '_' . md5_hex($self->{option_results}->{config}) ); my $sql_collected_sampling_old = $self->{sql_cache}->get(name => 'sql_collected_sampling'); # with cache, we need to load the sampling cache maybe. please a statefile-suffix to get uniq files. # sampling with a global cache can be a nonsense if (!defined($self->{sql_collected_sampling})) { $self->{sql_collected_sampling} = $sql_collected_sampling_old; } my $delta_time; if (defined($sql_collected_sampling_old->{epoch})) { $delta_time = $self->{sql_collected_sampling}->{epoch} - $sql_collected_sampling_old->{epoch}; $delta_time = 1 if ($delta_time <= 0); } foreach my $tbl_name (keys %{$self->{sql_collected_sampling}->{tables}}) { foreach my $instance (keys %{$self->{sql_collected_sampling}->{tables}->{$tbl_name}}) { foreach my $attr (keys %{$self->{sql_collected_sampling}->{tables}->{$tbl_name}->{$instance}}) { next if ( !defined($sql_collected_sampling_old->{tables}->{$tbl_name}) || !defined($sql_collected_sampling_old->{tables}->{$tbl_name}->{$instance}) || !defined($sql_collected_sampling_old->{tables}->{$tbl_name}->{$instance}->{$attr}) || $sql_collected_sampling_old->{tables}->{$tbl_name}->{$instance}->{$attr} !~ /\d/ ); my $old = $sql_collected_sampling_old->{tables}->{$tbl_name}->{$instance}->{$attr}; my $diff = $self->{sql_collected_sampling}->{tables}->{$tbl_name}->{$instance}->{$attr} - $old; my $diff_counter = $diff; $diff_counter = $self->{sql_collected_sampling}->{tables}->{$tbl_name}->{$instance}->{$attr} if ($diff_counter < 0); $self->{sql_collected}->{tables}->{$tbl_name}->{$instance}->{ $attr . 'Diff' } = $diff; $self->{sql_collected}->{tables}->{$tbl_name}->{$instance}->{ $attr . 'DiffCounter' } = $diff_counter; if (defined($delta_time)) { $self->{sql_collected}->{tables}->{$tbl_name}->{$instance}->{ $attr . 'PerSeconds' } = $diff_counter / $delta_time; $self->{sql_collected}->{tables}->{$tbl_name}->{$instance}->{ $attr . 'PerMinutes' } = $diff_counter / $delta_time / 60; } } } } $self->{sql_cache}->write(data => { sql_collected_sampling => $self->{sql_collected_sampling} }); } sub collect_sql { my ($self, %options) = @_; if (!defined($self->{config}->{sql})) { $self->{output}->add_option_msg(short_msg => 'please set sql config'); $self->{output}->option_exit(); } $self->add_builtin(name => 'currentTime', value => time()); if ($self->use_sql_cache(sql => $options{sql}) == 0) { $self->{sql_collected_sampling} = { tables => {}, epoch => time() }; $self->{sql_collected} = { tables => {}, epoch => time(), sampling => 0 }; $options{sql}->connect(); $self->collect_sql_tables(sql => $options{sql}); $self->{sql_collected}->{sampling} = 1 if ( scalar(keys(%{$self->{sql_collected_sampling}->{tables}})) > 0 ); $self->save_sql_cache(); } $self->collect_sql_sampling(sql => $options{sql}); } sub exist_table_name { my ($self, %options) = @_; return 1 if (defined($self->{sql_collected}->{tables}->{ $options{name} })); return 0; } sub get_local_variable { my ($self, %options) = @_; return $self->{expand}->{ $options{name} }; } sub set_local_variable { my ($self, %options) = @_; $self->{expand}->{ $options{name} } = $options{value}; } sub get_table { my ($self, %options) = @_; return undef if ( !defined($self->{sql_collected}->{tables}->{ $options{table} }) ); return $self->{sql_collected}->{tables}->{ $options{table} }; } sub get_table_instance { my ($self, %options) = @_; return undef if ( !defined($self->{sql_collected}->{tables}->{ $options{table} }) || !defined($self->{sql_collected}->{tables}->{ $options{table} }->{ $options{instance} }) ); return $self->{sql_collected}->{tables}->{ $options{table} }->{ $options{instance} }; } sub get_table_attribute_value { my ($self, %options) = @_; return undef if ( !defined($self->{sql_collected}->{tables}->{ $options{table} }) || !defined($self->{sql_collected}->{tables}->{ $options{table} }->{ $options{instance} }) || !defined($self->{sql_collected}->{tables}->{ $options{table} }->{ $options{instance} }->{ $options{attribute} }) ); return $self->{sql_collected}->{tables}->{ $options{table} }->{ $options{instance} }->{ $options{attribute} }; } sub set_table_attribute_value { my ($self, %options) = @_; $self->{sql_collected}->{tables}->{ $options{table} } = {} if (!defined($self->{sql_collected}->{tables}->{ $options{table} })); $self->{sql_collected}->{tables}->{ $options{table} } = {} if (!defined($self->{sql_collected}->{tables}->{ $options{table} }->{ $options{instance} })); $self->{sql_collected}->{tables}->{ $options{table} }->{ $options{instance} }->{ $options{attribute} } = $options{value}; } sub get_special_variable_value { my ($self, %options) = @_; my $data; if ($options{type} == 0) { $data = $self->get_local_variable(name => $options{label}); } elsif ($options{type} == 2) { $data = $self->get_table(table => $options{table}); } elsif ($options{type} == 4) { $data = $self->get_table_attribute_value( table => $options{table}, instance => $options{instance}, attribute => $options{label} ); } return $data; } sub set_special_variable_value { my ($self, %options) = @_; my $data; if ($options{type} == 0) { $data = $self->set_local_variable(name => $options{label}, value => $options{value}); } elsif ($options{type} == 4) { $data = $self->set_table_attribute_value( table => $options{table}, instance => $options{instance}, attribute => $options{label}, value => $options{value} ); } return $data; } sub strcmp { my ($self, %options) = @_; my @cmp = split //, $options{test}; for (my $i = 0; $i < scalar(@cmp); $i++) { return 0 if ( !defined($options{chars}->[ $options{start} + $i ]) || $options{chars}->[ $options{start} + $i ] ne $cmp[$i] ); } return 1; } sub parse_forward { my ($self, %options) = @_; my ($string, $i) = ('', 0); while (1) { return (1, 'cannot find ' . $options{stop} . ' character') if (!defined($options{chars}->[ $options{start} + $i ])); last if ($options{chars}->[ $options{start} + $i ] =~ /$options{stop}/); return (1, "character '" . $options{chars}->[ $options{start} + $i ] . "' forbidden") if ($options{chars}->[ $options{start} + $i ] !~ /$options{allowed}/); $string .= $options{chars}->[ $options{start} + $i ]; $i++; } return (0, undef, $options{start} + $i, $string); } =pod managed variables: %(sql.tables.servers) %(sql.tables.servers.[1]) %(sql.tables.servers.[1].plop) %(sql.tables.servers.[%(mytable.instance)] %(sql.tables.servers.[%(sql.tables.servers.[%(mytable.instance)].name)] %(test2) %(mytable.test) result: - type: 0=%(test) (label) 2=%(sql.tables.test) 3=%(sql.tables.test.[2]) 4=%(sql.tables.test.[2].attrname) =cut sub parse_sql_tables { my ($self, %options) = @_; my ($code, $msg_error, $end, $table_label, $instance_label, $label); ($code, $msg_error, $end, $table_label) = $self->parse_forward( chars => $options{chars}, start => $options{start}, allowed => '[a-zA-Z0-9_]', stop => '[).]' ); if ($code) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " $msg_error"); $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'"); $self->{output}->option_exit(); } if ($options{chars}->[$end] eq ')') { return { type => 2, end => $end, table => $table_label }; } # instance part managenent if (!defined($options{chars}->[$end + 1]) || $options{chars}->[$end + 1] ne '[') { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable sql.tables character '[' mandatory"); $self->{output}->option_exit(); } if ($self->strcmp(chars => $options{chars}, start => $end + 2, test => '%(')) { my $result = $self->parse_special_variable(chars => $options{chars}, start => $end + 2); # type allowed: 0,4 if ($result->{type} !~ /^(?:0|4)$/) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . ' special variable type not allowed'); $self->{output}->option_exit(); } $end = $result->{end} + 1; if ($result->{type} == 0) { $instance_label = $self->get_local_variable(name => $result->{label}); } elsif ($result->{type} == 4) { $instance_label = $self->get_table_attribute_value( table => $result->{table}, instance => $result->{instance}, attribute => $result->{label} ); } $instance_label = defined($instance_label) ? $instance_label : ''; } else { ($code, $msg_error, $end, $instance_label) = $self->parse_forward( chars => $options{chars}, start => $end + 2, allowed => '[^\]]', stop => '[\]]' ); if ($code) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " $msg_error"); $self->{output}->option_exit(); } } if (!defined($options{chars}->[$end + 1]) || $options{chars}->[$end + 1] !~ /[.)]/) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . ' special variable sql.tables character [.)] missing'); $self->{output}->option_exit(); } if ($options{chars}->[$end + 1] eq ')') { return { type => 3, end => $end + 1, table => $table_label, instance => $instance_label }; } ($code, $msg_error, $end, $label) = $self->parse_forward( chars => $options{chars}, start => $end + 2, allowed => '[a-zA-Z0-9_]', stop => '[)]' ); if ($code) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " $msg_error"); $self->{output}->option_exit(); } return { type => 4, end => $end, table => $table_label, instance => $instance_label, label => $label }; } sub parse_sql_type { my ($self, %options) = @_; if ($self->strcmp(chars => $options{chars}, start => $options{start}, test => 'tables.')) { return $self->parse_sql_tables(chars => $options{chars}, start => $options{start} + 7); } else { $self->{output}->add_option_msg(short_msg => $self->{current_section} . ' special variable sql not followed by tables'); $self->{output}->option_exit(); } } sub parse_special_variable { my ($self, %options) = @_; my $start = $options{start}; if ($options{chars}->[$start] ne '%' || $options{chars}->[$start + 1] ne '(') { $self->{output}->add_option_msg(short_msg => $self->{current_section} . ' special variable not starting by %('); $self->{output}->option_exit(); } my $result = { start => $options{start} }; if ($self->strcmp(chars => $options{chars}, start => $start + 2, test => 'sql.')) { my $parse = $self->parse_sql_type(chars => $options{chars}, start => $start + 2 + 4); $result = { %$parse, %$result }; } else { my ($code, $msg_error, $end, $label) = $self->parse_forward( chars => $options{chars}, start => $start + 2, allowed => '[a-zA-Z0-9\._]', stop => '[)]' ); if ($code) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " $msg_error"); $self->{output}->option_exit(); } $result->{end} = $end; $result->{type} = 0; $result->{label} = $label; } return $result; } sub substitute_string { my ($self, %options) = @_; my $arr = [split //, $options{value}]; my $results = {}; my $last_end = -1; while ($options{value} =~ /\Q%(\E/g) { next if ($-[0] < $last_end); my $result = $self->parse_special_variable(chars => $arr, start => $-[0]); if ($result->{type} !~ /^(?:0|4)$/) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed"); $self->{output}->option_exit(); } $last_end = $result->{end}; $results->{ $result->{start} } = $result; } my $end = -1; my $str = ''; for (my $i = 0; $i < scalar(@$arr); $i++) { next if ($i <= $end); if (defined($results->{$i})) { my $data = $self->get_special_variable_value(%{$results->{$i}}); $end = $results->{$i}->{end}; $str .= defined($data) ? $data : ''; } else { $str .= $arr->[$i]; } } return $str; } sub add_builtin { my ($self, %options) = @_; $self->{builtin}->{ $options{name} } = $options{value}; } sub set_builtin { my ($self, %options) = @_; foreach (keys %{$self->{builtin}}) { $self->{expand}->{ 'builtin.' . $_ } = $self->{builtin}->{$_}; } } sub set_constants { my ($self, %options) = @_; my $constants = {}; if (defined($self->{config}->{constants})) { foreach (keys %{$self->{config}->{constants}}) { $constants->{'constants.' . $_} = $self->{config}->{constants}->{$_}; } } foreach (keys %{$self->{option_results}->{constant}}) { $constants->{'constants.' . $_} = $self->{option_results}->{constant}->{$_}; } return $constants; } sub set_expand_table { my ($self, %options) = @_; return if (!defined($options{expand})); foreach my $name (keys %{$options{expand}}) { $self->{current_section} = '[' . $options{section} . ' > ' . $name . ']'; my $result = $self->parse_special_variable(chars => [split //, $options{expand}->{$name}], start => 0); if ($result->{type} != 3) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed"); $self->{output}->option_exit(); } my $table = $self->get_table_instance(table => $result->{table}, instance => $result->{instance}); next if (!defined($table)); $self->{expand}->{ $name . '.instance' } = $result->{instance}; foreach (keys %$table) { $self->{expand}->{ $name . '.' . $_ } = $table->{$_}; } } } sub set_expand { my ($self, %options) = @_; return if (!defined($options{expand})); foreach my $name (keys %{$options{expand}}) { $self->{current_section} = '[' . $options{section} . ' > ' . $name . ']'; $self->{expand}->{$name} = $self->substitute_string(value => $options{expand}->{$name}); } } sub exec_func_map { my ($self, %options) = @_; if (!defined($options{map_name}) || $options{map_name} eq '') { $self->{output}->add_option_msg(short_msg => "$self->{current_section} please set map_name attribute"); $self->{output}->option_exit(); } if (!defined($options{src}) || $options{src} eq '') { $self->{output}->add_option_msg(short_msg => "$self->{current_section} please set src attribute"); $self->{output}->option_exit(); } my $result = $self->parse_special_variable(chars => [split //, $options{src}], start => 0); if ($result->{type} !~ /^(?:0|1|4)$/) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed in src attribute"); $self->{output}->option_exit(); } my $data = $self->get_special_variable_value(%$result); my $value = $self->get_map_value(value => $data, map => $options{map_name}); if (!defined($value)) { $self->{output}->add_option_msg(short_msg => "$self->{current_section} unknown map attribute: $options{map_name}"); $self->{output}->option_exit(); } my $save = $result; if (defined($options{save}) && $options{save} ne '') { $save = $self->parse_special_variable(chars => [split //, $options{save}], start => 0); if ($save->{type} !~ /^(?:0|1|4)$/) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed in save attribute"); $self->{output}->option_exit(); } } elsif (defined($options{dst}) && $options{dst} ne '') { $save = $self->parse_special_variable(chars => [split //, $options{dst}], start => 0); if ($save->{type} !~ /^(?:0|1|4)$/) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed in dst attribute"); $self->{output}->option_exit(); } } $self->set_special_variable_value(value => $value, %$save); } sub scale { my ($self, %options) = @_; my ($src_quantity, $src_unit) = (undef, 'B'); if ($options{src_unit} =~ /([kmgtpe])?(b)/i) { $src_quantity = $1; $src_unit = $2; } my ($dst_quantity, $dst_unit) = ('auto', $src_unit); if ($options{dst_unit} =~ /([kmgtpe])?(b)/i) { $dst_quantity = $1; $dst_unit = $2; } my $base = 1024; $options{value} *= 8 if ($dst_unit eq 'b' && $src_unit eq 'B'); $options{value} /= 8 if ($dst_unit eq 'B' && $src_unit eq 'b'); $base = 1000 if ($dst_unit eq 'b'); my %expo = (k => 1, m => 2, g => 3, t => 4, p => 5, e => 6); my $src_expo = 0; $src_expo = $expo{ lc($src_quantity) } if (defined($src_quantity)); if (defined($dst_quantity) && $dst_quantity eq 'auto') { my @auto = ('', 'k', 'm', 'g', 't', 'p', 'e'); for (; $src_expo < scalar(@auto); $src_expo++) { last if ($options{value} < $base); $options{value} = $options{value} / $base; } return ($options{value}, uc($auto[$src_expo]) . $dst_unit); } my $dst_expo = 0; $dst_expo = $expo{ lc($dst_quantity) } if (defined($dst_quantity)); if ($dst_expo - $src_expo > 0) { $options{value} = $options{value} / ($base ** ($dst_expo - $src_expo)); } elsif ($dst_expo - $src_expo < 0) { $options{value} = $options{value} * ($base ** (($dst_expo - $src_expo) * -1)); } return ($options{value}, $options{dst_unit}); } sub exec_func_scale { my ($self, %options) = @_; #{ # "type": "scale", # "src": "%(memoryUsed)", # "src_unit": "KB", (default: 'B') # "dst_unit": "auto", (default: 'auto') # "save_value": "%(memoryUsedScaled)", # "save_unit": "%(memoryUsedUnit)" #} if (!defined($options{src}) || $options{src} eq '') { $self->{output}->add_option_msg(short_msg => "$self->{current_section} please set src attribute"); $self->{output}->option_exit(); } my $result = $self->parse_special_variable(chars => [split //, $options{src}], start => 0); if ($result->{type} !~ /^(?:0|4)$/) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed in src attribute"); $self->{output}->option_exit(); } my $data = $self->get_special_variable_value(%$result); my ($save_value, $save_unit) = $self->scale( value => $data, src_unit => $options{src_unit}, dst_unit => $options{dst_unit} ); if (defined($options{save_value}) && $options{save_value} ne '') { my $var_save_value = $self->parse_special_variable(chars => [split //, $options{save_value}], start => 0); if ($var_save_value->{type} !~ /^(?:0|4)$/) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed in save_value attribute"); $self->{output}->option_exit(); } $self->set_special_variable_value(value => $save_value, %$var_save_value); } if (defined($options{save_unit}) && $options{save_unit} ne '') { my $var_save_unit = $self->parse_special_variable(chars => [split //, $options{save_unit}], start => 0); if ($var_save_unit->{type} !~ /^(?:0|4)$/) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed in save_value attribute"); $self->{output}->option_exit(); } $self->set_special_variable_value(value => $save_unit, %$var_save_unit); } } sub exec_func_date2epoch { my ($self, %options) = @_; if (!defined($self->{module_datetime_loaded})) { centreon::plugins::misc::mymodule_load( module => 'DateTime', error_msg => "Cannot load module 'DateTime'." ); $self->{module_datetime_loaded} = 1; } #{ # "type": "date2epoch", # "src": "%(dateTest2)", # "format_custom": "(\\d+)-(\\d+)-(\\d+)", # "year": 1, # "month": 2, # "day": 3, # "timezone": "Europe/Paris", # "save_epoch": "%(plopDateEpoch)", # "save_diff1": "%(plopDateDiff1)", # "save_diff2": "%(plopDateDiff2)" #} if (!defined($options{src}) || $options{src} eq '') { $self->{output}->add_option_msg(short_msg => "$self->{current_section} please set src attribute"); $self->{output}->option_exit(); } my $result = $self->parse_special_variable(chars => [split //, $options{src}], start => 0); if ($result->{type} !~ /^(?:0|1|4)$/) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed in src attribute"); $self->{output}->option_exit(); } my $data = $self->get_special_variable_value(%$result); my $tz = {}; $tz->{time_zone} = $options{timezone} if (defined($options{timezone}) && $options{timezone} ne ''); my $dt; if (defined($options{format_custom}) && $options{format_custom} ne '') { my @matches = ($data =~ /$options{format_custom}/); my $date = {}; foreach (('year', 'month', 'day', 'hour', 'minute', 'second')) { $date->{$_} = $matches[ $options{$_} -1 ] if (defined($options{$_}) && $options{$_} =~ /^\d+$/ && defined($matches[ $options{$_} -1 ])); } foreach (('year', 'month', 'day')) { if (!defined($date->{$_})) { $self->{output}->add_option_msg(short_msg => "$self->{current_section} cannot find $_ attribute"); $self->{output}->option_exit(); } } $dt = DateTime->new(%$date, %$tz); } else { $self->{output}->add_option_msg(short_msg => "$self->{current_section} please set format_custom attribute"); $self->{output}->option_exit(); } my $results = { epoch => $dt->epoch(), diff1 => time() - $dt->epoch(), diff2 => $dt->epoch() - time() }; foreach (keys %$results) { my $attr = '%(' . $result->{label} . ucfirst($_) . ')'; $attr = $options{'save_' . $_} if (defined($options{'save_' . $_}) && $options{'save_' . $_} ne ''); my $var_save_value = $self->parse_special_variable(chars => [split //, $attr], start => 0); if ($var_save_value->{type} !~ /^(?:0|4)$/) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed in save_$_ attribute"); $self->{output}->option_exit(); } $self->set_special_variable_value(value => $results->{$_}, %$var_save_value); } } sub exec_func_epoch2date { my ($self, %options) = @_; if (!defined($self->{module_datetime_loaded})) { centreon::plugins::misc::mymodule_load( module => 'DateTime', error_msg => "Cannot load module 'DateTime'." ); $self->{module_datetime_loaded} = 1; } #{ # "type": "epoch2date", # "src": "%(dateTestEpoch)", # "format": "%a %b %e %H:%M:%S %Y", # "timezone": "Asia/Tokyo", # "locale": "fr", # "save": "%(dateTestReformat)" #} if (!defined($options{src}) || $options{src} eq '') { $self->{output}->add_option_msg(short_msg => "$self->{current_section} please set src attribute"); $self->{output}->option_exit(); } my $result = $self->parse_special_variable(chars => [split //, $options{src}], start => 0); if ($result->{type} !~ /^(?:0|4)$/) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed in src attribute"); $self->{output}->option_exit(); } my $data = $self->get_special_variable_value(%$result); my $extras = {}; $extras->{time_zone} = $options{timezone} if (defined($options{timezone}) && $options{timezone} ne ''); $extras->{locale} = $options{locale} if (defined($options{locale}) && $options{locale} ne ''); my $dt = DateTime->from_epoch( epoch => $data, %$extras ); my $time_value = $dt->strftime($options{format}); if (defined($options{save}) && $options{save} ne '') { my $var_save_value = $self->parse_special_variable(chars => [split //, $options{save}], start => 0); if ($var_save_value->{type} !~ /^(?:0|4)$/) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed in save attribute"); $self->{output}->option_exit(); } $self->set_special_variable_value(value => $time_value, %$var_save_value); } } sub exec_func_count { my ($self, %options) = @_; #{ # "type": "count", # "src": "%(sql.tables.test)", # "save": "%(testCount)" #} if (!defined($options{src}) || $options{src} eq '') { $self->{output}->add_option_msg(short_msg => "$self->{current_section} please set src attribute"); $self->{output}->option_exit(); } my $result = $self->parse_special_variable(chars => [split //, $options{src}], start => 0); if ($result->{type} !~ /^2$/) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed in src attribute"); $self->{output}->option_exit(); } my $data = $self->get_special_variable_value(%$result); my $value = 0; if (defined($data)) { $value = scalar(keys %$data); } if (defined($options{save}) && $options{save} ne '') { my $save = $self->parse_special_variable(chars => [split //, $options{save}], start => 0); if ($save->{type} !~ /^(?:0|4)$/) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed in save attribute"); $self->{output}->option_exit(); } $self->set_special_variable_value(value => $value, %$save); } } sub exec_func_replace { my ($self, %options) = @_; #{ # "type": "replace", # "src": "%(sql.tables.test)", # "expression": "s/name/name is/" #} if (!defined($options{src}) || $options{src} eq '') { $self->{output}->add_option_msg(short_msg => "$self->{current_section} please set src attribute"); $self->{output}->option_exit(); } if (!defined($options{expression}) || $options{expression} eq '') { $self->{output}->add_option_msg(short_msg => "$self->{current_section} please set expression attribute"); $self->{output}->option_exit(); } my $result = $self->parse_special_variable(chars => [split //, $options{src}], start => 0); if ($result->{type} !~ /^(?:0|4)$/) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed in src attribute"); $self->{output}->option_exit(); } my $data = $self->get_special_variable_value(%$result); if (defined($data)) { my $expression = $self->substitute_string(value => $options{expression}); our $assign_var = $data; $self->{safe_func}->reval("\$assign_var =~ $expression", 1); if ($@) { die 'Unsafe code evaluation: ' . $@; } $self->set_special_variable_value(value => $assign_var, %$result); } } sub exec_func_assign { my ($self, %options) = @_; #{ # "type": "assign", # "save": "%(sql.tables.test)", # "expression": "'%(sql.tables.test)' . 'toto'" #} if (!defined($options{save}) || $options{save} eq '') { $self->{output}->add_option_msg(short_msg => "$self->{current_section} please set save attribute"); $self->{output}->option_exit(); } if (!defined($options{expression}) || $options{expression} eq '') { $self->{output}->add_option_msg(short_msg => "$self->{current_section} please set expression attribute"); $self->{output}->option_exit(); } my $result = $self->parse_special_variable(chars => [split //, $options{save}], start => 0); if ($result->{type} !~ /^(?:0|4)$/) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed in src attribute"); $self->{output}->option_exit(); } my $expression = $self->substitute_string(value => $options{expression}); our $assign_var; $self->{safe_func}->reval("\$assign_var = $expression", 1); if ($@) { die 'Unsafe code evaluation: ' . $@; } $self->set_special_variable_value(value => $assign_var, %$result); } sub set_functions { my ($self, %options) = @_; return if (!defined($options{functions})); my $i = -1; foreach (@{$options{functions}}) { $i++; $self->{current_section} = '[' . $options{section} . ' > ' . $i . ']'; next if (defined($_->{position}) && $options{position} ne $_->{position}); next if (!defined($_->{position}) && !(defined($options{default}) && $options{default} == 1)); next if (!defined($_->{type})); if ($_->{type} eq 'map') { $self->exec_func_map(%$_); } elsif ($_->{type} eq 'scale') { $self->exec_func_scale(%$_); } elsif (lc($_->{type}) eq 'date2epoch') { $self->exec_func_date2epoch(%$_); } elsif (lc($_->{type}) eq 'epoch2date') { $self->exec_func_epoch2date(%$_); } elsif (lc($_->{type}) eq 'count') { $self->exec_func_count(%$_); } elsif (lc($_->{type}) eq 'replace') { $self->exec_func_replace(%$_); } elsif (lc($_->{type}) eq 'assign') { $self->exec_func_assign(%$_); } } } sub prepare_variables { my ($self, %options) = @_; return undef if (!defined($options{value})); $options{value} =~ s/%\(([a-zA-Z0-9\._:]+?)\)/\$expand->{'$1'}/g; return $options{value}; } sub check_filter { my ($self, %options) = @_; return 0 if (!defined($options{filter}) || $options{filter} eq ''); our $expand = $self->{expand}; $options{filter} =~ s/%\(([a-zA-Z0-9\._:]+?)\)/\$expand->{'$1'}/g; my $result = $self->{safe}->reval("$options{filter}"); if ($@) { $self->{output}->add_option_msg(short_msg => 'Unsafe code evaluation: ' . $@); $self->{output}->option_exit(); } return 0 if ($result); return 1; } sub check_filter_option { my ($self, %options) = @_; foreach (keys %{$self->{option_results}->{filter_selection}}) { return 1 if ( defined($self->{expand}->{$_}) && $self->{option_results}->{filter_selection}->{$_} ne '' && $self->{expand}->{$_} !~ /$self->{option_results}->{filter_selection}->{$_}/ ); } return 0; } sub prepare_perfdatas { my ($self, %options) = @_; return undef if (!defined($options{perfdatas})); my $perfdatas = []; foreach (@{$options{perfdatas}}) { next if (!defined($_->{nlabel}) || $_->{nlabel} eq ''); next if (!defined($_->{value}) || $_->{value} eq ''); my $perf = {}; $perf->{nlabel} = $self->substitute_string(value => $_->{nlabel}); $perf->{value} = $self->substitute_string(value => $_->{value}); foreach my $label (('warning', 'critical', 'min', 'max', 'unit')) { next if (!defined($_->{$label})); $perf->{$label} = $self->substitute_string(value => $_->{$label}); } if (defined($_->{instances})) { $perf->{instances} = []; foreach my $instance (@{$_->{instances}}) { push @{$perf->{instances}}, $self->substitute_string(value => $instance); } } push @$perfdatas, $perf; } return $perfdatas; } sub prepare_formatting { my ($self, %options) = @_; return undef if (!defined($options{formatting})); my $format = {}; $format->{printf_msg} = $options{formatting}->{printf_msg}; $format->{display_ok} = $options{formatting}->{display_ok}; if (defined($options{formatting}->{printf_var})) { $format->{printf_var} = []; foreach my $var (@{$options{formatting}->{printf_var}}) { push @{$format->{printf_var}}, $self->substitute_string(value => $var); } } return $format } sub add_selection { my ($self, %options) = @_; return if (!defined($self->{config}->{selection})); my $i = -1; foreach (@{$self->{config}->{selection}}) { $i++; my $config = {}; $self->{expand} = $self->set_constants(); $self->set_builtin(); $self->{expand}->{name} = $_->{name} if (defined($_->{name})); $self->set_functions(section => "selection > $i > functions", functions => $_->{functions}, position => 'before_expand'); $self->set_expand_table(section => "selection > $i > expand_table", expand => $_->{expand_table}); $self->set_expand(section => "selection > $i > expand", expand => $_->{expand}); $self->set_functions(section => "selection > $i > functions", functions => $_->{functions}, position => 'after_expand', default => 1); next if ($self->check_filter(filter => $_->{filter})); next if ($self->check_filter_option()); $config->{unknown} = $self->prepare_variables(section => "selection > $i > unknown", value => $_->{unknown}); $config->{warning} = $self->prepare_variables(section => "selection > $i > warning", value => $_->{warning}); $config->{critical} = $self->prepare_variables(section => "selection > $i > critical", value => $_->{critical}); $config->{perfdatas} = $self->prepare_perfdatas(section => "selection > $i > perfdatas", perfdatas => $_->{perfdatas}); $config->{formatting} = $self->prepare_formatting(section => "selection > $i > formatting", formatting => $_->{formatting}); $config->{formatting_unknown} = $self->prepare_formatting(section => "selection > $i > formatting_unknown", formatting => $_->{formatting_unknown}); $config->{formatting_warning} = $self->prepare_formatting(section => "selection > $i > formatting_warning", formatting => $_->{formatting_warning}); $config->{formatting_critical} = $self->prepare_formatting(section => "selection > $i > formatting_critical", formatting => $_->{formatting_critical}); $self->{selections}->{'s' . $i} = { expand => $self->{expand}, config => $config }; } } sub add_selection_loop { my ($self, %options) = @_; return if (!defined($self->{config}->{selection_loop})); my $i = -1; foreach (@{$self->{config}->{selection_loop}}) { $i++; next if (!defined($_->{source}) || $_->{source} eq ''); $self->{current_section} = '[selection_loop > ' . $i . ' > source]'; my $result = $self->parse_special_variable(chars => [split //, $_->{source}], start => 0); if ($result->{type} != 2) { $self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed"); $self->{output}->option_exit(); } next if (!defined($self->{sql_collected}->{tables}->{ $result->{table} })); foreach my $instance (keys %{$self->{sql_collected}->{tables}->{ $result->{table} }}) { $self->{expand} = $self->set_constants(); $self->set_builtin(); $self->{expand}->{ $result->{table} . '.instance' } = $instance; foreach my $label (keys %{$self->{sql_collected}->{tables}->{ $result->{table} }->{$instance}}) { $self->{expand}->{ $result->{table} . '.' . $label } = $self->{sql_collected}->{tables}->{ $result->{table} }->{$instance}->{$label}; } my $config = {}; $self->{expand}->{name} = $_->{name} if (defined($_->{name})); $self->set_functions(section => "selection_loop > $i > functions", functions => $_->{functions}, position => 'before_expand'); $self->set_expand_table(section => "selection_loop > $i > expand_table", expand => $_->{expand_table}); $self->set_expand(section => "selection_loop > $i > expand", expand => $_->{expand}); $self->set_functions(section => "selection_loop > $i > functions", functions => $_->{functions}, position => 'after_expand', default => 1); next if ($self->check_filter(filter => $_->{filter})); next if ($self->check_filter_option()); $config->{unknown} = $self->prepare_variables(section => "selection_loop > $i > unknown", value => $_->{unknown}); $config->{warning} = $self->prepare_variables(section => "selection_loop > $i > warning", value => $_->{warning}); $config->{critical} = $self->prepare_variables(section => "selection_loop > $i > critical", value => $_->{critical}); $config->{perfdatas} = $self->prepare_perfdatas(section => "selection_loop > $i > perfdatas", perfdatas => $_->{perfdatas}); $config->{formatting} = $self->prepare_formatting(section => "selection_loop > $i > formatting", formatting => $_->{formatting}); $config->{formatting_unknown} = $self->prepare_formatting(section => "selection_loop > $i > formatting_unknown", formatting => $_->{formatting_unknown}); $config->{formatting_warning} = $self->prepare_formatting(section => "selection_loop > $i > formatting_warning", formatting => $_->{formatting_warning}); $config->{formatting_critical} = $self->prepare_formatting(section => "selection_loop > $i > formatting_critical", formatting => $_->{formatting_critical}); $self->{selections}->{'s' . $i . '-' . $instance} = { expand => $self->{expand}, config => $config }; } } } sub set_formatting { my ($self, %options) = @_; return if (!defined($self->{config}->{formatting})); if (defined($self->{config}->{formatting}->{custom_message_global})) { $self->{maps_counters_type}->[0]->{message_multiple} = $self->{config}->{formatting}->{custom_message_global}; } if (defined($self->{config}->{formatting}->{separator})) { $self->{maps_counters_type}->[0]->{message_separator} = $self->{config}->{formatting}->{separator}; } } sub disco_format { my ($self, %options) = @_; $self->{output}->add_disco_format(elements => ['name']); } sub disco_show { my ($self, %options) = @_; $self->read_config(); $self->collect_sql(sql => $options{sql}); $self->{selections} = {}; $self->add_selection(); $self->add_selection_loop(); foreach (values %{$self->{selections}}) { my $entry = {}; foreach my $label (keys %{$_->{expand}}) { next if ($label =~ /^(?:constants|builtin)\./); my $name = $label; $name =~ s/\./_/g; $entry->{$name} = defined($_->{expand}->{$label}) ? $_->{expand}->{$label} : ''; } $self->{output}->add_disco_entry(%$entry); } } sub manage_selection { my ($self, %options) = @_; $self->read_config(); $self->collect_sql(sql => $options{sql}); $self->{selections} = {}; $self->add_selection(); $self->add_selection_loop(); $self->set_formatting(); } 1; __END__ =head1 MODE Collect and compute SQL datas. =over 8 =item B<--config> config used (Required). Can be a file or json content. =item B<--filter-selection> Filter selections. Eg: --filter-selection='name=test' =item B<--constant> Add a constant. Eg: --constant='warning=30' --constant='critical=45' =back =cut centreon-plugins-20220113/centreon/common/protocols/sql/mode/connectiontime.pm000066400000000000000000000066651417000230700275010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::protocols::sql::mode::connectiontime; use base qw(centreon::plugins::mode); use strict; use warnings; use Time::HiRes; use POSIX; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $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) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; my $now = Time::HiRes::time(); my ($exit, $msg_error) = $self->{sql}->connect(dontquit => 1); my $now2 = Time::HiRes::time(); $self->{sql}->disconnect(); if ($exit == -1) { $self->{output}->output_add( severity => 'CRITICAL', short_msg => $msg_error ); } else { my $milliseconds = $now2 - $now; $milliseconds = floor($milliseconds * 1000); my $exit_code = $self->{perfdata}->threshold_check(value => $milliseconds, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add( severity => $exit_code, short_msg => sprintf("Connection established in %.3fs.", $milliseconds / 1000) ); $self->{output}->perfdata_add( label => 'connection_time', nlabel => 'connection.time.milliseconds', value => $milliseconds, unit => 'ms', warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0 ); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check database connection time. =over 8 =item B<--warning> Threshold warning in milliseconds. =item B<--critical> Threshold critical in milliseconds. =back =cut centreon-plugins-20220113/centreon/common/protocols/sql/mode/sql.pm000066400000000000000000000116621417000230700252530ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::protocols::sql::mode::sql; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Time::HiRes qw(gettimeofday tv_interval); sub custom_value_output { my ($self, %options) = @_; return sprintf($self->{instance_mode}->{option_results}->{format}, $self->{result_values}->{value}); } sub custom_value_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{instance_mode}->{option_results}->{perfdata_name}, unit => $self->{instance_mode}->{option_results}->{perfdata_unit}, value => $self->{result_values}->{value}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}), min => $self->{instance_mode}->{option_results}->{perfdata_min}, max => $self->{instance_mode}->{option_results}->{perfdata_max} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 } ]; $self->{maps_counters}->{global} = [ { label => 'value', set => { key_values => [ { name => 'value' } ], closure_custom_output => $self->can('custom_value_output'), closure_custom_perfdata => $self->can('custom_value_perfdata') } }, { label => 'execution-time', nlabel => 'sqlrequest.execution.time.seconds', display_ok => 0, set => { key_values => [ { name => 'time' } ], output_template => 'execution time: %.3f second(s)', perfdatas => [ { template => '%.3f', min => 0, unit => 's' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'sql-statement:s' => { name => 'sql_statement' }, 'format:s' => { name => 'format', default => 'SQL statement result : %i.' }, 'perfdata-unit:s' => { name => 'perfdata_unit', default => '' }, 'perfdata-name:s' => { name => 'perfdata_name', default => 'value' }, 'perfdata-min:s' => { name => 'perfdata_min', default => '' }, 'perfdata-max:s' => { name => 'perfdata_max', default => '' }, 'warning:s' => { name => 'warning', redirect => 'warning-value' }, 'critical:s' => { name => 'critical', redirect => 'critical-value' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{sql_statement}) || $self->{option_results}->{sql_statement} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify '--sql-statement' option."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{format}) || $self->{option_results}->{format} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify '--format' option."); $self->{output}->option_exit(); } } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); my $timing0 = [gettimeofday]; $options{sql}->query(query => $self->{option_results}->{sql_statement}); my $value = $options{sql}->fetchrow_array(); $self->{global} = { value => $value, time => tv_interval($timing0, [gettimeofday]) }; $options{sql}->disconnect(); } 1; __END__ =head1 MODE Check SQL statement. =over 8 =item B<--sql-statement> SQL statement that returns a number. =item B<--format> Output format (Default: 'SQL statement result : %i.'). =item B<--perfdata-unit> Perfdata unit in perfdata output (Default: '') =item B<--perfdata-name> Perfdata name in perfdata output (Default: 'value') =item B<--perfdata-min> Minimum value to add in perfdata output (Default: '') =item B<--perfdata-max> Maximum value to add in perfdata output (Default: '') =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'value', 'execution-time'. =back =cut centreon-plugins-20220113/centreon/common/protocols/sql/mode/sqlstring.pm000066400000000000000000000140721417000230700265000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::protocols::sql::mode::sqlstring; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'rows', type => 1, message_multiple => "SQL Query is OK" }, ]; $self->{maps_counters}->{rows} = [ { label => 'string', type => 2, set => { key_values => [ { name => 'key_field' }, { name => 'value_field' } ], closure_custom_output => $self->can('custom_string_output'), closure_custom_threshold_check => \&catalog_status_threshold_ng, closure_custom_perfdata => sub { return 0; } } } ]; } sub custom_string_output { my ($self, %options) = @_; my $msg; my $message; if (defined($self->{instance_mode}->{option_results}->{printf_format}) && $self->{instance_mode}->{option_results}->{printf_format} ne '') { eval { local $SIG{__WARN__} = sub { $message = $_[0]; }; local $SIG{__DIE__} = sub { $message = $_[0]; }; $msg = sprintf("$self->{instance_mode}->{option_results}->{printf_format}", eval $self->{instance_mode}->{option_results}->{printf_value}); }; } else { $msg = sprintf("'%s'", $self->{result_values}->{value_field}); } if (defined($message)) { $self->{output}->output_add(long_msg => 'output value issue: ' . $message); } return $msg; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'sql-statement:s' => { name => 'sql_statement' }, 'key-column:s' => { name => 'key_column' }, 'value-column:s' => { name => 'value_column' }, 'printf-format:s' => { name => 'printf_format' }, 'printf-value:s' => { name => 'printf_value' }, 'dual-table' => { name => 'dual_table' }, 'empty-sql-string:s' => { name => 'empty_sql_string', default => 'No row returned or --key-column/--value-column do not correctly match selected field' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{sql_statement}) || $self->{option_results}->{sql_statement} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify '--sql-statement' option."); $self->{output}->option_exit(); } } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); $options{sql}->query(query => $self->{option_results}->{sql_statement}); $self->{rows} = {}; my $row_count = 0; while (my $row = $options{sql}->fetchrow_hashref()) { if (defined($self->{option_results}->{dual_table})) { $row->{$self->{option_results}->{value_column}} = delete $row->{keys %{$row}}; foreach (keys %{$row}) { $row->{$self->{option_results}->{value_column}} = $row->{$_}; } } if (!defined($self->{option_results}->{key_column})) { $self->{rows}->{$self->{option_results}->{value_column} . $row_count} = { key_field => $row->{ $self->{option_results}->{value_column} }, value_field => $row->{ $self->{option_results}->{value_column} } }; $row_count++; } else { $self->{rows}->{$self->{option_results}->{key_column} . $row_count} = { key_field => $row->{ $self->{option_results}->{key_column} }, value_field => $row->{ $self->{option_results}->{value_column} } }; $row_count++; } } $options{sql}->disconnect(); if (scalar(keys %{$self->{rows}}) <= 0) { $self->{output}->add_option_msg(short_msg => $self->{option_results}->{empty_sql_string}); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check SQL statement to query string pattern (You cannot have more than to fiels in select) =over 8 =item B<--sql-statement> SQL statement that returns a string. =item B<--key-column> Key column (must be one of the selected field). NOT mandatory if you select only one field =item B<--value-column> Value column (must be one of the selected field). MANDATORY =item B<--printf-format> Specify a custom output message relying on printf formatting =item B<--printf-value> Specify scalar used to replace in printf (Can be: $self->{result_values}->{key_field}, $self->{result_values}->{value_field}) =item B<--warning-string> Set warning condition (if statement syntax) for status evaluation. (Can be: %{key_field}, %{value_field}) e.g --warning-string '%{key_field} eq 'Central' && %{value_field} =~ /127.0.0.1/' =item B<--critical-string> Set critical condition (if statement syntax) for status evaluation. (Can be: %{key_field} or %{value_field}) =item B<--dual-table> Set this option to ensure compatibility with dual table and Oracle. =item B<--empty-sql-string> Set this option to change the output message when the sql statement result is empty. (Default: 'No row returned or --key-column/--value-column do not correctly match selected field') =back =cut centreon-plugins-20220113/centreon/common/protocols/ssh/000077500000000000000000000000001417000230700231625ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/protocols/ssh/custom/000077500000000000000000000000001417000230700244745ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/protocols/ssh/custom/api.pm000066400000000000000000000132521417000230700256060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::protocols::ssh::custom::api; use strict; use warnings; use Libssh::Session qw(:all); 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 => { 'hostname:s@' => { name => 'hostname' }, 'port:s@' => { name => 'port' }, 'timeout:s@' => { name => 'timeout' }, 'ssh-username:s@' => { name => 'ssh_username' }, 'ssh-password:s@' => { name => 'ssh_password' }, 'ssh-dir:s@' => { name => 'ssh_dir' }, 'ssh-identity:s@' => { name => 'ssh_identity' }, 'ssh-skip-serverkey-issue' => { name => 'ssh_skip_serverkey_issue' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'SSH OPTIONS', once => 1); $self->{output} = $options{output}; $self->{ssh} = undef; return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? shift(@{$self->{option_results}->{hostname}}) : undef; $self->{port} = (defined($self->{option_results}->{port})) ? shift(@{$self->{option_results}->{port}}) : 22; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? shift(@{$self->{option_results}->{timeout}}) : 10; $self->{ssh_username} = (defined($self->{option_results}->{ssh_username})) ? shift(@{$self->{option_results}->{ssh_username}}) : undef; $self->{ssh_password} = (defined($self->{option_results}->{ssh_password})) ? shift(@{$self->{option_results}->{ssh_password}}) : undef; $self->{ssh_dir} = (defined($self->{option_results}->{ssh_dir})) ? shift(@{$self->{option_results}->{ssh_dir}}) : undef; $self->{ssh_identity} = (defined($self->{option_results}->{ssh_identity})) ? shift(@{$self->{option_results}->{ssh_identity}}) : undef; $self->{ssh_skip_serverkey_issue} = defined($self->{option_results}->{ssh_skip_serverkey_issue}) ? 1 : 0; if (!defined($self->{hostname}) || $self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Please set option --hostname."); $self->{output}->option_exit(); } if (!defined($self->{hostname}) || scalar(@{$self->{option_results}->{hostname}}) == 0) { return 0; } return 1; } sub login { my ($self, %options) = @_; my $result = { status => 0, message => 'authentification succeeded' }; $self->{ssh} = Libssh::Session->new(); foreach (['hostname', 'host'], ['port', 'port'], ['timeout', 'timeout'], ['ssh_username', 'user'], ['ssh_dir', 'sshdir'], ['ssh_identity', 'identity']) { next if (!defined($self->{$_->[0]}) || $self->{$_->[0]} eq ''); if ($self->{ssh}->options($_->[1] => $self->{$_->[0]}) != SSH_OK) { $result->{message} = $self->{ssh}->error(); $result->{status} = 1; return $result; } } if ($self->{ssh}->connect(SkipKeyProblem => $self->{ssh_skip_serverkey_issue}) != SSH_OK) { $result->{message} = $self->{ssh}->error(); $result->{status} = 1; return $result; } if ($self->{ssh}->auth_publickey_auto() != SSH_AUTH_SUCCESS) { if (defined($self->{ssh_username}) && $self->{ssh_username} ne '' && defined($self->{ssh_password}) && $self->{ssh_password} ne '' && $self->{ssh}->auth_password(password => $self->{ssh_password}) == SSH_AUTH_SUCCESS) { return $result; } my $msg_error = $self->{ssh}->error(GetErrorSession => 1); $result->{message} = sprintf("auth issue: %s", defined($msg_error) && $msg_error ne '' ? $msg_error : 'pubkey issue'); $result->{status} = 1; } return $result; } 1; __END__ =head1 NAME SSH connector library =head1 SYNOPSIS my ssh connector =head1 SSH OPTIONS =over 8 =item B<--hostname> SSH server hostname (required). =item B<--port> SSH port. =item B<--timeout> Timeout in seconds for connection (Defaults: 10 seconds) =item B<--ssh-username> SSH username. =item B<--ssh-password> SSH password. =item B<--ssh-dir> Set the ssh directory. =item B<--ssh-identity> Set the identity file name (default: id_dsa and id_rsa are checked). =item B<--ssh-skip-serverkey-issue> Connection will be OK even if there is a problem (server known changed or server found other) with the ssh server. =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/centreon/common/radlan/000077500000000000000000000000001417000230700216025ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/radlan/snmp/000077500000000000000000000000001417000230700225575ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/radlan/snmp/mode/000077500000000000000000000000001417000230700235035ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/radlan/snmp/mode/components/000077500000000000000000000000001417000230700256705ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/radlan/snmp/mode/components/fan.pm000066400000000000000000000104661417000230700270010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::radlan::snmp::mode::components::fan; use strict; use warnings; use centreon::common::radlan::snmp::mode::components::resources qw( $rl_envmon_state $oid_rlPhdUnitEnvParamMonitorAutoRecoveryEnable $oid_rlPhdUnitEnvParamEntry ); my $mapping_stack = { new => { rlPhdUnitEnvParamFan1Status => { oid => '.1.3.6.1.4.1.89.53.15.1.4', map => $rl_envmon_state }, rlPhdUnitEnvParamFan2Status => { oid => '.1.3.6.1.4.1.89.53.15.1.5', map => $rl_envmon_state }, rlPhdUnitEnvParamFan3Status => { oid => '.1.3.6.1.4.1.89.53.15.1.6', map => $rl_envmon_state }, rlPhdUnitEnvParamFan4Status => { oid => '.1.3.6.1.4.1.89.53.15.1.7', map => $rl_envmon_state }, rlPhdUnitEnvParamFan5Status => { oid => '.1.3.6.1.4.1.89.53.15.1.8', map => $rl_envmon_state }, rlPhdUnitEnvParamFan6Status => { oid => '.1.3.6.1.4.1.89.53.15.1.9', map => $rl_envmon_state } }, old => { rlPhdUnitEnvParamFan1Status => { oid => '.1.3.6.1.4.1.89.53.15.1.4', map => $rl_envmon_state }, rlPhdUnitEnvParamFan2Status => { oid => '.1.3.6.1.4.1.89.53.15.1.5', map => $rl_envmon_state }, rlPhdUnitEnvParamFan3Status => { oid => '.1.3.6.1.4.1.89.53.15.1.6', map => $rl_envmon_state }, rlPhdUnitEnvParamFan4Status => { oid => '.1.3.6.1.4.1.89.53.15.1.7', map => $rl_envmon_state }, rlPhdUnitEnvParamFan5Status => { oid => '.1.3.6.1.4.1.89.53.15.1.8', map => $rl_envmon_state } } }; sub load { my ($self) = @_; } sub check_fan_stack { my ($self) = @_; my $num_fans = 5; $num_fans = 6 if ($self->{radlan_new} == 1); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_rlPhdUnitEnvParamEntry}})) { next if ($oid !~ /^$mapping_stack->{new}->{rlPhdUnitEnvParamFan1Status}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance( mapping => $self->{radlan_new} == 1 ? $mapping_stack->{new} : $mapping_stack->{old}, results => $self->{results}->{$oid_rlPhdUnitEnvParamEntry}, instance => $instance ); for (my $i = 1; $i <= $num_fans; $i++) { my $instance2 = 'stack.' . $instance . '.fan.' . $i; my $name = 'rlPhdUnitEnvParamFan' . $i . 'Status'; next if ($self->check_filter(section => 'fan', instance => $instance2)); next if ($result->{$name} =~ /notPresent/i && $self->absent_problem(section => 'fan', instance => $instance2)); $self->{components}->{fan}->{total}++; $self->{output}->output_add( long_msg => sprintf( "fan '%s' status is '%s' [instance: %s]", $instance2, $result->{$name}, $instance2 ) ); my $exit = $self->get_severity(label => 'default', section => 'fan', value => $result->{$name}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Fan '%s' status is '%s'", $instance2, $result->{$name} ) ); } } } } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking fans"); $self->{components}->{fan} = { name => 'fan', total => 0, skip => 0 }; return if ($self->check_filter(section => 'fan')); check_fan_stack($self); } 1; centreon-plugins-20220113/centreon/common/radlan/snmp/mode/components/psu.pm000066400000000000000000000122231417000230700270350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::radlan::snmp::mode::components::psu; use strict; use warnings; use centreon::common::radlan::snmp::mode::components::resources qw( $rl_envmon_state $oid_rlPhdUnitEnvParamEntry ); my $mapping_stack = { rlPhdUnitEnvParamMainPSStatus => { oid => '.1.3.6.1.4.1.89.53.15.1.2', map => $rl_envmon_state }, rlPhdUnitEnvParamRedundantPSStatus => { oid => '.1.3.6.1.4.1.89.53.15.1.3', map => $rl_envmon_state } }; my $mapping = { rlEnvMonSupplyStatusDescr => { oid => '.1.3.6.1.4.1.89.83.1.2.1.2' }, rlEnvMonSupplyState => { oid => '.1.3.6.1.4.1.89.83.1.2.1.3', map => $rl_envmon_state } }; my $oid_rlEnvMonSupplyStatusEntry = '.1.3.6.1.4.1.89.83.1.2.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_rlEnvMonSupplyStatusEntry, $mapping->{rlEnvMonSupplyStatusDescr}->{oid}, $mapping->{rlEnvMonSupplyState}->{oid} }; } sub check_psu_stack { my ($self) = @_; foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_rlPhdUnitEnvParamEntry}})) { next if ($oid !~ /^$mapping_stack->{rlPhdUnitEnvParamMainPSStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping_stack, results => $self->{results}->{$oid_rlPhdUnitEnvParamEntry}, instance => $instance); foreach (['rlPhdUnitEnvParamMainPSStatus', 'main.psu'], ['rlPhdUnitEnvParamRedundantPSStatus', 'redundant.psu']) { my $instance2 = 'stack.' . $instance . '.' . $_->[1]; next if ($self->check_filter(section => 'psu', instance => $instance2)); next if ($result->{$_->[0]} =~ /notPresent/i && $self->absent_problem(section => 'psu', instance => $instance2)); $self->{components}->{psu}->{total}++; $self->{output}->output_add( long_msg => sprintf( "power supply '%s' status is '%s' [instance: %s]", $instance2, $result->{$_->[0]}, $instance2 ) ); my $exit = $self->get_severity(label => 'default', section => 'psu', value => $result->{$_->[0]}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Power supply '%s' status is '%s'", $instance2, $result->{$_->[0]} ) ); } } } } sub check_psu { my ($self) = @_; foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_rlEnvMonSupplyStatusEntry}})) { next if ($oid !~ /^$mapping->{rlEnvMonSupplyState}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_rlEnvMonSupplyStatusEntry}, instance => $instance); next if ($self->check_filter(section => 'psu', instance => $instance)); if ($result->{rlEnvMonSupplyState} =~ /notPresent/i) { $self->absent_problem(section => 'psu', instance => $instance); next; } $self->{components}->{psu}->{total}++; $self->{output}->output_add( long_msg => sprintf( "power supply '%s' status is '%s' [instance: %s]", $result->{rlEnvMonSupplyStatusDescr}, $result->{rlEnvMonSupplyState}, $instance ) ); my $exit = $self->get_severity(label => 'default', section => 'psu', value => $result->{rlEnvMonSupplyState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Power supply '%s' status is '%s'", $result->{rlEnvMonSupplyStatusDescr}, $result->{rlEnvMonSupplyState} ) ); } } } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking power supplies"); $self->{components}->{psu} = { name => 'psu', total => 0, skip => 0 }; return if ($self->check_filter(section => 'psu')); check_psu($self); check_psu_stack($self); } 1; centreon-plugins-20220113/centreon/common/radlan/snmp/mode/components/resources.pm000066400000000000000000000027401417000230700302430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::radlan::snmp::mode::components::resources; use strict; use warnings; use Exporter; our $rl_envmon_state; our $oid_rlPhdUnitEnvParamMonitorAutoRecoveryEnable; our $oid_rlPhdUnitEnvParamEntry; our @ISA = qw(Exporter); our @EXPORT_OK = qw( $rl_envmon_state $oid_rlPhdUnitEnvParamMonitorAutoRecoveryEnable $oid_rlPhdUnitEnvParamEntry ); $rl_envmon_state = { 1 => 'normal', 2 => 'warning', 3 => 'critical', 4 => 'shutdown', 5 => 'notPresent', 6 => 'notFunctioning', 7 => 'notAvailable', 8 => 'backingUp', 9 => 'readingFailed' }; $oid_rlPhdUnitEnvParamMonitorAutoRecoveryEnable = '.1.3.6.1.4.1.89.53.15.1.15'; $oid_rlPhdUnitEnvParamEntry = '.1.3.6.1.4.1.89.53.15.1'; 1; centreon-plugins-20220113/centreon/common/radlan/snmp/mode/components/temperature.pm000066400000000000000000000127621417000230700305730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::radlan::snmp::mode::components::temperature; use strict; use warnings; use centreon::common::radlan::snmp::mode::components::resources qw($oid_rlPhdUnitEnvParamEntry); my $map_entity_sensor = { 1 => 'ok', 2 => 'unavailable', 3 => 'nonoperational' }; my $mapping = { new => { rlPhdUnitEnvParamTempSensorValue => { oid => '.1.3.6.1.4.1.89.53.15.1.10' }, rlPhdUnitEnvParamTempSensorStatus => { oid => '.1.3.6.1.4.1.89.53.15.1.11', map => $map_entity_sensor }, rlPhdUnitEnvParamTempSensorWarningThresholdValue => { oid => '.1.3.6.1.4.1.89.53.15.1.12' }, rlPhdUnitEnvParamTempSensorCriticalThresholdValue => { oid => '.1.3.6.1.4.1.89.53.15.1.13' } }, old => { rlPhdUnitEnvParamTempSensorValue => { oid => '.1.3.6.1.4.1.89.53.15.1.9' }, rlPhdUnitEnvParamTempSensorStatus => { oid => '.1.3.6.1.4.1.89.53.15.1.10', map => $map_entity_sensor }, } }; sub load {} sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking temperatures"); $self->{components}->{temperature} = { name => 'temperatures', total => 0, skip => 0 }; return if ($self->check_filter(section => 'temperature')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_rlPhdUnitEnvParamEntry}})) { next if ($oid !~ /^$mapping->{new}->{rlPhdUnitEnvParamTempSensorValue}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance( mapping => $self->{radlan_new} == 1 ? $mapping->{new} : $mapping->{old}, results => $self->{results}->{$oid_rlPhdUnitEnvParamEntry}, instance => $instance ); next if ($self->check_filter(section => 'temperature', instance => $instance)); $self->{components}->{temperature}->{total}++; $self->{output}->output_add( long_msg => sprintf( "temperature '%s' status is '%s' [instance = %s, value: %s degree centigrade]", $instance, $result->{rlPhdUnitEnvParamTempSensorStatus}, $instance, $result->{rlPhdUnitEnvParamTempSensorValue} ) ); my $exit = $self->get_severity(section => 'temperature', value => $result->{rlPhdUnitEnvParamTempSensorStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Temperature '%s' status is '%s'", $instance, $result->{rlPhdUnitEnvParamTempSensorStatus} ) ); } my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $instance, value => $result->{rlPhdUnitEnvParamTempSensorValue}); if ($checked == 0 && defined($result->{rlPhdUnitEnvParamTempSensorWarningThresholdValue})) { my $warn_th = ':' . $result->{rlPhdUnitEnvParamTempSensorWarningThresholdValue}; my $crit_th = ':' . $result->{rlPhdUnitEnvParamTempSensorCriticalThresholdValue}; $self->{perfdata}->threshold_validate(label => 'warning-temperature-instance-' . $instance, value => $warn_th); $self->{perfdata}->threshold_validate(label => 'critical-temperature-instance-' . $instance, value => $crit_th); $exit2 = $self->{perfdata}->threshold_check( value => $result->{rlPhdUnitEnvParamTempSensorValue}, threshold => [ { label => 'critical-temperature-instance-' . $instance, exit_litteral => 'critical' }, { label => 'warning-temperature-instance-' . $instance, exit_litteral => 'warning' } ] ); $warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-temperature-instance-' . $instance); $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-temperature-instance-' . $instance); } if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit2, short_msg => sprintf( "Temperature '%s' is %s degree centigrade", $instance, $result->{rlPhdUnitEnvParamTempSensorValue} ) ); } $self->{output}->perfdata_add( label => 'temp', unit => 'C', nlabel => 'hardware.temperature.celsius', instances => $instance, value => $result->{rlPhdUnitEnvParamTempSensorValue}, warning => $warn, critical => $crit ); } } 1; centreon-plugins-20220113/centreon/common/radlan/snmp/mode/cpu.pm000066400000000000000000000066731417000230700246440ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::radlan::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 => 0, cb_prefix_output => 'prefix_message_output', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{cpu} = [ { label => 'average-1s', nlabel => 'cpu.utilization.1s.percentage', set => { key_values => [ { name => 'average_1s' } ], output_template => '%.2f %% (1s)', perfdatas => [ { value => 'average_1s', template => '%.2f', min => 0, max => 100, unit => '%' } ] } }, { label => 'average-1m', nlabel => 'cpu.utilization.1m.percentage', set => { key_values => [ { name => 'average_1m' } ], output_template => '%.2f %% (1m)', perfdatas => [ { value => 'average_1m', template => '%.2f', min => 0, max => 100, unit => '%' } ] } }, { label => 'average-5m', nlabel => 'cpu.utilization.5m.percentage', set => { key_values => [ { name => 'average_5m' } ], output_template => '%.2f %% (5m)', perfdatas => [ { value => 'average_5m', template => '%.2f', min => 0, max => 100, unit => '%' } ] } } ]; } sub prefix_message_output { my ($self, %options) = @_; return "CPU average usage: "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $oid_rlCpuUtilDuringLastSecond = '.1.3.6.1.4.1.89.1.7.0'; my $oid_rlCpuUtilDuringLastMinute = '.1.3.6.1.4.1.89.1.8.0'; my $oid_rlCpuUtilDuringLast5Minutes = '.1.3.6.1.4.1.89.1.9.0'; my $result = $options{snmp}->get_leef( oids => [$oid_rlCpuUtilDuringLastSecond, $oid_rlCpuUtilDuringLastMinute, $oid_rlCpuUtilDuringLast5Minutes], nothing_quit => 1 ); $self->{cpu} = { average_1s => $result->{$oid_rlCpuUtilDuringLastSecond}, average_1m => $result->{$oid_rlCpuUtilDuringLastMinute}, average_5m => $result->{$oid_rlCpuUtilDuringLast5Minutes} } } 1; __END__ =head1 MODE Check cpu usage. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'average-1s' (%), 'average-1m' (%), 'average-5m' (%). =back =cut centreon-plugins-20220113/centreon/common/radlan/snmp/mode/environment.pm000066400000000000000000000072521417000230700264130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::radlan::snmp::mode::environment; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; use centreon::common::radlan::snmp::mode::components::resources qw( $oid_rlPhdUnitEnvParamEntry $oid_rlPhdUnitEnvParamMonitorAutoRecoveryEnable ); sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^temperature$'; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { default => [ ['normal', 'OK'], ['notPresent', 'OK'], ['warning', 'WARNING'], ['critical', 'CRITICAL'], ['shutdown', 'CRITICAL'], ['notFunctioning', 'CRITICAL'], ], temperature => [ ['ok', 'OK'], ['unavailable', 'OK'], ['nonoperational', 'CRITICAL'], ] }; $self->{components_path} = 'centreon::common::radlan::snmp::mode::components'; $self->{components_module} = ['psu', 'fan', 'temperature']; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; push @{$self->{request}}, { oid => $oid_rlPhdUnitEnvParamEntry, start => '.1.3.6.1.4.1.89.53.15.1.2', # rlPhdUnitEnvParamMainPSStatus end => $oid_rlPhdUnitEnvParamMonitorAutoRecoveryEnable }; $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); $self->{radlan_new} = 0; foreach (keys %{$self->{results}->{$oid_rlPhdUnitEnvParamEntry}}) { if (/^$oid_rlPhdUnitEnvParamMonitorAutoRecoveryEnable\./) { $self->{radlan_new} = 1; last; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } 1; __END__ =head1 MODE Check environment. =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'fan', 'psu', 'temperature'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=psu) Can also exclude specific instance: --filter=psu,0 =item B<--absent-problem> Return an error if an entity is not 'present' (default is skipping) (comma seperated list) Can be specific or global: --absent-problem=fan#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='fan,CRITICAL,^(?!(normal)$)' =item B<--warning> Set warning threshold (syntax: type,regexp,threshold) Example: --warning='temperature,.*,30' =item B<--critical> Set critical threshold (syntax: type,regexp,threshold) Example: --critical='temperature,.*,40' =back =cut centreon-plugins-20220113/centreon/common/redfish/000077500000000000000000000000001417000230700217655ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/redfish/restapi/000077500000000000000000000000001417000230700234345ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/redfish/restapi/mode/000077500000000000000000000000001417000230700243605ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/redfish/restapi/mode/components/000077500000000000000000000000001417000230700265455ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/redfish/restapi/mode/components/chassis.pm000066400000000000000000000047261417000230700305510ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::redfish::restapi::mode::components::chassis; use strict; use warnings; 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')); $self->get_chassis() if (!defined($self->{chassis})); foreach my $chassis (@{$self->{chassis}}) { my $instance = $chassis->{Id}; next if ($self->check_filter(section => 'chassis', instance => $instance)); $self->{components}->{chassis}->{total}++; $self->{output}->output_add( long_msg => sprintf( "chassis '%s' status is '%s' [instance: %s, state: %s]", $instance, $chassis->{Status}->{Health}, $instance, $chassis->{Status}->{State} ) ); my $exit = $self->get_severity(label => 'state', section => 'chassis.state', value => $chassis->{Status}->{State}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Chassis '%s' state is '%s'", $instance, $chassis->{Status}->{State}) ); } $exit = $self->get_severity(label => 'status', section => 'chassis.status', value => $chassis->{Status}->{Health}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Chassis '%s' status is '%s'", $instance, $chassis->{Status}->{Health}) ); } } } 1; centreon-plugins-20220113/centreon/common/redfish/restapi/mode/components/device.pm000066400000000000000000000060361417000230700303470ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::redfish::restapi::mode::components::device; use strict; use warnings; sub check { my ($self) = @_; $self->{output}->output_add(long_msg => 'checking devices'); $self->{components}->{device} = { name => 'devices', total => 0, skip => 0 }; return if ($self->check_filter(section => 'device')); $self->get_devices(); foreach my $chassis (@{$self->{chassis}}) { my $chassis_name = 'chassis:' . $chassis->{Id}; next if (!defined($chassis->{Devices})); foreach my $device (@{$chassis->{Devices}}) { my $device_name = $device->{Name}; my $instance = $chassis->{Id} . '.' . $device->{Id}; $device->{Status}->{Health} = defined($device->{Status}->{Health}) ? $device->{Status}->{Health} : 'n/a'; $device->{Status}->{State} = defined($device->{Status}->{State}) ? $device->{Status}->{State} : 'n/a'; next if ($self->check_filter(section => 'device', instance => $instance)); $self->{components}->{device}->{total}++; $self->{output}->output_add( long_msg => sprintf( "device '%s/%s' status is '%s' [instance: %s, state: %s]", $chassis_name, $device_name, $device->{Status}->{Health}, $instance, $device->{Status}->{State} ) ); my $exit = $self->get_severity(label => 'state', section => 'device.state', value => $device->{Status}->{State}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Device '%s/%s' state is '%s'", $chassis_name, $device_name, $device->{Status}->{State}) ); } $exit = $self->get_severity(label => 'status', section => 'device.status', value => $device->{Status}->{Health}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Device '%s/%s' status is '%s'", $chassis_name, $device_name, $device->{Status}->{Health}) ); } } } } 1; centreon-plugins-20220113/centreon/common/redfish/restapi/mode/components/fan.pm000066400000000000000000000104621417000230700276520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::redfish::restapi::mode::components::fan; use strict; use warnings; my $reading_units = { percent => { short => '%', long => 'percentage' }, rpm => { short => 'rpm', long => 'rpm' } }; sub check { my ($self) = @_; $self->{output}->output_add(long_msg => 'checking fans'); $self->{components}->{fan} = { name => 'fans', total => 0, skip => 0 }; return if ($self->check_filter(section => 'fan')); $self->get_chassis() if (!defined($self->{chassis})); foreach my $chassis (@{$self->{chassis}}) { my $chassis_name = 'chassis:' . $chassis->{Id}; $chassis->{Thermal}->{result} = $self->get_thermal(chassis => $chassis) if (!defined($chassis->{Thermal}->{result})); next if (!defined($chassis->{Thermal}->{result}->{Fans})); foreach my $fan (@{$chassis->{Thermal}->{result}->{Fans}}) { my $fan_name = $fan->{Name}; my $instance = $chassis->{Id} . '.' . $fan->{MemberId}; $fan->{Status}->{Health} = defined($fan->{Status}->{Health}) ? $fan->{Status}->{Health} : 'n/a'; next if ($self->check_filter(section => 'fan', instance => $instance)); $self->{components}->{fan}->{total}++; $self->{output}->output_add( long_msg => sprintf( "fan '%s/%s' status is '%s' [instance: %s, state: %s, speed: %s %s]", $chassis_name, $fan_name, $fan->{Status}->{Health}, $instance, $fan->{Status}->{State}, $fan->{Reading}, $fan->{ReadingUnits} ) ); my $exit = $self->get_severity(label => 'state', section => 'fan.state', value => $fan->{Status}->{State}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Fan '%s/%s' state is '%s'", $chassis_name, $fan_name, $fan->{Status}->{State}) ); } $exit = $self->get_severity(label => 'status', section => 'fan.status', value => $fan->{Status}->{Health}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Fan '%s/%s' status is '%s'", $chassis_name, $fan_name, $fan->{Status}->{Health}) ); } my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'fan', instance => $instance, value => $fan->{Reading}); if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit2, short_msg => sprintf( "Fan '%s/%s' speed is %s %s", $chassis_name, $fan_name, $fan->{Reading}, $reading_units->{lc($fan->{ReadingUnits})}->{short} ) ); } $self->{output}->perfdata_add( unit => $reading_units->{lc($fan->{ReadingUnits})}->{short}, nlabel => 'hardware.fan.speed.' . $reading_units->{lc($fan->{ReadingUnits})}->{long}, instances => [$chassis_name, $fan_name], value => $fan->{Reading}, warning => $warn, critical => $crit, min => 0, max => $fan->{ReadingUnits} eq 'Percent' ? 100 : undef ); } } } 1; centreon-plugins-20220113/centreon/common/redfish/restapi/mode/components/psu.pm000066400000000000000000000100741417000230700277140ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::redfish::restapi::mode::components::psu; use strict; use warnings; sub check { my ($self) = @_; $self->{output}->output_add(long_msg => 'checking power supplies'); $self->{components}->{psu} = { name => 'psu', total => 0, skip => 0 }; return if ($self->check_filter(section => 'psu')); $self->get_chassis() if (!defined($self->{chassis})); foreach my $chassis (@{$self->{chassis}}) { my $chassis_name = 'chassis:' . $chassis->{Id}; $chassis->{Power}->{result} = $self->get_power(chassis => $chassis) if (!defined($chassis->{Power}->{result})); next if (!defined($chassis->{Power}->{result}->{PowerSupplies})); foreach my $psu (@{$chassis->{Power}->{result}->{PowerSupplies}}) { my $psu_name = 'psu:' . $psu->{MemberId}; my $instance = $chassis->{Id} . '.' . $psu->{MemberId}; $psu->{Status}->{Health} = defined($psu->{Status}->{Health}) ? $psu->{Status}->{Health} : 'n/a'; next if ($self->check_filter(section => 'psu', instance => $instance)); $self->{components}->{psu}->{total}++; $self->{output}->output_add( long_msg => sprintf( "power supply '%s/%s' status is '%s' [instance: %s, state: %s, value: %s]", $chassis_name, $psu_name, $psu->{Status}->{Health}, $instance, $psu->{Status}->{State}, $psu->{LastPowerOutputWatts}, ) ); my $exit = $self->get_severity(label => 'state', section => 'psu.state', value => $psu->{Status}->{State}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Power supply '%s/%s' state is '%s'", $chassis_name, $psu_name, $psu->{Status}->{State}) ); } $exit = $self->get_severity(label => 'status', section => 'psu.status', value => $psu->{Status}->{Health}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Power supply '%s/%s' status is '%s'", $chassis_name, $psu_name, $psu->{Status}->{Health}) ); } my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'psu', instance => $instance, value => $psu->{LastPowerOutputWatts}); if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit2, short_msg => sprintf( "Power supply '%s/%s' power is %s W", $chassis_name, $psu_name, $psu->{LastPowerOutputWatts} ) ); } $self->{output}->perfdata_add( unit => 'W', nlabel => 'hardware.powersupply.power.watt', instances => [$chassis_name, $psu_name], value => $psu->{LastPowerOutputWatts}, warning => $warn, critical => $crit, min => 0 ); } } } 1; centreon-plugins-20220113/centreon/common/redfish/restapi/mode/components/temperature.pm000066400000000000000000000116531417000230700314460ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::redfish::restapi::mode::components::temperature; use strict; use warnings; sub check { my ($self) = @_; $self->{output}->output_add(long_msg => 'checking temperatures'); $self->{components}->{temperature} = { name => 'temperatures', total => 0, skip => 0 }; return if ($self->check_filter(section => 'temperature')); $self->get_chassis() if (!defined($self->{chassis})); foreach my $chassis (@{$self->{chassis}}) { my $chassis_name = 'chassis:' . $chassis->{Id}; $chassis->{Thermal}->{result} = $self->get_thermal(chassis => $chassis) if (!defined($chassis->{Thermal}->{result})); next if (!defined($chassis->{Thermal}->{result}->{Temperatures})); foreach my $temp (@{$chassis->{Thermal}->{result}->{Temperatures}}) { my $temp_name = $temp->{Name}; my $instance = $chassis->{Id} . '.' . $temp->{MemberId}; $temp->{Status}->{Health} = defined($temp->{Status}->{Health}) ? $temp->{Status}->{Health} : 'n/a'; next if ($self->check_filter(section => 'temperature', instance => $instance)); $self->{components}->{temperature}->{total}++; $self->{output}->output_add( long_msg => sprintf( "temperature '%s/%s' status is '%s' [instance: %s, state: %s, value: %s]", $chassis_name, $temp_name, $temp->{Status}->{Health}, $instance, $temp->{Status}->{State}, $temp->{ReadingCelsius} ) ); my $exit = $self->get_severity(label => 'state', section => 'temperature.state', value => $temp->{Status}->{State}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Temperature '%s/%s' state is '%s'", $chassis_name, $temp_name, $temp->{Status}->{State}) ); } $exit = $self->get_severity(label => 'status', section => 'temperature.status', value => $temp->{Status}->{Health}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Temperature '%s/%s' status is '%s'", $chassis_name, $temp_name, $temp->{Status}->{Health}) ); } next if (!defined($temp->{ReadingCelsius}) || $temp->{ReadingCelsius} == 0); my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $instance, value => $temp->{ReadingCelsius}); if ($checked == 0) { my $warn_th = defined($temp->{UpperThresholdCritical}) ? ':' . $temp->{UpperThresholdCritical} : ''; my $crit_th = defined($temp->{UpperThresholdFatal}) ? ':' . $temp->{UpperThresholdFatal} : ''; $self->{perfdata}->threshold_validate(label => 'warning-temperature-instance-' . $instance, value => $warn_th); $self->{perfdata}->threshold_validate(label => 'critical-temperature-instance-' . $instance, value => $crit_th); $warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-temperature-instance-' . $instance); $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-temperature-instance-' . $instance); } if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit2, short_msg => sprintf( "Temperature '%s/%s' is %s C", $chassis_name, $temp_name, $temp->{ReadingCelsius} ) ); } $self->{output}->perfdata_add( unit => 'C', nlabel => 'hardware.temperature.celsius', instances => [$chassis_name, $temp_name], value => $temp->{ReadingCelsius}, warning => $warn, critical => $crit ); } } } 1; centreon-plugins-20220113/centreon/common/redfish/restapi/mode/hardware.pm000066400000000000000000000105561417000230700265220ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::redfish::restapi::mode::hardware; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^(?:fan|temperature|psu)$'; $self->{cb_hook2} = 'execute_custom'; $self->{thresholds} = { status => [ ['ok', 'OK'], ['warning', 'WARNING'], ['critical', 'CRITICAL'], ['n/a', 'OK'], ], state => [ # can be: absent, deferring, disabled, enabled, # inTest, quiesced, standbyOffline, standbySpare # starting, unavailableOffline, updating ['updating', 'WARNING'], ['.*', 'OK'], ], }; $self->{components_exec_load} = 0; $self->{components_path} = 'centreon::common::redfish::restapi::mode::components'; $self->{components_module} = ['chassis', 'device', 'fan', 'psu', 'temperature']; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_absent => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub get_power { my ($self, %options) = @_; return {} if (!defined($options{chassis}->{Power}->{'@odata.id'})); return $self->{custom}->request_api(url_path => $options{chassis}->{Power}->{'@odata.id'}); } sub get_thermal { my ($self, %options) = @_; return {} if (!defined($options{chassis}->{Thermal}->{'@odata.id'})); return $self->{custom}->request_api(url_path => $options{chassis}->{Thermal}->{'@odata.id'}); } sub get_devices { my ($self, %options) = @_; $self->get_chassis() if (!defined($self->{chassis})); foreach my $chassis (@{$self->{chassis}}) { $chassis->{Devices} = []; my $result = $self->{custom}->request_api(url_path => $chassis->{'@odata.id'} . 'Devices'); foreach (@{$result->{Members}}) { my $device_detailed = $self->{custom}->request_api(url_path => $_->{'@odata.id'}); push @{$chassis->{Devices}}, $device_detailed; } } } sub get_chassis { my ($self, %options) = @_; $self->{chassis} = []; # "Members":[ # { "@odata.id":"/redfish/v1/Chassis/1/" } # ], my $result = $self->{custom}->request_api(url_path => '/redfish/v1/chassis/'); foreach (@{$result->{Members}}) { my $chassis_detailed = $self->{custom}->request_api(url_path => $_->{'@odata.id'}); push @{$self->{chassis}}, $chassis_detailed; } } sub execute_custom { my ($self, %options) = @_; $self->{custom} = $options{custom}; } 1; =head1 MODE Check hardware. =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'chassis', 'device', 'fan', 'psu', 'temperature'. =item B<--filter> Exclude some parts (comma seperated list) 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='chassis.state,WARNING,inTest' =item B<--warning> Set warning threshold for 'temperature', 'fan', 'psu' (syntax: type,regexp,threshold) Example: --warning='temperature,.*,30' =item B<--critical> Set critical threshold for 'temperature', 'fan', 'psu' (syntax: type,regexp,threshold) Example: --critical='temperature,.*,50' =back =cut centreon-plugins-20220113/centreon/common/riverbed/000077500000000000000000000000001417000230700221435ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/riverbed/steelhead/000077500000000000000000000000001417000230700241015ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/riverbed/steelhead/snmp/000077500000000000000000000000001417000230700250565ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/riverbed/steelhead/snmp/mode/000077500000000000000000000000001417000230700260025ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/riverbed/steelhead/snmp/mode/bwoptimization.pm000066400000000000000000000117001417000230700314160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::riverbed::steelhead::snmp::mode::bwoptimization; 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 => 'global', type => 0, cb_prefix_output => 'prefix_output' } ]; $self->{maps_counters}->{global} = [ { label => 'wan2lan-lan', set => { key_values => [ { name => 'bwHCAggInLan', per_second => 1 } ], output_template => 'Wan2Lan on Lan: %s %s/s', output_change_bytes => 1, perfdatas => [ { label => 'wan2lan_lan', template => '%s', min => 0, unit => 'B/s' } ] } }, { label => 'wan2lan-wan', set => { key_values => [ { name => 'bwHCAggInWan', per_second => 1 } ], output_template => 'Wan2Lan on Wan: %s %s/s', output_change_bytes => 1, perfdatas => [ { label => 'wan2lan_wan', template => '%s', min => 0, unit => 'B/s' } ] } }, { label => 'lan2wan-lan', set => { key_values => [ { name => 'bwHCAggOutLan', per_second => 1 } ], output_template => 'Lan2Wan on Lan: %s %s/s', output_change_bytes => 1, perfdatas => [ { label => 'lan2wan_lan', template => '%s', min => 0, unit => 'B/s' } ] } }, { label => 'lan2wan-wan', set => { key_values => [ { name => 'bwHCAggOutWan', per_second => 1 } ], output_template => 'Lan2Wan on Wan: %s %s/s', output_change_bytes => 1, perfdatas => [ { label => 'lan2wan_wan', template => '%s', min => 0, unit => 'B/s' } ] } } ]; } sub prefix_output { my ($self, %options) = @_; return 'Optimized '; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my $mappings = { common => { bwHCAggInLan => { oid => '.1.3.6.1.4.1.17163.1.1.5.6.1.1' }, bwHCAggInWan => { oid => '.1.3.6.1.4.1.17163.1.1.5.6.1.2' }, bwHCAggOutLan => { oid => '.1.3.6.1.4.1.17163.1.1.5.6.1.3' }, bwHCAggOutWan => { oid => '.1.3.6.1.4.1.17163.1.1.5.6.1.4' } }, ex => { bwHCAggInLan => { oid => '.1.3.6.1.4.1.17163.1.51.5.6.1.1' }, bwHCAggInWan => { oid => '.1.3.6.1.4.1.17163.1.51.5.6.1.2' }, bwHCAggOutLan => { oid => '.1.3.6.1.4.1.17163.1.51.5.6.1.3' }, bwHCAggOutWan => { oid => '.1.3.6.1.4.1.17163.1.51.5.6.1.4' } } }; my $oids = { common => '.1.3.6.1.4.1.17163.1.1.5.6.1', ex => '.1.3.6.1.4.1.17163.1.51.5.6.1' }; sub manage_selection { my ($self, %options) = @_; my $results = $options{snmp}->get_multiple_table( oids => [ { oid => $oids->{common}, start => $mappings->{common}->{bwHCAggInLan}->{oid}, end => $mappings->{common}->{bwHCAggOutWan}->{oid} }, { oid => $oids->{ex}, start => $mappings->{ex}->{bwHCAggInLan}->{oid}, end => $mappings->{ex}->{bwHCAggOutWan}->{oid} } ] ); foreach my $equipment (keys %{$oids}) { next if (!%{$results->{$oids->{$equipment}}}); $self->{global} = $options{snmp}->map_instance(mapping => $mappings->{$equipment}, results => $results->{$oids->{$equipment}}, instance => 0); } $self->{cache_name} = 'riverbed_steelhead_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . $self->{mode} . '_' . md5_hex('all'); } 1; __END__ =head1 MODE Total optimized bytes across all application ports in both directions and on both sides, in bytes per second (STEELHEAD-MIB and STEELHEAD-EX-MIB). =over 8 =item B<--warning-*> Threshold warning (Can be: 'wan2lan-lan', 'wan2lan-wan', 'lan2wan-lan', 'lan2wan-wan') =item B<--critical-*> Threshold critical (Can be: 'wan2lan-lan', 'wan2lan-wan', 'lan2wan-lan', 'lan2wan-wan') =over 8 =back =cut centreon-plugins-20220113/centreon/common/riverbed/steelhead/snmp/mode/bwpassthrough.pm000066400000000000000000000075441417000230700312520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::riverbed::steelhead::snmp::mode::bwpassthrough; 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 => 'global', type => 0, cb_prefix_output => 'prefix_output' } ]; $self->{maps_counters}->{global} = [ { label => 'traffic-in', set => { key_values => [ { name => 'bwPassThroughIn', per_second => 1 } ], output_template => 'Traffic In (Wan2Lan): %s %s/s', output_change_bytes => 1, perfdatas => [ { label => 'traffic_in', template => '%s', min => 0, unit => 'B/s' } ] } }, { label => 'traffic-out', set => { key_values => [ { name => 'bwPassThroughOut', per_second => 1 } ], output_template => 'Traffic Out (Lan2Wan): %s %s/s', output_change_bytes => 1, perfdatas => [ { label => 'traffic_out', template => '%s', min => 0, unit => 'B/s' } ] } } ]; } sub prefix_output { my ($self, %options) = @_; return 'Passthrough '; } my $mappings = { common => { bwPassThroughIn => { oid => '.1.3.6.1.4.1.17163.1.1.5.3.3.1' }, bwPassThroughOut => { oid => '.1.3.6.1.4.1.17163.1.1.5.3.3.2' } }, ex => { bwPassThroughIn => { oid => '.1.3.6.1.4.1.17163.1.51.5.3.3.1' }, bwPassThroughOut => { oid => '.1.3.6.1.4.1.17163.1.51.5.3.3.2' } } }; my $oids = { common => '.1.3.6.1.4.1.17163.1.1.5.3.3', ex => '.1.3.6.1.4.1.17163.1.51.5.3.3' }; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $results = $options{snmp}->get_multiple_table( oids => [ { oid => $oids->{common}, start => $mappings->{common}->{bwPassThroughIn}->{oid}, end => $mappings->{common}->{bwPassThroughOut}->{oid} }, { oid => $oids->{ex}, start => $mappings->{ex}->{bwPassThroughIn}->{oid}, end => $mappings->{ex}->{bwPassThroughOut}->{oid} } ] ); foreach my $equipment (keys %{$oids}) { next if (!%{$results->{$oids->{$equipment}}}); $self->{global} = $options{snmp}->map_instance(mapping => $mappings->{$equipment}, results => $results->{$oids->{$equipment}}, instance => 0); } $self->{cache_name} = 'riverbed_steelhead_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . $self->{mode} . '_' . md5_hex('all'); } 1; __END__ =head1 MODE Check passthrough bandwidth in both directions (STEELHEAD-MIB and STEELHEAD-EX-MIB). =over 8 =item B<--warning-traffic-*> Threshold warning (Can be: 'in' (Wan2Lan), 'out' (Lan2Wan)) =item B<--critical-traffic-*> Threshold critical (Can be: 'in' (Wan2Lan), 'out' (Lan2Wan)) =over 8 =back =cut centreon-plugins-20220113/centreon/common/riverbed/steelhead/snmp/mode/connections.pm000066400000000000000000000170331417000230700306660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::riverbed::steelhead::snmp::mode::connections; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_optimized_output { my ($self, %options) = @_; return sprintf( "optimized total: %s used: %s (%.2f%%) free: %s (%.2f%%)", $self->{result_values}->{max_optimized}, $self->{result_values}->{optimized}, $self->{result_values}->{prct_optimized}, $self->{result_values}->{optimized_free}, $self->{result_values}->{prct_optimized_free} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_connection_output' } ]; $self->{maps_counters}->{global} = [ { label => 'total', nlabel => 'connections.total.count', set => { key_values => [ { name => 'total' } ], output_template => 'total %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'established', nlabel => 'connections.established.count', set => { key_values => [ { name => 'established' } ], output_template => 'established %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'active', nlabel => 'connections.active.count', set => { key_values => [ { name => 'active' } ], output_template => 'active %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'optimized', nlabel => 'connections.optimized.count', set => { key_values => [ { name => 'optimized' }, { name => 'optimized_free' }, { name => 'prct_optimized' }, { name => 'prct_optimized_free' }, { name => 'max_optimized' } ], closure_custom_output => $self->can('custom_optimized_output'), perfdatas => [ { template => '%d', min => 0, max => 'max_optimized' } ] } }, { label => 'optimized-prct', display_ok => 0, nlabel => 'connections.optimized.percentage', set => { key_values => [ { name => 'prct_optimized' }, { name => 'optimized_free' }, { name => 'optimized' }, { name => 'prct_optimized_free' }, { name => 'max_optimized' } ], closure_custom_output => $self->can('custom_optimized_output'), perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%' } ] } }, { label => 'passthrough', nlabel => 'connections.passthrough.count', set => { key_values => [ { name => 'passthrough' } ], output_template => 'passthrough %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'half-opened', nlabel => 'connections.half_opened.count', set => { key_values => [ { name => 'half_opened' } ], output_template => 'half opened %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'half-closed', nlabel => 'connections.half_closed.count', set => { key_values => [ { name => 'half_closed' } ], output_template => 'half closed %s', perfdatas => [ { template => '%s', min => 0 } ] } } ]; } sub prefix_connection_output { my ($self, %options) = @_; return 'Connections: '; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my $mappings = { common => { max_optimized => { oid => '.1.3.6.1.4.1.17163.1.1.2.13.1' }, # shMaxConnections optimized => { oid => '.1.3.6.1.4.1.17163.1.1.5.2.1' }, # optimizedConnections passthrough => { oid => '.1.3.6.1.4.1.17163.1.1.5.2.2' }, # passthroughConnections half_opened => { oid => '.1.3.6.1.4.1.17163.1.1.5.2.3' }, # halfOpenedConnections half_closed => { oid => '.1.3.6.1.4.1.17163.1.1.5.2.4' }, # halfClosedConnections established => { oid => '.1.3.6.1.4.1.17163.1.1.5.2.5' }, # establishedConnections active => { oid => '.1.3.6.1.4.1.17163.1.1.5.2.6' }, # activeConnections total => { oid => '.1.3.6.1.4.1.17163.1.1.5.2.7' } # totalConnections }, ex => { max_optimized => { oid => '.1.3.6.1.4.1.17163.1.51.2.13.1' }, # shMaxConnections optimized => { oid => '.1.3.6.1.4.1.17163.1.51.5.2.1' }, # optimizedConnections passthrough => { oid => '.1.3.6.1.4.1.17163.1.51.5.2.2' }, # passthroughConnections half_opened => { oid => '.1.3.6.1.4.1.17163.1.51.5.2.3' }, # halfOpenedConnections half_closed => { oid => '.1.3.6.1.4.1.17163.1.51.5.2.4' }, # halfClosedConnections established => { oid => '.1.3.6.1.4.1.17163.1.51.5.2.5' }, # establishedConnections active => { oid => '.1.3.6.1.4.1.17163.1.51.5.2.6' }, # activeConnections total => { oid => '.1.3.6.1.4.1.17163.1.51.5.2.7' } # totalConnections } }; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_leef( oids => [ map($_->{oid} . '.0', values(%{$mappings->{common}})), map($_->{oid} . '.0', values(%{$mappings->{ex}})) ], nothing_quit => 1 ); my $result = $options{snmp}->map_instance(mapping => $mappings->{common}, results => $snmp_result, instance => 0); if (!defined($result->{optimized})) { $result = $options{snmp}->map_instance(mapping => $mappings->{ex}, results => $snmp_result, instance => 0); } $self->{global} = $result; $self->{global}->{optimized_free} = $result->{max_optimized} - $result->{optimized}; $self->{global}->{prct_optimized} = $result->{optimized} * 100 / $result->{max_optimized}; $self->{global}->{prct_optimized_free} = 100 - $self->{global}->{prct_optimized}; } 1; __END__ =head1 MODE Current connections: total, established, active, optimized, passthrough, half opened and half closed ones (STEELHEAD-MIB and STEELHEAD-EX-MIB). =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^(total)$' =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'total', 'established', 'active', 'optimized', 'optimized-prct', 'passthrough', 'half-opened', 'half-closed'. =back =cut centreon-plugins-20220113/centreon/common/riverbed/steelhead/snmp/mode/diskutilization.pm000066400000000000000000000105311417000230700315660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::riverbed::steelhead::snmp::mode::diskutilization; 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 => 'global', type => 0 } ]; $self->{maps_counters}->{global} = [ { label => 'usage', set => { key_values => [ { name => 'dsAveDiskUtilization' } ], output_template => 'Datastore Usage: %.2f%%', perfdatas => [ { label => 'used', template => '%.2f', min => 0, max => 100, unit => '%' } ] } }, { label => 'hits', set => { key_values => [ { name => 'dsHitsTotal', per_second => 1 } ], output_template => 'Hits: %s/s', perfdatas => [ { label => 'hits', template => '%.2f', min => 0, unit => 'hits/s' } ] } }, { label => 'misses', set => { key_values => [ { name => 'dsMissTotal', per_second => 1 } ], output_template => 'Misses: %s/s', perfdatas => [ { label => 'misses', template => '%.2f', min => 0, unit => 'misses/s' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments =>{ }); return $self; } my $mappings = { common => { dsHitsTotal => { oid => '.1.3.6.1.4.1.17163.1.1.5.4.1' }, dsMissTotal => { oid => '.1.3.6.1.4.1.17163.1.1.5.4.2' }, dsCostPerSegment => { oid => '.1.3.6.1.4.1.17163.1.1.5.4.3' }, dsAveDiskUtilization => { oid => '.1.3.6.1.4.1.17163.1.1.5.4.4' } }, ex => { dsHitsTotal => { oid => '.1.3.6.1.4.1.17163.1.51.5.4.1' }, dsMissTotal => { oid => '.1.3.6.1.4.1.17163.1.51.5.4.2' }, dsCostPerSegment => { oid => '.1.3.6.1.4.1.17163.1.51.5.4.3' }, dsAveDiskUtilization => { oid => '.1.3.6.1.4.1.17163.1.51.5.4.4' } } }; my $oids = { common => '.1.3.6.1.4.1.17163.1.1.5.4', ex => '.1.3.6.1.4.1.17163.1.51.5.4', }; sub manage_selection { my ($self, %options) = @_; my $results = $options{snmp}->get_multiple_table( oids => [ { oid => $oids->{common}, start => $mappings->{common}->{dsHitsTotal}->{oid}, end => $mappings->{common}->{dsAveDiskUtilization}->{oid} }, { oid => $oids->{ex}, start => $mappings->{ex}->{dsHitsTotal}->{oid}, end => $mappings->{ex}->{dsAveDiskUtilization}->{oid} } ] ); foreach my $equipment (keys %{$oids}) { next if (!%{$results->{$oids->{$equipment}}}); my $result = $options{snmp}->map_instance(mapping => $mappings->{$equipment}, results => $results->{$oids->{$equipment}}, instance => 0); $self->{global} = { dsHitsTotal => $result->{dsHitsTotal}, dsMissTotal => $result->{dsMissTotal}, dsAveDiskUtilization => $result->{dsAveDiskUtilization} }; } $self->{cache_name} = 'riverbed_steelhead_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . $self->{mode} . '_' . md5_hex('all'); } 1; __END__ =head1 MODE Check disk utilization : usage, hits and misses. =over 8 =item B<--warning-*> Threshold warning. Can be: 'usage' (%), 'hits' (/s), 'misses' (/s). =item B<--critical-usage> Threshold critical. Can be: 'usage' (%), 'hits' (/s), 'misses' (/s). =back =cut centreon-plugins-20220113/centreon/common/riverbed/steelhead/snmp/mode/loadaverage.pm000066400000000000000000000116001417000230700306100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::riverbed::steelhead::snmp::mode::loadaverage; 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 } ]; $self->{maps_counters}->{global} = [ { label => 'average', nlabel => 'cpu.usage.percentage', set => { key_values => [ { name => 'cpuUtil1' } ], output_template => 'CPU Average: %.2f%%', perfdatas => [ { label => 'total_cpu_avg', template => '%.2f', min => 0, max => 100, unit => '%' } ] } }, { label => '1min', nlabel => 'cpu.1m.usage.percentage', set => { key_values => [ { name => 'cpuLoad1' } ], output_template => 'Load 1 min: %.2f', perfdatas => [ { label => 'load1', template => '%.2f', min => 0 } ] } }, { label => '5min', nlabel => 'cpu.5m.usage.percentage', set => { key_values => [ { name => 'cpuLoad5' } ], output_template => 'Load 5 min: %.2f', perfdatas => [ { label => 'load5', template => '%.2f', min => 0 } ] } }, { label => '15min', nlabel => 'cpu.15m.usage.percentage', set => { key_values => [ { name => 'cpuLoad15' } ], output_template => 'Load 15 min: %.2f', perfdatas => [ { label => 'load15', template => '%.2f', min => 0 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments =>{ }); return $self; } my $mappings = { common => { cpuLoad1 => { oid => '.1.3.6.1.4.1.17163.1.1.5.1.1' }, cpuLoad5 => { oid => '.1.3.6.1.4.1.17163.1.1.5.1.2' }, cpuLoad15 => { oid => '.1.3.6.1.4.1.17163.1.1.5.1.3' }, cpuUtil1 => { oid => '.1.3.6.1.4.1.17163.1.1.5.1.4' } }, ex => { cpuLoad1 => { oid => '.1.3.6.1.4.1.17163.1.51.5.1.1' }, cpuLoad5 => { oid => '.1.3.6.1.4.1.17163.1.51.5.1.2' }, cpuLoad15 => { oid => '.1.3.6.1.4.1.17163.1.51.5.1.3' }, cpuUtil1 => { oid => '.1.3.6.1.4.1.17163.1.51.5.1.4' } }, interceptor => { cpuLoad1 => { oid => '.1.3.6.1.4.1.17163.1.3.5.1.1' }, cpuLoad5 => { oid => '.1.3.6.1.4.1.17163.1.3.5.1.2' }, cpuLoad15 => { oid => '.1.3.6.1.4.1.17163.1.3.5.1.3' }, cpuUtil1 => { oid => '.1.3.6.1.4.1.17163.1.3.5.1.4' } }, }; my $oids = { common => '.1.3.6.1.4.1.17163.1.1.5.1', ex => '.1.3.6.1.4.1.17163.1.51.5.1', interceptor => '.1.3.6.1.4.1.17163.1.3.5.1' }; sub manage_selection { my ($self, %options) = @_; my $results = $options{snmp}->get_multiple_table( oids => [ { oid => $oids->{common}, start => $mappings->{common}->{cpuLoad1}->{oid}, end => $mappings->{common}->{cpuUtil1}->{oid} }, { oid => $oids->{ex}, start => $mappings->{ex}->{cpuLoad1}->{oid}, end => $mappings->{ex}->{cpuUtil1}->{oid} }, { oid => $oids->{interceptor}, start => $mappings->{interceptor}->{cpuLoad1}->{oid}, end => $mappings->{interceptor}->{cpuUtil1}->{oid} } ] ); foreach my $equipment (keys %{$oids}) { next if (!%{$results->{$oids->{$equipment}}}); my $result = $options{snmp}->map_instance(mapping => $mappings->{$equipment}, results => $results->{$oids->{$equipment}}, instance => 0); $self->{global} = { cpuLoad1 => $result->{cpuLoad1} / 100, cpuLoad5 => $result->{cpuLoad5} / 100, cpuLoad15 => $result->{cpuLoad15} / 100, cpuUtil1 => $result->{cpuUtil1}, }; } } 1; __END__ =head1 MODE Check system load average. =over 8 =item B<--warning-*> Warning thresholds Can be --warning-(average|1m|5m|15m) =item B<--critical-*> Critical thresholds Can be --critical-(average|1m|5m|15m) =back =cut centreon-plugins-20220113/centreon/common/riverbed/steelhead/snmp/mode/status.pm000066400000000000000000000124251417000230700276670ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::riverbed::steelhead::snmp::mode::status; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf( "Health is '%s', Status is '%s'", $self->{result_values}->{health}, $self->{result_values}->{status} ); } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{health} = $options{new_datas}->{$self->{instance} . '_health'}; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_serviceStatus'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_status_output' }, ]; $self->{maps_counters}->{global} = [ { label => 'status', type => 2, critical_default => '%{health} !~ /Healthy/ || %{status} !~ /running/', set => { key_values => [ { name => 'health' }, { name => 'serviceStatus' } ], 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 => \&catalog_status_threshold_ng } }, { label => 'uptime', set => { key_values => [ { name => 'serviceUptime' }, { name => 'serviceUptime_human' } ], output_template => 'Uptime: %s', output_use => 'serviceUptime_human', perfdatas => [ { label => 'uptime', template => '%d', min => 0, unit => 's' } ] } } ]; } sub prefix_status_output { my ($self, %options) = @_; return "Optimization Service "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my $mappings = { common => { health => { oid => '.1.3.6.1.4.1.17163.1.1.2.2' }, serviceStatus => { oid => '.1.3.6.1.4.1.17163.1.1.2.3' }, serviceUptime => { oid => '.1.3.6.1.4.1.17163.1.1.2.4' } }, ex => { health => { oid => '.1.3.6.1.4.1.17163.1.51.2.2' }, serviceStatus => { oid => '.1.3.6.1.4.1.17163.1.51.2.3' }, serviceUptime => { oid => '.1.3.6.1.4.1.17163.1.51.2.4' } }, interceptor => { health => { oid => '.1.3.6.1.4.1.17163.1.3.2.2' }, serviceStatus => { oid => '.1.3.6.1.4.1.17163.1.3.2.3' }, serviceUptime => { oid => '.1.3.6.1.4.1.17163.1.3.2.4' } }, }; my $oids = { common => '.1.3.6.1.4.1.17163.1.1.2', ex => '.1.3.6.1.4.1.17163.1.51.2', interceptor => '.1.3.6.1.4.1.17163.1.3.2' }; sub manage_selection { my ($self, %options) = @_; my $results = $options{snmp}->get_multiple_table( oids => [ { oid => $oids->{common}, start => $mappings->{common}->{health}->{oid}, end => $mappings->{common}->{serviceUptime}->{oid} }, { oid => $oids->{ex}, start => $mappings->{ex}->{health}->{oid}, end => $mappings->{ex}->{serviceUptime}->{oid} }, { oid => $oids->{interceptor}, start => $mappings->{interceptor}->{health}->{oid}, end => $mappings->{interceptor}->{serviceUptime}->{oid} } ] ); foreach my $equipment (keys %{$oids}) { next if (!%{$results->{$oids->{$equipment}}}); my $result = $options{snmp}->map_instance(mapping => $mappings->{$equipment}, results => $results->{$oids->{$equipment}}, instance => 0); $self->{global} = { health => $result->{health}, serviceStatus => $result->{serviceStatus}, serviceUptime => $result->{serviceUptime} / 100, serviceUptime_human => centreon::plugins::misc::change_seconds(value => $result->{serviceUptime} / 100), }; } } 1; __END__ =head1 MODE Check the current status of the optimization service. =over 8 =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{health}, %{status} =item B<--critical-status> Set critical threshold for status (Default: '%{health} !~ /Healthy/ || %{status} !~ /running/'). Can used special variables like: %{health}, %{status} =item B<--warning-uptime> Warning thresholds in seconds. =item B<--critical-uptime> Critical thresholds in seconds. =back =cut centreon-plugins-20220113/centreon/common/riverbed/steelhead/snmp/mode/temperature.pm000066400000000000000000000057621417000230700307070ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::riverbed::steelhead::snmp::mode::temperature; 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 }, ]; $self->{maps_counters}->{global} = [ { label => 'temperature', set => { key_values => [ { name => 'systemTemperature' } ], output_template => 'Temperature: %.2f C', perfdatas => [ { label => 'temperature', template => '%.2f', min => 0, unit => 'C' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments =>{ }); return $self; } my $mappings = { common => { systemTemperature => { oid => '.1.3.6.1.4.1.17163.1.1.2.9' }, }, ex => { systemTemperature => { oid => '.1.3.6.1.4.1.17163.1.51.2.9' }, } }; my $oids = { common => '.1.3.6.1.4.1.17163.1.1.2.9', ex => '.1.3.6.1.4.1.17163.1.51.2.9' }; sub manage_selection { my ($self, %options) = @_; my $results = $options{snmp}->get_multiple_table( oids => [ { oid => $oids->{common}, start => $mappings->{common}->{systemTemperature}->{oid}, end => $mappings->{common}->{systemTemperature}->{oid} }, { oid => $oids->{ex}, start => $mappings->{ex}->{systemTemperature}->{oid}, end => $mappings->{ex}->{systemTemperature}->{oid} } ] ); foreach my $equipment (keys %{$oids}) { next if (!%{$results->{$oids->{$equipment}}}); my $result = $options{snmp}->map_instance(mapping => $mappings->{$equipment}, results => $results->{$oids->{$equipment}}, instance => 0); $self->{global} = { systemTemperature => $result->{systemTemperature}, }; } } 1; __END__ =head1 MODE Check the temperature of the system in Celcius (STEELHEAD-MIB and STEELHEAD-EX-MIB). =over 8 =item B<--warning-temperature> Threshold warning for temperature in Celsius. =item B<--critical-temperature> Threshold critical for temperature in Celsius. =back =cut centreon-plugins-20220113/centreon/common/smcli/000077500000000000000000000000001417000230700214505ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/smcli/custom/000077500000000000000000000000001417000230700227625ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/smcli/custom/custom.pm000066400000000000000000000173021417000230700246350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::smcli::custom::custom; use strict; use warnings; use centreon::plugins::misc; sub new { my ($class, %options) = @_; my $self = {}; bless $self, $class; # $options{options} = options object # $options{output} = output object # $options{exit_value} = integer # $options{noptions} = integer 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 => { "smcli-command:s" => { name => 'smcli_command', default => 'SMcli' }, "smcli-path:s" => { name => 'smcli_path', }, "sudo:s" => { name => 'sudo', }, "extra-options:s@" => { name => 'extra_options' }, "special-arg:s@" => { name => 'special_arg' }, "hostname:s@" => { name => 'hostname' }, "hostname2:s@" => { name => 'hostname2' }, "password:s@" => { name => 'password' }, "timeout:s@" => { name => 'timeout' }, "show-output:s" => { name => 'show_output' }, }); } $options{options}->add_help(package => __PACKAGE__, sections => 'SMCLI OPTIONS', once => 1); $self->{output} = $options{output}; $self->{custommode_name} = $options{custommode_name}; # 1 means we use a file to read $self->{no_smclicmd} = 0; return $self; } # Method to manage multiples sub set_options { my ($self, %options) = @_; # options{options_result} $self->{option_results} = $options{option_results}; } # Method to manage multiples sub set_defaults { my ($self, %options) = @_; # options{default} # Manage default value foreach (keys %{$options{default}}) { if ($_ eq $self->{custommode_name}) { if (ref($options{default}->{$_}) eq 'ARRAY') { 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}; } } } } if (ref($options{default}->{$_}) eq 'HASH') { foreach my $opt (keys %{$options{default}->{$_}}) { if (!defined($self->{option_results}->{$opt})) { $self->{option_results}->{$opt} = $options{default}->{$_}->{$opt}; } } } } } } sub build_command { my ($self, %options) = @_; $self->{cmd} = ''; $self->{cmd} .= $self->{option_results}->{smcli_path} . '/' if (defined($self->{option_results}->{smcli_path})); $self->{cmd} .= $self->{option_results}->{smcli_command}; if (defined($self->{special_arg}) && $self->{special_arg} ne '') { $self->{cmd} .= ' ' . $self->{special_arg}; $self->{no_smclicmd} = 1; # It's ok if we use a file. return ; } if (!defined($self->{hostname})) { $self->{output}->add_option_msg(short_msg => "Need to specify hostname option."); $self->{output}->option_exit(); } $self->{cmd} .= " " . $self->{hostname}; $self->{cmd} .= " " . $self->{hostname2} if (defined($self->{hostname2})); $self->{cmd} .= " -p '" . $self->{password} . "'" if (defined($self->{password})); $self->{cmd} .= " " . $self->{extra_options} if (defined($self->{extra_options})); } sub check_options { my ($self, %options) = @_; # return 1 = ok still hostname # return 0 = no hostname left $self->{hostname} = (defined($self->{option_results}->{hostname})) ? shift(@{$self->{option_results}->{hostname}}) : undef; $self->{hostname2} = (defined($self->{option_results}->{hostname2})) ? shift(@{$self->{option_results}->{hostname2}}) : undef; $self->{password} = (defined($self->{option_results}->{password})) ? shift(@{$self->{option_results}->{password}}) : undef; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? shift(@{$self->{option_results}->{timeout}}) : 30; $self->{extra_options} = (defined($self->{option_results}->{extra_options})) ? shift(@{$self->{option_results}->{extra_options}}) : '-quick -S'; $self->{special_arg} = (defined($self->{option_results}->{special_arg})) ? shift(@{$self->{option_results}->{special_arg}}) : undef; $self->{sudo} = $self->{option_results}->{sudo}; $self->build_command(); if (!defined($self->{hostname}) || scalar(@{$self->{option_results}->{hostname}}) == 0) { return 0; } return 1; } ############## # Specific methods ############## sub execute_command { my ($self, %options) = @_; if ($self->{no_smclicmd} == 0) { $self->{cmd} .= " -c '" . $options{cmd} . "'"; } # Need to set timeout over command. $self->{option_results}->{timeout} = $self->{timeout}; my ($response, $exit_code) = centreon::plugins::misc::execute(output => $self->{output}, options => $self->{option_results}, sudo => $self->{sudo}, command => $self->{cmd}, command_path => undef, command_options => undef, no_quit => 1 ); if ($exit_code != 0) { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => "Command execution error (verbose mode for more details)"); $self->{output}->output_add(long_msg => $response); $self->{output}->display(); $self->{output}->exit(); } return $response; } 1; __END__ =head1 NAME Smcli =head1 SYNOPSIS my smcli manage =head1 SMCLI OPTIONS =over 8 =item B<--smcli-path> Specify smcli path (default: for dell '/opt/dell/mdstoragemanager/client', for ibm '/opt/IBM_DS/client') =item B<--smcli-command> Specify navicli command (default: 'SMcli'). =item B<--extra-option> Set SMcli extras options (Default: '-quick -S'). =item B<--sudo> Use 'sudo' to execute the command. =item B<--special-arg> Set a special argument for the command. To be used for set a file. (Need to change command and use 'cat' instead). =item B<--hostname> Set controller hostname. =item B<--hostname2> Set controller 2 hostname. =item B<--password> Password to connect. =item B<--timeout> Set timeout for system command (Default: '30'). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/centreon/common/smcli/mode/000077500000000000000000000000001417000230700223745ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/smcli/mode/healthstatus.pm000066400000000000000000000044221417000230700254450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::smcli::mode::healthstatus; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "storage-command:s" => { name => 'storage_command', }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my $smcli = $options{custom}; my $response = $smcli->execute_command(cmd => $self->{option_results}->{storage_command}); # IBM smcli: Storage Subsystem health status = optimal. # Dell smcli: Storage array health status = optimal. my $match_ok_regexp = 'health status.*optimal'; $self->{output}->output_add(severity => 'OK', short_msg => sprintf("storage health status is optimal")); if ($response !~ /$match_ok_regexp/msi) { $self->{output}->output_add(severity => 'CRITICAL', short_msg => sprintf("Some failures have been found (verbose mode for more details)")); $self->{output}->output_add(long_msg => $response); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check health status =over 8 =item B<--storage-command> By default for Dell MD: 'show storageArray healthstatus;' By default for IBM DS: 'show storageSubsystem healthstatus;' =back =cut centreon-plugins-20220113/centreon/common/sun/000077500000000000000000000000001417000230700211465ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/sun/snmp/000077500000000000000000000000001417000230700221235ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/sun/snmp/mode/000077500000000000000000000000001417000230700230475ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/sun/snmp/mode/components/000077500000000000000000000000001417000230700252345ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/sun/snmp/mode/components/entity.pm000066400000000000000000000163131417000230700271120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::sun::snmp::mode::components::entity; use strict; use warnings; my %map_class = ( 1 => 'other', 2 => 'unknown', 3 => 'chassis', 4 => 'backplane', 5 => 'container', 6 => 'powerSupply', 7 => 'fan', 8 => 'sensor', 9 => 'module', 10 => 'port', 11 => 'stack', ); my %map_oper_state = (1 => 'disabled', 2 => 'enabled'); my %map_alarm = ( 1 => 'critical', 2 => 'major', 3 => 'minor', 4 => 'indeterminate', 5 => 'warning', 6 => 'pending', 7 => 'cleared' ); my %map_sensor_type = (1 => 'other', 2 => 'unknown', 3 => 'temperature', 4 => 'voltage', 5 => 'current', 6 => 'tachometer', 7 => 'counter', 8 => 'switch', 9 => 'lock', 10 => 'humidity', 11 => 'smokeDetection', 12 => 'presence', 13 => 'airFlow'); my %mapping_units = ( 1 => 'unknown', 2 => 'unknown', 3 => 'celsius', 4 => 'fahrenheit', 5 => 'kelvin', 6 => 'volt', 7 => 'ampere', 8 => 'watt', 9 => 'Joules', 10 => 'Coulombs', 11 => 'VA', 12 => 'Nits', 13 => 'Lumens', 14 => 'Lux', 15 => 'Candelas', 16 => 'kPa', 17 => 'PSI', 18 => 'Newtons', 19 => 'CFM', 20 => 'rpm', 21 => 'Hz', # Hertz 22 => 'Seconds', 23 => 'Minutes', 24 => 'Hours', 25 => 'Days', 26 => 'Weeks', 27 => 'Mils', 28 => 'Inches', 29 => 'Feet', 30 => 'Cubic_Inches', 31 => 'CubicFeet', 32 => 'Meters', 33 => 'CubicCentimeters', 34 => 'CubicMeters', 35 => 'Liters', 36 => 'FluidOunces', 37 => 'Radians', 38 => 'Steradians', 39 => 'Revolutions', 40 => 'Cycles', 41 => 'Gravities', 42 => 'Ounces', 43 => 'Pounds', 44 => 'FootPounds', 45 => 'OunceInches', 46 => 'Gauss', 47 => 'Gilberts', 48 => 'Henries', 49 => 'Farads', 50 => 'Ohms', 51 => 'Siemens', 52 => 'Moles', 53 => 'Becquerels', 54 => 'PPM', 55 => 'Decibels', 56 => 'DbA', 57 => 'DbC', 58 => 'Grays', 59 => 'Sieverts', 60 => 'ColorTemperatureDegreesKelvin', 61 => 'bits', 62 => 'bytes', 63 => 'Words', 64 => 'DoubleWords', 65 => 'QuadWords', 66 => 'percentage', 67 => 'Pascals', ); my $mapping = { entPhysicalClass => { oid => '.1.3.6.1.2.1.47.1.1.1.1.5', map => \%map_class }, entPhysicalName => { oid => '.1.3.6.1.2.1.47.1.1.1.1.7' }, sunPlatEquipmentOperationalState => { oid => '.1.3.6.1.4.1.42.2.70.101.1.1.2.1.2', map => \%map_oper_state }, sunPlatEquipmentAlarmStatus => { oid => '.1.3.6.1.4.1.42.2.70.101.1.1.2.1.3', map => \%map_alarm }, sunPlatSensorType => { oid => '.1.3.6.1.4.1.42.2.70.101.1.1.6.1.2', map => \%map_sensor_type }, sunPlatNumericSensorBaseUnits => { oid => '.1.3.6.1.4.1.42.2.70.101.1.1.8.1.1', map => \%mapping_units }, sunPlatNumericSensorExponent => { oid => '.1.3.6.1.4.1.42.2.70.101.1.1.8.1.2' }, sunPlatNumericSensorCurrent => { oid => '.1.3.6.1.4.1.42.2.70.101.1.1.8.1.4' }, }; my $oid_sunPlatEquipmentEntry = '.1.3.6.1.4.1.42.2.70.101.1.1.2.1'; my $oid_sunPlatNumericSensorEntry = '.1.3.6.1.4.1.42.2.70.101.1.1.8.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping->{entPhysicalName}->{oid} }, { oid => $mapping->{entPhysicalClass}->{oid} }, { oid => $oid_sunPlatEquipmentEntry }, { oid => $oid_sunPlatNumericSensorEntry }, { oid => $mapping->{sunPlatSensorType}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking entities"); $self->{components}->{entity} = {name => 'entity', total => 0, skip => 0}; return if ($self->check_filter(section => 'entity')); my ($exit, $warn, $crit, $checked); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}})) { next if ($oid !~ /^$mapping->{entPhysicalName}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}, instance => $instance); next if ($self->check_filter(section => 'entity', instance => $result->{entPhysicalClass} . '.' . $instance)); next if ($result->{sunPlatEquipmentOperationalState} eq 'disabled'); if (defined($result->{sunPlatNumericSensorCurrent})) { $result->{sunPlatNumericSensorCurrent} *= 10 ** $result->{sunPlatNumericSensorExponent} } $self->{components}->{entity}->{total}++; $self->{output}->output_add(long_msg => sprintf("%s '%s' status is '%s' [instance = %s, value = %s]", $result->{entPhysicalClass}, $result->{entPhysicalName}, $result->{sunPlatEquipmentAlarmStatus}, $result->{entPhysicalClass} . '.' . $instance, defined($result->{sunPlatNumericSensorCurrent}) ? $result->{sunPlatNumericSensorCurrent} : '-')); $exit = $self->get_severity(label => 'default', section => 'entity', instance => $result->{entPhysicalClass} . '.' . $instance, value => $result->{sunPlatEquipmentAlarmStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("%s '%s' status is '%s'", $result->{entPhysicalClass}, $result->{entPhysicalName}, $result->{sunPlatEquipmentAlarmStatus})); } next if (!defined($result->{sunPlatNumericSensorCurrent})); ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => $result->{sunPlatSensorType}, instance => $result->{entPhysicalClass} . '.' . $instance,, value => $result->{sunPlatNumericSensorCurrent}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("%s '%s' is '%s' %s", $result->{sunPlatSensorType}, $result->{entPhysicalName}, $result->{sunPlatNumericSensorCurrent}, $result->{sunPlatNumericSensorBaseUnits})); } $self->{output}->perfdata_add( label => $result->{sunPlatSensorType}, unit => $result->{sunPlatNumericSensorBaseUnits}, nlabel => 'hardware.entity.' . $result->{sunPlatSensorType} . '.' . lc($result->{sunPlatNumericSensorBaseUnits}), instances => $result->{entPhysicalName}, value => $result->{sunPlatNumericSensorCurrent}, warning => $warn, critical => $crit ); } } 1; centreon-plugins-20220113/centreon/common/sun/snmp/mode/hardware.pm000066400000000000000000000055571417000230700252160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::sun::snmp::mode::hardware; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^(other|unknown|temperature|voltage|current|tachometer|counter|switch|lock|humidity|smokeDetection|presence|airFlow)$'; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { default => [ ['critical', 'CRITICAL'], ['major', 'CRITICAL'], ['minor', 'WARNING'], ['indeterminate', 'OK'], ['warning', 'WARNING'], ['pending', 'OK'], ['cleared', 'OK'], ], }; $self->{components_path} = 'centreon::common::sun::snmp::mode::components'; $self->{components_module} = ['entity']; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}, return_type => 1); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_absent => 1); bless $self, $class; $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: 'entity'. =item B<--filter> Exclude some parts (comma seperated list) Can also exclude specific instance: --filter=entity,sensor.18 =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='entity,sensor..*,CRITICAL,minor' =item B<--warning> Set warning threshold (syntax: type,regexp,threshold) Example: --warning='temperature,.*,20' =item B<--critical> Set critical threshold (syntax: type,regexp,threshold) Example: --critical='temperature,.*,30' =back =cut centreon-plugins-20220113/centreon/common/violin/000077500000000000000000000000001417000230700216415ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/violin/snmp/000077500000000000000000000000001417000230700226165ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/violin/snmp/mode/000077500000000000000000000000001417000230700235425ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/violin/snmp/mode/components/000077500000000000000000000000001417000230700257275ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/violin/snmp/mode/components/ca.pm000066400000000000000000000043361417000230700266560ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::violin::snmp::mode::components::ca; use base qw(centreon::plugins::mode); use strict; use warnings; my $oid_chassisSystemLedAlarm = '.1.3.6.1.4.1.35897.1.2.2.3.17.1.7'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_chassisSystemLedAlarm }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking chassis alarm"); $self->{components}->{ca} = {name => 'chassis alarm', total => 0, skip => 0}; return if ($self->check_filter(section => 'ca')); foreach my $oid (keys %{$self->{results}->{$oid_chassisSystemLedAlarm}}) { $oid =~ /^$oid_chassisSystemLedAlarm\.(.*)$/; my ($dummy, $array_name) = $self->convert_index(value => $1); my $instance = $array_name; my $ca_state = $self->{results}->{$oid_chassisSystemLedAlarm}->{$oid}; next if ($self->check_filter(section => 'ca', instance => $instance)); $self->{components}->{ca}->{total}++; $self->{output}->output_add(long_msg => sprintf("Chassis alarm '%s' is %s.", $instance, $ca_state)); my $exit = $self->get_severity(section => 'ca', value => $ca_state); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Chassis alarm '%s' is %s", $instance, $ca_state)); } } } 1; centreon-plugins-20220113/centreon/common/violin/snmp/mode/components/fan.pm000066400000000000000000000045401417000230700270340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::violin::snmp::mode::components::fan; use base qw(centreon::plugins::mode); use strict; use warnings; my $oid_arrayFanEntry_speed = '.1.3.6.1.4.1.35897.1.2.2.3.18.1.3'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_arrayFanEntry_speed }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking fans"); $self->{components}->{fan} = {name => 'fans', total => 0, skip => 0}; return if ($self->check_filter(section => 'fan')); foreach my $oid (keys %{$self->{results}->{$oid_arrayFanEntry_speed}}) { $oid =~ /^$oid_arrayFanEntry_speed\.(.*)$/; my ($dummy, $array_name, $fan_name) = $self->convert_index(value => $1); my $instance = $array_name . '-' . $fan_name; my $fan_state = $self->{results}->{$oid_arrayFanEntry_speed}->{$oid}; next if ($self->check_filter(section => 'fan', instance => $instance)); next if ($fan_state =~ /Absent/i && $self->absent_problem(section => 'fan', instance => $instance)); $self->{components}->{fan}->{total}++; $self->{output}->output_add(long_msg => sprintf("Fan '%s' state is %s.", $instance, $fan_state)); my $exit = $self->get_severity(section => 'fan', value => $fan_state); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Fan '%s' state is %s", $instance, $fan_state)); } } } 1; centreon-plugins-20220113/centreon/common/violin/snmp/mode/components/gfc.pm000066400000000000000000000050561417000230700270320ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::violin::snmp::mode::components::gfc; use base qw(centreon::plugins::mode); use strict; use warnings; my $oid_globalTargetFcEntry = '.1.3.6.1.4.1.35897.1.2.1.10.1'; my $oid_wwn = '.1.3.6.1.4.1.35897.1.2.1.10.1.3'; my $oid_enable = '.1.3.6.1.4.1.35897.1.2.1.10.1.4'; my $oid_portState = '.1.3.6.1.4.1.35897.1.2.1.10.1.8'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_globalTargetFcEntry }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking global fc"); $self->{components}->{gfc} = {name => 'global fc', total => 0, skip => 0}; return if ($self->check_filter(section => 'gfc')); foreach my $oid (keys %{$self->{results}->{$oid_globalTargetFcEntry}}) { next if ($oid !~ /^$oid_wwn\.(.*)$/); my $wwn = $self->{results}->{$oid_globalTargetFcEntry}->{$oid}; my $enable = $self->{results}->{$oid_globalTargetFcEntry}->{$oid_enable . '.' .$1}; my $state = $self->{results}->{$oid_globalTargetFcEntry}->{$oid_portState . '.' .$1}; if ($enable == 2) { $self->{output}->output_add(long_msg => sprintf("Skipping instance '$wwn' (not enable)")); next; } next if ($self->check_filter(section => 'gfc', instance => $wwn)); $self->{components}->{gfc}->{total}++; $self->{output}->output_add(long_msg => sprintf("Global FC '%s' is %s.", $wwn, $state)); my $exit = $self->get_severity(section => 'gfc', value => $state); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Global FC '%s' is %s", $wwn, $state)); } } } 1; centreon-plugins-20220113/centreon/common/violin/snmp/mode/components/lfc.pm000066400000000000000000000050401417000230700270300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::violin::snmp::mode::components::lfc; use base qw(centreon::plugins::mode); use strict; use warnings; my $oid_localTargetFcEntry = '.1.3.6.1.4.1.35897.1.2.1.6.1'; my $oid_wwn = '.1.3.6.1.4.1.35897.1.2.1.6.1.2'; my $oid_enable = '.1.3.6.1.4.1.35897.1.2.1.6.1.3'; my $oid_portState = '.1.3.6.1.4.1.35897.1.2.1.6.1.7'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_localTargetFcEntry }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking local fc"); $self->{components}->{lfc} = {name => 'local fc', total => 0, skip => 0}; return if ($self->check_filter(section => 'lfc')); foreach my $oid (keys %{$self->{results}->{$oid_localTargetFcEntry}}) { next if ($oid !~ /^$oid_wwn\.(.*)$/); my $wwn = $self->{results}->{$oid_localTargetFcEntry}->{$oid}; my $enable = $self->{results}->{$oid_localTargetFcEntry}->{$oid_enable . '.' .$1}; my $state = $self->{results}->{$oid_localTargetFcEntry}->{$oid_portState . '.' .$1}; if ($enable == 2) { $self->{output}->output_add(long_msg => sprintf("Skipping instance '$wwn' (not enable)")); next; } next if ($self->check_filter(section => 'lfc', instance => $wwn)); $self->{components}->{lfc}->{total}++; $self->{output}->output_add(long_msg => sprintf("Local FC '%s' is %s.", $wwn, $state)); my $exit = $self->get_severity(section => 'lfc', value => $state); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Local FC '%s' is %s", $wwn, $state)); } } } 1; centreon-plugins-20220113/centreon/common/violin/snmp/mode/components/psu.pm000066400000000000000000000056611417000230700271040ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::violin::snmp::mode::components::psu; use base qw(centreon::plugins::mode); use strict; use warnings; my $oid_chassisSystemPowerPSUA = '.1.3.6.1.4.1.35897.1.2.2.3.17.1.17'; my $oid_chassisSystemPowerPSUB = '.1.3.6.1.4.1.35897.1.2.2.3.17.1.18'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_chassisSystemPowerPSUA }, { oid => $oid_chassisSystemPowerPSUB }; } sub psu { my ($self, %options) = @_; my $oid = $options{oid}; $options{oid} =~ /^$options{oid_short}\.(.*)$/; my ($dummy, $array_name) = $self->convert_index(value => $1); my $instance = $array_name . '-' . $options{extra_instance}; my $psu_state = $options{value}; return if ($self->check_filter(section => 'psu', instance => $instance)); return if ($psu_state =~ /Absent/i && $self->absent_problem(section => 'psu', instance => $instance)); $self->{components}->{psu}->{total}++; $self->{output}->output_add(long_msg => sprintf("Power Supply '%s' status is %s.", $instance, $psu_state)); my $exit = $self->get_severity(section => 'psu', value => $psu_state); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Power Supply '%s' status is %s", $instance, $psu_state)); } } 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')); foreach my $oid (keys %{$self->{results}->{$oid_chassisSystemPowerPSUA}}) { psu($self, oid => $oid, oid_short => $oid_chassisSystemPowerPSUA, value => $self->{results}->{$oid_chassisSystemPowerPSUA}->{$oid}, extra_instance => 'A'); } foreach my $oid (keys %{$self->{results}->{$oid_chassisSystemPowerPSUB}}) { psu($self, oid => $oid, oid_short => $oid_chassisSystemPowerPSUB, value => $self->{results}->{$oid_chassisSystemPowerPSUB}->{$oid}, extra_instance => 'B'); } } 1; centreon-plugins-20220113/centreon/common/violin/snmp/mode/components/temperature.pm000066400000000000000000000071761417000230700306350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::violin::snmp::mode::components::temperature; use base qw(centreon::plugins::mode); use strict; use warnings; my $oid_chassisSystemTempAmbient = '.1.3.6.1.4.1.35897.1.2.2.3.17.1.21'; my $oid_chassisSystemTempController = '.1.3.6.1.4.1.35897.1.2.2.3.17.1.21'; my $oid_arrayVimmEntry_temp = '.1.3.6.1.4.1.35897.1.2.2.3.16.1.12'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_arrayVimmEntry_temp }, { oid => $oid_chassisSystemTempAmbient }, { oid => $oid_chassisSystemTempController }; } sub temperature { my ($self, %options) = @_; my $oid = $options{oid}; $options{oid} =~ /^$options{oid_short}\.(.*)$/; my ($dummy, $array_name, $extra_name) = $self->convert_index(value => $1); my $instance = $array_name . '-' . (defined($extra_name) ? $extra_name : $options{extra_instance}); my $temperature = $options{value}; return if ($self->check_filter(section => 'temperature', instance => $instance)); $self->{components}->{temperature}->{total}++; $self->{output}->output_add(long_msg => sprintf("Temperature '%s' is %s degree centigrade.", $instance, $temperature)); my ($exit, $warn, $crit) = $self->get_severity_numeric(section => 'temperature', instance => $instance, value => $temperature); $self->{output}->perfdata_add( label => 'temp', unit => 'C', nlabel => 'hardware.temperature.celsius', instances => $instance, value => $temperature, warning => $warn, critical => $crit ); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Temperature '%s' is %s degree centigrade", $instance, $temperature)); } } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking temperatures"); $self->{components}->{temperature} = {name => 'temperatures', total => 0, skip => 0}; return if ($self->check_filter(section => 'temperature')); foreach my $oid (keys %{$self->{results}->{$oid_chassisSystemTempAmbient}}) { temperature($self, oid => $oid, oid_short => $oid_chassisSystemTempAmbient, value => $self->{results}->{$oid_chassisSystemTempAmbient}->{$oid}, extra_instance => 'ambient'); } foreach my $oid (keys %{$self->{results}->{$oid_chassisSystemTempController}}) { temperature($self, oid => $oid, oid_short => $oid_chassisSystemTempController, value => $self->{results}->{$oid_chassisSystemTempController}->{$oid}, extra_instance => 'controller'); } foreach my $oid (keys %{$self->{results}->{$oid_arrayVimmEntry_temp}}) { temperature($self, oid => $oid, oid_short => $oid_arrayVimmEntry_temp, value => $self->{results}->{$oid_arrayVimmEntry_temp}->{$oid}); } } 1; centreon-plugins-20220113/centreon/common/violin/snmp/mode/components/vimm.pm000066400000000000000000000054231417000230700272410ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::violin::snmp::mode::components::vimm; use base qw(centreon::plugins::mode); use strict; use warnings; my $oid_arrayVimmEntry_present = '.1.3.6.1.4.1.35897.1.2.2.3.16.1.4'; my $oid_arrayVimmEntry_failed = '.1.3.6.1.4.1.35897.1.2.2.3.16.1.10'; my %map_vimm_state = ( 1 => 'failed', 2 => 'not failed', ); my %map_vimm_present = ( 1 => 'present', 2 => 'absent', ); sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_arrayVimmEntry_present }, { oid => $oid_arrayVimmEntry_failed }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking vimms"); $self->{components}->{vimm} = {name => 'vimms', total => 0, skip => 0}; return if ($self->check_filter(section => 'vimm')); foreach my $oid (keys %{$self->{results}->{$oid_arrayVimmEntry_present}}) { next if ($oid !~ /^$oid_arrayVimmEntry_present\.(.*)$/); my $state = $self->{results}->{$oid_arrayVimmEntry_failed}->{$oid_arrayVimmEntry_failed . '.' . $1}; my $present = $self->{results}->{$oid_arrayVimmEntry_present}->{$oid}; my ($dummy, $array_name, $vimm_name) = $self->convert_index(value => $1); my $instance = $array_name . '-' . $vimm_name; next if ($self->check_filter(section => 'vimm', instance => $instance)); next if ($map_vimm_present{$present} =~ /Absent/i && $self->absent_problem(section => 'vimm', instance => $instance)); $self->{components}->{vimm}->{total}++; $self->{output}->output_add(long_msg => sprintf("Vimm '%s' is %s.", $instance, $map_vimm_state{$state})); my $exit = $self->get_severity(section => 'vimm', value => $map_vimm_state{$state}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Vimm '%s' is %s", $instance, $map_vimm_state{$state})); } } } 1; centreon-plugins-20220113/centreon/common/violin/snmp/mode/hardware.pm000066400000000000000000000107061417000230700257010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::violin::snmp::mode::hardware; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^(temperature)$'; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { vimm => [ ['not failed', 'OK'], ['failed', 'CRITICAL'], ], ca => [ ['ON', 'CRITICAL'], ['OFF', 'OK'], ], psu => [ ['OFF', 'CRITICAL'], ['Absent', 'OK'], ['ON', 'OK'], ], fan => [ ['OFF', 'CRITICAL'], ['Absent', 'OK'], ['Low', 'OK'], ['Medium', 'OK'], ['High', 'WARNING'], ], gfc => [ ['Online', 'OK'], ['Unconfigured', 'OK'], ['Unknown', 'UNKNOWN'], ['Not\s*Supported', 'WARNING'], ['Dead', 'CRITICAL'], ['Lost', 'CRITICAL'], ['Failover\s*Failed', 'CRITICAL'], ['Failover', 'WARNING'], ], lfc => [ ['Online', 'OK'], ['Unconfigured', 'OK'], ['Unknown', 'UNKNOWN'], ['Not\s*Supported', 'WARNING'], ['Dead', 'CRITICAL'], ['Lost', 'CRITICAL'], ['Failover\s*Failed', 'CRITICAL'], ['Failover', 'WARNING'], ], }; $self->{components_path} = 'centreon::common::violin::snmp::mode::components'; $self->{components_module} = ['ca', 'psu', 'fan', 'vimm', 'temperature', 'gfc', 'lfc']; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub convert_index { my ($self, %options) = @_; my @results = (); my $separator = 32; my $result = ''; foreach (split /\./, $options{value}) { if ($_ < $separator) { push @results, $result; $result = ''; } else { $result .= chr; } } push @results, $result; return @results; } 1; __END__ =head1 MODE Check components (Fans, Power Supplies, Temperatures, Chassis alarm, vimm, global fc, local fc). =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'psu', 'fan', 'ca', 'vimm', 'lfc', 'gfc', 'temperature'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=fan --filter=psu) Can also exclude specific instance: --filter=fan,41239F00647-A =item B<--absent-problem> Return an error if an entity is not 'present' (default is skipping) (comma seperated list) Can be specific or global: --absent-problem=fan,41239F00647-fan02 =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='gfc,CRITICAL,^(?!(Online)$)' =item B<--warning> Set warning threshold for temperatures (syntax: type,regexp,threshold) Example: --warning='temperature,41239F00647-vimm46,20' --warning='temperature,41239F00647-vimm5.*,30' =item B<--critical> Set critical threshold for temperatures (syntax: type,regexp,threshold) Example: --critical='temperature,.*,25' --warning='temperature,.*,35' =back =cut centreon-plugins-20220113/centreon/common/xppc/000077500000000000000000000000001417000230700213135ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/xppc/snmp/000077500000000000000000000000001417000230700222705ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/xppc/snmp/mode/000077500000000000000000000000001417000230700232145ustar00rootroot00000000000000centreon-plugins-20220113/centreon/common/xppc/snmp/mode/batterystatus.pm000066400000000000000000000133061417000230700264730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::xppc::snmp::mode::batterystatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf("battery status is '%s'", $self->{result_values}->{status}); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'status', type => 2, unknown_default => '%{status} =~ /unknown/i', warning_default => '%{status} =~ /low/i', set => { key_values => [ { name => 'status' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'charge-remaining', , nlabel => 'battery.charge.remaining.percent', set => { key_values => [ { name => 'upsSmartBatteryCapacity' } ], output_template => 'remaining capacity: %s %%', perfdatas => [ { template => '%s', min => 0, max => 100, unit => '%' } ] } }, { label => 'charge-remaining-minutes', nlabel => 'battery.charge.remaining.minutes', display_ok => 0, set => { key_values => [ { name => 'upsSmartBatteryRunTimeRemaining' } ], output_template => 'remaining time: %s minutes', perfdatas => [ { template => '%s', min => 0, unit => 'm' } ] } }, { label => 'voltage', nlabel => 'battery.voltage.volt', display_ok => 0, set => { key_values => [ { name => 'upsSmartBatteryVoltage', no_value => 0 } ], output_template => 'voltage: %s V', perfdatas => [ { template => '%s', unit => 'V' } ] } }, { label => 'temperature', nlabel => 'battery.temperature.celsius', display_ok => 0, set => { key_values => [ { name => 'upsSmartBatteryTemperature', no_value => 0 } ], output_template => 'temperature: %s C', perfdatas => [ { template => '%s', unit => 'C' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my $map_battery_status = { 1 => 'unknown', 2 => 'normal', 3 => 'low' }; my $mapping = { batteryNormal => { oid => '.1.3.6.1.4.1.935.1.1.1.2.1.1', map => $map_battery_status }, upsSmartBatteryVoltage => { oid => '.1.3.6.1.4.1.935.1.1.1.2.2.2' }, # in dV upsSmartBatteryTemperature => { oid => '.1.3.6.1.4.1.935.1.1.1.2.2.3' }, # in tenth of celsius upsSmartBatteryRunTimeRemaining => { oid => '.1.3.6.1.4.1.935.1.1.1.2.2.4' }, # in seconds upsSmartBatteryCapacity => { oid => '.1.3.6.1.4.1.935.1.1.1.2.2.1' } }; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_leef( oids => [ map($_->{oid} . '.0', values(%$mapping)) ], nothing_quit => 1 ); my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => '0'); $result->{upsSmartBatteryVoltage} = defined($result->{upsSmartBatteryVoltage}) ? $result->{upsSmartBatteryVoltage} * 0.1 : 0; $result->{upsSmartBatteryTemperature} = defined($result->{upsSmartBatteryTemperature}) ? $result->{upsSmartBatteryTemperature} * 0.1 : 0; $result->{upsSmartBatteryRunTimeRemaining} = defined($result->{upsSmartBatteryRunTimeRemaining}) && $result->{upsSmartBatteryRunTimeRemaining} != 0 ? int($result->{upsSmartBatteryRunTimeRemaining} / 60) : undef; $result->{status} = $result->{batteryNormal}; $self->{global} = $result; } 1; __END__ =head1 MODE Check battery status. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='status|current' =item B<--unknown-status> Set unknown threshold for status (Default: '%{status} =~ /unknown/i'). Can used special variables like: %{status}. =item B<--warning-status> Set warning threshold for status (Default: '%{status} =~ /low/i'). Can used special variables like: %{status}. =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{status}. =item B<--warning-*> B<--critical-*> Thresholds. Can be: Can be: 'charge-remaining' (%), 'charge-remaining-minutes', 'temperature' (C), 'voltage' (V). =back =cut centreon-plugins-20220113/centreon/common/xppc/snmp/mode/inputlines.pm000066400000000000000000000061211417000230700257440ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::xppc::snmp::mode::inputlines; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_global_output { my ($self, %options) = @_; return 'Input lines '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ { label => 'frequence', nlabel => 'lines.input.frequence.hertz', set => { key_values => [ { name => 'upsSmartInputFrequency', no_value => 0 } ], output_template => 'frequence: %.2f Hz', perfdatas => [ { template => '%.2f', unit => 'Hz' } ] } }, { label => 'voltage', nlabel => 'lines.input.voltage.volt', set => { key_values => [ { name => 'upsSmartInputLineVoltage', no_value => 0 } ], output_template => 'voltage: %s V', perfdatas => [ { template => '%s', unit => 'V' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my $mapping = { upsSmartInputLineVoltage => { oid => '.1.3.6.1.4.1.935.1.1.1.3.2.1' }, # in dV upsSmartInputFrequency => { oid => '.1.3.6.1.4.1.935.1.1.1.3.2.4' } # in tenth of Hz }; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_leef( oids => [ map($_->{oid} . '.0', values(%$mapping)) ], nothing_quit => 1 ); my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => '0'); $result->{upsSmartInputLineVoltage} = defined($result->{upsSmartInputLineVoltage}) ? $result->{upsSmartInputLineVoltage} * 0.1 : 0; $result->{upsSmartInputFrequency} = defined($result->{upsSmartInputFrequency}) ? $result->{upsSmartInputFrequency} * 0.1 : 0; $self->{global} = $result; } 1; __END__ =head1 MODE Check input lines metrics. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'frequence', 'voltage'. =back =cut centreon-plugins-20220113/centreon/common/xppc/snmp/mode/outputlines.pm000066400000000000000000000120701417000230700261450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::common::xppc::snmp::mode::outputlines; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf("status is '%s'", $self->{result_values}->{status}); } sub prefix_global_output { my ($self, %options) = @_; return 'Output lines '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'status', type => 2, unknown_default => '%{status} =~ /unknown/i', warning_default => '%{status} =~ /rebooting|onBypass/i', critical_default => '%{status} =~ /onBattery/i', set => { key_values => [ { name => 'status' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'load', nlabel => 'lines.output.load.percentage', set => { key_values => [ { name => 'upsSmartOutputLoad', no_value => -1 } ], output_template => 'load: %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100 } ] } }, { label => 'frequence', nlabel => 'lines.output.frequence.hertz', set => { key_values => [ { name => 'upsSmartOutputFrequency', no_value => 0 } ], output_template => 'frequence: %.2f Hz', perfdatas => [ { template => '%.2f', unit => 'Hz' } ] } }, { label => 'voltage', nlabel => 'lines.output.voltage.volt', set => { key_values => [ { name => 'upsSmartOutputVoltage', no_value => 0 } ], output_template => 'voltage: %s V', perfdatas => [ { template => '%s', unit => 'V' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my $map_status = { 1 => 'unknown', 2 => 'onLine', 3 => 'onBattery', 4 => 'onBoost', 5 => 'sleeping', 6 => 'onBypass', 7 => 'rebooting', 8 => 'standBy', 9 => 'onBuck' }; my $mapping = { upsBaseOutputStatus => { oid => '.1.3.6.1.4.1.935.1.1.1.4.1.1', map => $map_status }, upsSmartOutputVoltage => { oid => '.1.3.6.1.4.1.935.1.1.1.4.2.1' }, # in dV upsSmartOutputFrequency => { oid => '.1.3.6.1.4.1.935.1.1.1.4.2.2' }, # in tenth of Hz upsSmartOutputLoad => { oid => '.1.3.6.1.4.1.935.1.1.1.4.2.3' } # in % }; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_leef( oids => [ map($_->{oid} . '.0', values(%$mapping)) ], nothing_quit => 1 ); my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => '0'); $result->{upsSmartOutputFrequency} = defined($result->{upsSmartOutputFrequency}) ? $result->{upsSmartOutputFrequency} * 0.1 : 0; $result->{upsSmartOutputVoltage} = defined($result->{upsSmartOutputVoltage}) ? $result->{upsSmartOutputVoltage} * 0.1 : 0; $result->{status} = $result->{upsBaseOutputStatus}; $self->{global} = $result; } 1; __END__ =head1 MODE Check output lines metrics. =over 8 =item B<--unknown-status> Set unknown threshold for status (Default: '%{status} =~ /unknown/i'). Can used special variables like: %{status}. =item B<--warning-status> Set warning threshold for status (Default: '%{status} =~ /rebooting|onBypass/i'). Can used special variables like: %{status}. =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /onBattery/i'). Can used special variables like: %{status}. =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'load', 'voltage', 'current', 'power'. =back =cut centreon-plugins-20220113/centreon/plugins/000077500000000000000000000000001417000230700205325ustar00rootroot00000000000000centreon-plugins-20220113/centreon/plugins/alternative/000077500000000000000000000000001417000230700230505ustar00rootroot00000000000000centreon-plugins-20220113/centreon/plugins/alternative/FatPackerOptions.pm000066400000000000000000000033511417000230700266240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::alternative::FatPackerOptions; use base qw(centreon::plugins::options); use strict; use warnings; use Pod::Usage; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; return $self; } sub display_help { my ($self, %options) = @_; my $stdout; foreach (@{$self->{pod_package}}) { { my $pp = $_->{package} . ".pm"; $pp =~ s{::}{/}g; my $content_class = $INC{$pp}->{$pp}; open my $str_fh, '<', \$content_class; local *STDOUT; open STDOUT, '>', \$stdout; pod2usage(-exitval => 'NOEXIT', -input => $str_fh, -verbose => 99, -sections => $_->{sections}); close $str_fh; } $self->{output}->add_option_msg(long_msg => $stdout) if (defined($stdout)); } } 1; __END__ centreon-plugins-20220113/centreon/plugins/alternative/Getopt.pm000066400000000000000000000066741417000230700246650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::alternative::Getopt; use strict; use warnings; use Exporter; use vars qw(@ISA @EXPORT @EXPORT_OK); @ISA = qw(Exporter); BEGIN { @EXPORT = qw(&GetOptions); @EXPORT_OK = qw(); } use vars @EXPORT, @EXPORT_OK; our $warn_message = 0; sub get_assigned_value { my (%options) = @_; if (!defined($options{val}) || $options{val} eq '') { # Add defined also. Hardened code: already see: $ARGV[6] = undef for example if ($options{pos} + 1 < $options{num_args} && defined($ARGV[$options{pos} + 1]) && $ARGV[$options{pos} + 1] !~ /^--/) { my $val = $ARGV[$options{pos} + 1]; splice @ARGV, $options{pos} + 1, 1; return ($options{num_args} - 1, $val); } else { return ($options{num_args}, ''); } } return ($options{num_args}, $options{val}); } sub GetOptions { my (%opts) = @_; my $search_str = ',' . join(',', keys %opts) . ','; my $num_args = scalar(@ARGV); for (my $i = 0; $i < $num_args;) { if (defined($ARGV[$i]) && $ARGV[$i] =~ /^--(.*?)(?:=|$)((?s).*)/) { my ($option, $value) = ($1, $2); # find type of option if ($search_str !~ /,((?:[^,]*?\|){0,}$option(?:\|.*?){0,}(:.*?){0,1}),/) { warn "Unknown option: $option" if ($warn_message == 1); $i++; next; } my ($option_selected, $type_opt) = ($1, $2); if (!defined($type_opt)) { ${$opts{$option_selected}} = 1; } elsif ($type_opt =~ /:s$/) { ($num_args, my $assigned) = get_assigned_value(num_args => $num_args, pos => $i, val => $value); ${$opts{$option_selected}} = $assigned; } elsif ($type_opt =~ /:s\@$/) { ${$opts{$option . $type_opt}} = [] if (!defined(${$opts{$option . $type_opt}})); ($num_args, my $assigned) = get_assigned_value(num_args => $num_args, pos => $i, val => $value); push @{${$opts{$option_selected}}}, $assigned; } elsif ($type_opt =~ /:s\%$/) { ${$opts{$option . $type_opt}} = {} if (!defined(${$opts{$option . $type_opt}})); ($num_args, my $assigned) = get_assigned_value(num_args => $num_args, pos => $i, val => $value); if ($assigned =~ /^(.*?)=(.*)/) { ${$opts{$option_selected}}->{$1} = $2; } } splice @ARGV, $i, 1; $num_args--; } else { warn "argument $ARGV[$i] alone" if ($warn_message == 1 && $i != 0 && defined($ARGV[$i])); $i++; } } } 1; __END__ centreon-plugins-20220113/centreon/plugins/backend/000077500000000000000000000000001417000230700221215ustar00rootroot00000000000000centreon-plugins-20220113/centreon/plugins/backend/http/000077500000000000000000000000001417000230700231005ustar00rootroot00000000000000centreon-plugins-20220113/centreon/plugins/backend/http/curl.pm000066400000000000000000000512101417000230700244020ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::backend::http::curl; use strict; use warnings; use URI; use centreon::plugins::misc; sub new { my ($class, %options) = @_; my $self = {}; bless $self, $class; if (!defined($options{noptions}) || $options{noptions} != 1) { $options{options}->add_options(arguments => { 'curl-opt:s@' => { name => 'curl_opt' } }); $options{options}->add_help(package => __PACKAGE__, sections => 'BACKEND CURL OPTIONS', once => 1); } $self->{output} = $options{output}; return $self; } sub check_options { my ($self, %options) = @_; centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'Net::Curl::Easy', error_msg => "Cannot load module 'Net::Curl::Easy'." ); centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'centreon::plugins::backend::http::curlconstants', error_msg => "Cannot load module 'centreon::plugins::backend::http::curlconstants'." ); $self->{constant_cb} = \¢reon::plugins::backend::http::curlconstants::get_constant_value; foreach (('unknown_status', 'warning_status', 'critical_status')) { if (defined($options{request}->{$_})) { $options{request}->{$_} =~ s/%\{http_code\}/\$values->{code}/g; } } if (!defined($options{request}->{curl_opt})) { $options{request}->{curl_opt} = []; } } my $http_code_explained = { 100 => 'Continue', 101 => 'Switching Protocols', 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 306 => '(Unused)', 307 => 'Temporary Redirect', 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Timeout', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Long', 415 => 'Unsupported Media Type', 416 => 'Requested Range Not Satisfiable', 417 => 'Expectation Failed', 450 => 'Timeout reached', # custom code 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Timeout', 505 => 'HTTP Version Not Supported' }; sub cb_debug { my ($easy, $type, $data, $uservar) = @_; my $msg = ''; if ($type == $uservar->{constant_cb}->(name => 'CURLINFO_TEXT')) { $msg = sprintf("== Info: %s", $data); } if ($type == $uservar->{constant_cb}->(name => 'CURLINFO_HEADER_OUT')) { $msg = sprintf("=> Send header: %s", $data); } if ($type == $uservar->{constant_cb}->(name => 'CURLINFO_DATA_OUT')) { $msg = sprintf("=> Send data: %s", $data); } if ($type == $uservar->{constant_cb}->(name => 'CURLINFO_HEADER_IN')) { $msg = sprintf("=> Recv header: %s", $data); } if ($type == $uservar->{constant_cb}->(name => 'CURLINFO_DATA_IN')) { $msg = sprintf("=> Recv data: %s", $data); } return 0 if ($type == $uservar->{constant_cb}->(name => 'CURLINFO_SSL_DATA_OUT')); return 0 if ($type == $uservar->{constant_cb}->(name => 'CURLINFO_SSL_DATA_IN')); $uservar->{output}->output_add(long_msg => $msg, debug => 1); return 0; } sub curl_setopt { my ($self, %options) = @_; eval { $self->{curl_easy}->setopt($options{option}, $options{parameter}); }; if ($@) { $self->{output}->add_option_msg(short_msg => "curl setopt error: '" . $@ . "'."); $self->{output}->option_exit(); } } sub set_method { my ($self, %options) = @_; $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_CUSTOMREQUEST'), parameter => undef); $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_POSTFIELDS'), parameter => undef); $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_HTTPGET'), parameter => 1); if ($options{content_type_forced} == 1) { $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_POSTFIELDS'), parameter => $options{request}->{query_form_post}) if (defined($options{request}->{query_form_post})); } elsif (defined($options{request}->{post_params})) { my $uri_post = URI->new(); $uri_post->query_form($options{request}->{post_params}); push @{$options{headers}}, 'Content-Type: application/x-www-form-urlencoded'; $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_POSTFIELDS'), parameter => $uri_post->query); } if ($options{request}->{method} eq 'GET') { return ; } if ($options{request}->{method} eq 'POST') { $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_POST'), parameter => 1); } if ($options{request}->{method} eq 'PUT') { $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_CUSTOMREQUEST'), parameter => $options{request}->{method}); } if ($options{request}->{method} eq 'DELETE') { $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_CUSTOMREQUEST'), parameter => $options{request}->{method}); } if ($options{request}->{method} eq 'PATCH') { $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_CUSTOMREQUEST'), parameter => $options{request}->{method}); } } sub set_auth { my ($self, %options) = @_; if (defined($options{request}->{credentials})) { if (defined($options{request}->{basic})) { $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_HTTPAUTH'), parameter => $self->{constant_cb}->(name => 'CURLAUTH_BASIC')); } elsif (defined($options{request}->{ntlmv2})) { $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_HTTPAUTH'), parameter => $self->{constant_cb}->(name => 'CURLAUTH_NTLM')); } if (defined($options{request}->{digest})) { $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_HTTPAUTH'), parameter => $self->{constant_cb}->(name => 'CURLAUTH_DIGEST')); }else { $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_HTTPAUTH'), parameter => $self->{constant_cb}->(name => 'CURLAUTH_ANY')); } $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_USERPWD'), parameter => $options{request}->{username} . ':' . $options{request}->{password}); } if (defined($options{request}->{cert_file}) && $options{request}->{cert_file} ne '') { $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_SSLCERT'), parameter => $options{request}->{cert_file}); $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_SSLKEY'), parameter => $options{request}->{key_file}); $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_KEYPASSWD'), parameter => $options{request}->{cert_pwd}); } $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_SSLCERTTYPE'), parameter => "PEM"); if (defined($options{request}->{cert_pkcs12})) { $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_SSLCERTTYPE'), parameter => "P12"); } } sub set_form { my ($self, %options) = @_; if (!defined($self->{form_loaded})) { centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'Net::Curl::Form', error_msg => "Cannot load module 'Net::Curl::Form'." ); $self->{form_loaded} = 1; } my $form = Net::Curl::Form->new(); foreach (@{$options{form}}) { my %args = (); $args{ $self->{constant_cb}->(name => 'CURLFORM_COPYNAME()') } = $_->{copyname} if (defined($_->{copyname})); $args{ $self->{constant_cb}->(name => 'CURLFORM_COPYCONTENTS()') } = $_->{copycontents} if (defined($_->{copycontents})); $form->add(%args); } $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_HTTPPOST()'), parameter => $form); } sub set_proxy { my ($self, %options) = @_; if (defined($options{request}->{proxyurl}) && $options{request}->{proxyurl} ne '') { $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_PROXY'), parameter => $options{request}->{proxyurl}); } if (defined($options{request}->{proxypac}) && $options{request}->{proxypac} ne '') { $self->{output}->add_option_msg(short_msg => 'Unsupported proxypac option'); $self->{output}->option_exit(); } } sub set_extra_curl_opt { my ($self, %options) = @_; my $entries = {}; foreach (@{$options{request}->{curl_opt}}) { my ($key, $value) = split /=>/; $key = centreon::plugins::misc::trim($key); if (!defined($entries->{$key})) { $entries->{$key} = { val => [], force_array => 0 }; } $value = centreon::plugins::misc::trim($value); if ($value =~ /^\[(.*)\]$/) { $entries->{$key}->{force_array} = 1; $value = centreon::plugins::misc::trim($1); } if ($value =~ /^CURLOPT|CURL/) { $value = $self->{constant_cb}->(name => $value); } push @{$entries->{$key}->{val}}, $value; } foreach (keys %$entries) { my $key = $_; if (/^CURLOPT|CURL/) { $key = $self->{constant_cb}->(name => $_); } if ($entries->{$_}->{force_array} == 1 || scalar(@{$entries->{$_}->{val}}) > 1) { $self->curl_setopt(option => $key, parameter => $entries->{$_}->{val}); } else { $self->curl_setopt(option => $key, parameter => pop @{$entries->{$_}->{val}}); } } } sub cb_get_header { my ($easy, $header, $uservar) = @_; $header =~ s/[\r\n]//g; if ($header =~ /^[\r\n]*$/) { $uservar->{nheaders}++; } else { $uservar->{response_headers}->[$uservar->{nheaders}] = {} if (!defined($uservar->{response_headers}->[$uservar->{nheaders}])); if ($header =~ /^(\S(?:.*?))\s*:\s*(.*)/) { my $header_name = lc($1); $uservar->{response_headers}->[$uservar->{nheaders}]->{$header_name} = [] if (!defined($uservar->{response_headers}->[$uservar->{nheaders}]->{$header_name})); push @{$uservar->{response_headers}->[$uservar->{nheaders}]->{$header_name}}, $2; } else { $uservar->{response_headers}->[$uservar->{nheaders}]->{response_line} = $header; } } return length($_[1]); } sub request { my ($self, %options) = @_; if (!defined($self->{curl_easy})) { $self->{curl_easy} = Net::Curl::Easy->new(); } if ($self->{output}->is_debug()) { $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_DEBUGFUNCTION'), parameter => \&cb_debug); $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_DEBUGDATA'), parameter => $self); $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_VERBOSE'), parameter => 1); } if (defined($options{request}->{timeout}) && $options{request}->{timeout} =~ /\d/) { $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_TIMEOUT'), parameter => $options{request}->{timeout}); } if (defined($options{request}->{cookies_file})) { $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_COOKIEFILE'), parameter => $options{request}->{cookies_file}); } $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_FOLLOWLOCATION'), parameter => 1); if (defined($options{request}->{no_follow})) { $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_FOLLOWLOCATION'), parameter => 0); } my $url; if (defined($options{request}->{full_url})) { $url = $options{request}->{full_url}; } elsif (defined($options{request}->{port}) && $options{request}->{port} =~ /^[0-9]+$/) { $url = $options{request}->{proto}. "://" . $options{request}->{hostname} . ':' . $options{request}->{port} . $options{request}->{url_path}; } else { $url = $options{request}->{proto}. "://" . $options{request}->{hostname} . $options{request}->{url_path}; } if (defined($options{request}->{http_peer_addr}) && $options{request}->{http_peer_addr} ne '') { $url =~ /^(?:http|https):\/\/(.*?)(\/|\:|$)/; $self->{curl_easy}->setopt( $self->{constant_cb}->(name => 'CURLOPT_RESOLVE'), [$1 . ':' . $options{request}->{port_force} . ':' . $options{request}->{http_peer_addr}] ); } my $uri = URI->new($url); if (defined($options{request}->{get_params})) { $uri->query_form($options{request}->{get_params}); } $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_URL'), parameter => $uri); my $headers = []; my $content_type_forced = 0; foreach my $key (keys %{$options{request}->{headers}}) { push @$headers, $key . ':' . (defined($options{request}->{headers}->{$key}) ? $options{request}->{headers}->{$key} : ''); if ($key =~ /content-type/i) { $content_type_forced = 1; } } $self->set_method(%options, content_type_forced => $content_type_forced, headers => $headers); if (defined($options{request}->{form})) { $self->set_form(form => $options{request}->{form}); } if (scalar(@$headers) > 0) { $self->{curl_easy}->setopt($self->{constant_cb}->(name => 'CURLOPT_HTTPHEADER'), $headers); } if (defined($options{request}->{cacert_file}) && $options{request}->{cacert_file} ne '') { $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_CAINFO'), parameter => $options{request}->{cacert_file}); } if (defined($options{request}->{insecure})) { $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_SSL_VERIFYPEER'), parameter => 0); $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_SSL_VERIFYHOST'), parameter => 0); } $self->set_auth(%options); $self->set_proxy(%options); $self->set_extra_curl_opt(%options); $self->{response_body} = ''; $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_FILE'), parameter => \$self->{response_body}); $self->{nheaders} = 0; $self->{response_headers} = [{}]; $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_HEADERDATA'), parameter => $self); $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_HEADERFUNCTION'), parameter => \&cb_get_header); if (defined($options{request}->{certinfo}) && $options{request}->{certinfo} == 1) { $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_CERTINFO'), parameter => 1); } $self->{response_code} = undef; eval { $self->{curl_easy}->perform(); }; if ($@) { if (ref($@) eq "Net::Curl::Easy::Code") { my $num = $@; if ($num == $self->{constant_cb}->(name => 'CURLE_OPERATION_TIMEDOUT')) { $self->{response_code} = 450; } } if (!defined($self->{response_code})) { $self->{output}->add_option_msg(short_msg => 'curl perform error : ' . $@); $self->{output}->option_exit(); } } $self->{response_code} = $self->{curl_easy}->getinfo($self->{constant_cb}->(name => 'CURLINFO_RESPONSE_CODE')) if (!defined($self->{response_code})); # Check response my $status = 'ok'; if (defined($options{request}->{critical_status}) && $options{request}->{critical_status} ne '' && $self->{output}->test_eval(test => $options{request}->{critical_status}, values => { code => $self->{response_code} })) { $status = 'critical'; } elsif (defined($options{request}->{warning_status}) && $options{request}->{warning_status} ne '' && $self->{output}->test_eval(test => $options{request}->{warning_status}, values => { code => $self->{response_code} })) { $status = 'warning'; } elsif (defined($options{request}->{unknown_status}) && $options{request}->{unknown_status} ne '' && $self->{output}->test_eval(test => $options{request}->{unknown_status}, values => { code => $self->{response_code} })) { $status = 'unknown'; } if (!$self->{output}->is_status(value => $status, compare => 'ok', litteral => 1)) { my $short_msg = $self->{response_code} . ' ' . (defined($http_code_explained->{$self->{response_code}}) ? $http_code_explained->{$self->{response_code}} : 'unknown'); $self->{output}->output_add( severity => $status, short_msg => $short_msg ); $self->{output}->display(); $self->{output}->exit(); } return $self->{response_body}; } sub get_headers { my ($self, %options) = @_; my $headers = ''; foreach (keys %{$self->{response_headers}->[$options{nheader}]}) { next if (/response_line/); foreach my $value (@{$self->{response_headers}->[$options{nheader}]->{$_}}) { $headers .= "$_: " . $value . "\n"; } } return $headers; } sub get_first_header { my ($self, %options) = @_; if (!defined($options{name})) { return $self->get_headers(nheader => 0); } return undef if (!defined($self->{response_headers}->[0]->{ lc($options{name}) })); return wantarray ? @{$self->{response_headers}->[0]->{ lc($options{name}) }} : $self->{response_headers}->[0]->{ lc($options{name}) }->[0]; } sub get_header { my ($self, %options) = @_; if (!defined($options{name})) { return $self->get_headers(nheader => -1); } return undef if (!defined($self->{response_headers}->[-1]->{ lc($options{name}) })); return wantarray ? @{$self->{response_headers}->[-1]->{ lc($options{name}) }} : $self->{response_headers}->[-1]->{ lc($options{name}) }->[0]; } sub get_code { my ($self, %options) = @_; return $self->{response_code}; } sub get_message { my ($self, %options) = @_; return defined($http_code_explained->{$self->{response_code}}) ? $http_code_explained->{$self->{response_code}} : 'Unknown code'; } sub get_certificate { my ($self, %options) = @_; my $certs = $self->{curl_easy}->getinfo($self->{constant_cb}->(name => 'CURLINFO_CERTINFO')); return ('pem', $certs->[0]->{Cert}); } sub get_times { my ($self, %options) = @_; # TIME_T = 7.61.0 my $resolve = $self->{curl_easy}->getinfo($self->{constant_cb}->(name => 'CURLINFO_NAMELOOKUP_TIME')); my $connect = $self->{curl_easy}->getinfo($self->{constant_cb}->(name => 'CURLINFO_CONNECT_TIME')); my $appconnect = $self->{curl_easy}->getinfo($self->{constant_cb}->(name => 'CURLINFO_APPCONNECT_TIME')); my $start = $self->{curl_easy}->getinfo($self->{constant_cb}->(name => 'CURLINFO_STARTTRANSFER_TIME')); my $total = $self->{curl_easy}->getinfo($self->{constant_cb}->(name => 'CURLINFO_TOTAL_TIME')); my $times = { resolve => $resolve * 1000, connect => ($connect - $resolve) * 1000, transfer => ($total - $start) * 1000 }; if ($appconnect > 0) { $times->{tls} = ($appconnect - $connect) * 1000; $times->{processing} = ($start - $appconnect) * 1000; } else { $times->{processing} = ($start - $connect) * 1000; } return $times; } 1; __END__ =head1 NAME HTTP Curl backend layer. =head1 SYNOPSIS HTTP Curl backend layer. =head1 BACKEND CURL OPTIONS =over 8 =item B<--curl-opt> Set CURL Options (--curl-opt="CURLOPT_SSL_VERIFYPEER => 0" --curl-opt="CURLOPT_SSLVERSION => CURL_SSLVERSION_TLSv1_1" ). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/centreon/plugins/backend/http/curlconstants.pm000066400000000000000000000017551417000230700263500ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::backend::http::curlconstants; use strict; use warnings; use Net::Curl::Easy qw(:constants); use Net::Curl::Form qw(:constants); sub get_constant_value { my (%options) = @_; return eval $options{name}; } 1; centreon-plugins-20220113/centreon/plugins/backend/http/lwp.pm000066400000000000000000000324461417000230700242510ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::backend::http::lwp; use strict; use warnings; use centreon::plugins::backend::http::useragent; use URI; use IO::Socket::SSL; sub new { my ($class, %options) = @_; my $self = {}; bless $self, $class; if (!defined($options{noptions}) || $options{noptions} != 1) { $options{options}->add_options(arguments => { 'ssl:s' => { name => 'ssl' }, 'ssl-opt:s@' => { name => 'ssl_opt' }, }); $options{options}->add_help(package => __PACKAGE__, sections => 'BACKEND LWP OPTIONS', once => 1); } $self->{output} = $options{output}; $self->{ua} = undef; $self->{debug_handlers} = 0; return $self; } sub check_options { my ($self, %options) = @_; foreach (('unknown_status', 'warning_status', 'critical_status')) { if (defined($options{request}->{$_})) { $options{request}->{$_} =~ s/%\{http_code\}/\$values->{code}/g; } } $self->{ssl_context} = ''; if (!defined($options{request}->{ssl_opt})) { $options{request}->{ssl_opt} = []; } if (defined($options{request}->{ssl}) && $options{request}->{ssl} ne '') { push @{$options{request}->{ssl_opt}}, 'SSL_version => ' . $options{request}->{ssl}; } if (defined($options{request}->{cert_file}) && !defined($options{request}->{cert_pkcs12})) { push @{$options{request}->{ssl_opt}}, 'SSL_use_cert => 1'; push @{$options{request}->{ssl_opt}}, 'SSL_cert_file => "' . $options{request}->{cert_file} . '"'; push @{$options{request}->{ssl_opt}}, 'SSL_key_file => "' . $options{request}->{key_file} . '"' if (defined($options{request}->{key_file})); push @{$options{request}->{ssl_opt}}, 'SSL_ca_file => "' . $options{request}->{cacert_file} . '"' if (defined($options{request}->{cacert_file})); } if ($options{request}->{insecure}) { push @{$options{request}->{ssl_opt}}, 'SSL_verify_mode => SSL_VERIFY_NONE'; } my $append = ''; foreach (@{$options{request}->{ssl_opt}}) { if ($_ ne '') { $self->{ssl_context} .= $append . $_; $append = ', '; } } } sub set_proxy { my ($self, %options) = @_; if (defined($options{request}->{proxypac}) && $options{request}->{proxypac} ne '') { centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'HTTP::ProxyPAC', error_msg => "Cannot load module 'HTTP::ProxyPAC'." ); my ($pac, $pac_uri); eval { if ($options{request}->{proxypac} =~ /^(http|https):\/\//) { $pac_uri = URI->new($options{request}->{proxypac}); $pac = HTTP::ProxyPAC->new($pac_uri); } else { $pac = HTTP::ProxyPAC->new($options{request}->{proxypac}); } }; if ($@) { $self->{output}->add_option_msg(short_msg => 'issue to load proxypac: ' . $@); $self->{output}->option_exit(); } my $res = $pac->find_proxy($options{url}); if (defined($res->direct) && $res->direct != 1) { my $proxy_uri = URI->new($res->proxy); $proxy_uri->userinfo($pac_uri->userinfo) if (defined($pac_uri->userinfo)); $self->{ua}->proxy(['http', 'https'], $proxy_uri->as_string); } } if (defined($options{request}->{proxyurl}) && $options{request}->{proxyurl} ne '') { my $proxyurl = $options{request}->{proxyurl}; if ($options{request}->{proto} eq "https" || (defined($options{request}->{full_url}) && $options{request}->{full_url} =~ /^https/)) { $proxyurl = 'connect://' . $2 if ($proxyurl =~ /^(http|https):\/\/(.*)/); } $self->{ua}->proxy(['http', 'https'], $proxyurl); } } sub request { my ($self, %options) = @_; my %user_agent_params = (keep_alive => 1); if (defined($options{request}->{certinfo}) && $options{request}->{certinfo} == 1) { centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'LWP::ConnCache', error_msg => "Cannot load module 'LWP::ConnCache'." ); $self->{cache} = LWP::ConnCache->new(); $self->{cache}->total_capacity(1); %user_agent_params = (conn_cache => $self->{cache}); } my $request_options = $options{request}; if (!defined($self->{ua})) { my $timeout; $timeout = $1 if (defined($request_options->{timeout}) && $request_options->{timeout} =~ /(\d+)/); $self->{ua} = centreon::plugins::backend::http::useragent->new( %user_agent_params, protocols_allowed => ['http', 'https'], timeout => $timeout, credentials => $request_options->{credentials}, username => $request_options->{username}, password => $request_options->{password} ); if (defined($request_options->{cookies_file})) { centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'HTTP::Cookies', error_msg => "Cannot load module 'HTTP::Cookies'." ); $self->{ua}->cookie_jar( HTTP::Cookies->new( file => $request_options->{cookies_file}, autosave => 1 ) ); } } if ($self->{output}->is_debug() && $self->{debug_handlers} == 0) { $self->{debug_handlers} = 1; $self->{ua}->add_handler('request_send', sub { my ($response, $ua, $handler) = @_; $self->{output}->output_add(long_msg => '======> request send', debug => 1); $self->{output}->output_add(long_msg => $response->as_string, debug => 1); return ; }); $self->{ua}->add_handler("response_done", sub { my ($response, $ua, $handler) = @_; $self->{output}->output_add(long_msg => '======> response done', debug => 1); $self->{output}->output_add(long_msg => $response->as_string, debug => 1); return ; }); } if (defined($request_options->{no_follow})) { $self->{ua}->requests_redirectable(undef); } else { $self->{ua}->requests_redirectable([ 'GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'PATCH' ]); } if (defined($request_options->{http_peer_addr})) { push @LWP::Protocol::http::EXTRA_SOCK_OPTS, PeerAddr => $request_options->{http_peer_addr}; } my ($req, $url); if (defined($request_options->{full_url})) { $url = $request_options->{full_url}; } elsif (defined($request_options->{port}) && $request_options->{port} =~ /^[0-9]+$/) { $url = $request_options->{proto}. '://' . $request_options->{hostname} . ':' . $request_options->{port} . $request_options->{url_path}; } else { $url = $request_options->{proto}. '://' . $request_options->{hostname} . $request_options->{url_path}; } my $uri = URI->new($url); if (defined($request_options->{get_params})) { $uri->query_form($request_options->{get_params}); } $req = HTTP::Request->new($request_options->{method}, $uri); my $content_type_forced = 0; foreach my $key (keys %{$request_options->{headers}}) { $req->header($key => $request_options->{headers}->{$key}); if ($key =~ /content-type/i) { $content_type_forced = 1; } } if ($content_type_forced == 1) { $req->content($request_options->{query_form_post}); } elsif (defined($options{request}->{post_params})) { my $uri_post = URI->new(); $uri_post->query_form($request_options->{post_params}); $req->content_type('application/x-www-form-urlencoded'); $req->content($uri_post->query); } if (defined($request_options->{form})) { $self->{output}->add_option_msg(short_msg => 'unsupported form param'); $self->{output}->option_exit(); } if (defined($request_options->{credentials}) && defined($request_options->{ntlmv2})) { centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'Authen::NTLM', error_msg => "Cannot load module 'Authen::NTLM'." ); Authen::NTLM::ntlmv2(1); } if (defined($request_options->{credentials}) && (defined($request_options->{basic}) || defined($request_options->{digest}))) { $req->authorization_basic($request_options->{username}, $request_options->{password}); } $self->set_proxy(request => $request_options, url => $url); if (defined($request_options->{cert_pkcs12}) && $request_options->{cert_file} ne '' && $request_options->{cert_pwd} ne '') { eval 'use Net::SSL'; die $@ if $@; $ENV{HTTPS_PKCS12_FILE} = $request_options->{cert_file}; $ENV{HTTPS_PKCS12_PASSWORD} = $request_options->{cert_pwd}; } if (defined($self->{ssl_context}) && $self->{ssl_context} ne '') { my $context = new IO::Socket::SSL::SSL_Context(eval $self->{ssl_context}); IO::Socket::SSL::set_default_context($context); } $self->{response} = $self->{ua}->request($req); $self->{response_code} = $self->{response}->code(); $self->{response_message} = $self->{response}->message(); $self->{headers} = $self->{response}->headers(); if ($self->{response_code} == 500) { my $client_warning = $self->get_header(name => 'Client-Warning'); if (defined($client_warning) && $client_warning eq 'Internal response') { $self->{response_code} = 450; $self->{response_message} = 'Timeout reached'; } } # Check response my $status = 'ok'; if (defined($request_options->{critical_status}) && $request_options->{critical_status} ne '' && $self->{output}->test_eval(test => $request_options->{critical_status}, values => { code => $self->{response_code} })) { $status = 'critical'; } elsif (defined($request_options->{warning_status}) && $request_options->{warning_status} ne '' && $self->{output}->test_eval(test => $request_options->{warning_status}, values => { code => $self->{response_code} })) { $status = 'warning'; } elsif (defined($request_options->{unknown_status}) && $request_options->{unknown_status} ne '' && $self->{output}->test_eval(test => $request_options->{unknown_status}, values => { code => $self->{response_code} })) { $status = 'unknown'; } if (!$self->{output}->is_status(value => $status, compare => 'ok', litteral => 1)) { my $short_msg = $self->{response}->status_line; if ($short_msg =~ /^401/) { $short_msg .= ' (' . $1 . ' authentication expected)' if (defined($self->{response}->www_authenticate) && $self->{response}->www_authenticate =~ /(\S+)/); } $self->{output}->output_add( severity => $status, short_msg => $short_msg ); $self->{output}->display(); $self->{output}->exit(); } return $self->{response}->content; } sub get_headers { my ($self, %options) = @_; my $headers = ''; foreach ($options{response}->header_field_names()) { my $value = $options{response}->header($_); $headers .= "$_: " . (defined($value) ? $value : '') . "\n"; } return $headers; } sub get_first_header { my ($self, %options) = @_; my @redirects = $self->{response}->redirects(); if (!defined($options{name})) { return $self->get_headers(response => defined($redirects[0]) ? $redirects[0] : $self->{response}); } return defined($redirects[0]) ? $redirects[0]->headers()->header($options{name}) : $self->{headers}->header($options{name}) ; } sub get_header { my ($self, %options) = @_; if (!defined($options{name})) { return $self->get_headers(response => $self->{response}); } return $self->{headers}->header($options{name}); } sub get_code { my ($self, %options) = @_; return $self->{response_code}; } sub get_message { my ($self, %options) = @_; return $self->{response_message}; } sub get_certificate { my ($self, %options) = @_; my ($con) = $self->{cache}->get_connections('https'); return ('socket', $con); } sub get_times { my ($self, %options) = @_; return undef; } 1; __END__ =head1 NAME HTTP LWP backend layer. =head1 SYNOPSIS HTTP LWP backend layer. =head1 BACKEND LWP OPTIONS =over 8 =item B<--ssl-opt> Set SSL Options (--ssl-opt="SSL_version => TLSv1" --ssl-opt="SSL_verify_mode => SSL_VERIFY_NONE"). =item B<--ssl> Set SSL version (--ssl=TLSv1). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/centreon/plugins/backend/http/useragent.pm000066400000000000000000000030761417000230700254410ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::backend::http::useragent; use strict; use warnings; use base 'LWP::UserAgent'; sub new { my ($class, %options) = @_; my $self = {}; bless $self, $class; $self = LWP::UserAgent::new(@_); $self->agent("centreon::plugins::backend::http::useragent"); $self->{credentials} = $options{credentials} if defined($options{credentials}); $self->{username} = $options{username} if defined($options{username}); $self->{password} = $options{password} if defined($options{password}); return $self; } sub get_basic_credentials { my($self, $realm, $uri, $proxy) = @_; return if $proxy; return $self->{username}, $self->{password} if $self->{credentials} and wantarray; return $self->{username} . ':' . $self->{password} if $self->{credentials}; return undef; } 1; centreon-plugins-20220113/centreon/plugins/backend/ssh/000077500000000000000000000000001417000230700227165ustar00rootroot00000000000000centreon-plugins-20220113/centreon/plugins/backend/ssh/libssh.pm000066400000000000000000000151621417000230700245450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::backend::ssh::libssh; use strict; use warnings; sub new { my ($class, %options) = @_; my $self = {}; bless $self, $class; if (!defined($options{noptions}) || $options{noptions} != 1) { $options{options}->add_options(arguments => { 'libssh-strict-connect' => { name => 'libssh_strict_connect' } }); $options{options}->add_help(package => __PACKAGE__, sections => 'BACKEND LIBSSH OPTIONS', once => 1); } $self->{connected} = 0; $self->{output} = $options{output}; return $self; } sub check_options { my ($self, %options) = @_; centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'Libssh::Session', error_msg => "Cannot load module 'Libssh::Session'." ); centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'centreon::plugins::backend::ssh::libsshconstants', error_msg => "Cannot load module 'centreon::plugins::backend::ssh::libsshconstants'." ); $self->{constant_cb} = \¢reon::plugins::backend::ssh::libsshconstants::get_constant_value; if (!defined($self->{ssh})) { $self->{ssh} = Libssh::Session->new(); } $self->{ssh_port} = defined($options{option_results}->{ssh_port}) && $options{option_results}->{ssh_port} =~ /(\d+)/ ? $1 : 22; $self->{ssh}->options(port => $self->{ssh_port}); $self->{ssh_username} = $options{option_results}->{ssh_username}; $self->{ssh_password} = $options{option_results}->{ssh_password}; $self->{ssh}->options(identity => $options{option_results}->{ssh_priv_key}) if (defined($options{option_results}->{ssh_priv_key}) && $options{option_results}->{ssh_priv_key} ne ''); $self->{ssh}->options(user => $options{option_results}->{ssh_username}) if (defined($options{option_results}->{ssh_username}) && $options{option_results}->{ssh_username} ne ''); $self->{ssh_strict_connect} = defined($options{option_results}->{libssh_strict_connect}) ? 0 : 1; } sub connect { my ($self, %options) = @_; return if ($self->{connected} == 1); $self->{ssh}->options(host => $options{hostname}); if ($self->{ssh}->connect(SkipKeyProblem => $self->{ssh_strict_connect}) != $self->{constant_cb}->(name => 'SSH_OK')) { $self->{output}->add_option_msg(short_msg => 'connect issue: ' . $self->{ssh}->error()); $self->{output}->option_exit(); } if ($self->{ssh}->auth_publickey_auto() != $self->{constant_cb}->(name => 'SSH_AUTH_SUCCESS')) { if (defined($self->{ssh_username}) && $self->{ssh_username} ne '' && defined($self->{ssh_password}) && $self->{ssh_password} ne '' && $self->{ssh}->auth_password(password => $self->{ssh_password}) == $self->{constant_cb}->(name => 'SSH_AUTH_SUCCESS')) { $self->{connected} = 1; return ; } my $msg_error = $self->{ssh}->error(GetErrorSession => 1); $self->{output}->add_option_msg(short_msg => sprintf("auth issue: %s", defined($msg_error) && $msg_error ne '' ? $msg_error : 'pubkey issue')); $self->{output}->option_exit(); } $self->{connected} = 1; } sub execute { my ($self, %options) = @_; if (defined($options{timeout}) && $options{timeout} =~ /(\d+)/) { $self->{ssh}->options(timeout => $options{timeout}); } $self->connect(hostname => $options{hostname}); my $cmd = ''; $cmd = 'sudo ' if (defined($options{sudo})); $cmd .= $options{command_path} . '/' if (defined($options{command_path})); $cmd .= $options{command} . ' ' if (defined($options{command})); $cmd .= $options{command_options} if (defined($options{command_options})); my $ret; if (!defined($options{ssh_pipe}) || $options{ssh_pipe} == 0) { $ret = $self->{ssh}->execute_simple( cmd => $cmd, timeout => $options{timeout}, timeout_nodata => $options{timeout} ); } else { $ret = $self->{ssh}->execute_simple( input_data => $cmd, timeout => $options{timeout}, timeout_nodata => $options{timeout} ); } $self->{output}->output_add(long_msg => $ret->{stdout}, debug => 1) if (defined($ret->{stdout})); $self->{output}->output_add(long_msg => $ret->{stderr}, debug => 1) if (defined($ret->{stderr})); my ($content, $exit_code); if ($ret->{exit} == $self->{constant_cb}->(name => 'SSH_OK')) { $content = $ret->{stdout}; $exit_code = $ret->{exit_code}; } elsif ($ret->{exit} == $self->{constant_cb}->(name => 'SSH_AGAIN')) { # AGAIN means timeout $self->{output}->add_option_msg(short_msg => sprintf('command execution timeout')); $self->{output}->option_exit(); } else { $self->{output}->add_option_msg(short_msg => sprintf( 'command execution error: %s', $self->{ssh}->error(GetErrorSession => 1) ) ); $self->{output}->option_exit(); } if (defined($options{ssh_pipe}) && $options{ssh_pipe} == 1) { # Last failed login: Tue Feb 25 09:30:20 EST 2020 from 10.40.1.160 on ssh:notty # There was 1 failed login attempt since the last successful login. $content =~ s/^(?:Last failed login:|There was.*?failed login).*?\n//msg; } if ($exit_code != 0 && (!defined($options{no_quit}) || $options{no_quit} != 1)) { $self->{output}->add_option_msg(short_msg => sprintf('command execution error [exit code: %s]', $exit_code)); $self->{output}->option_exit(); } return ($content, $exit_code); } 1; __END__ =head1 NAME libssh backend. =head1 SYNOPSIS libssh backend. =head1 BACKEND LIBSSH OPTIONS =over 8 =item B<--libssh-strict-connect> Connection won't be OK even if there is a problem (server known changed or server found other) with the ssh server. =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/centreon/plugins/backend/ssh/libsshconstants.pm000066400000000000000000000017041417000230700264770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::backend::ssh::libsshconstants; use strict; use warnings; use Libssh::Session qw(:all); sub get_constant_value { my (%options) = @_; return eval $options{name}; } 1; centreon-plugins-20220113/centreon/plugins/backend/ssh/plink.pm000066400000000000000000000107251417000230700243760ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::backend::ssh::plink; use strict; use warnings; use centreon::plugins::misc; sub new { my ($class, %options) = @_; my $self = {}; bless $self, $class; if (!defined($options{noptions}) || $options{noptions} != 1) { $options{options}->add_options(arguments => { 'plink-command:s' => { name => 'plink_command', default => 'plink' }, 'plink-path:s' => { name => 'plink_path' }, 'plink-option:s@' => { name => 'plink_option' } }); $options{options}->add_help(package => __PACKAGE__, sections => 'BACKEND PLINK OPTIONS', once => 1); } $self->{output} = $options{output}; return $self; } sub check_options { my ($self, %options) = @_; $self->{ssh_command} = defined($options{option_results}->{plink_command}) && $options{option_results}->{plink_command} ne '' ? $options{option_results}->{plink_command} : 'plink'; $self->{ssh_path} = $options{option_results}->{plink_path}; $self->{ssh_option} = defined($options{option_results}->{plink_option}) ? $options{option_results}->{plink_option} : []; $self->{ssh_port} = defined($options{option_results}->{ssh_port}) && $options{option_results}->{ssh_port} =~ /(\d+)/ ? $1 : 22; $self->{ssh_priv_key} = $options{option_results}->{ssh_priv_key}; $self->{ssh_username} = $options{option_results}->{ssh_username}; $self->{ssh_password} = $options{option_results}->{ssh_password}; push @{$self->{ssh_option}}, '-batch'; push @{$self->{ssh_option}}, '-l=' . $self->{ssh_username} if (defined($self->{ssh_username}) && $self->{ssh_username} ne ''); push @{$self->{ssh_option}}, '-pw=' . $self->{ssh_password} if (defined($self->{ssh_password}) && $self->{ssh_password} ne ''); push @{$self->{ssh_option}}, '-P=' . $self->{ssh_port} if (defined($self->{ssh_port}) && $self->{ssh_port} ne ''); push @{$self->{ssh_option}}, '-i=' . $self->{ssh_priv_key} if (defined($self->{ssh_priv_key}) && $self->{ssh_priv_key} ne ''); } sub execute { my ($self, %options) = @_; push @{$self->{ssh_option}}, '-T' if (defined($options{ssh_pipe}) && $options{ssh_pipe} == 1); $options{command} .= $options{cmd_exit} if (defined($options{cmd_exit}) && $options{cmd_exit} ne ''); my ($content, $exit_code) = centreon::plugins::misc::execute( output => $self->{output}, sudo => $options{sudo}, command => $options{command}, command_path => $options{command_path}, command_options => $options{command_options}, ssh_pipe => $options{ssh_pipe}, options => { remote => 1, ssh_address => $options{hostname}, ssh_command => $self->{ssh_command}, ssh_path => $self->{ssh_path}, ssh_option => $self->{ssh_option}, timeout => $options{timeout} }, no_quit => $options{no_quit} ); if (defined($options{ssh_pipe}) && $options{ssh_pipe} == 1) { # Using username "root". $content =~ s/^Using username ".*?"\.\n//msg; } # plink exit code is 0 even connection is abandoned if ($content =~ /server.*?key fingerprint.*connection abandoned/msi) { $self->{output}->add_option_msg(short_msg => 'please connect with plink command to your host and accept the server host key'); $self->{output}->option_exit(); } return ($content, $exit_code); } 1; __END__ =head1 NAME plink backend. =head1 SYNOPSIS plink backend. =head1 BACKEND PLINK OPTIONS =over 8 =item B<--plink-command> plink command (default: 'plink'). =item B<--plink-path> plink command path (default: none) =item B<--plink-option> Specify plink options (example: --plink-option='-T'). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/centreon/plugins/backend/ssh/sshcli.pm000066400000000000000000000107021417000230700245410ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::backend::ssh::sshcli; use strict; use warnings; use centreon::plugins::misc; sub new { my ($class, %options) = @_; my $self = {}; bless $self, $class; if (!defined($options{noptions}) || $options{noptions} != 1) { $options{options}->add_options(arguments => { 'sshcli-command:s' => { name => 'sshcli_command', default => 'ssh' }, 'sshcli-path:s' => { name => 'sshcli_path' }, 'sshcli-option:s@' => { name => 'sshcli_option' } }); $options{options}->add_help(package => __PACKAGE__, sections => 'BACKEND SSHCLI OPTIONS', once => 1); } $self->{output} = $options{output}; return $self; } sub check_options { my ($self, %options) = @_; $self->{ssh_command} = defined($options{option_results}->{sshcli_command}) && $options{option_results}->{sshcli_command} ne '' ? $options{option_results}->{sshcli_command} : 'ssh'; $self->{ssh_path} = $options{option_results}->{sshcli_path}; $self->{ssh_option} = defined($options{option_results}->{sshcli_option}) ? $options{option_results}->{sshcli_option} : []; $self->{ssh_port} = defined($options{option_results}->{ssh_port}) && $options{option_results}->{ssh_port} =~ /(\d+)/ ? $1 : 22; $self->{ssh_priv_key} = $options{option_results}->{ssh_priv_key}; $self->{ssh_username} = $options{option_results}->{ssh_username}; if (defined($options{option_results}->{ssh_password}) && $options{option_results}->{ssh_password} ne '') { $self->{output}->add_option_msg(short_msg => 'sshcli backend cannot use ssh password. please use backend plink or libssh'); $self->{output}->option_exit(); } push @{$self->{ssh_option}}, '-o=BatchMode=yes'; push @{$self->{ssh_option}}, '-l=' . $self->{ssh_username} if (defined($self->{ssh_username}) && $self->{ssh_username} ne ''); push @{$self->{ssh_option}}, '-p=' . $self->{ssh_port} if (defined($self->{ssh_port}) && $self->{ssh_port} ne ''); push @{$self->{ssh_option}}, '-i=' . $self->{ssh_priv_key} if (defined($self->{ssh_priv_key}) && $self->{ssh_priv_key} ne ''); } sub execute { my ($self, %options) = @_; push @{$self->{ssh_option}}, '-T' if (defined($options{ssh_pipe}) && $options{ssh_pipe} == 1); $options{command} .= $options{cmd_exit} if (defined($options{cmd_exit}) && $options{cmd_exit} ne ''); my ($content, $exit_code) = centreon::plugins::misc::execute( output => $self->{output}, sudo => $options{sudo}, command => $options{command}, command_path => $options{command_path}, command_options => $options{command_options}, ssh_pipe => $options{ssh_pipe}, options => { remote => 1, ssh_address => $options{hostname}, ssh_command => $self->{ssh_command}, ssh_path => $self->{ssh_path}, ssh_option => $self->{ssh_option}, timeout => $options{timeout} }, no_quit => $options{no_quit} ); if (defined($options{ssh_pipe}) && $options{ssh_pipe} == 1) { # Last failed login: Tue Feb 25 09:30:20 EST 2020 from 10.40.1.160 on ssh:notty # There was 1 failed login attempt since the last successful login. $content =~ s/^(?:Last failed login:|There was.*?failed login).*?\n//msg; } return ($content, $exit_code); } 1; __END__ =head1 NAME ssh cli backend. =head1 SYNOPSIS ssh cli backend. =head1 BACKEND SSHCLI OPTIONS =over 8 =item B<--sshcli-command> ssh command (default: 'ssh'). =item B<--sshcli-path> ssh command path (default: none) =item B<--sshcli-option> Specify ssh cli options (example: --sshcli-option='-o=StrictHostKeyChecking=no'). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/centreon/plugins/dbi.pm000066400000000000000000000237071417000230700216370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::dbi; use strict; use warnings; use DBI; use Digest::MD5 qw(md5_hex); my %handlers = ( ALRM => {} ); sub new { my ($class, %options) = @_; my $self = {}; bless $self, $class; # $options{options} = options object # $options{output} = output object # $options{exit_value} = integer # $options{noptions} = integer if (!defined($options{output})) { print "Class DBI: Need to specify 'output' argument.\n"; exit 3; } if (!defined($options{options})) { $options{output}->add_option_msg(short_msg => "Class DBI: Need to specify 'options' argument."); $options{output}->option_exit(); } if (!defined($options{noptions})) { $options{options}->add_options(arguments => { 'datasource:s@' => { name => 'data_source' }, 'username:s@' => { name => 'username' }, 'password:s@' => { name => 'password' }, 'connect-options:s@' => { name => 'connect_options' }, 'connect-query:s@' => { name => 'connect_query' }, 'sql-errors-exit:s' => { name => 'sql_errors_exit', default => 'unknown' }, 'timeout:s' => { name => 'timeout' }, }); } $options{options}->add_help(package => __PACKAGE__, sections => 'DBI OPTIONS', once => 1); $self->{output} = $options{output}; $self->{sqlmode_name} = $options{sqlmode_name}; $self->{instance} = undef; $self->{statement_handle} = undef; $self->{version} = undef; $self->{data_source} = undef; $self->{username} = undef; $self->{password} = undef; $self->{connect_options} = undef; $self->{connect_options_hash} = {}; # Sometimes, we need to set ENV $self->{env} = undef; return $self; } sub prepare_destroy { my ($self) = @_; %handlers = (); } sub set_signal_handlers { my $self = shift; $SIG{ALRM} = \&class_handle_ALRM; $handlers{ALRM}->{$self} = sub { $self->handle_ALRM() }; } sub class_handle_ALRM { foreach (keys %{$handlers{ALRM}}) { &{$handlers{ALRM}->{$_}}(); } } sub handle_ALRM { my $self = shift; $self->prepare_destroy(); $self->disconnect(); $self->{output}->output_add( severity => $self->{sql_errors_exit}, short_msg => 'Timeout' ); $self->{output}->display(); $self->{output}->exit(); } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults { my ($self, %options) = @_; foreach (keys %{$options{default}}) { if ($_ eq $self->{sqlmode_name}) { 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->{data_source} = (defined($self->{option_results}->{data_source})) ? shift(@{$self->{option_results}->{data_source}}) : undef; $self->{username} = (defined($self->{option_results}->{username})) ? shift(@{$self->{option_results}->{username}}) : undef; $self->{password} = (defined($self->{option_results}->{password})) ? shift(@{$self->{option_results}->{password}}) : undef; $self->{connect_options} = (defined($self->{option_results}->{connect_options})) ? shift(@{$self->{option_results}->{connect_options}}) : undef; $self->{connect_query} = (defined($self->{option_results}->{connect_query})) ? shift(@{$self->{option_results}->{connect_query}}) : undef; $self->{env} = (defined($self->{option_results}->{env})) ? shift(@{$self->{option_results}->{env}}) : undef; $self->{sql_errors_exit} = $self->{option_results}->{sql_errors_exit}; $self->{timeout} = 10; if (defined($self->{option_results}->{timeout}) && $self->{option_results}->{timeout} =~ /^\d+$/ && $self->{option_results}->{timeout} > 0) { $self->{timeout} = $self->{option_results}->{timeout}; } if (!defined($self->{data_source}) || $self->{data_source} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify data_source arguments.'); $self->{output}->option_exit(exit_litteral => $self->{sql_errors_exit}); } if (defined($self->{connect_options}) && $self->{connect_options} ne '') { foreach my $entry (split /,/, $self->{connect_options}) { if ($entry !~ /^\s*([^=]+)=([^=]+)\s*$/) { $self->{output}->add_option_msg(short_msg => "Wrong format for --connect-options '" . $entry . "'."); $self->{output}->option_exit(exit_litteral => $self->{sql_errors_exit}); } $self->{connect_options_hash}->{$1} = $2; } } if (scalar(@{$self->{option_results}->{data_source}}) == 0) { return 0; } return 1; } sub quote { my $self = shift; if (defined($self->{instance})) { return $self->{instance}->quote($_[0]); } return undef; } sub is_version_minimum { my ($self, %options) = @_; # $options{version} = string version to check my @version_src = split /\./, $self->{version}; my @versions = split /\./, $options{version}; for (my $i = 0; $i < scalar(@versions); $i++) { return 1 if ($versions[$i] eq 'x'); return 1 if (!defined($version_src[$i])); $version_src[$i] =~ /^([0-9]*)/; next if ($versions[$i] == int($1)); return 0 if ($versions[$i] > int($1)); return 1 if ($versions[$i] < int($1)); } return 1; } sub set_version { my ($self) = @_; $self->{version} = $self->{instance}->get_info(18); # SQL_DBMS_VER } sub disconnect { my ($self) = @_; if (defined($self->{instance})) { $self->{statement_handle} = undef; $self->{instance}->disconnect(); $self->{instance} = undef; } } sub connect { my ($self, %options) = @_; my $dontquit = (defined($options{dontquit}) && $options{dontquit} == 1) ? 1 : 0; return if (defined($self->{instance})); # Set ENV if (defined($self->{env})) { foreach (keys %{$self->{env}}) { $ENV{$_} = $self->{env}->{$_}; } } $self->set_signal_handlers(); alarm($self->{timeout}) if (defined($self->{timeout})); $self->{instance} = DBI->connect( "DBI:". $self->{data_source}, $self->{username}, $self->{password}, { RaiseError => 0, PrintError => 0, AutoCommit => 1, %{$self->{connect_options_hash}} } ); alarm(0) if (defined($self->{timeout})); $self->prepare_destroy(); if (!defined($self->{instance})) { my $err_msg = sprintf('Cannot connect: %s', defined($DBI::errstr) ? $DBI::errstr : '(no error string)'); if ($dontquit == 0) { $self->{output}->add_option_msg(short_msg => $err_msg); $self->{output}->option_exit(exit_litteral => $self->{sql_errors_exit}); } return (-1, $err_msg); } if (defined($self->{connect_query}) && $self->{connect_query} ne '') { $self->query(query => $self->{connect_query}); } $self->set_version(); return 0; } sub get_id { my ($self, %options) = @_; return $self->{data_source}; } sub get_unique_id4save { my ($self, %options) = @_; return md5_hex($self->{data_source}); } sub fetchall_arrayref { my ($self, %options) = @_; return $self->{statement_handle}->fetchall_arrayref(); } sub fetchrow_array { my ($self, %options) = @_; return $self->{statement_handle}->fetchrow_array(); } sub fetchrow_hashref { my ($self, %options) = @_; return $self->{statement_handle}->fetchrow_hashref(); } sub query { my ($self, %options) = @_; my $continue_error = defined($options{continue_error}) && $options{continue_error} == 1 ? 1 : 0; $self->{statement_handle} = $self->{instance}->prepare($options{query}); if (!defined($self->{statement_handle})) { return 1 if ($continue_error == 1); $self->{output}->add_option_msg(short_msg => 'Cannot execute query: ' . $self->{instance}->errstr); $self->disconnect(); $self->{output}->option_exit(exit_litteral => $self->{sql_errors_exit}); } my $rv = $self->{statement_handle}->execute(); if (!$rv) { return 1 if ($continue_error == 1); $self->{output}->add_option_msg(short_msg => 'Cannot execute query: ' . $self->{statement_handle}->errstr); $self->disconnect(); $self->{output}->option_exit(exit_litteral => $self->{sql_errors_exit}); } return 0; } 1; __END__ =head1 NAME DBI global =head1 SYNOPSIS dbi class =head1 DBI OPTIONS =over 8 =item B<--datasource> Datasource (required. Depends of database server). =item B<--username> Database username. =item B<--password> Database password. =item B<--connect-options> Add options in database connect. Format: name=value,name2=value2,... =item B<--connect-query> Execute a query just after connection. =item B<--sql-errors-exit> Exit code for DB Errors (default: unknown) =item B<--timeout> Timeout in seconds for connection =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/centreon/plugins/http.pm000066400000000000000000000206131417000230700220510ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::http; use strict; use warnings; sub new { my ($class, %options) = @_; my $self = {}; bless $self, $class; if (!defined($options{noptions}) || $options{noptions} != 1) { $options{options}->add_options(arguments => { 'http-peer-addr:s' => { name => 'http_peer_addr' }, 'proxyurl:s' => { name => 'proxyurl' }, 'proxypac:s' => { name => 'proxypac' }, 'insecure' => { name => 'insecure' }, 'http-backend:s' => { name => 'http_backend', default => 'lwp' } }); $options{options}->add_help(package => __PACKAGE__, sections => 'HTTP GLOBAL OPTIONS'); } centreon::plugins::misc::mymodule_load( output => $options{output}, module => 'centreon::plugins::backend::http::lwp', error_msg => "Cannot load module 'centreon::plugins::backend::http::lwp'." ); $self->{backend_lwp} = centreon::plugins::backend::http::lwp->new(%options); centreon::plugins::misc::mymodule_load( output => $options{output}, module => 'centreon::plugins::backend::http::curl', error_msg => "Cannot load module 'centreon::plugins::backend::http::curl'." ); $self->{backend_curl} = centreon::plugins::backend::http::curl->new(%options); $self->{output} = $options{output}; $self->{options} = { proto => 'http', url_path => '/', timeout => 5, method => 'GET', unknown_status => '%{http_code} < 200 or %{http_code} >= 300', warning_status => undef, critical_status => undef, }; $self->{add_headers} = {}; return $self; } sub set_options { my ($self, %options) = @_; $self->{options} = { %{$self->{options}} }; foreach (keys %options) { $self->{options}->{$_} = $options{$_} if (defined($options{$_})); } } sub add_header { my ($self, %options) = @_; $self->{add_headers}->{$options{key}} = $options{value}; } sub remove_header { my ($self, %options) = @_; delete $self->{add_headers}->{$options{key}} if (defined($self->{add_headers}->{$options{key}})); } sub check_options { my ($self, %options) = @_; $options{request}->{http_backend} = 'lwp' if (!defined($options{request}->{http_backend}) || $options{request}->{http_backend} eq ''); $self->{http_backend} = $options{request}->{http_backend}; if ($self->{http_backend} !~ /^\s*lwp|curl\s*$/i) { $self->{output}->add_option_msg(short_msg => "Unsupported http backend specified '" . $self->{http_backend} . "'."); $self->{output}->option_exit(); } if (defined($options{request}->{$self->{http_backend} . '_backend_options'})) { foreach (keys %{$options{request}->{$self->{http_backend} . '_backend_options'}}) { $options{request}->{$_} = $options{request}->{$self->{http_backend} . '_backend_options'}->{$_}; } } if (($options{request}->{proto} ne 'http') && ($options{request}->{proto} ne 'https')) { $self->{output}->add_option_msg(short_msg => "Unsupported protocol specified '" . $self->{option_results}->{proto} . "'."); $self->{output}->option_exit(); } if (!defined($options{request}->{hostname})) { $self->{output}->add_option_msg(short_msg => "Please set the hostname option"); $self->{output}->option_exit(); } if ((defined($options{request}->{credentials})) && (!defined($options{request}->{username}) || !defined($options{request}->{password}))) { $self->{output}->add_option_msg(short_msg => "You need to set --username= and --password= options when --credentials is used"); $self->{output}->option_exit(); } if ((defined($options{request}->{cert_pkcs12})) && (!defined($options{request}->{cert_file}) && !defined($options{request}->{cert_pwd}))) { $self->{output}->add_option_msg(short_msg => "You need to set --cert-file= and --cert-pwd= options when --pkcs12 is used"); $self->{output}->option_exit(); } $options{request}->{port_force} = $self->get_port(); $options{request}->{headers} = {}; if (defined($options{request}->{header})) { foreach (@{$options{request}->{header}}) { if (/^(:.+?|.+?):(.*)/) { $options{request}->{headers}->{$1} = $2; } } } foreach (keys %{$self->{add_headers}}) { $options{request}->{headers}->{$_} = $self->{add_headers}->{$_}; } foreach my $method (('get', 'post')) { if (defined($options{request}->{$method . '_param'})) { $options{request}->{$method . '_params'} = {}; foreach (@{$options{request}->{$method . '_param'}}) { if (/^([^=]+)={0,1}(.*)$/s) { my $key = $1; my $value = defined($2) ? $2 : 1; if (defined($options{request}->{$method . '_params'}->{$key})) { if (ref($options{request}->{$method . '_params'}->{$key}) ne 'ARRAY') { $options{request}->{$method . '_params'}->{$key} = [ $options{request}->{$method . '_params'}->{$key} ]; } push @{$options{request}->{$method . '_params'}->{$key}}, $value; } else { $options{request}->{$method . '_params'}->{$key} = $value; } } } } } $self->{'backend_' . $self->{http_backend}}->check_options(%options); } sub get_port { my ($self, %options) = @_; my $port = ''; if (defined($self->{options}->{port}) && $self->{options}->{port} ne '') { $port = $self->{options}->{port}; } else { $port = 80 if ($self->{options}->{proto} eq 'http'); $port = 443 if ($self->{options}->{proto} eq 'https'); } return $port; } sub get_port_request { my ($self, %options) = @_; my $port = ''; if (defined($self->{options}->{port}) && $self->{options}->{port} ne '') { $port = $self->{options}->{port}; } return $port; } sub request { my ($self, %options) = @_; my $request_options = { %{$self->{options}} }; foreach (keys %options) { $request_options->{$_} = $options{$_} if (defined($options{$_})); } $self->check_options(request => $request_options); return $self->{'backend_' . $self->{http_backend}}->request(request => $request_options); } sub get_first_header { my ($self, %options) = @_; return $self->{'backend_' . $self->{http_backend}}->get_first_header(%options); } sub get_header { my ($self, %options) = @_; return $self->{'backend_' . $self->{http_backend}}->get_header(%options); } sub get_code { my ($self, %options) = @_; return $self->{'backend_' . $self->{http_backend}}->get_code(); } sub get_message { my ($self, %options) = @_; return $self->{'backend_' . $self->{http_backend}}->get_message(); } sub get_certificate { my ($self, %options) = @_; return $self->{'backend_' . $self->{http_backend}}->get_certificate(); } sub get_times { my ($self, %options) = @_; return $self->{'backend_' . $self->{http_backend}}->get_times(); } 1; __END__ =head1 NAME HTTP abstraction layer. =head1 SYNOPSIS HTTP abstraction layer for lwp and curl backends =head1 HTTP GLOBAL OPTIONS =over 8 =item B<--http-peer-addr> Set the address you want to connect (Useful if hostname is only a vhost. no ip resolve) =item B<--proxyurl> Proxy URL =item B<--proxypac> Proxy pac file (can be an url or local file) =item B<--insecure> Insecure SSL connections. =item B<--http-backend> Set the backend used (Default: 'lwp') For curl: --http-backend=curl =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/centreon/plugins/misc.pm000066400000000000000000000425341417000230700220330ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::misc; use strict; use warnings; use utf8; sub execute { my (%options) = @_; if ($^O eq 'MSWin32') { return windows_execute(%options, timeout => $options{options}->{timeout}); } else { return unix_execute(%options); } } sub windows_execute { my (%options) = @_; my $result; my ($stdout, $pid, $ended) = (''); my ($exit_code, $cmd); $cmd = $options{command_path} . '/' if (defined($options{command_path})); $cmd .= $options{command} . ' ' if (defined($options{command})); $cmd .= $options{command_options} if (defined($options{command_options})); centreon::plugins::misc::mymodule_load( output => $options{output}, module => 'Win32::Job', error_msg => "Cannot load module 'Win32::Job'." ); centreon::plugins::misc::mymodule_load( output => $options{output}, module => 'Time::HiRes', error_msg => "Cannot load module 'Time::HiRes'." ); $| = 1; pipe FROM_CHILD, TO_PARENT or do { $options{output}->add_option_msg(short_msg => "Internal error: can't create pipe from child to parent: $!"); $options{output}->option_exit(); }; my $job = Win32::Job->new; my $stderr = 'NUL'; $stderr = \*TO_PARENT if ($options{output}->is_debug()); if (!($pid = $job->spawn(undef, $cmd, { stdin => 'NUL', stdout => \*TO_PARENT, stderr => $stderr }))) { $options{output}->add_option_msg(short_msg => "Internal error: execution issue: $^E"); $options{output}->option_exit(); } close TO_PARENT; my $ein = ''; vec($ein, fileno(FROM_CHILD), 1) = 1; $job->watch( sub { my ($buffer); my $time = $options{timeout}; my $last_time = Time::HiRes::time(); $ended = 0; while (select($ein, undef, undef, $options{timeout})) { if (sysread(FROM_CHILD, $buffer, 16384)) { $buffer =~ s/\r//g; $stdout .= $buffer; } else { $ended = 1; last; } $options{timeout} -= Time::HiRes::time() - $last_time; last if ($options{timeout} <= 0); $last_time = Time::HiRes::time(); } return 1 if ($ended == 0); return 0; }, 0.1 ); $result = $job->status; close FROM_CHILD; if ($ended == 0) { $options{output}->add_option_msg(short_msg => 'Command too long to execute (timeout)...'); $options{output}->option_exit(); } chomp $stdout; if (defined($options{no_quit}) && $options{no_quit} == 1) { return ($stdout, $result->{$pid}->{exitcode}); } if ($result->{$pid}->{exitcode} != 0) { $stdout =~ s/\n/ - /g; $options{output}->add_option_msg(short_msg => "Command error: $stdout"); $options{output}->option_exit(); } return ($stdout, $result->{$pid}->{exitcode}); } sub unix_execute { my (%options) = @_; my $cmd = ''; my $args = []; my ($lerror, $stdout, $exit_code); my $redirect_stderr = 1; $redirect_stderr = $options{redirect_stderr} if (defined($options{redirect_stderr})); my $wait_exit = 1; $wait_exit = $options{wait_exit} if (defined($options{wait_exit})); # Build command line # Can choose which command is done remotely (can filter and use local file) if (defined($options{options}->{remote}) && ($options{options}->{remote} eq '' || !defined($options{label}) || $options{label} =~ /$options{options}->{remote}/)) { my $sub_cmd; $cmd = $options{options}->{ssh_path} . '/' if (defined($options{options}->{ssh_path})); $cmd .= $options{options}->{ssh_command} if (defined($options{options}->{ssh_command})); foreach (@{$options{options}->{ssh_option}}) { if (/^(.*?)(?:=(.*))?$/) { push @$args, $1 if (defined($1)); push @$args, $2 if (defined($2)); } } if (defined($options{options}->{ssh_address}) && $options{options}->{ssh_address} ne '') { push @$args, $options{options}->{ssh_address}; } else { push @$args, $options{options}->{hostname}; } $sub_cmd = 'sudo ' if (defined($options{sudo})); $sub_cmd .= $options{command_path} . '/' if (defined($options{command_path})); $sub_cmd .= $options{command} . ' ' if (defined($options{command})); $sub_cmd .= $options{command_options} if (defined($options{command_options})); # On some equipment. Cannot get a pseudo terminal if (defined($options{ssh_pipe}) && $options{ssh_pipe} == 1) { $cmd = "echo '" . $sub_cmd . "' | " . $cmd . ' ' . join(' ', @$args); ($lerror, $stdout, $exit_code) = backtick( command => $cmd, timeout => $options{options}->{timeout}, wait_exit => $wait_exit, redirect_stderr => $redirect_stderr ); } else { ($lerror, $stdout, $exit_code) = backtick( command => $cmd, arguments => [@$args, $sub_cmd], timeout => $options{options}->{timeout}, wait_exit => $wait_exit, redirect_stderr => $redirect_stderr ); } } else { $cmd = 'sudo ' if (defined($options{sudo})); $cmd .= $options{command_path} . '/' if (defined($options{command_path})); $cmd .= $options{command} . ' ' if (defined($options{command})); $cmd .= $options{command_options} if (defined($options{command_options})); ($lerror, $stdout, $exit_code) = backtick( command => $cmd, timeout => $options{options}->{timeout}, wait_exit => $wait_exit, redirect_stderr => $redirect_stderr ); } if (defined($options{options}->{show_output}) && ($options{options}->{show_output} eq '' || (defined($options{label}) && $options{label} eq $options{options}->{show_output}))) { print $stdout; exit $exit_code; } $stdout =~ s/\r//g; if ($lerror <= -1000) { $options{output}->add_option_msg(short_msg => $stdout); $options{output}->option_exit(); } if (defined($options{no_quit}) && $options{no_quit} == 1) { return ($stdout, $exit_code); } if ($exit_code != 0 && (!defined($options{no_errors}) || !defined($options{no_errors}->{$exit_code}))) { $stdout =~ s/\n/ - /g; $options{output}->add_option_msg(short_msg => "Command error: $stdout"); $options{output}->option_exit(); } return $stdout; } sub mymodule_load { my (%options) = @_; my $file; ($file = ($options{module} =~ /\.pm$/ ? $options{module} : $options{module} . '.pm')) =~ s{::}{/}g; eval { local $SIG{__DIE__} = 'IGNORE'; require $file; $file =~ s{/}{::}g; $file =~ s/\.pm$//; }; if ($@) { return 1 if (defined($options{no_quit}) && $options{no_quit} == 1); $options{output}->add_option_msg(long_msg => $@); $options{output}->add_option_msg(short_msg => $options{error_msg}); $options{output}->option_exit(); } return wantarray ? (0, $file) : 0; } sub backtick { my %arg = ( command => undef, arguments => [], timeout => 30, wait_exit => 0, redirect_stderr => 0, @_, ); my @output; my $pid; my $return_code; my $sig_do; if ($arg{wait_exit} == 0) { $sig_do = 'IGNORE'; $return_code = undef; } else { $sig_do = 'DEFAULT'; } local $SIG{CHLD} = $sig_do; $SIG{TTOU} = 'IGNORE'; $| = 1; if (!defined($pid = open( KID, "-|" ))) { return (-1001, "Cant fork: $!", -1); } if ($pid) { eval { local $SIG{ALRM} = sub { die "Timeout by signal ALARM\n"; }; alarm( $arg{timeout} ); while () { chomp; push @output, $_; } alarm(0); }; if ($@) { if ($pid != -1) { kill -9, $pid; } alarm(0); return (-1000, 'Command too long to execute (timeout)...', -1); } else { if ($arg{wait_exit} == 1) { # We're waiting the exit code waitpid($pid, 0); $return_code = ($? >> 8); } close KID; } } else { # child # set the child process to be a group leader, so that # kill -9 will kill it and all its descendents # We have ignore SIGTTOU to let write background processes setpgrp( 0, 0 ); if ($arg{redirect_stderr} == 1) { open STDERR, '>&STDOUT'; } if (scalar(@{$arg{arguments}}) <= 0) { exec($arg{command}); } else { exec($arg{command}, @{$arg{arguments}}); } # Exec is in error. No such command maybe. exit(127); } return (0, join("\n", @output), $return_code); } sub trim { my ($value) = $_[0]; # Sometimes there is a null character $value =~ s/\x00$//; $value =~ s/^[ \t\n]+//; $value =~ s/[ \t\n]+$//; return $value; } sub powershell_encoded { require Encode; require MIME::Base64; my $bytes = Encode::encode('utf16LE', $_[0]); return MIME::Base64::encode_base64($bytes, ''); } sub powershell_escape { my ($value) = $_[0]; $value =~ s/`/``/g; $value =~ s/#/`#/g; $value =~ s/'/`'/g; $value =~ s/"/`"/g; return $value; } sub minimal_version { my ($version_src, $version_dst) = @_; # No Version. We skip if (!defined($version_src) || !defined($version_dst) || $version_src !~ /^[0-9]+(?:\.[0-9\.]+)*$/ || $version_dst !~ /^[0-9x]+(?:\.[0-9x]+)*$/) { return 1; } my @version_src = split /\./, $version_src; my @versions = split /\./, $version_dst; for (my $i = 0; $i < scalar(@versions); $i++) { return 1 if ($versions[$i] eq 'x'); return 1 if (!defined($version_src[$i])); $version_src[$i] =~ /^([0-9]*)/; next if ($versions[$i] == int($1)); return 0 if ($versions[$i] > int($1)); return 1 if ($versions[$i] < int($1)); } return 1; } sub change_seconds { my %options = @_; my ($str, $str_append) = ('', ''); my $periods = [ { unit => 'y', value => 31556926 }, { unit => 'M', value => 2629743 }, { unit => 'w', value => 604800 }, { unit => 'd', value => 86400 }, { unit => 'h', value => 3600 }, { unit => 'm', value => 60 }, { unit => 's', value => 1 }, ]; my %values = ('y' => 1, 'M' => 2, 'w' => 3, 'd' => 4, 'h' => 5, 'm' => 6, 's' => 7); my $sign = ''; if ($options{value} <= 0) { $sign = '-'; $options{value} = abs($options{value}); } foreach (@$periods) { next if (defined($options{start}) && $values{$_->{unit}} < $values{$options{start}}); my $count = int($options{value} / $_->{value}); next if ($count == 0); $str .= $str_append . $count . $_->{unit}; $options{value} = $options{value} % $_->{value}; $str_append = ' '; } if ($str eq '') { $str = $options{value}; $str .= $options{start} if (defined($options{start})); } return $sign . $str; } sub scale_bytesbit { my (%options) = @_; my $base = 1024; if (defined($options{dst_unit}) && defined($options{src_unit})) { $options{value} *= 8 if ($options{dst_unit} =~ /b/ && $options{src_unit} =~ /B/); $options{value} /= 8 if ($options{dst_unit} =~ /B/ && $options{src_unit} =~ /b/); if ($options{dst_unit} =~ /b/) { $base = 1000; } } my %expo = ('' => 0, k => 1, m => 2, g => 3, t => 4, p => 5, e => 6); my ($src_expo, $dst_expo) = (0, 0); $src_expo = $expo{lc($options{src_quantity})} if (defined($options{src_quantity}) && $options{src_quantity} =~ /[kmgtpe]/i); if ($options{dst_unit} eq 'auto') { my @auto = ('', 'k', 'm', 'g', 't', 'p', 'e'); my $i = defined($options{src_quantity}) ? $expo{$options{src_quantity}} : 0; for (; $i < scalar(@auto); $i++) { last if ($options{value} < $base); $options{value} = $options{value} / $base; } return ($options{value}, $auto[$i], $options{src_unit}); } elsif (defined($options{dst_quantity}) && ($options{dst_quantity} eq '' || $options{dst_quantity} =~ /[kmgtpe]/i )) { my $dst_expo = $expo{lc($options{dst_quantity})}; if ($dst_expo - $src_expo > 0) { $options{value} = $options{value} / ($base ** ($dst_expo - $src_expo)); } elsif ($dst_expo - $src_expo < 0) { $options{value} = $options{value} * ($base ** (($dst_expo - $src_expo) * -1)); } } return $options{value}; } sub convert_bytes { my (%options) = @_; my %expo = (k => 1, m => 2, g => 3, t => 4, p => 5); my ($value, $unit) = ($options{value}, $options{unit}); if (defined($options{pattern})) { return undef if ($value !~ /$options{pattern}/); $value = $1; $unit = $2; } my $base = defined($options{network}) ? 1000 : 1024; if ($unit =~ /([kmgtp])i?b/i) { $value = $value * ($base ** $expo{lc($1)}); } return $value; } sub convert_fahrenheit { my (%options) = @_; return ($options{value} - 32) / 1.8; } sub expand_exponential { my (%options) = @_; return $options{value} unless ($options{value} =~ /^(.*)e([-+]?)(.*)$/); my ($num, $sign, $exp) = ($1, $2, $3); my $sig = $sign eq '-' ? "." . ($exp - 1 + length $num) : ''; return sprintf("%${sig}f", $options{value}); } sub parse_threshold { my (%options) = @_; my $perf = trim($options{threshold}); my $perf_result = { arobase => 0, infinite_neg => 0, infinite_pos => 0, start => '', end => '' }; my $global_status = 1; if ($perf =~ /^(\@?)((?:~|(?:\+|-)?\d+(?:[\.,]\d+)?(?:[KMGTPE][bB])?|):)?((?:\+|-)?\d+(?:[\.,]\d+)?(?:[KMGTPE][bB])?)?$/) { $perf_result->{start} = $2 if (defined($2)); $perf_result->{end} = $3 if (defined($3)); $perf_result->{arobase} = 1 if (defined($1) && $1 eq '@'); $perf_result->{start} =~ s/[\+:]//g; $perf_result->{end} =~ s/\+//; if ($perf_result->{start} =~ s/([KMGTPE])([bB])//) { $perf_result->{start} = scale_bytesbit( value => $perf_result->{start}, src_unit => $2, dst_unit => $2, src_quantity => $1, dst_quantity => '', ); } if ($perf_result->{end} =~ s/([KMGTPE])([bB])//) { $perf_result->{end} = scale_bytesbit( value => $perf_result->{end}, src_unit => $2, dst_unit => $2, src_quantity => $1, dst_quantity => '', ); } if ($perf_result->{end} eq '') { $perf_result->{end} = 1e500; $perf_result->{infinite_pos} = 1; } $perf_result->{start} = 0 if ($perf_result->{start} eq ''); $perf_result->{start} =~ s/,/\./; $perf_result->{end} =~ s/,/\./; if ($perf_result->{start} eq '~') { $perf_result->{start} = -1e500; $perf_result->{infinite_neg} = 1; } } else { $global_status = 0; } return ($global_status, $perf_result); } sub get_threshold_litteral { my (%options) = @_; my $perf_output = ($options{arobase} == 1 ? '@' : '') . (($options{infinite_neg} == 0) ? $options{start} : '~') . ':' . (($options{infinite_pos} == 0) ? $options{end} : ''); return $perf_output; } sub set_timezone { my (%options) = @_; return {} if (!defined($options{name}) || $options{name} eq ''); centreon::plugins::misc::mymodule_load( output => $options{output}, module => 'DateTime::TimeZone', error_msg => "Cannot load module 'DateTime::TimeZone'." ); if (DateTime::TimeZone->is_valid_name($options{name})) { return { time_zone => DateTime::TimeZone->new(name => $options{name}) }; } # try to manage syntax (:Pacific/Noumea for example) if ($options{name} =~ /^:(.*)$/ && DateTime::TimeZone->is_valid_name($1)) { return { time_zone => DateTime::TimeZone->new(name => $1) }; } return {}; } sub uniq { my %seen; return grep { !$seen{$_}++ } @_; } 1; __END__ centreon-plugins-20220113/centreon/plugins/mode.pm000066400000000000000000000042271417000230700220210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::mode; use strict; use warnings; use centreon::plugins::perfdata; sub new { my ($class, %options) = @_; my $self = {}; bless $self, $class; $self->{perfdata} = centreon::plugins::perfdata->new(output => $options{output}); %{$self->{option_results}} = (); $self->{output} = $options{output}; $self->{output}->use_new_perfdata(value => 1) if (defined($options{force_new_perfdata}) && $options{force_new_perfdata} == 1); $self->{mode} = $options{mode}; $self->{version} = '1.0'; return $self; } sub init { my ($self, %options) = @_; # options{default} = { mode_xxx => { option_name => option_value }, } %{$self->{option_results}} = %{$options{option_results}}; # Manage default value return if (!defined($options{default})); foreach (keys %{$options{default}}) { if ($_ eq $self->{mode}) { foreach my $value (keys %{$options{default}->{$_}}) { if (!defined($self->{option_results}->{$value})) { $self->{option_results}->{$value} = $options{default}->{$_}->{$value}; } } } } } sub version { my ($self, %options) = @_; $self->{output}->add_option_msg(short_msg => "Mode Version: " . $self->{version}); } sub disco_format { my ($self, %options) = @_; } sub disco_show { my ($self, %options) = @_; } 1; __END__ centreon-plugins-20220113/centreon/plugins/multi.pm000066400000000000000000000074371417000230700222350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::multi; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'modes-exec:s' => { name => 'modes_exec' }, 'option-mode:s@' => { name => 'option_mode' } }); $self->{options} = $options{options}; return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{modes_exec})) { $self->{output}->add_option_msg(short_msg => "Need to specify --modes-exec option."); $self->{output}->option_exit(); } $self->{options_mode_extra} = {}; if (defined($self->{option_results}->{option_mode})) { foreach (@{$self->{option_results}->{option_mode}}) { next if (! /^(.+?),(.*)$/); $self->{options_mode_extra}->{$1} = [] if (!defined($self->{options_mode_extra}->{$1})); push @{$self->{options_mode_extra}->{$1}}, $2; } } $self->{modes} = $options{modes}; } sub run { my ($self, %options) = @_; $self->{output}->parameter(attr => 'nodisplay', value => 1); $self->{output}->parameter(attr => 'noexit_die', value => 1); $self->{output}->use_new_perfdata(value => 1); my @modes = split /,/, $self->{option_results}->{modes_exec}; foreach (@modes) { next if (!defined($self->{modes}->{$_})); eval { centreon::plugins::misc::mymodule_load( output => $self->{output}, module => $self->{modes}->{$_}, error_msg => "Cannot load module --mode $_" ); @ARGV = (@{$self->{options_mode_extra}->{$_}}) if (defined($self->{options_mode_extra}->{$_})); $self->{output}->mode(name => $_); my $mode = $self->{modes}->{$_}->new(options => $self->{options}, output => $self->{output}, mode => $_); $self->{options}->parse_options(); my $option_results = $self->{options}->get_options(); $mode->check_options(option_results => $option_results, %options); $mode->run(%options); }; if ($@) { $self->{output}->output_add(long_msg => 'eval result mode ' . $_ . ': ' . $@, debug => 1); } } $self->{output}->mode(name => 'multi'); $self->{output}->parameter(attr => 'nodisplay', value => 0); $self->{output}->parameter(attr => 'noexit_die', value => 0); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check multiple modes at once. =over 8 =item B<--modes-exec> Which modes to select (separated by coma). Example for linux: --modes-exec=cpu,memory,storage,interfaces =item B<--option-mode> Set options for a specifi mode (can be multiple). Example interfaces and storage snmp: --option-mode='interfaces,--statefile-dir=/tmp' --option-mode='interfaces,--add-traffic' --option-mode='storage,--statefile-dir=/tmp' =back =cut centreon-plugins-20220113/centreon/plugins/nrpe.pm000066400000000000000000000343311417000230700220400ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::nrpe; use strict; use warnings; use centreon::plugins::misc; use Convert::Binary::C; use Digest::CRC 'crc32'; use IO::Socket; use IO::Socket::INET6; use IO::Socket::SSL; use Socket qw(SOCK_STREAM AF_INET6 AF_INET); sub new { my ($class, %options) = @_; my $self = {}; bless $self, $class; if (!defined($options{output})) { print "Class NRPE: Need to specify 'output' argument.\n"; exit 3; } if (!defined($options{options})) { $options{output}->add_option_msg(short_msg => "Class NRPE: Need to specify 'options' argument."); $options{output}->option_exit(); } if (!defined($options{noptions})) { $options{options}->add_options(arguments => { 'nrpe-version:s' => { name => 'nrpe_version', default => 2 }, 'nrpe-port:s' => { name => 'nrpe_port', default => 5666 }, 'nrpe-payload:s' => { name => 'nrpe_payload', default => 1024 }, 'nrpe-bindaddr:s' => { name => 'nrpe_bindaddr' }, 'nrpe-use-ipv4' => { name => 'nrpe_use_ipv4' }, 'nrpe-use-ipv6' => { name => 'nrpe_use_ipv6' }, 'nrpe-timeout:s' => { name => 'nrpe_timeout', default => 10 }, 'ssl-opt:s@' => { name => 'ssl_opt' }, }); } $options{options}->add_help(package => __PACKAGE__, sections => 'NRPE CLASS OPTIONS'); $self->{output} = $options{output}; return $self; } sub check_options { my ($self, %options) = @_; $options{option_results}->{nrpe_version} =~ s/^v//; if ($options{option_results}->{nrpe_version} !~ /2|3|4/) { $self->{output}->add_option_msg(short_msg => "Unknown NRPE version."); $self->{output}->option_exit(); } $self->{nrpe_version} = $options{option_results}->{nrpe_version}; $self->{nrpe_payload} = $options{option_results}->{nrpe_payload}; %{$self->{nrpe_params}} = ( PeerHost => $options{option_results}->{hostname}, PeerPort => $options{option_results}->{nrpe_port}, Timeout => $options{option_results}->{nrpe_timeout}, ); if ($options{option_results}->{bindaddr}) { $self->{nrpe_params}->{LocalAddr} = $options{option_results}->{nrpe_bindaddr}; } if ($options{option_results}->{nrpe_use_ipv4}) { $self->{nrpe_params}->{Domain} = AF_INET; } elsif ($options{option_results}->{nrpe_use_ipv6}) { $self->{nrpe_params}->{Domain} = AF_INET6; } $self->{ssl_context} = {}; foreach (@{$options{option_results}->{ssl_opt}}) { if (/(SSL_[A-Za-z_]+)\s+=>\s*(\S+)/) { my $value = $2; $value = $self->assign_eval(eval => $value); $self->{ssl_context}->{$1} = $value; } } } sub load_eval { my ($self) = @_; my ($code) = centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'Safe', no_quit => 1 ); if ($code == 0) { $self->{safe} = Safe->new(); $self->{safe}->permit_only(':base_core', 'rv2gv', 'padany'); $self->{safe}->share('$values'); $self->{safe}->share('$assign_var'); $self->{safe}->share_from('IO::Socket::SSL', [ 'SSL_VERIFY_NONE', 'SSL_VERIFY_PEER', 'SSL_VERIFY_FAIL_IF_NO_PEER_CERT', 'SSL_VERIFY_CLIENT_ONCE', 'SSL_RECEIVED_SHUTDOWN', 'SSL_SENT_SHUTDOWN', 'SSL_OCSP_NO_STAPLE', 'SSL_OCSP_MUST_STAPLE', 'SSL_OCSP_FAIL_HARD', 'SSL_OCSP_FULL_CHAIN', 'SSL_OCSP_TRY_STAPLE' ]); } $self->{safe_test} = 1; } sub assign_eval { my ($self, %options) = @_; $self->load_eval() if (!defined($self->{safe_test}) || $self->{safe_test} == 0); our $assign_var; if (defined($self->{safe})) { our $values = $options{values}; $self->{safe}->reval("\$assign_var = $options{eval}", 1); if ($@) { die 'Unsafe code evaluation: ' . $@; } } else { my $values = $options{values}; eval "\$assign_var = $options{eval}"; } return $assign_var; } sub create_socket { my ($self, %options) = @_; my $socket; if (scalar(keys %{$self->{ssl_context}} > 0)) { $socket = IO::Socket::SSL->new(%{$self->{nrpe_params}}, %{$self->{ssl_context}}); if (!$socket) { $self->{output}->add_option_msg(short_msg => "Failed to establish SSL connection: $!, ssl_error=$SSL_ERROR"); $self->{output}->option_exit(); } } else { $socket = IO::Socket::INET6->new(Proto => 'tcp', Type => SOCK_STREAM, %{$self->{nrpe_params}}); if (!$socket) { $self->{output}->add_option_msg(short_msg => "Failed to create socket: $!"); $self->{output}->option_exit(); } } return $socket; } sub assemble { my ($self, %options) = @_; $self->{c} = Convert::Binary::C->new(ByteOrder => 'BigEndian', Alignment => 0); my $packed; if ($options{version} eq 2) { $packed = $self->assemble_v2(%options); } elsif ($options{version} eq 4) { $packed = $self->assemble_v4(%options); } else { $packed = $self->assemble_v3(%options); } return $packed; } sub assemble_v4 { my ($self, %options) = @_; my $buffer = $options{check}; my $len = length($buffer); # In order for crc32 calculation to be correct we need to pad the buffer with \0 # It seems that the buffer must be in multiples of 1024 so to achive this we use # some integer arithmetic to find the next multiple of 1024 that can hold our message my $pack_len; { use integer; $pack_len = (($len / 1024) * 1024) + 1024; } $buffer = pack("Z$pack_len", $buffer); $len = length($buffer) + 4; my $unpacked; $unpacked->{alignment} = 0; $unpacked->{buffer_length} = $len; $unpacked->{buffer} = $buffer; $unpacked->{crc32_value} = "\x00\x00\x00\x00"; $unpacked->{packet_type} = defined($options{type}) ? $options{type} : 1; $unpacked->{packet_version} = 4; $unpacked->{result_code} = defined($options{result_code}) ? $options{result_code} : 2324; $self->{c}->parse(<{c}->tag('Packet.buffer', Format => 'String'); my $packed = $self->{c}->pack('Packet', $unpacked); $unpacked->{crc32_value} = crc32($packed); $packed = $self->{c}->pack('Packet', $unpacked); return $packed; } sub assemble_v3 { my ($self, %options) = @_; my $buffer = $options{check}; my $len = length($buffer); # In order for crc32 calculation to be correct we need to pad the buffer with \0 # It seems that the buffer must be in multiples of 1024 so to achive this we use # some integer arithmetic to find the next multiple of 1024 that can hold our message my $pack_len; { use integer; $pack_len = (($len / 1024) * 1024) + 1024; } $buffer = pack("Z$pack_len", $buffer); $len = length($buffer) + 1; my $unpacked; $unpacked->{alignment} = 0; $unpacked->{buffer_length} = $len; $unpacked->{buffer} = $buffer; $unpacked->{crc32_value} = "\x00\x00\x00\x00"; $unpacked->{packet_type} = defined($options{type}) ? $options{type} : 1; $unpacked->{packet_version} = 3; $unpacked->{result_code} = defined($options{result_code}) ? $options{result_code} : 2324; $self->{c}->parse(<{c}->tag('Packet.buffer', Format => 'String'); my $packed = $self->{c}->pack('Packet', $unpacked); $unpacked->{crc32_value} = crc32($packed); $packed = $self->{c}->pack('Packet', $unpacked); return $packed; } sub assemble_v2 { my ($self, %options) = @_; my $len = $options{payload}; my $unpacked; $unpacked->{buffer} = $options{check}; $unpacked->{crc32_value} = "\x00\x00\x00\x00"; $unpacked->{packet_type} = defined($options{type}) ? $options{type} : 1; $unpacked->{packet_version} = 2; $unpacked->{result_code} = defined($options{result_code}) ? $options{result_code} : 2324; $self->{c}->parse(<{c}->tag('Packet.buffer', Format => 'String'); my $packed = $self->{c}->pack('Packet', $unpacked); $unpacked->{crc32_value} = crc32($packed); $packed = $self->{c}->pack('Packet', $unpacked); return $packed; } sub validate { my ($self, $packet) = @_; my $unpacked = $self->disassemble($packet, 1); if (!$unpacked->{packet_version}) { # If version is missing this is probably not an NRPE Packet. return undef; } my $checksum = $unpacked->{crc32_value}; $unpacked->{crc32_value} = "\x00\x00\x00\x00"; my $packed = $self->assemble( %{ { check => $unpacked->{buffer}, version => $unpacked->{packet_version}, type => $unpacked->{packet_type}, result_code => $unpacked->{result_code} } } ); if (crc32($packed) != $checksum) { return undef; } else { return 1; } } sub disassemble { my ($self, $packet, $novalidate) = @_; if (!$packet) { $self->{output}->add_option_msg(short_msg => "Could not disassemble packet."); $self->{output}->option_exit(); } unless ($novalidate) { unless ($self->validate($packet)) { $self->{output}->add_option_msg(short_msg => "Packet had invalid CRC32."); $self->{output}->option_exit(); } } my $version = unpack("n", $packet); if (!defined($version) || $version eq '') { $self->{output}->add_option_msg(short_msg => "Could not disassemble packet."); $self->{output}->option_exit(); } my $unpacked = {}; if ($version eq 2) { $unpacked = $self->disassemble_v2($packet); } else { $unpacked = $self->disassemble_v3($packet); } return $unpacked; } sub disassemble_v3 { my ($self, $packet) = @_; my @arr = unpack("n2 N n2 N Z*", $packet); my $unpacked = {}; $unpacked->{packet_version} = $arr[0]; $unpacked->{packet_type} = $arr[1]; $unpacked->{crc32_value} = $arr[2]; $unpacked->{result_code} = $arr[3]; $unpacked->{alignment} = $arr[4]; $unpacked->{buffer_length} = $arr[5]; $unpacked->{buffer} = $arr[6]; return $unpacked; } sub disassemble_v2 { my ($self, $packet) = @_; my @arr = unpack("n2 N n Z*", $packet); my $unpacked = {}; $unpacked->{packet_version} = $arr[0]; $unpacked->{packet_type} = $arr[1]; $unpacked->{crc32_value} = $arr[2]; $unpacked->{result_code} = $arr[3]; $unpacked->{buffer} = $arr[4]; return $unpacked; } sub request { my ($self, %options) = @_; my $check; if (!defined($options{arg}) || scalar @{$options{arg}} == 0) { $check = $options{check}; } else { $check = join('!', $options{check}, @{$options{arg}}); } my $socket = $self->create_socket(%options); my $assembled = $self->assemble( type => 1, check => $check, version => $self->{nrpe_version}, payload => $self->{nrpe_payload} ); my $response; print $socket $assembled; while (<$socket>) { $response .= $_; } close($socket); if (!defined($response) || $response eq '') { $self->{output}->add_option_msg(short_msg => "No response from remote host."); $self->{output}->option_exit(); } my $response_packet = $self->disassemble($response, 1); if (!defined($response_packet->{packet_version}) || $response_packet->{packet_version} != $self->{nrpe_version}) { $self->{output}->add_option_msg(short_msg => "Bad response from remote host."); $self->{output}->option_exit(); } return $response_packet; } sub set_nrpe_connect_params { my ($self, %options) = @_; foreach (keys %options) { $self->{nrpe_params}->{$_} = $options{$_}; } } sub set_nrpe_params { my ($self, %options) = @_; foreach (keys %options) { $self->{$_} = $options{$_}; } } sub get_hostname { my ($self) = @_; my $host = $self->{nrpe_params}->{PeerHost}; $host =~ s/.*://; return $host; } sub get_port { my ($self) = @_; return $self->{nrpe_params}->{PeerPort}; } 1; __END__ =head1 NAME NRPE global =head1 SYNOPSIS NRPE class =head1 NRPE CLASS OPTIONS =over 8 =item B<--nrpe-version> Version: 2 for NRPE v2 (Default), 3 for NRPE v3, 4 for NRPE v4. =item B<--nrpe-port> Port (Default: 5666). =item B<--nrpe-payload> Buffer payload (For v2 only) (Default: 1024). =item B<--nrpe-bindaddr> Bind to local address. =item B<--nrpe-use-ipv4> Use IPv4 only =item B<--nrpe-use-ipv6> Use IPv6 only =item B<--nrpe-timeout> Timeout in secondes (Default: 10). =item B<--ssl-opt> Set SSL Options (--ssl-opt="SSL_version => 'TLSv1'" --ssl-opt="SSL_verify_mode => SSL_VERIFY_NONE" --ssl-opt="SSL_cipher_list => 'ALL'"). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/centreon/plugins/options.pm000066400000000000000000000130171417000230700225650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::options; use Pod::Usage; use strict; use warnings; my $alternative = 1; sub new { my ($class) = @_; my $self = {}; bless $self, $class; $self->{pod_where_loaded} = 0; $self->{sanity} = 0; $self->{options_stored} = {}; $self->{options} = {}; @{$self->{pod_package}} = (); $self->{pod_packages_once} = {}; if ($alternative == 0) { require Getopt::Long; Getopt::Long->import(); Getopt::Long::Configure("pass_through"); Getopt::Long::Configure('bundling'); Getopt::Long::Configure('no_auto_abbrev'); } else { require centreon::plugins::alternative::Getopt; $centreon::plugins::alternative::Getopt::warn_message = 0; centreon::plugins::alternative::Getopt->import(); } return $self; } sub set_sanity { my ($self, %options) = @_; if ($alternative == 0) { Getopt::Long::Configure('no_pass_through'); } else { $centreon::plugins::alternative::Getopt::warn_message = 1; } $self->{sanity} = 1; } sub set_output { my ($self, %options) = @_; $self->{output} = $options{output}; } sub display_help { my ($self, %options) = @_; my $stdout; foreach (@{$self->{pod_package}}) { my $where = $self->pod_where(package => $_->{package}); { local *STDOUT; open STDOUT, '>', \$stdout; pod2usage( -exitval => 'NOEXIT', -input => $where, -verbose => 99, -sections => $_->{sections} ) if (defined($where)); } $self->{output}->add_option_msg(long_msg => $stdout) if (defined($stdout)); } } sub add_help { my ($self, %options) = @_; # $options{package} = string package # $options{sections} = string sections # $options{help_first} = put at the beginning # $options{once} = put help only one time for a package if (defined($options{once}) && defined($self->{pod_packages_once}->{$options{package}})) { return ; } if (defined($options{help_first})) { unshift @{$self->{pod_package}}, {package => $options{package}, sections => $options{sections}}; } else { push @{$self->{pod_package}}, { package => $options{package}, sections => $options{sections} }; } $self->{pod_packages_once}->{$options{package}} = 1; } sub add_options { my ($self, %options) = @_; # $options{arguments} = ref to hash table with string and name to store (example: { 'mode:s' => { name => 'mode', default => 'defaultvalue' ) foreach (keys %{$options{arguments}}) { if (defined($options{arguments}->{$_}->{redirect})) { $self->{options}->{$_} = \$self->{options_stored}->{$options{arguments}->{$_}->{redirect}}; next; } if (defined($options{arguments}->{$_}->{default})) { $self->{options_stored}->{$options{arguments}->{$_}->{name}} = $options{arguments}->{$_}->{default}; } else { $self->{options_stored}->{$options{arguments}->{$_}->{name}} = undef; } $self->{options}->{$_} = \$self->{options_stored}->{$options{arguments}->{$_}->{name}}; } } sub parse_options { my $self = shift; #%{$self->{options_stored}} = (); my $save_warn_handler; if ($self->{sanity} == 1) { $save_warn_handler = $SIG{__WARN__}; $SIG{__WARN__} = sub { $self->{output}->add_option_msg(short_msg => $_[0]); $self->{output}->option_exit(nolabel => 1); }; } GetOptions( %{$self->{options}} ); %{$self->{options}} = (); $SIG{__WARN__} = $save_warn_handler if ($self->{sanity} == 1); } sub pod_where { my ($self, %options) = @_; if ($self->{pod_where_loaded} == 0) { $self->{pod_where_loaded} = 1; my ($code) = centreon::plugins::misc::mymodule_load( module => 'Pod::Find', no_quit => 1 ); if ($code) { $code = centreon::plugins::misc::mymodule_load( module => 'Pod::Simple::Search', no_quit => 1 ); die "Cannot load module 'Pod::Simple::Search'" if ($code); $self->{pod_where_loaded} = 2; $self->{pod_simple_search} = Pod::Simple::Search->new(); $self->{pod_simple_search}->inc(1); } } if ($self->{pod_where_loaded} == 1) { return Pod::Find::pod_where({-inc => 1}, $options{package}); } return $self->{pod_simple_search}->find($options{package}); } sub get_option { my ($self, %options) = @_; return $self->{options_stored}->{$options{argument}}; } sub get_options { my $self = shift; return $self->{options_stored}; } sub clean { my $self = shift; $self->{options_stored} = {}; } 1; __END__ centreon-plugins-20220113/centreon/plugins/output.pm000066400000000000000000001535261417000230700224440ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::output; use strict; use warnings; use centreon::plugins::misc; sub new { my ($class, %options) = @_; my $self = {}; bless $self, $class; if (!defined($options{options})) { print "Class Output: Need to specify 'options' argument to load.\n"; exit 3; } $options{options}->add_options(arguments => { 'explode-perfdata-max:s@' => { name => 'explode_perfdata_max' }, 'range-perfdata:s' => { name => 'range_perfdata' }, 'filter-perfdata:s' => { name => 'filter_perfdata' }, 'filter-perfdata-adv:s' => { name => 'filter_perfdata_adv' }, 'change-perfdata:s@' => { name => 'change_perfdata' }, 'extend-perfdata:s@' => { name => 'extend_perfdata' }, 'extend-perfdata-group:s@'=> { name => 'extend_perfdata_group' }, 'change-exit:s@' => { name => 'change_exit' }, 'change-short-output:s@' => { name => 'change_short_output' }, 'use-new-perfdata' => { name => 'use_new_perfdata' }, 'filter-uom:s' => { name => 'filter_uom' }, 'verbose' => { name => 'verbose' }, 'debug' => { name => 'debug' }, 'opt-exit:s' => { name => 'opt_exit', default => 'unknown' }, 'output-xml' => { name => 'output_xml' }, 'output-json' => { name => 'output_json' }, 'output-ignore-perfdata' => { name => 'output_ignore_perfdata' }, 'output-ignore-label' => { name => 'output_ignore_label' }, 'output-openmetrics' => { name => 'output_openmetrics' }, 'output-file:s' => { name => 'output_file' }, 'disco-format' => { name => 'disco_format' }, 'disco-show' => { name => 'disco_show' }, 'float-precision:s' => { name => 'float_precision', default => 8 }, 'source-encoding:s' => { name => 'source_encoding' , default => 'UTF-8' } }); $self->{option_results} = {}; $self->{option_msg} = []; $self->{nodisplay} = 0; $self->{noexit_die} = 0; $self->{is_output_xml} = 0; $self->{is_output_json} = 0; $self->{errors} = {OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3, PENDING => 4}; $self->{errors_num} = {0 => 'OK', 1 => 'WARNING', 2 => 'CRITICAL', 3 => 'UNKNOWN', 4 => 'PENDING'}; $self->{myerrors} = {0 => "OK", 1 => "WARNING", 3 => "UNKNOWN", 7 => "CRITICAL"}; $self->{myerrors_mask} = {CRITICAL => 7, WARNING => 1, UNKNOWN => 3, OK => 0}; $self->{global_short_concat_outputs} = {OK => undef, WARNING => undef, CRITICAL => undef, UNKNOWN => undef, UNQUALIFIED_YET => undef}; $self->{global_short_outputs} = {OK => [], WARNING => [], CRITICAL => [], UNKNOWN => [], UNQUALIFIED_YET => []}; $self->{global_long_output} = []; $self->{perfdatas} = []; $self->{explode_perfdatas} = {}; $self->{change_perfdata} = {}; $self->{explode_perfdata_total} = 0; $self->{range_perfdata} = 0; $self->{global_status} = 0; $self->{encode_import} = 0; $self->{perlqq} = 0; $self->{safe_test} = 0; $self->{disco_elements} = []; $self->{disco_entries} = []; $self->{plugin} = ''; $self->{mode} = ''; return $self; } sub check_options { my ($self, %options) = @_; # $options{option_results} = ref to options result %{$self->{option_results}} = %{$options{option_results}}; $self->{option_results}->{opt_exit} = lc($self->{option_results}->{opt_exit}); if (!$self->is_litteral_status(status => $self->{option_results}->{opt_exit})) { $self->add_option_msg(short_msg => "Unknown value '" . $self->{option_results}->{opt_exit} . "' for --opt-exit."); $self->option_exit(exit_litteral => 'unknown'); } # Go in XML Mode if ($self->is_disco_show() || $self->is_disco_format()) { # By Default XML if (!defined($self->{option_results}->{output_json})) { $self->{option_results}->{output_xml} = 1; } } if (defined($self->{option_results}->{range_perfdata})) { $self->{range_perfdata} = $self->{option_results}->{range_perfdata}; $self->{range_perfdata} = 1 if ($self->{range_perfdata} eq ''); if ($self->{range_perfdata} !~ /^[012]$/) { $self->add_option_msg(short_msg => "Wrong range-perfdata option '" . $self->{range_perfdata} . "'"); $self->option_exit(); } } if (defined($self->{option_results}->{change_exit})) { $self->{change_exit} = {}; foreach (@{$self->{option_results}->{change_exit}}) { my ($src, $dst) = split(/=/); next if (!defined($src) || !defined($self->{errors}->{ uc($src) })); next if (!defined($dst) || !defined($self->{errors}->{ uc($dst) })); $self->{change_exit}->{uc($src)} = uc($dst); } } if (defined($self->{option_results}->{explode_perfdata_max})) { if (${$self->{option_results}->{explode_perfdata_max}}[0] eq '') { $self->{explode_perfdata_total} = 2; } else { $self->{explode_perfdata_total} = 1; foreach (@{$self->{option_results}->{explode_perfdata_max}}) { my ($perf_match, $perf_result) = split /,/; if (!defined($perf_result)) { $self->add_option_msg(short_msg => "Wrong explode-perfdata-max option '" . $_ . "' (syntax: match,value)"); $self->option_exit(); } $self->{explode_perfdatas}->{$perf_match} = $perf_result; } } } if (defined($self->{option_results}->{filter_perfdata_adv}) && $self->{option_results}->{filter_perfdata_adv} ne '') { $self->{option_results}->{filter_perfdata_adv} =~ s/%\{(.*?)\}/\$values->{$1}/g; $self->{option_results}->{filter_perfdata_adv} =~ s/%\((.*?)\)/\$values->{$1}/g; } $self->load_perfdata_extend_args(); $self->{option_results}->{use_new_perfdata} = 1 if (defined($self->{option_results}->{output_openmetrics})); $self->{source_encoding} = (!defined($self->{option_results}->{source_encoding}) || $self->{option_results}->{source_encoding} eq '') ? 'UTF-8' : $self->{option_results}->{source_encoding}; } sub add_option_msg { my ($self, %options) = @_; # $options{short_msg} = string msg # $options{long_msg} = string msg $options{severity} = 'UNQUALIFIED_YET'; $self->output_add(%options); } sub set_ignore_label { my ($self, %options) = @_; $self->{option_results}->{output_ignore_label} = 1; } sub set_status { my ($self, %options) = @_; # $options{exit_litteral} = string litteral exit # Nothing to do for 'UNQUALIFIED_YET' if (!$self->{myerrors_mask}->{uc($options{exit_litteral})}) { return ; } $self->{global_status} |= $self->{myerrors_mask}->{uc($options{exit_litteral})}; } sub output_add { my ($self, %params) = @_; my %args = ( severity => 'OK', separator => ' - ', debug => 0, short_msg => undef, long_msg => undef, ); my $options = {%args, %params}; if (defined($options->{short_msg})) { chomp $options->{short_msg}; if (defined($self->{global_short_concat_outputs}->{uc($options->{severity})})) { $self->{global_short_concat_outputs}->{uc($options->{severity})} .= $options->{separator} . $options->{short_msg}; } else { $self->{global_short_concat_outputs}->{uc($options->{severity})} = $options->{short_msg}; } push @{$self->{global_short_outputs}->{uc($options->{severity})}}, $options->{short_msg}; $self->set_status(exit_litteral => $options->{severity}); } if (defined($options->{long_msg}) && ($options->{debug} == 0 || defined($self->{option_results}->{debug}))) { chomp $options->{long_msg}; push @{$self->{global_long_output}}, $options->{long_msg}; } } sub perfdata_add { my ($self, %options) = @_; my $perfdata = { label => '', value => '', unit => '', warning => '', critical => '', min => '', max => '', mode => $self->{mode} }; foreach (keys %options) { next if (!defined($options{$_})); $perfdata->{$_} = $options{$_}; } if ((defined($self->{option_results}->{use_new_perfdata}) || defined($options{force_new_perfdata})) && defined($options{nlabel})) { $perfdata->{label} = $options{nlabel}; } if (defined($options{instances})) { $options{instances} = [$options{instances}] if (!ref($options{instances})); my ($external_instance_separator, $internal_instance_separator) = ('#', '~'); if (defined($self->{option_results}->{use_new_perfdata}) || defined($options{force_new_perfdata})) { $perfdata->{label} = join('~', @{$options{instances}}) . '#' . $perfdata->{label}; } else { $perfdata->{label} .= '_' . join('_', @{$options{instances}}); } } $perfdata->{label} =~ s/'/''/g; push @{$self->{perfdatas}}, $perfdata; } sub filter_perfdata { my ($self, %options) = @_; return 1 if ( defined($self->{option_results}->{filter_perfdata}) && $options{perf}->{label} !~ /$self->{option_results}->{filter_perfdata}/ ); return 1 if ( defined($self->{option_results}->{filter_perfdata_adv}) && $self->{option_results}->{filter_perfdata_adv} ne '' && !$self->test_eval(test => $self->{option_results}->{filter_perfdata_adv}, values => $options{perf}) ); return 0; } sub range_perfdata { my ($self, %options) = @_; return if ($self->{range_perfdata} == 0); if ($self->{range_perfdata} == 1) { for (my $i = 0; $i < scalar(@{$options{ranges}}); $i++) { ${${$options{ranges}}[$i]} =~ s/^(@?)-?[0\.]+:/$1/; } } else { for (my $i = 0; $i < scalar(@{$options{ranges}}); $i++) { ${${$options{ranges}}[$i]} = ''; } } } sub output_json { my ($self, %options) = @_; my $force_ignore_perfdata = (defined($options{force_ignore_perfdata}) && $options{force_ignore_perfdata} == 1) ? 1 : 0; my $force_long_output = (defined($options{force_long_output}) && $options{force_long_output} == 1) ? 1 : 0; my $json_content = { plugin => { name => $self->{plugin}, mode => $self->{mode}, exit => $options{exit_litteral}, outputs => [], perfdatas => [] } }; foreach my $code_litteral (keys %{$self->{global_short_outputs}}) { foreach (@{$self->{global_short_outputs}->{$code_litteral}}) { my ($child_output, $child_type, $child_msg, $child_exit); my $lcode_litteral = ($code_litteral eq 'UNQUALIFIED_YET' ? uc($options{exit_litteral}) : $code_litteral); push @{$json_content->{plugin}->{outputs}}, { type => 1, msg => ($options{nolabel} == 0 ? ($lcode_litteral . ': ') : '') . $_, exit => $lcode_litteral }; } } if (defined($self->{option_results}->{verbose}) || $force_long_output == 1) { foreach (@{$self->{global_long_output}}) { push @{$json_content->{plugin}->{outputs}}, { type => 2, msg => $_, }; } } if ($options{force_ignore_perfdata} == 0) { $self->change_perfdata(); foreach my $perf (@{$self->{perfdatas}}) { next if ($self->filter_perfdata(perf => $perf)); $self->range_perfdata(ranges => [\$perf->{warning}, \$perf->{critical}]); my %values = (); foreach my $key (keys %$perf) { $perf->{$key} = '' if (defined($self->{option_results}->{filter_uom}) && $key eq 'unit' && $perf->{$key} !~ /$self->{option_results}->{filter_uom}/); $values{$key} = $perf->{$key}; } push @{$json_content->{plugin}->{perfdatas}}, { %values }; } } print $self->{json_output}->encode($json_content); } sub output_xml { my ($self, %options) = @_; my $force_ignore_perfdata = (defined($options{force_ignore_perfdata}) && $options{force_ignore_perfdata} == 1) ? 1 : 0; my $force_long_output = (defined($options{force_long_output}) && $options{force_long_output} == 1) ? 1 : 0; my ($child_plugin_name, $child_plugin_mode, $child_plugin_exit, $child_plugin_output, $child_plugin_perfdata); my $root = $self->{xml_output}->createElement('plugin'); $self->{xml_output}->setDocumentElement($root); $child_plugin_name = $self->{xml_output}->createElement('name'); $child_plugin_name->appendText($self->{plugin}); $child_plugin_mode = $self->{xml_output}->createElement('mode'); $child_plugin_mode->appendText($self->{mode}); $child_plugin_exit = $self->{xml_output}->createElement('exit'); $child_plugin_exit->appendText($options{exit_litteral}); $child_plugin_output = $self->{xml_output}->createElement('outputs'); $child_plugin_perfdata = $self->{xml_output}->createElement('perfdatas'); $root->addChild($child_plugin_name); $root->addChild($child_plugin_mode); $root->addChild($child_plugin_exit); $root->addChild($child_plugin_output); $root->addChild($child_plugin_perfdata); foreach my $code_litteral (keys %{$self->{global_short_outputs}}) { foreach (@{$self->{global_short_outputs}->{$code_litteral}}) { my ($child_output, $child_type, $child_msg, $child_exit); my $lcode_litteral = ($code_litteral eq 'UNQUALIFIED_YET' ? uc($options{exit_litteral}) : $code_litteral); $child_output = $self->{xml_output}->createElement('output'); $child_plugin_output->addChild($child_output); $child_type = $self->{xml_output}->createElement('type'); $child_type->appendText(1); # short $child_msg = $self->{xml_output}->createElement('msg'); $child_msg->appendText(($options{nolabel} == 0 ? ($lcode_litteral . ': ') : '') . $_); $child_exit = $self->{xml_output}->createElement('exit'); $child_exit->appendText($lcode_litteral); $child_output->addChild($child_type); $child_output->addChild($child_exit); $child_output->addChild($child_msg); } } if (defined($self->{option_results}->{verbose}) || $force_long_output == 1) { foreach (@{$self->{global_long_output}}) { my ($child_output, $child_type, $child_msg); $child_output = $self->{xml_output}->createElement('output'); $child_plugin_output->addChild($child_output); $child_type = $self->{xml_output}->createElement('type'); $child_type->appendText(2); # long $child_msg = $self->{xml_output}->createElement('msg'); $child_msg->appendText($_); $child_output->addChild($child_type); $child_output->addChild($child_msg); } } if ($options{force_ignore_perfdata} == 0) { $self->change_perfdata(); foreach my $perf (@{$self->{perfdatas}}) { next if ($self->filter_perfdata(perf => $perf)); $self->range_perfdata(ranges => [\$perf->{warning}, \$perf->{critical}]); my ($child_perfdata); $child_perfdata = $self->{xml_output}->createElement('perfdata'); $child_plugin_perfdata->addChild($child_perfdata); foreach my $key (keys %$perf) { $perf->{$key} = '' if (defined($self->{option_results}->{filter_uom}) && $key eq 'unit' && $perf->{$key} !~ /$self->{option_results}->{filter_uom}/); my $child = $self->{xml_output}->createElement($key); $child->appendText($perf->{$key}); $child_perfdata->addChild($child); } } } print $self->{xml_output}->toString(1); } sub output_openmetrics { my ($self, %options) = @_; centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'Time::HiRes', error_msg => "Cannot load module 'Time::HiRes'." ); my $time_ms = int(Time::HiRes::time() * 1000); $self->change_perfdata(); foreach my $perf (@{$self->{perfdatas}}) { next if ($self->filter_perfdata(perf => $perf)); $perf->{unit} = '' if ( defined($self->{option_results}->{filter_uom}) && $perf->{unit} !~ /$self->{option_results}->{filter_uom}/ ); $self->range_perfdata(ranges => [\$perf->{warning}, \$perf->{critical}]); my $label = $perf->{label}; my $instance; if ($label =~ /^(.*?)#(.*)$/) { ($perf->{instance}, $label) = ($1, $2); } my ($bucket, $append) = ('{plugin="' . $self->{plugin} . '",mode="' . $perf->{mode} . '"', ''); foreach ('unit', 'warning', 'critical', 'min', 'max', 'instance') { if (defined($perf->{$_}) && $perf->{$_} ne '') { $bucket .= ',' . $_ . '="' . $perf->{$_} . '"'; } } $bucket .= '}'; print $label . $bucket . ' ' . $perf->{value} . ' ' . $time_ms . "\n"; } } sub output_txt_short_display { my ($self, %options) = @_; if (defined($self->{global_short_concat_outputs}->{CRITICAL})) { print (($options{nolabel} == 0 ? 'CRITICAL: ' : '') . $self->{global_short_concat_outputs}->{CRITICAL} . " "); } if (defined($self->{global_short_concat_outputs}->{WARNING})) { print (($options{nolabel} == 0 ? 'WARNING: ' : '') . $self->{global_short_concat_outputs}->{WARNING} . " "); } if (defined($self->{global_short_concat_outputs}->{UNKNOWN})) { print (($options{nolabel} == 0 ? 'UNKNOWN: ' : '') . $self->{global_short_concat_outputs}->{UNKNOWN} . " "); } if (uc($options{exit_litteral}) eq 'OK') { print (($options{nolabel} == 0 ? 'OK: ' : '') . (defined($self->{global_short_concat_outputs}->{OK}) ? $self->{global_short_concat_outputs}->{OK} : '') . " "); } } sub output_txt_short { my ($self, %options) = @_; if (!defined($self->{option_results}->{change_short_output})) { $self->output_txt_short_display(%options); return ; } my $stdout = ''; { local *STDOUT; open STDOUT, '>', \$stdout; $self->output_txt_short_display(%options); } foreach (@{$self->{option_results}->{change_short_output}}) { my ($pattern, $replace, $modifier) = split /~/; next if (!defined($pattern)); $replace = '' if (!defined($replace)); $modifier = '' if (!defined($modifier)); eval "\$stdout =~ s{$pattern}{$replace}$modifier"; } print $stdout; } sub output_txt { my ($self, %options) = @_; my $force_ignore_perfdata = (defined($options{force_ignore_perfdata}) && $options{force_ignore_perfdata} == 1) ? 1 : 0; my $force_long_output = (defined($options{force_long_output}) && $options{force_long_output} == 1) ? 1 : 0; return if ($self->{nodisplay} == 1); if (defined($self->{global_short_concat_outputs}->{UNQUALIFIED_YET})) { $self->output_add(severity => uc($options{exit_litteral}), short_msg => $self->{global_short_concat_outputs}->{UNQUALIFIED_YET}); } $self->output_txt_short(%options); if ($force_ignore_perfdata == 0) { my $pipe = 0; $self->change_perfdata(); foreach my $perf (@{$self->{perfdatas}}) { next if ($self->filter_perfdata(perf => $perf)); $perf->{unit} = '' if (defined($self->{option_results}->{filter_uom}) && $perf->{unit} !~ /$self->{option_results}->{filter_uom}/); $self->range_perfdata(ranges => [\$perf->{warning}, \$perf->{critical}]); if ($pipe == 0) { print '|'; $pipe = 1; } print " '" . $perf->{label} . "'=" . $perf->{value} . $perf->{unit} . ';' . $perf->{warning} . ';' . $perf->{critical} . ';' . $perf->{min} . ';' . $perf->{max}; } } print "\n"; if (defined($self->{option_results}->{verbose}) || $force_long_output == 1) { if (scalar(@{$self->{global_long_output}})) { print join("\n", @{$self->{global_long_output}}); print "\n"; } } } sub display { my ($self, %options) = @_; my $nolabel = (defined($options{nolabel}) || defined($self->{option_results}->{output_ignore_label})) ? 1 : 0; my $force_ignore_perfdata = ((defined($options{force_ignore_perfdata}) && $options{force_ignore_perfdata} == 1) || $self->{option_results}->{output_ignore_perfdata}) ? 1 : 0; my $force_long_output = (defined($options{force_long_output}) && $options{force_long_output} == 1) ? 1 : 0; $force_long_output = 1 if (defined($self->{option_results}->{debug})); if (defined($self->{option_results}->{output_openmetrics})) { $self->perfdata_add(nlabel => 'plugin.mode.status', value => $self->{errors}->{$self->{myerrors}->{$self->{global_status}}}); } return if ($self->{nodisplay} == 1); if (defined($self->{option_results}->{output_file})) { if (!open (STDOUT, '>', $self->{option_results}->{output_file})) { $self->output_add( severity => 'UNKNOWN', short_msg => "cannot open file '" . $self->{option_results}->{output_file} . "': $!" ); } } if (defined($self->{option_results}->{output_xml})) { $self->create_xml_document(); if ($self->{is_output_xml}) { $self->output_xml( exit_litteral => $self->get_litteral_status(), nolabel => $nolabel, force_ignore_perfdata => $force_ignore_perfdata, force_long_output => $force_long_output ); return ; } } elsif (defined($self->{option_results}->{output_json})) { $self->create_json_document(); if ($self->{is_output_json}) { $self->output_json( exit_litteral => $self->get_litteral_status(), nolabel => $nolabel, force_ignore_perfdata => $force_ignore_perfdata, force_long_output => $force_long_output ); return ; } } elsif (defined($self->{option_results}->{output_openmetrics})) { $self->output_openmetrics(); return ; } $self->output_txt( exit_litteral => $self->get_litteral_status(), nolabel => $nolabel, force_ignore_perfdata => $force_ignore_perfdata, force_long_output => $force_long_output ); } sub die_exit { my ($self, %options) = @_; # $options{exit_litteral} = string litteral exit # $options{nolabel} = interger label display my $exit_litteral = defined($options{exit_litteral}) ? $options{exit_litteral} : $self->{option_results}->{opt_exit}; my $nolabel = (defined($options{nolabel}) || defined($self->{option_results}->{output_ignore_label})) ? 1 : 0; # ignore long output in the following case $self->{option_results}->{verbose} = undef; if (defined($self->{option_results}->{output_xml})) { $self->create_xml_document(); if ($self->{is_output_xml}) { $self->output_xml(exit_litteral => $exit_litteral, nolabel => $nolabel, force_ignore_perfdata => 1); $self->exit(exit_litteral => $exit_litteral); } } elsif (defined($self->{option_results}->{output_json})) { $self->create_json_document(); if ($self->{is_output_json}) { $self->output_json(exit_litteral => $exit_litteral, nolabel => $nolabel, force_ignore_perfdata => 1); $self->exit(exit_litteral => $exit_litteral); } } $self->output_txt(exit_litteral => $exit_litteral, nolabel => $nolabel, force_ignore_perfdata => 1); $self->exit(exit_litteral => $exit_litteral); } sub option_exit { my ($self, %options) = @_; # $options{exit_litteral} = string litteral exit # $options{nolabel} = interger label display my $exit_litteral = defined($options{exit_litteral}) ? $options{exit_litteral} : $self->{option_results}->{opt_exit}; my $nolabel = (defined($options{nolabel}) || defined($self->{option_results}->{output_ignore_label})) ? 1 : 0; if (defined($self->{option_results}->{output_xml})) { $self->create_xml_document(); if ($self->{is_output_xml}) { $self->output_xml(exit_litteral => $exit_litteral, nolabel => $nolabel, force_ignore_perfdata => 1, force_long_output => 1); $self->exit(exit_litteral => $exit_litteral); } } elsif (defined($self->{option_results}->{output_json})) { $self->create_json_document(); if ($self->{is_output_json}) { $self->output_json(exit_litteral => $exit_litteral, nolabel => $nolabel, force_ignore_perfdata => 1, force_long_output => 1); $self->exit(exit_litteral => $exit_litteral); } } elsif (defined($self->{option_results}->{output_openmetrics})) { $self->set_status(exit_litteral => $exit_litteral); $self->output_openmetrics(); $self->exit(exit_litteral => $exit_litteral); } $self->output_txt(exit_litteral => $exit_litteral, nolabel => $nolabel, force_ignore_perfdata => 1, force_long_output => 1); $self->exit(exit_litteral => $exit_litteral); } sub exit { my ($self, %options) = @_; if ($self->{noexit_die} == 1) { die 'exit'; } my $exit; if (defined($options{exit_litteral})) { $exit = uc($options{exit_litteral}); } else { $exit = $self->{myerrors}->{ $self->{global_status} }; } if (defined($self->{change_exit}) && defined($self->{change_exit}->{$exit})) { $exit = $self->{change_exit}->{$exit}; } exit $self->{errors}->{$exit}; } sub get_option { my ($self, %options) = @_; return $self->{option_results}->{$options{option}}; } sub get_most_critical { my ($self, %options) = @_; my $current_status = 0; # For 'OK' foreach (@{$options{status}}) { if ($self->{myerrors_mask}->{uc($_)} > $current_status) { $current_status = $self->{myerrors_mask}->{uc($_)}; } } return $self->{myerrors}->{$current_status}; } sub get_litteral_status { my ($self, %options) = @_; if (defined($options{status})) { if (defined($self->{errors_num}->{$options{status}})) { return $self->{errors_num}->{$options{status}}; } return $options{status}; } else { return $self->{myerrors}->{$self->{global_status}}; } } sub is_status { my ($self, %options) = @_; # $options{value} = string status # $options{litteral} = value is litteral # $options{compare} = string status if (defined($options{litteral})) { my $value = defined($options{value}) ? $options{value} : $self->get_litteral_status(); if (uc($value) eq uc($options{compare})) { return 1; } return 0; } my $value = defined($options{value}) ? $options{value} : $self->{global_status}; my $dec_val = $self->{myerrors_mask}->{$value}; my $lresult = $value & $dec_val; # Need to manage 0 if ($lresult > 0 || ($dec_val == 0 && $value == 0)) { return 1; } return 0; } sub is_litteral_status { my ($self, %options) = @_; # $options{status} = string status if (defined($self->{errors}->{uc($options{status})})) { return 1; } return 0; } sub create_json_document { my ($self) = @_; if (centreon::plugins::misc::mymodule_load( no_quit => 1, module => 'JSON', error_msg => "Cannot load module 'JSON'.") ) { print "Cannot load module 'JSON'\n"; $self->exit(exit_litteral => 'unknown'); } $self->{is_output_json} = 1; $self->{json_output} = JSON->new->utf8(); } sub create_xml_document { my ($self) = @_; if (centreon::plugins::misc::mymodule_load( no_quit => 1, module => 'XML::LibXML', error_msg => "Cannot load module 'XML::LibXML'.") ) { print "Cannot load module 'XML::LibXML'\n"; $self->exit(exit_litteral => 'unknown'); } $self->{is_output_xml} = 1; $self->{xml_output} = XML::LibXML::Document->new('1.0', 'utf-8'); } sub plugin { my ($self, %options) = @_; # $options{name} = string name if (defined($options{name})) { $self->{plugin} = $options{name}; } return $self->{plugin}; } sub mode { my ($self, %options) = @_; # $options{name} = string name if (defined($options{name})) { $self->{mode} = $options{name}; } return $self->{mode}; } sub add_disco_format { my ($self, %options) = @_; push @{$self->{disco_elements}}, @{$options{elements}}; } sub display_disco_format { my ($self, %options) = @_; if (defined($self->{option_results}->{output_xml})) { $self->create_xml_document(); my $root = $self->{xml_output}->createElement('data'); $self->{xml_output}->setDocumentElement($root); foreach (@{$self->{disco_elements}}) { my $child = $self->{xml_output}->createElement("element"); $child->appendText($_); $root->addChild($child); } print $self->{xml_output}->toString(1); } elsif (defined($self->{option_results}->{output_json})) { $self->create_json_document(); my $json_content = {data => [] }; foreach (@{$self->{disco_elements}}) { push @{$json_content->{data}}, $_; } print $self->{json_output}->encode($json_content); } } sub display_disco_show { my ($self, %options) = @_; if (defined($self->{option_results}->{output_xml})) { $self->create_xml_document(); my $root = $self->{xml_output}->createElement('data'); $self->{xml_output}->setDocumentElement($root); foreach (@{$self->{disco_entries}}) { my $child = $self->{xml_output}->createElement('label'); foreach my $key (keys %$_) { $child->setAttribute($key, $_->{$key}); } $root->addChild($child); } print $self->{xml_output}->toString(1); } elsif (defined($self->{option_results}->{output_json})) { $self->create_json_document(); my $json_content = {data => [] }; foreach (@{$self->{disco_entries}}) { my %values = (); foreach my $key (keys %$_) { $values{$key} = $_->{$key}; } push @{$json_content->{data}}, {%values}; } print $self->{json_output}->encode($json_content); } } sub decode { my ($self, $value) = @_; if ($self->{encode_import} == 0) { # Some Perl version dont have the following module (like Perl 5.6.x) my $rv = centreon::plugins::misc::mymodule_load( no_quit => 1, module => 'Encode', error_msg => "Cannot load module 'Encode'." ); return $value if ($rv); $self->{encode_import} = 1; eval '$self->{perlqq} = Encode::PERLQQ'; } return centreon::plugins::misc::trim(Encode::decode($self->{source_encoding}, $value, $self->{perlqq})); } sub parameter { my ($self, %options) = @_; if (defined($options{attr})) { $self->{$options{attr}} = $options{value}; } return $self->{$options{attr}}; } sub add_disco_entry { my ($self, %options) = @_; push @{$self->{disco_entries}}, {%options}; } sub is_disco_format { my ($self) = @_; if (defined($self->{option_results}->{disco_format})) { return 1; } return 0; } sub is_disco_show { my ($self) = @_; if (defined($self->{option_results}->{disco_show})) { return 1; } return 0; } sub is_verbose { my ($self) = @_; if (defined($self->{option_results}->{verbose})) { return 1; } return 0; } sub is_debug { my ($self) = @_; if (defined($self->{option_results}->{debug})) { return 1; } return 0; } sub load_eval { my ($self) = @_; my ($code) = centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'Safe', no_quit => 1 ); if ($code == 0) { $self->{safe} = Safe->new(); $self->{safe}->share('$values'); $self->{safe}->share('$assign_var'); } $self->{safe_test} = 1; } sub test_eval { my ($self, %options) = @_; $self->load_eval() if ($self->{safe_test} == 0); my $result; if (defined($self->{safe})) { our $values = $options{values}; $result = $self->{safe}->reval($options{test}, 1); if ($@) { die 'Unsafe code evaluation: ' . $@; } } elsif (defined($options{values})) { my $values = $options{values}; { local $SIG{__WARN__} = sub {}; # ignore $result = eval "$options{test}"; if ($@) { die 'Code evaluation error: ' . $@; } } } return $result; } sub open_eval { my ($self, %options) = @_; $self->load_eval() if ($self->{safe_test} == 0); our $values = $options{values}; $self->{safe}->reval("$options{eval}", 1); return $values; } sub assign_eval { my ($self, %options) = @_; $self->load_eval() if ($self->{safe_test} == 0); our $assign_var; if (defined($self->{safe})) { our $values = $options{values}; $self->{safe}->reval("\$assign_var = $options{eval}", 1); if ($@) { die 'Unsafe code evaluation: ' . $@; } } else { my $values = $options{values}; eval "\$assign_var = $options{eval}"; } return $assign_var; } sub use_new_perfdata { my ($self, %options) = @_; $self->{option_results}->{use_new_perfdata} = $options{value} if (defined($options{value})); if (defined($self->{option_results}->{use_new_perfdata})) { return 1; } return 0; } sub get_instance_perfdata_separator { my ($self) = @_; if (defined($self->{option_results}->{use_new_perfdata})) { return '~'; } return '_'; } sub parse_pfdata_scale { my ($self, %options) = @_; # --extend-perfdata=traffic_in,,scale(Mbps),mbps my $args = { unit => 'auto' }; if ($options{args} =~ /^([KMGTPEkmgtpe])?(B|b|bps|Bps|b\/s|auto)$/) { $args->{quantity} = defined($1) ? $1 : ''; $args->{unit} = $2; } elsif ($options{args} ne '') { return 1; } return (0, $args); } sub parse_pfdata_math { my ($self, %options) = @_; # --extend-perfdata=perfx,,math(current + 10 - 100, 1) my $args = { math => undef, apply_threshold => 0 }; my ($math, $apply_threshold) = split /\|/, $options{args}; if ($math =~ /^((?:[\s\.\-\+\*\/0-9\(\)]|current)+)$/) { $args->{math} = $1; } elsif ($options{args} ne '') { return 1; } if (defined($apply_threshold) && $apply_threshold =~ /^\s*(0|1)\s*$/ ) { $args->{apply_threshold} = $1; } return (0, $args); } sub parse_pfdata_eval { my ($self, %options) = @_; # --extend-perfdata=perfx,,eval(%(label) =~ s/a/A/g) my $args = { expr => $options{args} }; $args->{expr} =~ s/%\{(.*?)\}/\$values->{$1}/g; $args->{expr} =~ s/%\((.*?)\)/\$values->{$1}/g; return (0, $args); } sub parse_group_pfdata { my ($self, %options) = @_; $options{args} =~ s/^\s+//; $options{args} =~ s/\s+$//; my $args = { pattern_pf => $options{args} }; return $args; } sub parse_pfdata_min { my ($self, %options) = @_; my $args = $self->parse_group_pfdata(%options); return (0, $args); } sub parse_pfdata_max { my ($self, %options) = @_; my $args = $self->parse_group_pfdata(%options); return (0, $args); } sub parse_pfdata_average { my ($self, %options) = @_; my $args = $self->parse_group_pfdata(%options); return (0, $args); } sub parse_pfdata_sum { my ($self, %options) = @_; my $args = $self->parse_group_pfdata(%options); return (0, $args); } sub apply_pfdata_scale { my ($self, %options) = @_; return if (${$options{perf}}->{unit} !~ /^([KMGTPEkmgtpe])?(B|b|bps|Bps|b\/s)$/); my ($src_quantity, $src_unit) = ($1, $2); my ($value, $dst_quantity, $dst_unit) = centreon::plugins::misc::scale_bytesbit( value => ${$options{perf}}->{value}, src_quantity => $src_quantity, src_unit => $src_unit, dst_quantity => $options{args}->{quantity}, dst_unit => $options{args}->{unit} ); ${$options{perf}}->{value} = sprintf('%.2f', $value); if (defined($dst_unit)) { ${$options{perf}}->{unit} = $dst_quantity . $dst_unit; } else { ${$options{perf}}->{unit} = $options{args}->{quantity} . $options{args}->{unit}; } if (defined(${$options{perf}}->{max}) && ${$options{perf}}->{max} ne '') { ($value) = centreon::plugins::misc::scale_bytesbit(value => ${$options{perf}}->{max}, src_quantity => $src_quantity, src_unit => $src_unit, dst_quantity => defined($dst_unit) ? $dst_quantity : $options{args}->{quantity}, dst_unit => defined($dst_unit) ? $dst_unit : $options{args}->{unit}); ${$options{perf}}->{max} = sprintf('%.2f', $value); } foreach my $threshold ('warning', 'critical') { next if (${$options{perf}}->{$threshold} eq ''); my ($status, $result) = centreon::plugins::misc::parse_threshold(threshold => ${$options{perf}}->{$threshold}); next if ($status == 0); if ($result->{start} ne '' && $result->{infinite_neg} == 0) { ($result->{start}) = centreon::plugins::misc::scale_bytesbit(value => $result->{start}, src_quantity => $src_quantity, src_unit => $src_unit, dst_quantity => defined($dst_unit) ? $dst_quantity : $options{args}->{quantity}, dst_unit => defined($dst_unit) ? $dst_unit : $options{args}->{unit}); } if ($result->{end} ne '' && $result->{infinite_pos} == 0) { ($result->{end}) = centreon::plugins::misc::scale_bytesbit(value => $result->{end}, src_quantity => $src_quantity, src_unit => $src_unit, dst_quantity => defined($dst_unit) ? $dst_quantity : $options{args}->{quantity}, dst_unit => defined($dst_unit) ? $dst_unit : $options{args}->{unit}); } ${$options{perf}}->{$threshold} = centreon::plugins::misc::get_threshold_litteral(%$result); } } sub apply_pfdata_invert { my ($self, %options) = @_; return if (!defined(${$options{perf}}->{max}) || ${$options{perf}}->{max} eq ''); ${$options{perf}}->{value} = ${$options{perf}}->{max} - ${$options{perf}}->{value}; foreach my $threshold ('warning', 'critical') { next if (${$options{perf}}->{$threshold} eq ''); my ($status, $result) = centreon::plugins::misc::parse_threshold(threshold => ${$options{perf}}->{$threshold}); next if ($status == 0); my $tmp = { arobase => $result->{arobase}, infinite_pos => 0, infinite_neg => 0, start => $result->{start}, end => $result->{end} }; $tmp->{infinite_neg} = 1 if ($result->{infinite_pos} == 1); $tmp->{infinite_pos} = 1 if ($result->{infinite_neg} == 1); if ($result->{start} ne '' && $result->{infinite_neg} == 0) { $tmp->{end} = ${$options{perf}}->{max} - $result->{start}; } if ($result->{end} ne '' && $result->{infinite_pos} == 0) { $tmp->{start} = ${$options{perf}}->{max} - $result->{end}; } ${$options{perf}}->{$threshold} = centreon::plugins::misc::get_threshold_litteral(%$tmp); } } sub apply_pfdata_percent { my ($self, %options) = @_; return if (!defined(${$options{perf}}->{max}) || ${$options{perf}}->{max} eq ''); ${$options{perf}}->{value} = sprintf('%.2f', ${$options{perf}}->{value} * 100 / ${$options{perf}}->{max}); ${$options{perf}}->{unit} = '%'; foreach my $threshold ('warning', 'critical') { next if (${$options{perf}}->{$threshold} eq ''); my ($status, $result) = centreon::plugins::misc::parse_threshold(threshold => ${$options{perf}}->{$threshold}); next if ($status == 0); if ($result->{start} ne '' && $result->{infinite_neg} == 0) { $result->{start} = sprintf('%.2f', $result->{start} * 100 / ${$options{perf}}->{max}); } if ($result->{end} ne '' && $result->{infinite_pos} == 0) { $result->{end} = sprintf('%.2f', $result->{end} * 100 / ${$options{perf}}->{max}); } ${$options{perf}}->{$threshold} = centreon::plugins::misc::get_threshold_litteral(%$result); } ${$options{perf}}->{max} = 100; } sub apply_pfdata_eval { my ($self, %options) = @_; ${$options{perf}} = $self->open_eval(eval => $options{args}->{expr}, values => ${$options{perf}}); } sub apply_pfdata_math { my ($self, %options) = @_; my $math = $options{args}->{math}; $math =~ s/current/\$value/g; my $value = ${$options{perf}}->{value}; eval "\${\$options{perf}}->{value} = $math"; return if ($options{args}->{apply_threshold} == 0); foreach my $threshold ('warning', 'critical') { next if (${$options{perf}}->{$threshold} eq ''); my ($status, $result) = centreon::plugins::misc::parse_threshold(threshold => ${$options{perf}}->{$threshold}); next if ($status == 0); if ($result->{start} ne '' && $result->{infinite_neg} == 0) { $value = $result->{start}; eval "\$result->{start} = $math"; } if ($result->{end} ne '' && $result->{infinite_pos} == 0) { $value = $result->{end}; eval "\$result->{end} = $math"; } ${$options{perf}}->{$threshold} = centreon::plugins::misc::get_threshold_litteral(%$result); } ${$options{perf}}->{max} = 100; } sub apply_pfdata_min { my ($self, %options) = @_; my $pattern_pf = $self->assign_eval(eval => "\"$options{args}->{pattern_pf}\""); my $min; for (my $i = 0; $i < scalar(@{$self->{perfdatas}}); $i++) { next if ($self->{perfdatas}->[$i]->{label} !~ /$pattern_pf/); next if ($self->{perfdatas}->[$i]->{value} !~ /\d+/); $min = $self->{perfdatas}->[$i]->{value} if (!defined($min) || $min > $self->{perfdatas}->[$i]->{value}); } ${$options{perf}}->{value} = $min if (defined($min)); } sub apply_pfdata_max { my ($self, %options) = @_; my $pattern_pf = $self->assign_eval(eval => "\"$options{args}->{pattern_pf}\""); my $max; for (my $i = 0; $i < scalar(@{$self->{perfdatas}}); $i++) { next if ($self->{perfdatas}->[$i]->{label} !~ /$pattern_pf/); next if ($self->{perfdatas}->[$i]->{value} !~ /\d+/); $max = $self->{perfdatas}->[$i]->{value} if (!defined($max) || $max < $self->{perfdatas}->[$i]->{value}); } ${$options{perf}}->{value} = $max if (defined($max)); } sub apply_pfdata_sum { my ($self, %options) = @_; my $pattern_pf = $self->assign_eval(eval => "\"$options{args}->{pattern_pf}\""); my ($sum, $num) = (0, 0); for (my $i = 0; $i < scalar(@{$self->{perfdatas}}); $i++) { next if ($self->{perfdatas}->[$i]->{label} !~ /$pattern_pf/); next if ($self->{perfdatas}->[$i]->{value} !~ /\d+/); $sum += $self->{perfdatas}->[$i]->{value}; $num++; } ${$options{perf}}->{value} = $sum if ($num > 0); } sub apply_pfdata_average { my ($self, %options) = @_; my $pattern_pf = $self->assign_eval(eval => "\"$options{args}->{pattern_pf}\""); my ($sum, $num) = (0, 0); for (my $i = 0; $i < scalar(@{$self->{perfdatas}}); $i++) { next if ($self->{perfdatas}->[$i]->{label} !~ /$pattern_pf/); next if ($self->{perfdatas}->[$i]->{value} !~ /\d+/); $sum += $self->{perfdatas}->[$i]->{value}; $num++; } ${$options{perf}}->{value} = sprintf("%.2f", ($sum / $num)) if ($num > 0); } sub apply_perfdata_thresholds { my ($self, %options) = @_; foreach (('warning', 'critical')) { next if (!defined($options{$_})); my @thresholds = split(':', $options{$_}, -1); for (my $i = 0; $i < scalar(@thresholds); $i++) { if ($thresholds[$i] =~ /(\d+(?:\.\d+)?)\s*%/) { if (!defined($options{max}) || $options{max} eq '') { $thresholds[$i] = ''; next; } $thresholds[$i] = $1 * $options{max} / 100; } elsif ($thresholds[$i] =~ /(\d+(?:\.\d+)?)/) { $thresholds[$i] = $1; } else { $thresholds[$i] = ''; } } ${$options{perf}}->{$_} = join(':', @thresholds); } } sub load_perfdata_extend_args { my ($self, %options) = @_; foreach ( [$self->{option_results}->{change_perfdata}, 1], [$self->{option_results}->{extend_perfdata}, 2], [$self->{option_results}->{extend_perfdata_group}, 3], ) { next if (!defined($_->[0])); foreach my $arg (@{$_->[0]}) { $self->parse_perfdata_extend_args(arg => $arg, type => $_->[1]); } } } sub parse_perfdata_extend_args { my ($self, %options) = @_; # --extend-perfdata=searchlabel,newlabel,method[,[newuom],[min],[max],[warning],[critical]] my ($pfdata_match, $pfdata_substitute, $method, $uom_sub, $min_sub, $max_sub, $warn_sub, $crit_sub) = split /,/, $options{arg}; return if ((!defined($pfdata_match) || $pfdata_match eq '') && $options{type} != 3); $self->{pfdata_extends} = [] if (!defined($self->{pfdata_extends})); my $pfdata_extends = { pfdata_match => defined($pfdata_match) && $pfdata_match ne '' ? $pfdata_match : undef, pfdata_substitute => defined($pfdata_substitute) && $pfdata_substitute ne '' ? $pfdata_substitute : undef, uom_sub => defined($uom_sub) && $uom_sub ne '' ? $uom_sub : undef, min_sub => defined($min_sub) && $min_sub ne '' ? $min_sub : undef, max_sub => defined($max_sub) && $max_sub ne '' ? $max_sub : undef, warn_sub => defined($warn_sub) && $warn_sub ne '' ? $warn_sub : undef, crit_sub => defined($crit_sub) && $crit_sub ne '' ? $crit_sub : undef, type => $options{type} }; if (defined($method) && $method ne '') { if ($method !~ /^\s*(invert|percent|scale|math|min|max|average|sum|eval)\s*\(\s*(.*?)\s*\)\s*$/) { $self->output_add(long_msg => "method in argument '$options{arg}' is unknown", debug => 1); return ; } $pfdata_extends->{method_name} = $1; my $args = $2; if (my $func = $self->can('parse_pfdata_' . $pfdata_extends->{method_name})) { (my $status, $pfdata_extends->{method_args}) = $func->($self, args => $args); if ($status == 1) { $self->output_add(long_msg => "argument in method '$options{arg}' is unknown", debug => 1); return ; } } } push @{$self->{pfdata_extends}}, $pfdata_extends; } sub apply_perfdata_explode { my ($self, %options) = @_; return if ($self->{explode_perfdata_total} == 0); foreach (@{$self->{perfdatas}}) { next if ($_->{max} eq ''); if ($self->{explode_perfdata_total} == 2) { $self->perfdata_add(label => $_->{label} . '_max', value => $_->{max}, unit => $_->{unit}); next; } foreach my $regexp (keys %{$self->{explode_perfdatas}}) { if ($_->{label} =~ /$regexp/) { $self->perfdata_add(label => $self->{explode_perfdatas}->{$regexp}, value => $_->{max}, unit => $_->{unit}); last; } } } } sub apply_perfdata_extend { my ($self, %options) = @_; foreach my $extend (@{$self->{pfdata_extends}}) { my $new_pfdata = []; # Manage special case when type group and pfdata_match empty if ($extend->{type} == 3 && (!defined($extend->{pfdata_match}) || $extend->{pfdata_match} eq '')) { next if (!defined($extend->{pfdata_substitute}) || $extend->{pfdata_substitute} eq ''); my $new_perf = { label => $extend->{pfdata_substitute}, value => '', unit => defined($extend->{uom_sub}) ? $extend->{uom_sub} : '', warning => '', critical => '', min => defined($extend->{min_sub}) ? $extend->{min_sub} : '', max => defined($extend->{max_sub}) ? $extend->{max_sub} : '' }; if (defined($extend->{method_name})) { my $func = $self->can('apply_pfdata_' . $extend->{method_name}); $func->($self, perf => \$new_perf, args => $extend->{method_args}); } $self->apply_perfdata_thresholds( perf => \$new_perf, warning => $extend->{warn_sub}, critical => $extend->{crit_sub}, max => $new_perf->{max} ); if (length($new_perf->{value})) { push @{$self->{perfdatas}}, $new_perf; } next; } for (my $i = 0; $i < scalar(@{$self->{perfdatas}}); $i++) { next if ($self->{perfdatas}->[$i]->{label} !~ /$extend->{pfdata_match}/); my $new_perf = { %{$self->{perfdatas}->[$i]} }; if ($extend->{type} == 3) { $new_perf = { label => $self->{perfdatas}->[$i]->{label}, value => '', unit => '', warning => '', critical => '', min => '', max => '' }; } if (defined($extend->{pfdata_substitute})) { eval "\$new_perf->{label} =~ s{$extend->{pfdata_match}}{$extend->{pfdata_substitute}}"; } if (defined($extend->{method_name})) { my $func = $self->can('apply_pfdata_' . $extend->{method_name}); $func->($self, perf => \$new_perf, args => $extend->{method_args}); } $new_perf->{unit} = $extend->{uom_sub} if (defined($extend->{uom_sub})); $new_perf->{min} = $extend->{min_sub} if (defined($extend->{min_sub})); $new_perf->{max} = $extend->{max_sub} if (defined($extend->{max_sub})); $self->apply_perfdata_thresholds( perf => \$new_perf, warning => $extend->{warn_sub}, critical => $extend->{crit_sub}, max => $new_perf->{max} ); if ($extend->{type} == 1) { $self->{perfdatas}->[$i] = $new_perf; } else { push @$new_pfdata, $new_perf if (length($new_perf->{value})); } } push @{$self->{perfdatas}}, @$new_pfdata; } } sub change_perfdata { my ($self, %options) = @_; $self->apply_perfdata_extend(); $self->apply_perfdata_explode(); } 1; __END__ =head1 NAME Output class =head1 SYNOPSIS - =head1 OUTPUT OPTIONS =over 8 =item B<--verbose> Display long output. =item B<--debug> Display also debug messages. =item B<--filter-perfdata> Filter perfdata that match the regexp. =item B<--filter-perfdata-adv> Advanced perfdata filter. Eg: --filter-perfdata-adv='not (%(value) == 0 and %(max) eq "")' =item B<--explode-perfdata-max> Put max perfdata (if it exist) in a specific perfdata (without values: same with '_max' suffix) (Multiple options) =item B<--change-perfdata> B<--extend-perfdata> Change or extend perfdata. Syntax: --extend-perfdata=searchlabel,newlabel,target[,[newuom],[min],[max]] Common examples: =over 4 Change storage free perfdata in used: --change-perfdata=free,used,invert() Change storage free perfdata in used: --change-perfdata=used,free,invert() Scale traffic values automaticaly: --change-perfdata=traffic,,scale(auto) Scale traffic values in Mbps: --change-perfdata=traffic_in,,scale(Mbps),mbps Change traffic values in percent: --change-perfdata=traffic_in,,percent() =back =item B<--extend-perfdata-group> Extend perfdata from multiple perfdatas (methods in target are: min, max, average, sum) Syntax: --extend-perfdata-group=searchlabel,newlabel,target[,[newuom],[min],[max]] Common examples: =over 4 Sum wrong packets from all interfaces (with interface need --units-errors=absolute): --extend-perfdata-group=',packets_wrong,sum(packets_(discard|error)_(in|out))' Sum traffic by interface: --extend-perfdata-group='traffic_in_(.*),traffic_$1,sum(traffic_(in|out)_$1)' =back =item B<--change-short-output> Change short output display: --change-short-output=pattern~replace~modifier =item B<--change-exit> Change exit code: --change-exit=unknown=critical =item B<--range-perfdata> Change perfdata range thresholds display: 1 = start value equals to '0' is removed, 2 = threshold range is not display. =item B<--filter-uom> Filter UOM that match the regexp. =item B<--opt-exit> Optional exit code for an execution error (i.e. wrong option provided, SSH connection refused, timeout, etc) (Default: unknown). =item B<--output-ignore-perfdata> Remove perfdata from output. =item B<--output-ignore-label> Remove label status from output. =item B<--output-xml> Display output in XML format. =item B<--output-json> Display output in JSON format. =item B<--output-openmetrics> Display metrics in OpenMetrics format. =item B<--output-file> Write output in file (can be used with json and xml options) =item B<--disco-format> Display discovery arguments (if the mode manages it). =item B<--disco-show> Display discovery values (if the mode manages it). =item B<--float-precision> Set the float precision for thresholds (Default: 8). =item B<--source-encoding> Set encoding of monitoring sources (In some case. Default: 'UTF-8'). =head1 DESCRIPTION B. =cut centreon-plugins-20220113/centreon/plugins/passwordmgr/000077500000000000000000000000001417000230700231025ustar00rootroot00000000000000centreon-plugins-20220113/centreon/plugins/passwordmgr/hashicorpvault.pm000066400000000000000000000257041417000230700265040ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::passwordmgr::hashicorpvault; use strict; use warnings; use Data::Dumper; use centreon::plugins::http; use Digest::MD5 qw(md5_hex); use JSON::XS; use vars qw($vault_connections); sub new { my ($class, %options) = @_; my $self = {}; bless $self, $class; if (!defined($options{output})) { print "Class PasswordMgr: Need to specify 'output' argument.\n"; exit 3; } if (!defined($options{options})) { $options{output}->add_option_msg(short_msg => "Class PasswordMgr: Need to specify 'options' argument."); $options{output}->option_exit(); } $options{options}->add_options(arguments => { 'auth-method:s' => { name => 'auth_method', default => 'token' }, 'auth-settings:s%' => { name => 'auth_settings' }, 'map-option:s@' => { name => 'map_option' }, 'secret-path:s@' => { name => 'secret_path' }, 'vault-address:s' => { name => 'vault_address'}, 'vault-port:s' => { name => 'vault_port', default => '8200' }, 'vault-protocol:s' => { name => 'vault_protocol', default => 'http'}, 'vault-token:s' => { name => 'vault_token'} }); $options{options}->add_help(package => __PACKAGE__, sections => 'VAULT OPTIONS'); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options, noptions => 1); return $self; } sub get_access_token { my ($self, %options) = @_; my $decoded; my $login = $self->parse_auth_method(method => $self->{auth_method}, settings => $self->{auth_settings}); my $post_json = JSON::XS->new->utf8->encode($login); my $url_path = '/v1/auth/'. $self->{auth_method} . '/login/'; $url_path .= $self->{auth_settings}->{username} if (defined($self->{auth_settings}->{username}) && $self->{auth_method} =~ 'userpass|login') ; my $content = $self->{http}->request( hostname => $self->{vault_address}, port => $self->{vault_port}, proto => $self->{vault_protocol}, method => 'POST', header => ['Content-type: application/json'], query_form_post => $post_json, url_path => $url_path ); if (!defined($content) || $content eq '') { $self->{output}->add_option_msg(short_msg => "Authentication endpoint returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->output_add(long_msg => $content, debug => 1); $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } if (defined($decoded->{errors}[0])) { $self->{output}->output_add(long_msg => "Error message : " . $decoded->{errors}[0], debug => 1); $self->{output}->add_option_msg(short_msg => "Authentication endpoint returns error code '" . $decoded->{errors}[0] . "' (add --debug option for detailed message)"); $self->{output}->option_exit(); } my $access_token = $decoded->{auth}->{client_token}; return $access_token; } sub parse_auth_method { my ($self, %options) = @_; my $login_settings; my $settings_mapping = { azure => [ 'role', 'jwt' ], cert => [ 'name' ], github => [ 'token' ], ldap => [ 'username', 'password' ], okta => [ 'username', 'password', 'totp' ], radius => [ 'username', 'password' ], userpass => [ 'username', 'password' ] }; foreach (@{$settings_mapping->{$options{method}}}) { if (!defined($options{settings}->{$_})) { $self->{output}->add_option_msg(short_msg => 'Missing authentication setting: ' . $_); $self->{output}->option_exit(); } $login_settings->{$_} = $options{settings}->{$_}; }; return $login_settings; } sub settings { my ($self, %options) = @_; if (!defined($options{option_results}->{vault_address}) || $options{option_results}->{vault_address} eq '') { $self->{output}->add_option_msg(short_msg => "Please set the --vault-address option"); $self->{output}->option_exit(); } if ($options{option_results}->{auth_method} eq 'token' && (!defined($options{option_results}->{vault_token}) || $options{option_results}->{vault_token} eq '')) { $self->{output}->add_option_msg(short_msg => "Please set the --vault-token option"); $self->{output}->option_exit(); } if (!defined($options{option_results}->{secret_path}) || $options{option_results}->{secret_path} eq '') { $self->{output}->add_option_msg(short_msg => "Please set the --secret-path option"); $self->{output}->option_exit(); } $self->{auth_method} = lc($options{option_results}->{auth_method}); $self->{auth_settings} = defined($options{option_results}->{auth_settings}) && $options{option_results}->{auth_settings} ne '' ? $options{option_results}->{auth_settings} : {}; $self->{vault_address} = $options{option_results}->{vault_address}; $self->{vault_port} = $options{option_results}->{vault_port}; $self->{vault_protocol} = $options{option_results}->{vault_protocol}; $self->{vault_token} = $options{option_results}->{vault_token}; if (lc($self->{auth_method}) !~ m/azure|cert|github|ldap|okta|radius|userpass|token/ ) { $self->{output}->add_option_msg(short_msg => "Incorrect or unsupported authentication method set in --auth-method"); $self->{output}->option_exit(); } foreach (@{$options{option_results}->{secret_path}}) { $self->{request_endpoint}->{$_} = '/v1/' . $_; } if (defined($options{option_results}->{auth_method}) && $options{option_results}->{auth_method} ne 'token') { $self->{vault_token} = $self->get_access_token(%options); }; $self->{http}->add_header(key => 'Accept', value => 'application/json'); if (defined($self->{vault_token})) { $self->{http}->add_header(key => 'X-Vault-Token', value => $self->{vault_token}); } } sub request_api { my ($self, %options) = @_; $self->settings(%options); my ($raw_data, $raw_response); foreach my $endpoint (keys %{$self->{request_endpoint}}) { my $json; my $response = $self->{http}->request( hostname => $self->{vault_address}, port => $self->{vault_port}, proto => $self->{vault_protocol}, method => 'GET', url_path => $self->{request_endpoint}->{$endpoint} ); $self->{output}->output_add(long_msg => $response, debug => 1); eval { $json = JSON::XS->new->utf8->decode($response); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode Vault JSON response: $@"); $self->{output}->option_exit(); } if ((defined($json->{data}->{metadata}->{deletion_time}) && $json->{data}->{metadata}->{deletion_time} ne '') || $json->{data}->{metadata}->{destroyed} eq 'true') { $self->{output}->add_option_msg(short_msg => "This secret is not valid anymore"); $self->{output}->option_exit(); } foreach (keys %{$json->{data}->{data}}) { $self->{lookup_values}->{'key_' . $endpoint} = $_; $self->{lookup_values}->{'value_' . $endpoint} = $json->{data}->{data}->{$_}; } push(@{$raw_data}, $json); push(@{$raw_response}, $response); } return ($raw_data, $raw_response); } sub do_map { my ($self, %options) = @_; return if (!defined($options{option_results}->{map_option})); foreach (@{$options{option_results}->{map_option}}) { next if (! /^(.+?)=(.+)$/); my ($option, $map) = ($1, $2); # Change %{xxx} options usage while ($map =~ /\%\{(.*?)\}/g) { my $sub = ''; $sub = $self->{lookup_values}->{$1} if (defined($self->{lookup_values}->{$1})); $map =~ s/\%\{$1\}/$sub/g } $option =~ s/-/_/g; $options{option_results}->{$option} = $map; } } sub manage_options { my ($self, %options) = @_; my ($content, $debug) = $self->request_api(%options); if (!defined($content)) { $self->{output}->add_option_msg(short_msg => "Cannot read Vault information"); $self->{output}->option_exit(); } $self->do_map(%options); $self->{output}->output_add(long_msg => Data::Dumper::Dumper($debug), debug => 1) if ($self->{output}->is_debug()); } 1; __END__ =head1 NAME HashiCorp Vault global =head1 SYNOPSIS HashiCorp Vault class To be used with K/V engines =head1 VAULT OPTIONS =over 8 =item B<--vault-address> IP address of the HashiCorp Vault server (Mandatory). =item B<--vault-port> Port of the HashiCorp Vault server (Default: '8200'). =item B<--vault-protocol> HTTP of the HashiCorp Vault server. Can be: 'http', 'https' (Default: http). =item B<--auth-method> Authentication method to log in against the Vault server. Can be: 'azure', 'cert', 'github', 'ldap', 'okta', 'radius', 'userpass' (Default: 'token'); =item B<--vault-token> Directly specify a valid token to log in (only for --auth-method='token'). =item B<--auth-settings> Required information to log in according to the selected method. Examples: for 'userpass': --auth-settings='username=user1' --auth-settings='password=my_password' for 'azure': --auth-settings='role=my_azure_role' --auth-settings='jwt=my_azure_token' More information here: https://www.vaultproject.io/api-docs/auth =item B<--secret-path> Location of the secret in the Vault K/V engine (Mandatory - Can be multiple). Examples: for v1 engine: --secret-path='mysecrets/servicecredentials' for v2 engine: --secret-path='mysecrets/data/servicecredentials?version=12' More information here: https://www.vaultproject.io/api-docs/secret/kv =item B<--map-option> Overload Plugin option with K/V values. Use the following syntax: the_option_to_overload='%{key_$secret_path$}' or the_option_to_overload='%{value_$secret_path$}' Example: --map-option='username=%{key_mysecrets/servicecredentials}' --map-option='password=%{value_mysecrets/servicecredentials}' =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/centreon/plugins/passwordmgr/keepass.pm000066400000000000000000000156141417000230700251020ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::passwordmgr::keepass; use strict; use warnings; use JSON::Path; use Data::Dumper; use KeePass::Reader; use vars qw($keepass_connections); sub new { my ($class, %options) = @_; my $self = {}; bless $self, $class; if (!defined($options{output})) { print "Class PasswordMgr: Need to specify 'output' argument.\n"; exit 3; } if (!defined($options{options})) { $options{output}->add_option_msg(short_msg => "Class PasswordMgr: Need to specify 'options' argument."); $options{output}->option_exit(); } $options{options}->add_options(arguments => { 'keepass-endpoint:s' => { name => 'keepass_endpoint' }, 'keepass-endpoint-file:s' => { name => 'keepass_endpoint_file' }, 'keepass-file:s' => { name => 'keepass_file' }, 'keepass-password:s' => { name => 'keepass_password' }, 'keepass-search-value:s@' => { name => 'keepass_search_value' }, 'keepass-map-option:s@' => { name => 'keepass_map_option' } }); $options{options}->add_help(package => __PACKAGE__, sections => 'KEEPASS OPTIONS'); $self->{output} = $options{output}; $JSON::Path::Safe = 0; return $self; } sub build_api_args { my ($self, %options) = @_; $self->{connection_info} = { file => undef, password => undef }; if (defined($options{option_results}->{keepass_endpoint_file}) && $options{option_results}->{keepass_endpoint_file} ne '') { if (! -f $options{option_results}->{keepass_endpoint_file} or ! -r $options{option_results}->{keepass_endpoint_file}) { $self->{output}->add_option_msg(short_msg => "Cannot read keepass endpoint file: $!"); $self->{output}->option_exit(); } require $options{option_results}->{keepass_endpoint_file}; if (defined($keepass_connections) && defined($options{option_results}->{keepass_endpoint}) && $options{option_results}->{keepass_endpoint} ne '') { if (!defined($keepass_connections->{$options{option_results}->{keepass_endpoint}})) { $self->{output}->add_option_msg(short_msg => "Endpoint $options{option_results}->{keepass_endpoint} doesn't exist in keepass endpoint file"); $self->{output}->option_exit(); } $self->{connection_info} = $keepass_connections->{$options{option_results}->{keepass_endpoint}}; } } foreach (['keepass_file', 'file'], ['keepass_password', 'password']) { if (defined($options{option_results}->{$_->[0]}) && $options{option_results}->{$_->[0]} ne '') { $self->{connection_info}->{$_->[1]} = $options{option_results}->{$_->[0]}; } } if (defined($self->{connection_info}->{file}) && $self->{connection_info}->{file} ne '') { if (!defined($self->{connection_info}->{password}) || $self->{connection_info}->{password} eq '') { $self->{output}->add_option_msg(short_msg => "Please set keepass-password option"); $self->{output}->option_exit(); } } } sub do_lookup { my ($self, %options) = @_; $self->{lookup_values} = {}; return if (!defined($options{option_results}->{keepass_search_value})); foreach (@{$options{option_results}->{keepass_search_value}}) { next if (! /^(.+?)=(.+)$/); my ($map, $lookup) = ($1, $2); # Change %{xxx} options usage while ($lookup =~ /\%\{(.*?)\}/g) { my $sub = ''; $sub = $options{option_results}->{$1} if (defined($options{option_results}->{$1})); $lookup =~ s/\%\{$1\}/$sub/g } my $jpath = JSON::Path->new($lookup); my $result = $jpath->value($options{json}); $self->{output}->output_add(long_msg => 'lookup = ' . $lookup. ' - response = ' . Data::Dumper::Dumper($result), debug => 1); $self->{lookup_values}->{$map} = $result; } } sub do_map { my ($self, %options) = @_; return if (!defined($options{option_results}->{keepass_map_option})); foreach (@{$options{option_results}->{keepass_map_option}}) { next if (! /^(.+?)=(.+)$/); my ($option, $map) = ($1, $2); # Change %{xxx} options usage while ($map =~ /\%\{(.*?)\}/g) { my $sub = ''; $sub = $self->{lookup_values}->{$1} if (defined($self->{lookup_values}->{$1})); $map =~ s/\%\{$1\}/$sub/g } $option =~ s/-/_/g; $options{option_results}->{$option} = $map; } } sub manage_options { my ($self, %options) = @_; $self->build_api_args(%options); return if (!defined($self->{connection_info}->{file})); my $keepass = KeePass::Reader->new(); my $content = $keepass->load_db(file => $self->{connection_info}->{file}, password => $self->{connection_info}->{password}); if (!defined($content)) { $self->{output}->add_option_msg(short_msg => "Cannot read keepass file: " . $keepass->error()); $self->{output}->option_exit(); } $self->{output}->output_add(long_msg => Data::Dumper::Dumper($content), debug => 1) if ($self->{output}->is_debug()); $self->do_lookup(%options, json => $content); $self->do_map(%options); } 1; __END__ =head1 NAME Keepass global =head1 SYNOPSIS keepass class =head1 KEEPASS OPTIONS =over 8 =item B<--keepass-endpoint> Connection information to be used in keepass file. =item B<--keepass-endpoint-file> File with keepass connection informations. =item B<--keepass-file> Keepass file. =item B<--keepass-password> Keepass master password. =item B<--keepass-search-value> Looking for a value in the JSON keepass. Can use JSON Path and other option values. Example: --keepass-search-value='password=$..entries.[?($_->{title} =~ /serveurx/i)].password' --keepass-search-value='username=$..entries.[?($_->{title} =~ /serveurx/i)].username' --keepass-search-value='password=$..entries.[?($_->{title} =~ /%{hostname}/i)].password' =item B<--keepass-map-option> Overload plugin option. Example: --keepass-map-option="password=%{password}" --keepass-map-option="username=%{username}" =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/centreon/plugins/passwordmgr/teampass.pm000066400000000000000000000173121417000230700252610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::passwordmgr::teampass; use strict; use warnings; use JSON::Path; use JSON::XS; use Data::Dumper; use centreon::plugins::http; use vars qw($teampass_connections); sub new { my ($class, %options) = @_; my $self = {}; bless $self, $class; if (!defined($options{output})) { print "Class PasswordMgr: Need to specify 'output' argument.\n"; exit 3; } if (!defined($options{options})) { $options{output}->add_option_msg(short_msg => "Class PasswordMgr: Need to specify 'options' argument."); $options{output}->option_exit(); } $options{options}->add_options(arguments => { "teampass-endpoint:s" => { name => 'teampass_endpoint' }, "teampass-endpoint-file:s" => { name => 'teampass_endpoint_file' }, "teampass-api-key:s" => { name => 'teampass_api_key' }, "teampass-api-address:s" => { name => 'teampass_api_address' }, "teampass-api-request:s" => { name => 'teampass_api_request' }, "teampass-search-value:s@" => { name => 'teampass_search_value' }, "teampass-map-option:s@" => { name => 'teampass_map_option' }, "teampass-timeout:s" => { name => 'teampass_timeout' }, }); $options{options}->add_help(package => __PACKAGE__, sections => 'TEAMPASS OPTIONS'); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options, noptions => 1); $JSON::Path::Safe = 0; return $self; } sub build_api_args { my ($self, %options) = @_; $self->{connection_info} = { address => undef, key => undef, request => undef }; if (defined($options{option_results}->{teampass_endpoint_file}) && $options{option_results}->{teampass_endpoint_file} ne '') { if (! -f $options{option_results}->{teampass_endpoint_file} or ! -r $options{option_results}->{teampass_endpoint_file}) { $self->{output}->add_option_msg(short_msg => "Cannot read teampass file: $!"); $self->{output}->option_exit(); } require $options{option_results}->{teampass_endpoint_file}; if (defined($teampass_connections) && defined($options{option_results}->{teampass_endpoint}) && $options{option_results}->{teampass_endpoint} ne '') { if (!defined($teampass_connections->{$options{option_results}->{teampass_endpoint}})) { $self->{output}->add_option_msg(short_msg => "Endpoint $options{option_results}->{teampass_endpoint} doesn't exist in teampass file"); $self->{output}->option_exit(); } $self->{connection_info} = $teampass_connections->{$options{option_results}->{teampass_endpoint}}; } } foreach (['teampass_api_address', 'address'], ['teampass_api_key', 'key'], ['teampass_api_request', 'request']) { if (defined($options{option_results}->{$_->[0]}) && $options{option_results}->{$_->[0]} ne '') { $self->{connection_info}->{$_->[1]} = $options{option_results}->{$_->[0]}; } } if (defined($self->{connection_info}->{address}) && $self->{connection_info}->{address} ne '') { foreach ('key', 'request') { if (!defined($self->{connection_info}->{$_}) || $self->{connection_info}->{$_} eq '') { $self->{output}->add_option_msg(short_msg => "Please set teampass-api-$_ option"); $self->{output}->option_exit(); } } } } sub do_lookup { my ($self, %options) = @_; $self->{lookup_values} = {}; return if (!defined($options{option_results}->{teampass_search_value})); foreach (@{$options{option_results}->{teampass_search_value}}) { next if (! /^(.+?)=(.+)$/); my ($map, $lookup) = ($1, $2); # Change %{xxx} options usage while ($lookup =~ /\%\{(.*?)\}/g) { my $sub = ''; $sub = $options{option_results}->{$1} if (defined($options{option_results}->{$1})); $lookup =~ s/\%\{$1\}/$sub/g } my $jpath = JSON::Path->new($lookup); my $result = $jpath->value($options{json}); $self->{output}->output_add(long_msg => 'lookup = ' . $lookup. ' - response = ' . Data::Dumper::Dumper($result), debug => 1); $self->{lookup_values}->{$map} = $result; } } sub do_map { my ($self, %options) = @_; return if (!defined($options{option_results}->{teampass_map_option})); foreach (@{$options{option_results}->{teampass_map_option}}) { next if (! /^(.+?)=(.+)$/); my ($option, $map) = ($1, $2); # Change %{xxx} options usage while ($map =~ /\%\{(.*?)\}/g) { my $sub = ''; $sub = $self->{lookup_values}->{$1} if (defined($self->{lookup_values}->{$1})); $map =~ s/\%\{$1\}/$sub/g } $option =~ s/-/_/g; $options{option_results}->{$option} = $map; } } sub manage_options { my ($self, %options) = @_; $self->build_api_args(%options); return if (!defined($self->{connection_info}->{address})); $self->{http}->set_options( timeout => $options{option_results}->{teampass_timeout}, unknown_status => '%{http_code} < 200 or %{http_code} >= 300', ); my $response = $self->{http}->request(method => 'GET', full_url => $self->{connection_info}->{address} . $self->{connection_info}->{request}, hostname => '', get_param => ['apikey=' . $self->{connection_info}->{key}], ); $self->{output}->output_add(long_msg => $response, debug => 1); my $json; eval { $json = JSON::XS->new->utf8->decode($response); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode teampass json response: $@"); $self->{output}->option_exit(); } $self->do_lookup(%options, json => $json); $self->do_map(%options); } 1; __END__ =head1 NAME Teampass global =head1 SYNOPSIS teampass class =head1 TEAMPASS OPTIONS =over 8 =item B<--teampass-endpoint> Connection information to be used in teampass file. =item B<--teampass-endpoint-file> File with teampass connection informations. =item B<--teampass-timeout> Set HTTP Rest API timeout (Default: 5). =item B<--teampass-api-key> Teampass API Key. =item B<--teampass-api-address> Teampass URL (example: http://10.0.0.1/teampass). =item B<--teampass-api-request> Teampass request (example: /api/index.php/folder/3). =item B<--teampass-search-value> Looking for a value in the JSON teampass response. Can use JSON Path and other option values. Example: --teampass-search-value='password=$.[?($_->{label} =~ /serveur1/i)].pw' --teampass-search-value='login=$.[?($_->{label} =~ /serveur1/i)].login' --teampass-search-value='password=$.[?($_->{label} =~ /%{hostname}/i)].pw' =item B<--teampass-map-option> Overload plugin option. Example: --teampass-map-option="password=%{password}" --teampass-map-option="username=%{login}" =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/centreon/plugins/perfdata.pm000066400000000000000000000154511417000230700226640ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::perfdata; use strict; use warnings; use centreon::plugins::misc; sub new { my ($class, %options) = @_; my $self = {}; bless $self, $class; $self->{output} = $options{output}; # Typical Nagios Perfdata 'with ~ @ ..' $self->{threshold_label} = {}; $self->{float_precision} = defined($self->{output}->{option_results}->{float_precision}) && $self->{output}->{option_results}->{float_precision} =~ /\d+/ ? int($self->{output}->{option_results}->{float_precision}) : 8; return $self; } sub get_perfdata_for_output { my ($self, %options) = @_; # $options{label} : threshold label # $options{total} : percent threshold to transform in global # $options{cast_int} : cast absolute to int # $options{op} : operator to apply to start/end value (uses with 'value'}) # $options{value} : value to apply with 'op' option if (!defined($self->{threshold_label}->{$options{label}}->{value}) || $self->{threshold_label}->{$options{label}}->{value} eq '') { return ''; } my %perf_value = %{$self->{threshold_label}->{$options{label}}}; if (defined($options{op}) && defined($options{value})) { eval "\$perf_value{start} = \$perf_value{start} $options{op} \$options{value}" if ($perf_value{infinite_neg} == 0); eval "\$perf_value{end} = \$perf_value{end} $options{op} \$options{value}" if ($perf_value{infinite_pos} == 0); } if (defined($options{total})) { $perf_value{start} = $perf_value{start} * $options{total} / 100 if ($perf_value{infinite_neg} == 0); $perf_value{end} = $perf_value{end} * $options{total} / 100 if ($perf_value{infinite_pos} == 0); $perf_value{start} = sprintf("%.2f", $perf_value{start}) if ($perf_value{infinite_neg} == 0 && (!defined($options{cast_int}) || $options{cast_int} != 1)); $perf_value{end} = sprintf("%.2f", $perf_value{end}) if ($perf_value{infinite_pos} == 0 && (!defined($options{cast_int}) || $options{cast_int} != 1)); } $perf_value{start} = int($perf_value{start}) if ($perf_value{infinite_neg} == 0 && defined($options{cast_int}) && $options{cast_int} == 1); $perf_value{end} = int($perf_value{end}) if ($perf_value{infinite_pos} == 0 && defined($options{cast_int}) && $options{cast_int} == 1); my $perf_output = ($perf_value{arobase} == 1 ? '@' : '') . (($perf_value{infinite_neg} == 0) ? $perf_value{start} : '~') . ':' . (($perf_value{infinite_pos} == 0) ? $perf_value{end} : ''); return $perf_output; } sub threshold_validate { my ($self, %options) = @_; # $options{label} : threshold label # $options{value} : threshold value my $status = 1; $self->{threshold_label}->{$options{label}} = { value => $options{value}, start => undef, end => undef, arobase => undef, infinite_neg => undef, infinite_pos => undef }; if (!defined($options{value}) || $options{value} eq '') { return $status; } ($status, my $result_perf) = centreon::plugins::misc::parse_threshold(threshold => $options{value}); $self->{threshold_label}->{$options{label}} = { %{$self->{threshold_label}->{$options{label}}}, %$result_perf }; $self->{threshold_label}->{$options{label}}->{start_precision} = $self->{threshold_label}->{$options{label}}->{start}; if ($self->{threshold_label}->{$options{label}}->{start} =~ /[.,]/) { $self->{threshold_label}->{$options{label}}->{start_precision} = sprintf("%.$self->{output}->{option_results}->{float_precision}f", $self->{threshold_label}->{$options{label}}->{start}); } $self->{threshold_label}->{$options{label}}->{end_precision} = $self->{threshold_label}->{$options{label}}->{end}; if ($self->{threshold_label}->{$options{label}}->{end} =~ /[.,]/) { $self->{threshold_label}->{$options{label}}->{end_precision} = sprintf("%.$self->{output}->{option_results}->{float_precision}f", $self->{threshold_label}->{$options{label}}->{end}); } return $status; } sub threshold_check { my ($self, %options) = @_; # Can check multiple threshold. First match: out. Order is important # options{value}: value to compare # options{threshold}: ref to an array (example: [ {label => 'warning', exit_litteral => 'warning' }, {label => 'critical', exit_litteral => 'critical'} ] if ($options{value} =~ /[.,]/) { $options{value} = sprintf("%.$self->{output}->{option_results}->{float_precision}f", $options{value}); } foreach (@{$options{threshold}}) { next if (!defined($self->{threshold_label}->{$_->{label}})); next if (!defined($self->{threshold_label}->{$_->{label}}->{value}) || $self->{threshold_label}->{$_->{label}}->{value} eq ''); if ($self->{threshold_label}->{$_->{label}}->{arobase} == 0 && ($options{value} < $self->{threshold_label}->{$_->{label}}->{start_precision} || $options{value} > $self->{threshold_label}->{$_->{label}}->{end_precision})) { return $_->{exit_litteral}; } elsif ($self->{threshold_label}->{$_->{label}}->{arobase} == 1 && ($options{value} >= $self->{threshold_label}->{$_->{label}}->{start_precision} && $options{value} <= $self->{threshold_label}->{$_->{label}}->{end_precision})) { return $_->{exit_litteral}; } } return 'ok'; } sub trim { my ($self, $value) = @_; $value =~ s/^[ \t]+//; $value =~ s/[ \t]+$//; return $value; } sub change_bytes { my ($self, %options) = @_; my $value = $options{value}; my $divide = defined($options{network}) ? 1000 : 1024; my @units = ('K', 'M', 'G', 'T'); my $unit = ''; my $sign = ''; $sign = '-' if ($value != abs($value)); $value = abs($value); for (my $i = 0; $i < scalar(@units); $i++) { last if (($value / $divide) < 1); $unit = $units[$i]; $value = $value / $divide; } return (sprintf('%.2f', $sign . $value), $unit . (defined($options{network}) ? 'b' : 'B')); } 1; __END__ =head1 NAME Perfdata class =head1 SYNOPSIS - =head1 DESCRIPTION B. =cut centreon-plugins-20220113/centreon/plugins/script.pm000066400000000000000000000342731417000230700224050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::script; use strict; use warnings; use centreon::plugins::output; use centreon::plugins::misc; use Pod::Usage; my %handlers = (DIE => {}, ALRM => {}); my $global_version = '(dev)'; my $alternative_fatpacker = 0; sub new { my ($class) = @_; my $self = {}; bless $self, $class; $self->{options} = undef; $self->{plugin} = undef; $self->{help} = undef; # Avoid to destroy because it keeps a ref on the object. # A problem if we execute it multiple times in the same perl execution # Use prepare_destroy $self->set_signal_handlers(); return $self; } sub prepare_destroy { my ($self) = @_; %handlers = (); } sub set_signal_handlers { my ($self) = @_; $SIG{__DIE__} = \&class_handle_DIE; $handlers{DIE}->{$self} = sub { $self->handle_DIE($_[0]) }; } sub class_handle_DIE { my ($msg) = @_; foreach (keys %{$handlers{DIE}}) { &{$handlers{DIE}->{$_}}($msg); } } sub class_handle_ALRM { foreach (keys %{$handlers{ALRM}}) { &{$handlers{ALRM}->{$_}}(); } } sub handle_DIE { my ($self, $msg) = @_; return unless defined $^S and $^S == 0; # Ignore errors in eval $self->{output}->add_option_msg(short_msg => $msg); $self->{output}->die_exit(); } sub handle_ALRM { my ($self) = @_; $self->{output}->add_option_msg(short_msg => 'script global timeout'); $self->{output}->option_exit(); } sub get_global_version { return $global_version; } sub get_plugin { my ($self) = @_; # Need to load global 'Output' and 'Options' if ($alternative_fatpacker == 0) { require centreon::plugins::options; $self->{options} = centreon::plugins::options->new(); } else { require centreon::plugins::alternative::FatPackerOptions; $self->{options} = centreon::plugins::alternative::FatPackerOptions->new(); } $self->{output} = centreon::plugins::output->new(options => $self->{options}); $self->{options}->set_output(output => $self->{output}); $self->{options}->add_options(arguments => { 'plugin:s' => { name => 'plugin' }, 'list-plugin' => { name => 'list_plugin' }, 'help' => { name => 'help' }, 'ignore-warn-msg' => { name => 'ignore_warn_msg' }, 'version' => { name => 'version' }, 'runas:s' => { name => 'runas' }, 'global-timeout:s' => { name => 'global_timeout' }, 'environment:s%' => { name => 'environment' }, 'convert-args:s' => { name => 'convert_args' }, }); $self->{options}->parse_options(); $self->{plugin} = $self->{options}->get_option(argument => 'plugin'); $self->{list_plugin} = $self->{options}->get_option(argument => 'list_plugin'); $self->{help} = $self->{options}->get_option(argument => 'help'); $self->{version} = $self->{options}->get_option(argument => 'version'); $self->{runas} = $self->{options}->get_option(argument => 'runas'); $self->{environment} = $self->{options}->get_option(argument => 'environment'); $self->{ignore_warn_msg} = $self->{options}->get_option(argument => 'ignore_warn_msg'); $self->{convert_args} = $self->{options}->get_option(argument => 'convert_args'); my $global_timeout = $self->{options}->get_option(argument => 'global_timeout'); if (defined($global_timeout) && $global_timeout =~ /(\d+)/) { $SIG{ALRM} = \&class_handle_ALRM; $handlers{ALRM}->{$self} = sub { $self->handle_ALRM() }; alarm($1); } $self->{output}->plugin(name => $self->{plugin}); $self->{output}->check_options(option_results => $self->{options}->get_options()); $self->{options}->clean(); } sub convert_args { my ($self) = @_; if ($self->{convert_args} =~ /^(.+?),(.*)/) { my ($search, $replace) = ($1, $2); for (my $i = 0; $i <= $#ARGV; $i++) { eval "\$ARGV[\$i] =~ s/$search/$replace/g"; } } } sub display_local_help { my ($self) = @_; my $stdout; if ($self->{help}) { local *STDOUT; open STDOUT, '>', \$stdout; if ($alternative_fatpacker == 0) { pod2usage(-exitval => 'NOEXIT', -input => $self->{options}->pod_where(package => __PACKAGE__)); } else { my $pp = __PACKAGE__ . '.pm'; $pp =~ s{::}{/}g; my $content_class = $INC{$pp}->{$pp}; open my $str_fh, '<', \$content_class; pod2usage(-exitval => 'NOEXIT', -input => $str_fh); close $str_fh; } } $self->{output}->add_option_msg(long_msg => $stdout) if (defined($stdout)); } sub check_directory { my ($self, $directory) = @_; opendir(my $dh, $directory) || return ; while (my $filename = readdir $dh) { $self->check_directory($directory . '/' . $filename) if ($filename !~ /^\./ && -d $directory . '/' . $filename); if ($filename eq 'plugin.pm') { my $stdout = ''; { local *STDOUT; open STDOUT, '>', \$stdout; pod2usage( -exitval => 'NOEXIT', -input => $directory . "/" . $filename, -verbose => 99, -sections => 'PLUGIN DESCRIPTION' ); } $self->{plugins_result}->{$directory . '/' . $filename} = $stdout; } } closedir $dh; } sub fatpacker_find_plugin { my ($self) = @_; my $plugins = []; foreach (@INC) { next if (ref($_) !~ /FatPacked/); foreach my $name (keys %$_) { if ($name =~ /plugin.pm$/) { push @$plugins, $name; } } } return $plugins; } sub check_plugin_option { my ($self) = @_; if (defined($self->{version})) { $self->{output}->add_option_msg(short_msg => 'Global Version: ' . $global_version); $self->{output}->option_exit(nolabel => 1); } my $no_plugin = 1; if ($alternative_fatpacker == 1) { my $integrated_plugins = $self->fatpacker_find_plugin(); if (scalar(@$integrated_plugins) == 1) { $self->{plugin} = $integrated_plugins->[0]; $no_plugin = 0; } } if ($no_plugin == 1) { $self->{output}->add_option_msg(short_msg => "Need to specify '--plugin' option."); $self->{output}->option_exit(); } } sub display_list_plugin { my ($self) = @_; $self->{plugins_result} = {}; if ($alternative_fatpacker == 1) { my $integrated_plugins = $self->fatpacker_find_plugin(); foreach my $key (sort @$integrated_plugins) { # Need to load it to get the description centreon::plugins::misc::mymodule_load( output => $self->{output}, module => $key, error_msg => 'Cannot load module --plugin.' ); my $name = $key; $name =~ s/\.pm//g; $name =~ s/\//::/g; $self->{output}->add_option_msg(long_msg => '-----------------'); $self->{output}->add_option_msg(long_msg => 'PLUGIN: ' . $name); { my $stdout = ''; local *STDOUT; open STDOUT, '>', \$stdout; my $content_class = $INC{$key}->{$key}; open my $str_fh, '<', \$content_class; pod2usage(-exitval => 'NOEXIT', -input => $str_fh, -verbose => 99, -sections => 'PLUGIN DESCRIPTION'); close $str_fh; $self->{output}->add_option_msg(long_msg => $stdout); } } return ; } centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'FindBin', error_msg => "Cannot load module 'FindBin'." ); my $directory = $FindBin::Bin; if (defined($ENV{PAR_TEMP})) { $directory = $ENV{PAR_TEMP} . '/inc/lib'; } # Search file 'plugin.pm' $self->check_directory($directory); foreach my $key (sort keys %{$self->{plugins_result}}) { my $name = $key; $name =~ s/^\Q$directory\E\/(.*)\.pm/$1/; $name =~ s/\//::/g; $self->{plugins_result}->{$key} =~ s/^Plugin Description/DESCRIPTION/i; $self->{output}->add_option_msg(long_msg => '-----------------'); $self->{output}->add_option_msg(long_msg => 'PLUGIN: ' . $name); $self->{output}->add_option_msg(long_msg => $self->{plugins_result}->{$key}); } } sub check_relaunch_get_args { my ($self) = @_; my $args = ['--plugin=' . $self->{plugin}, @ARGV]; push @$args, '--ignore-warn-msg' if (defined($self->{ignore_warn_msg})); push @$args, '--help' if (defined($self->{help})); push @$args, '--global-timeout', $self->{global_timeout} if (defined($self->{global_timeout})); foreach (( ['output_xml', 0], ['output_json', 0], ['output_openmetrics', 0], ['disco_format', 0], ['disco_show', 0], ['use_new_perfdata', 0], ['debug', 0], ['verbose', 0], ['range_perfdata', 1], ['filter_uom', 1], ['opt_exit', 1], ['filter_perfdata', 1], ['output_file', 1], ['float_precision', 1] )) { my $option = $self->{output}->get_option(option => $_->[0]); if (defined($option)) { my $option_label = $_->[0]; $option_label =~ s/_/-/g; push @$args, "--$option_label" if ($_->[1] == 0); push @$args, "--$option_label", $option if ($_->[1] == 1); } } return $args; } sub check_relaunch { my $self = shift; centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'FindBin', error_msg => "Cannot load module 'FindBin'." ); my $need_restart = 0; my $cmd = $FindBin::Bin . '/' . $FindBin::Script; my $args = []; if (defined($self->{environment})) { foreach (keys %{$self->{environment}}) { if ($_ ne '' && (!defined($ENV{$_}) || $ENV{$_} ne $self->{environment}->{$_})) { $ENV{$_} = $self->{environment}->{$_}; $need_restart = 1; } } } my $rebuild_args = $self->check_relaunch_get_args(); if (defined($self->{runas}) && $self->{runas} ne '') { # Check if it's already me and user exist ;) my ($name, $passwd, $uid) = getpwnam($self->{runas}); if (!defined($uid)) { $self->{output}->add_option_msg(short_msg => "Runas user '" . $self->{runas} . "' not exist."); $self->{output}->option_exit(); } if ($uid != $>) { if ($> == 0) { unshift @$args, '-s', '/bin/bash', '-l', $self->{runas}, '-c', join(' ', $cmd, $rebuild_args); $cmd = 'su'; } else { unshift @$args, '-S', '-u', $self->{runas}, $cmd, @$rebuild_args; $cmd = 'sudo'; } $need_restart = 1; } } if ($need_restart == 1) { if (scalar(@$args) <= 0) { unshift @$args, @$rebuild_args; } my ($lerror, $stdout, $exit_code) = centreon::plugins::misc::backtick( command => $cmd, arguments => $args, timeout => 30, wait_exit => 1 ); if ($exit_code <= -1000) { if ($exit_code == -1000) { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => $stdout ); } $self->{output}->display(); $self->{output}->exit(); } chomp $stdout; print $stdout . "\n"; # We put unknown if (!($exit_code >= 0 && $exit_code <= 4)) { exit 3; } exit $exit_code; } } sub run { my ($self) = @_; $self->get_plugin(); if (defined($self->{help}) && !defined($self->{plugin})) { $self->display_local_help(); $self->{output}->option_exit(); } if (defined($self->{list_plugin})) { $self->display_list_plugin(); $self->{output}->option_exit(); } $self->check_plugin_option() if (!defined($self->{plugin}) || $self->{plugin} eq ''); if (defined($self->{ignore_warn_msg})) { $SIG{__WARN__} = sub {}; } $self->convert_args() if (defined($self->{convert_args})); $self->check_relaunch(); (undef, $self->{plugin}) = centreon::plugins::misc::mymodule_load( output => $self->{output}, module => $self->{plugin}, error_msg => 'Cannot load module --plugin.' ); my $plugin = $self->{plugin}->new(options => $self->{options}, output => $self->{output}); $plugin->init( help => $self->{help}, version => $self->{version} ); $plugin->run(); } 1; __END__ =head1 NAME centreon_plugins.pl - main program to call Centreon plugins. =head1 SYNOPSIS centreon_plugins.pl [options] =head1 OPTIONS =over 8 =item B<--plugin> Specify the path to the plugin. =item B<--list-plugin> Print available plugins. =item B<--version> Print global version. =item B<--help> Print a brief help message and exits. =item B<--ignore-warn-msg> Perl warn messages are ignored (not displayed). =item B<--runas> Run the script as a different user (prefer to use directly the good user). =item B<--global-timeout> Set script timeout. =item B<--environment> Set environment variables for the script (prefer to set it before running it for better performance). =item B<--convert-args> Change strings of arguments. Useful to use '!' in nrpe protocol. Example: --convert-args='##,\x21' =back =head1 DESCRIPTION B . =cut centreon-plugins-20220113/centreon/plugins/script_custom.pm000066400000000000000000000247601417000230700237770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::script_custom; use strict; use warnings; use centreon::plugins::misc; sub new { my ($class, %options) = @_; my $self = {}; bless $self, $class; $self->{options} = $options{options}; $self->{output} = $options{output}; $self->{options}->add_options( arguments => { 'mode:s' => { name => 'mode_name' }, 'dyn-mode:s' => { name => 'dynmode_name' }, 'list-mode' => { name => 'list_mode' }, 'custommode:s' => { name => 'custommode_name' }, 'list-custommode' => { name => 'list_custommode' }, 'multiple' => { name => 'multiple' }, 'no-sanity-options' => { name => 'no_sanity_options' }, 'pass-manager:s' => { name => 'pass_manager' } } ); $self->{version} = '1.0'; $self->{modes} = {}; $self->{custom_modes} = {}; $self->{default} = undef; $self->{customdefault} = {}; $self->{custommode_current} = undef; $self->{custommode_stored} = []; $self->{options}->parse_options(); $self->{option_results} = $self->{options}->get_options(); foreach (keys %{$self->{option_results}}) { $self->{$_} = $self->{option_results}->{$_}; } $self->{options}->clean(); $self->{options}->add_help(package => $options{package}, sections => 'PLUGIN DESCRIPTION'); $self->{options}->add_help(package => __PACKAGE__, sections => 'GLOBAL OPTIONS'); $self->{output}->mode(name => $self->{mode_name}); return $self; } sub load_custom_mode { my ($self, %options) = @_; $self->is_custommode(custommode => $self->{custommode_name}); centreon::plugins::misc::mymodule_load( output => $self->{output}, module => $self->{custom_modes}->{$self->{custommode_name}}, error_msg => 'Cannot load module --custommode.' ); $self->{custommode_current} = $self->{custom_modes}->{$self->{custommode_name}}->new( options => $self->{options}, output => $self->{output}, custommode_name => $self->{custommode_name}, mode_name => $self->{mode_name} ); } sub init { my ($self, %options) = @_; # add meta mode $self->{modes}->{multi} = 'centreon::plugins::multi'; if (defined($options{help}) && !defined($self->{mode_name}) && !defined($self->{dynmode_name})) { $self->{options}->display_help(); $self->{output}->option_exit(); } if (defined($options{version}) && !defined($self->{mode_name})&& !defined($self->{dynmode_name})) { $self->version(); } if (defined($self->{list_mode})) { $self->list_mode(); } if (defined($self->{list_custommode})) { $self->list_custommode(); } $self->{options}->set_sanity() if (!defined($self->{no_sanity_options})); # Output HELP $self->{options}->add_help(package => 'centreon::plugins::output', sections => 'OUTPUT OPTIONS'); $self->load_password_mgr(); if (defined($self->{custommode_name}) && $self->{custommode_name} ne '') { $self->load_custom_mode(); } elsif (scalar(keys %{$self->{custom_modes}}) == 1) { $self->{custommode_name} = (keys(%{$self->{custom_modes}}))[0]; $self->load_custom_mode(); } else { $self->{output}->add_option_msg(short_msg => "Need to specify '--custommode'."); $self->{output}->option_exit(); } # Load mode if (defined($self->{mode_name}) && $self->{mode_name} ne '') { $self->is_mode(mode => $self->{mode_name}); centreon::plugins::misc::mymodule_load(output => $self->{output}, module => $self->{modes}{$self->{mode_name}}, error_msg => "Cannot load module --mode."); $self->{mode} = $self->{modes}{$self->{mode_name}}->new(options => $self->{options}, output => $self->{output}, mode => $self->{mode_name}); } elsif (defined($self->{dynmode_name}) && $self->{dynmode_name} ne '') { (undef, $self->{dynmode_name}) = centreon::plugins::misc::mymodule_load(output => $self->{output}, module => $self->{dynmode_name}, error_msg => "Cannot load module --dyn-mode."); $self->{mode} = $self->{dynmode_name}->new(options => $self->{options}, output => $self->{output}, mode => $self->{dynmode_name}); } else { $self->{output}->add_option_msg(short_msg => "Need to specify '--mode' or '--dyn-mode' option."); $self->{output}->option_exit(); } if (defined($options{help})) { if (defined($self->{mode_name}) && $self->{mode_name} ne '') { $self->{options}->add_help(package => $self->{modes}{$self->{mode_name}}, sections => 'MODE'); } else { $self->{options}->add_help(package => $self->{dynmode_name}, sections => 'MODE'); } $self->{options}->display_help(); $self->{output}->option_exit(); } if (defined($options{version})) { $self->{mode}->version(); $self->{output}->option_exit(nolabel => 1); } $self->{options}->parse_options(); $self->{option_results} = $self->{options}->get_options(); $self->{pass_mgr}->manage_options(option_results => $self->{option_results}) if (defined($self->{pass_mgr})); push @{$self->{custommode_stored}}, $self->{custommode_current}; $self->{custommode_current}->set_options(option_results => $self->{option_results}); $self->{custommode_current}->set_defaults(default => $self->{customdefault}); while ($self->{custommode_current}->check_options()) { $self->{custommode_current} = $self->{custom_modes}->{$self->{custommode_name}}->new(noptions => 1, options => $self->{options}, output => $self->{output}, mode => $self->{custommode_name}); $self->{custommode_current}->set_options(option_results => $self->{option_results}); push @{$self->{custommode_stored}}, $self->{custommode_current}; } $self->{mode}->check_options( option_results => $self->{option_results}, default => $self->{default}, modes => $self->{modes} # for meta mode multi ); } sub load_password_mgr { my ($self, %options) = @_; return if (!defined($self->{option_results}->{pass_manager}) || $self->{option_results}->{pass_manager} eq ''); (undef, my $pass_mgr_name) = centreon::plugins::misc::mymodule_load( output => $self->{output}, module => "centreon::plugins::passwordmgr::" . $self->{option_results}->{pass_manager}, error_msg => "Cannot load module 'centreon::plugins::passwordmgr::" . $self->{option_results}->{pass_manager} . "'" ); $self->{pass_mgr} = $pass_mgr_name->new(options => $self->{options}, output => $self->{output}); } sub run { my $self = shift; if ($self->{output}->is_disco_format()) { $self->{mode}->disco_format(); $self->{output}->display_disco_format(); $self->{output}->exit(exit_litteral => 'ok'); } if ($self->{output}->is_disco_show()) { if (defined($self->{multiple})) { $self->{mode}->disco_show(custom => $self->{custommode}); } else { $self->{mode}->disco_show(custom => $self->{custommode_stored}[0]); } $self->{output}->display_disco_show(); $self->{output}->exit(exit_litteral => 'ok'); } else { if (defined($self->{multiple})) { $self->{mode}->run(custom => $self->{custommode_stored}); } else { $self->{mode}->run(custom => $self->{custommode_stored}[0]); } } } sub is_mode { my ($self, %options) = @_; if (!defined($self->{modes}{$options{mode}})) { $self->{output}->add_option_msg(short_msg => "mode '" . $options{mode} . "' doesn't exist (use --list-mode option to show available modes)."); $self->{output}->option_exit(); } } sub is_custommode { my ($self, %options) = @_; if (!defined($self->{custom_modes}->{$options{custommode}})) { $self->{output}->add_option_msg(short_msg => "mode '" . $options{custommode} . "' doesn't exist (use --list-custommode option to show available modes)."); $self->{output}->option_exit(); } } sub version { my $self = shift; $self->{output}->add_option_msg(short_msg => "Plugin Version: " . $self->{version}); $self->{output}->option_exit(nolabel => 1); } sub list_mode { my $self = shift; $self->{options}->display_help(); $self->{output}->add_option_msg(long_msg => 'Modes Meta:'); $self->{output}->add_option_msg(long_msg => ' multi'); $self->{output}->add_option_msg(long_msg => ''); $self->{output}->add_option_msg(long_msg => 'Modes Available:'); foreach (sort keys %{$self->{modes}}) { next if ($_ eq 'multi'); $self->{output}->add_option_msg(long_msg => ' ' . $_); } $self->{output}->option_exit(nolabel => 1); } sub list_custommode { my $self = shift; $self->{options}->display_help(); $self->{output}->add_option_msg(long_msg => "Custom Modes Available:"); foreach (keys %{$self->{custom_modes}}) { $self->{output}->add_option_msg(long_msg => " " . $_); } $self->{output}->option_exit(nolabel => 1); } 1; __END__ =head1 NAME - =head1 SYNOPSIS - =head1 GLOBAL OPTIONS =over 8 =item B<--mode> Choose a mode. =item B<--dyn-mode> Specify a mode with the path (separated by '::'). =item B<--list-mode> List available modes. =item B<--mode-version> Check minimal version of mode. If not, unknown error. =item B<--version> Display plugin version. =item B<--custommode> Choose a custom mode. =item B<--list-custommode> List available custom modes. =item B<--multiple> Multiple custom mode objects (required by some specific modes) =item B<--pass-manager> Use a password manager. =back =head1 DESCRIPTION B<>. =cut centreon-plugins-20220113/centreon/plugins/script_custom/000077500000000000000000000000001417000230700234305ustar00rootroot00000000000000centreon-plugins-20220113/centreon/plugins/script_custom/cli.pm000066400000000000000000000125631417000230700245440ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::script_custom::cli; use strict; use warnings; use centreon::plugins::ssh; 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 => { 'hostname:s' => { name => 'hostname' }, 'timeout:s' => { name => 'timeout' }, 'command:s' => { name => 'command' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options' }, 'sudo:s' => { name => 'sudo' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'CLI OPTIONS', once => 1); $self->{output} = $options{output}; $self->{ssh} = centreon::plugins::ssh->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; if (defined($self->{option_results}->{timeout}) && $self->{option_results}->{timeout} =~ /(\d+)/) { $self->{timeout} = $1; } if (defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '') { $self->{ssh}->check_options(option_results => $self->{option_results}); } return 0; } sub get_identifier { my ($self, %options) = @_; my $id = defined($self->{option_results}->{hostname}) ? $self->{option_results}->{hostname} : 'me'; if (defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '') { $id .= ':' . $self->{ssh}->get_port(); } return $id; } sub execute_command { my ($self, %options) = @_; my $timeout = $self->{timeout}; if (!defined($timeout)) { $timeout = defined($options{timeout}) ? $options{timeout} : 45; } my $command_options = defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne '' ? $self->{option_results}->{command_options} : $options{command_options}; if (defined($options{command_options_suffix})) { $command_options .= $options{command_options_suffix}; } my ($stdout, $exit_code); if (defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '') { ($stdout, $exit_code) = $self->{ssh}->execute( hostname => $self->{option_results}->{hostname}, sudo => $self->{option_results}->{sudo}, command => defined($self->{option_results}->{command}) && $self->{option_results}->{command} ne '' ? $self->{option_results}->{command} : $options{command}, command_path => defined($self->{option_results}->{command_path}) && $self->{option_results}->{command_path} ne '' ? $self->{option_results}->{command_path} : $options{command_path}, command_options => $command_options, timeout => $timeout, no_quit => $options{no_quit} ); } else { ($stdout, $exit_code) = centreon::plugins::misc::execute( output => $self->{output}, sudo => $self->{option_results}->{sudo}, options => { timeout => $timeout }, command => defined($self->{option_results}->{command}) && $self->{option_results}->{command} ne '' ? $self->{option_results}->{command} : $options{command}, command_path => defined($self->{option_results}->{command_path}) && $self->{option_results}->{command_path} ne '' ? $self->{option_results}->{command_path} : $options{command_path}, command_options => $command_options, no_quit => $options{no_quit} ); } $self->{output}->output_add(long_msg => "command response: $stdout", debug => 1); return ($stdout, $exit_code); } 1; __END__ =head1 NAME ssh =head1 SYNOPSIS my ssh =head1 CLI OPTIONS =over 8 =item B<--hostname> Hostname to query. =item B<--timeout> Timeout in seconds for the command (Default: 45). Default value can be override by the mode. =item B<--command> Command to get information. Used it you have output in a file. =item B<--command-path> Command path. =item B<--command-options> Command options. =item B<--sudo> sudo command. =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/centreon/plugins/script_simple.pm000066400000000000000000000172131417000230700237510ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::script_simple; use strict; use warnings; sub new { my ($class, %options) = @_; my $self = {}; bless $self, $class; $self->{options} = $options{options}; $self->{output} = $options{output}; $self->{options}->add_options( arguments => { 'mode:s' => { name => 'mode_name' }, 'dyn-mode:s' => { name => 'dynmode_name' }, 'list-mode' => { name => 'list_mode' }, 'mode-version:s' => { name => 'mode_version' }, 'no-sanity-options' => { name => 'no_sanity_options' }, 'pass-manager:s' => { name => 'pass_manager' }, } ); $self->{version} = '1.0'; %{$self->{modes}} = (); $self->{default} = undef; $self->{options}->parse_options(); $self->{option_results} = $self->{options}->get_options(); foreach (keys %{$self->{option_results}}) { $self->{$_} = $self->{option_results}->{$_}; } $self->{options}->clean(); $self->{options}->add_help(package => $options{package}, sections => 'PLUGIN DESCRIPTION'); $self->{options}->add_help(package => __PACKAGE__, sections => 'GLOBAL OPTIONS'); $self->{output}->mode(name => $self->{mode_name}); return $self; } sub init { my ($self, %options) = @_; # add meta mode $self->{modes}->{multi} = 'centreon::plugins::multi'; if (defined($options{help}) && !defined($self->{mode_name}) && !defined($self->{dynmode_name})) { $self->{options}->display_help(); $self->{output}->option_exit(); } if (defined($options{version}) && !defined($self->{mode_name}) && !defined($self->{dynmode_name})) { $self->version(); } if (defined($self->{list_mode})) { $self->list_mode(); } $self->{options}->set_sanity() if (!defined($self->{no_sanity_options})); # Output HELP $self->{options}->add_help(package => 'centreon::plugins::output', sections => 'OUTPUT OPTIONS'); $self->load_password_mgr(); # Load mode if (defined($self->{mode_name}) && $self->{mode_name} ne '') { $self->is_mode(mode => $self->{mode_name}); centreon::plugins::misc::mymodule_load(output => $self->{output}, module => $self->{modes}{$self->{mode_name}}, error_msg => "Cannot load module --mode."); $self->{mode} = $self->{modes}{$self->{mode_name}}->new(options => $self->{options}, output => $self->{output}, mode => $self->{mode_name}); } elsif (defined($self->{dynmode_name}) && $self->{dynmode_name} ne '') { (undef, $self->{dynmode_name}) = centreon::plugins::misc::mymodule_load(output => $self->{output}, module => $self->{dynmode_name}, error_msg => "Cannot load module --dyn-mode."); $self->{mode} = $self->{dynmode_name}->new(options => $self->{options}, output => $self->{output}, mode => $self->{dynmode_name}); } else { $self->{output}->add_option_msg(short_msg => "Need to specify '--mode' or '--dyn-mode' option."); $self->{output}->option_exit(); } if (defined($options{help})) { if (defined($self->{mode_name}) && $self->{mode_name} ne '') { $self->{options}->add_help(package => $self->{modes}{$self->{mode_name}}, sections => 'MODE'); } else { $self->{options}->add_help(package => $self->{dynmode_name}, sections => 'MODE'); } $self->{options}->display_help(); $self->{output}->option_exit(); } if (defined($options{version})) { $self->{mode}->version(); $self->{output}->option_exit(nolabel => 1); } if (centreon::plugins::misc::minimal_version($self->{mode}->{version}, $self->{mode_version}) == 0) { $self->{output}->add_option_msg(short_msg => "Not good version for plugin mode. Excepted at least: " . $self->{mode_version} . ". Get: ". $self->{mode}->{version}); $self->{output}->option_exit(); } $self->{options}->parse_options(); $self->{option_results} = $self->{options}->get_options(); $self->{pass_mgr}->manage_options(option_results => $self->{option_results}) if (defined($self->{pass_mgr})); $self->{mode}->check_options( option_results => $self->{option_results}, default => $self->{default}, modes => $self->{modes} # for meta mode multi ); } sub load_password_mgr { my ($self, %options) = @_; return if (!defined($self->{option_results}->{pass_manager}) || $self->{option_results}->{pass_manager} eq ''); (undef, my $pass_mgr_name) = centreon::plugins::misc::mymodule_load( output => $self->{output}, module => "centreon::plugins::passwordmgr::" . $self->{option_results}->{pass_manager}, error_msg => "Cannot load module 'centreon::plugins::passwordmgr::" . $self->{option_results}->{pass_manager} . "'" ); $self->{pass_mgr} = $pass_mgr_name->new(options => $self->{options}, output => $self->{output}); } sub run { my $self = shift; if ($self->{output}->is_disco_format()) { $self->{mode}->disco_format(); $self->{output}->display_disco_format(); $self->{output}->exit(exit_litteral => 'ok'); } if ($self->{output}->is_disco_show()) { $self->{mode}->disco_show(snmp => $self->{snmp}); $self->{output}->display_disco_show(); $self->{output}->exit(exit_litteral => 'ok'); } else { $self->{mode}->run(); } } sub is_mode { my ($self, %options) = @_; # $options->{mode} = mode if (!defined($self->{modes}{$options{mode}})) { $self->{output}->add_option_msg(short_msg => "mode '" . $options{mode} . "' doesn't exist (use --list-mode option to show available modes)."); $self->{output}->option_exit(); } } sub version { my $self = shift; $self->{output}->add_option_msg(short_msg => "Plugin Version: " . $self->{version}); $self->{output}->option_exit(nolabel => 1); } sub list_mode { my $self = shift; $self->{options}->display_help(); $self->{output}->add_option_msg(long_msg => 'Modes Meta:'); $self->{output}->add_option_msg(long_msg => ' multi'); $self->{output}->add_option_msg(long_msg => ''); $self->{output}->add_option_msg(long_msg => 'Modes Available:'); foreach (sort keys %{$self->{modes}}) { next if ($_ eq 'multi'); $self->{output}->add_option_msg(long_msg => ' ' . $_); } $self->{output}->option_exit(nolabel => 1); } 1; __END__ =head1 NAME - =head1 SYNOPSIS - =head1 GLOBAL OPTIONS =over 8 =item B<--mode> Choose a mode. =item B<--dyn-mode> Specify a mode with the path (separated by '::'). =item B<--list-mode> List available modes. =item B<--mode-version> Check minimal version of mode. If not, unknown error. =item B<--version> Display plugin version. =item B<--pass-manager> Use a password manager. =back =head1 DESCRIPTION B<>. =cut centreon-plugins-20220113/centreon/plugins/script_snmp.pm000066400000000000000000000176511417000230700234430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::script_snmp; use strict; use warnings; use centreon::plugins::snmp; use centreon::plugins::misc; sub new { my ($class, %options) = @_; my $self = {}; bless $self, $class; $self->{options} = $options{options}; $self->{output} = $options{output}; $self->{options}->add_options( arguments => { 'mode:s' => { name => 'mode_name' }, 'dyn-mode:s' => { name => 'dynmode_name' }, 'list-mode' => { name => 'list_mode' }, 'mode-version:s' => { name => 'mode_version' }, 'no-sanity-options' => { name => 'no_sanity_options' }, 'pass-manager:s' => { name => 'pass_manager' }, } ); $self->{version} = '1.0'; $self->{modes} = {}; $self->{default} = undef; $self->{options}->parse_options(); $self->{option_results} = $self->{options}->get_options(); foreach (keys %{$self->{option_results}}) { $self->{$_} = $self->{option_results}->{$_}; } $self->{options}->clean(); $self->{options}->add_help(package => $options{package}, sections => 'PLUGIN DESCRIPTION'); $self->{options}->add_help(package => __PACKAGE__, sections => 'GLOBAL OPTIONS'); $self->{output}->mode(name => $self->{mode_name}); return $self; } sub init { my ($self, %options) = @_; # add meta mode $self->{modes}->{multi} = 'centreon::plugins::multi'; if (defined($options{help}) && !defined($self->{mode_name}) && !defined($self->{dynmode_name})) { $self->{options}->display_help(); $self->{output}->option_exit(); } if (defined($options{version}) && !defined($self->{mode_name}) && !defined($self->{dynmode_name})) { $self->version(); } if (defined($self->{list_mode})) { $self->list_mode(); } $self->{options}->set_sanity() if (!defined($self->{no_sanity_options})); # Output HELP $self->{options}->add_help(package => 'centreon::plugins::output', sections => 'OUTPUT OPTIONS'); $self->load_password_mgr(); # SNMP $self->{snmp} = centreon::plugins::snmp->new(options => $self->{options}, output => $self->{output}); # Load mode if (defined($self->{mode_name}) && $self->{mode_name} ne '') { $self->is_mode(mode => $self->{mode_name}); centreon::plugins::misc::mymodule_load(output => $self->{output}, module => $self->{modes}{$self->{mode_name}}, error_msg => "Cannot load module --mode."); $self->{mode} = $self->{modes}{$self->{mode_name}}->new(options => $self->{options}, output => $self->{output}, mode => $self->{mode_name}); } elsif (defined($self->{dynmode_name}) && $self->{dynmode_name} ne '') { (undef, $self->{dynmode_name}) = centreon::plugins::misc::mymodule_load(output => $self->{output}, module => $self->{dynmode_name}, error_msg => "Cannot load module --dyn-mode."); $self->{mode} = $self->{dynmode_name}->new(options => $self->{options}, output => $self->{output}, mode => $self->{dynmode_name}); } else { $self->{output}->add_option_msg(short_msg => "Need to specify '--mode' or '--dyn-mode' option."); $self->{output}->option_exit(); } if (defined($options{help})) { if (defined($self->{mode_name}) && $self->{mode_name} ne '') { $self->{options}->add_help(package => $self->{modes}{$self->{mode_name}}, sections => 'MODE'); } else { $self->{options}->add_help(package => $self->{dynmode_name}, sections => 'MODE'); } $self->{options}->display_help(); $self->{output}->option_exit(); } if (defined($options{version})) { $self->{mode}->version(); $self->{output}->option_exit(nolabel => 1); } if (centreon::plugins::misc::minimal_version($self->{mode}->{version}, $self->{mode_version}) == 0) { $self->{output}->add_option_msg(short_msg => "Not good version for plugin mode. Excepted at least: " . $self->{mode_version} . ". Get: ". $self->{mode}->{version}); $self->{output}->option_exit(); } $self->{options}->parse_options(); $self->{option_results} = $self->{options}->get_options(); $self->{pass_mgr}->manage_options(option_results => $self->{option_results}) if (defined($self->{pass_mgr})); $self->{snmp}->check_options(option_results => $self->{option_results}); $self->{mode}->check_options( option_results => $self->{option_results}, default => $self->{default}, snmp => $self->{snmp}, modes => $self->{modes} # for meta mode multi ); } sub load_password_mgr { my ($self, %options) = @_; return if (!defined($self->{option_results}->{pass_manager}) || $self->{option_results}->{pass_manager} eq ''); (undef, my $pass_mgr_name) = centreon::plugins::misc::mymodule_load( output => $self->{output}, module => "centreon::plugins::passwordmgr::" . $self->{option_results}->{pass_manager}, error_msg => "Cannot load module 'centreon::plugins::passwordmgr::" . $self->{option_results}->{pass_manager} . "'" ); $self->{pass_mgr} = $pass_mgr_name->new(options => $self->{options}, output => $self->{output}); } sub run { my ($self) = @_; if ($self->{output}->is_disco_format()) { $self->{mode}->disco_format(); $self->{output}->display_disco_format(); $self->{output}->exit(exit_litteral => 'ok'); } $self->{snmp}->connect(); if ($self->{output}->is_disco_show()) { $self->{mode}->disco_show(snmp => $self->{snmp}); $self->{output}->display_disco_show(); $self->{output}->exit(exit_litteral => 'ok'); } else { $self->{mode}->run(snmp => $self->{snmp}); } } sub is_mode { my ($self, %options) = @_; if (!defined($self->{modes}{$options{mode}})) { $self->{output}->add_option_msg(short_msg => "mode '" . $options{mode} . "' doesn't exist (use --list-mode option to show available modes)."); $self->{output}->option_exit(); } } sub version { my ($self) = @_; $self->{output}->add_option_msg(short_msg => 'Plugin Version: ' . $self->{version}); $self->{output}->option_exit(nolabel => 1); } sub list_mode { my ($self) = @_; $self->{options}->display_help(); $self->{output}->add_option_msg(long_msg => 'Modes Meta:'); $self->{output}->add_option_msg(long_msg => ' multi'); $self->{output}->add_option_msg(long_msg => ''); $self->{output}->add_option_msg(long_msg => 'Modes Available:'); foreach (sort keys %{$self->{modes}}) { next if ($_ eq 'multi'); $self->{output}->add_option_msg(long_msg => ' ' . $_); } $self->{output}->option_exit(nolabel => 1); } 1; __END__ =head1 NAME - =head1 SYNOPSIS - =head1 GLOBAL OPTIONS =over 8 =item B<--mode> Choose a mode. =item B<--dyn-mode> Specify a mode with the path (separated by '::'). =item B<--list-mode> List available modes. =item B<--mode-version> Check minimal version of mode. If not, unknown error. =item B<--version> Display plugin version. =item B<--pass-manager> Use a password manager. =back =head1 DESCRIPTION B<>. =cut centreon-plugins-20220113/centreon/plugins/script_sql.pm000066400000000000000000000251741417000230700232640ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::script_sql; use strict; use warnings; use centreon::plugins::misc; sub new { my ($class, %options) = @_; my $self = {}; bless $self, $class; $self->{options} = $options{options}; $self->{output} = $options{output}; $self->{options}->add_options( arguments => { 'mode:s' => { name => 'mode_name' }, 'dyn-mode:s' => { name => 'dynmode_name' }, 'list-mode' => { name => 'list_mode' }, 'mode-version:s' => { name => 'mode_version' }, 'sqlmode:s' => { name => 'sqlmode_name', default => 'dbi' }, 'list-sqlmode' => { name => 'list_sqlmode' }, 'multiple' => { name => 'multiple' }, 'no-sanity-options' => { name => 'no_sanity_options' }, 'pass-manager:s' => { name => 'pass_manager' } } ); $self->{version} = '1.0'; $self->{modes} = {}; $self->{sql_modes} = { 'dbi' => 'centreon::plugins::dbi' }; $self->{default} = undef; $self->{sqldefault} = {}; $self->{sqlmode_current} = undef; $self->{sqlmode_stored} = []; $self->{options}->parse_options(); $self->{option_results} = $self->{options}->get_options(); foreach (keys %{$self->{option_results}}) { $self->{$_} = $self->{option_results}->{$_}; } $self->{options}->clean(); $self->{options}->add_help(package => $options{package}, sections => 'PLUGIN DESCRIPTION'); $self->{options}->add_help(package => __PACKAGE__, sections => 'GLOBAL OPTIONS'); $self->{output}->mode(name => $self->{mode_name}); return $self; } sub init { my ($self, %options) = @_; # add meta mode $self->{modes}->{multi} = 'centreon::plugins::multi'; if (defined($options{help}) && !defined($self->{mode_name}) && !defined($self->{dynmode_name})) { $self->{options}->display_help(); $self->{output}->option_exit(); } if (defined($options{version}) && !defined($self->{mode_name}) && !defined($self->{dynmode_name})) { $self->version(); } if (defined($self->{list_mode})) { $self->list_mode(); } if (defined($self->{list_sqlmode})) { $self->list_sqlmode(); } $self->{options}->set_sanity() if (!defined($self->{no_sanity_options})); # Output HELP $self->{options}->add_help(package => 'centreon::plugins::output', sections => 'OUTPUT OPTIONS'); $self->load_password_mgr(); if (defined($self->{sqlmode_name}) && $self->{sqlmode_name} ne '') { $self->is_sqlmode(sqlmode => $self->{sqlmode_name}); centreon::plugins::misc::mymodule_load( output => $self->{output}, module => $self->{sql_modes}->{$self->{sqlmode_name}}, error_msg => "Cannot load module --sqlmode." ); $self->{sqlmode_current} = $self->{sql_modes}->{$self->{sqlmode_name}}->new( options => $self->{options}, output => $self->{output}, sqlmode_name => $self->{sqlmode_name}, mode_name => $self->{mode_name} ); } else { $self->{output}->add_option_msg(short_msg => "Need to specify '--sqlmode'."); $self->{output}->option_exit(); } # Load mode if (defined($self->{mode_name}) && $self->{mode_name} ne '') { $self->is_mode(mode => $self->{mode_name}); centreon::plugins::misc::mymodule_load(output => $self->{output}, module => $self->{modes}{$self->{mode_name}}, error_msg => "Cannot load module --mode."); $self->{mode} = $self->{modes}{$self->{mode_name}}->new(options => $self->{options}, output => $self->{output}, mode => $self->{mode_name}); } elsif (defined($self->{dynmode_name}) && $self->{dynmode_name} ne '') { (undef, $self->{dynmode_name}) = centreon::plugins::misc::mymodule_load(output => $self->{output}, module => $self->{dynmode_name}, error_msg => "Cannot load module --dyn-mode."); $self->{mode} = $self->{dynmode_name}->new(options => $self->{options}, output => $self->{output}, mode => $self->{dynmode_name}); } else { $self->{output}->add_option_msg(short_msg => "Need to specify '--mode' or '--dyn-mode' option."); $self->{output}->option_exit(); } if (defined($options{help})) { if (defined($self->{mode_name}) && $self->{mode_name} ne '') { $self->{options}->add_help(package => $self->{modes}{$self->{mode_name}}, sections => 'MODE'); } else { $self->{options}->add_help(package => $self->{dynmode_name}, sections => 'MODE'); } $self->{options}->display_help(); $self->{output}->option_exit(); } if (defined($options{version})) { $self->{mode}->version(); $self->{output}->option_exit(nolabel => 1); } if (centreon::plugins::misc::minimal_version($self->{mode}->{version}, $self->{mode_version}) == 0) { $self->{output}->add_option_msg(short_msg => "Not good version for plugin mode. Excepted at least: " . $self->{mode_version} . ". Get: ". $self->{mode}->{version}); $self->{output}->option_exit(); } $self->{options}->parse_options(); $self->{option_results} = $self->{options}->get_options(); $self->{pass_mgr}->manage_options(option_results => $self->{option_results}) if (defined($self->{pass_mgr})); push @{$self->{sqlmode_stored}}, $self->{sqlmode_current}; $self->{sqlmode_current}->set_options(option_results => $self->{option_results}); $self->{sqlmode_current}->set_defaults(default => $self->{sqldefault}); while ($self->{sqlmode_current}->check_options()) { $self->{sqlmode_current} = $self->{sql_modes}->{$self->{sqlmode_name}}->new(noptions => 1, options => $self->{options}, output => $self->{output}, mode => $self->{sqlmode_name}); $self->{sqlmode_current}->set_options(option_results => $self->{option_results}); push @{$self->{sqlmode_stored}}, $self->{sqlmode_current}; } $self->{mode}->check_options( option_results => $self->{option_results}, default => $self->{default}, modes => $self->{modes} # for meta mode multi ); } sub load_password_mgr { my ($self, %options) = @_; return if (!defined($self->{option_results}->{pass_manager}) || $self->{option_results}->{pass_manager} eq ''); (undef, my $pass_mgr_name) = centreon::plugins::misc::mymodule_load( output => $self->{output}, module => "centreon::plugins::passwordmgr::" . $self->{option_results}->{pass_manager}, error_msg => "Cannot load module 'centreon::plugins::passwordmgr::" . $self->{option_results}->{pass_manager} . "'" ); $self->{pass_mgr} = $pass_mgr_name->new(options => $self->{options}, output => $self->{output}); } sub run { my $self = shift; if ($self->{output}->is_disco_format()) { $self->{mode}->disco_format(); $self->{output}->display_disco_format(); $self->{output}->exit(exit_litteral => 'ok'); } if ($self->{output}->is_disco_show()) { if (defined($self->{multiple})) { $self->{mode}->disco_show(sql => $self->{sqlmode}); } else { $self->{mode}->disco_show(sql => $self->{sqlmode_stored}[0]); } $self->{output}->display_disco_show(); $self->{output}->exit(exit_litteral => 'ok'); } else { if (defined($self->{multiple})) { $self->{mode}->run(sql => $self->{sqlmode_stored}); } else { $self->{mode}->run(sql => $self->{sqlmode_stored}[0]); } } } sub is_mode { my ($self, %options) = @_; # $options->{mode} = mode if (!defined($self->{modes}{$options{mode}})) { $self->{output}->add_option_msg(short_msg => "mode '" . $options{mode} . "' doesn't exist (use --list-mode option to show available modes)."); $self->{output}->option_exit(); } } sub is_sqlmode { my ($self, %options) = @_; # $options->{sqlmode} = mode if (!defined($self->{sql_modes}->{$options{sqlmode}})) { $self->{output}->add_option_msg(short_msg => "mode '" . $options{sqlmode} . "' doesn't exist (use --list-sqlmode option to show available modes)."); $self->{output}->option_exit(); } } sub version { my $self = shift; $self->{output}->add_option_msg(short_msg => "Plugin Version: " . $self->{version}); $self->{output}->option_exit(nolabel => 1); } sub list_mode { my $self = shift; $self->{options}->display_help(); $self->{output}->add_option_msg(long_msg => 'Modes Meta:'); $self->{output}->add_option_msg(long_msg => ' multi'); $self->{output}->add_option_msg(long_msg => ''); $self->{output}->add_option_msg(long_msg => 'Modes Available:'); foreach (sort keys %{$self->{modes}}) { next if ($_ eq 'multi'); $self->{output}->add_option_msg(long_msg => ' ' . $_); } $self->{output}->option_exit(nolabel => 1); } sub list_sqlmode { my $self = shift; $self->{options}->display_help(); $self->{output}->add_option_msg(long_msg => "SQL Modes Available:"); foreach (keys %{$self->{sql_modes}}) { $self->{output}->add_option_msg(long_msg => " " . $_); } $self->{output}->option_exit(nolabel => 1); } 1; __END__ =head1 NAME - =head1 SYNOPSIS - =head1 GLOBAL OPTIONS =over 8 =item B<--mode> Choose a mode. =item B<--dyn-mode> Specify a mode with the path (separated by '::'). =item B<--list-mode> List available modes. =item B<--mode-version> Check minimal version of mode. If not, unknown error. =item B<--version> Display plugin version. =item B<--sqlmode> Choose a sql mode (Default: "dbi"). =item B<--list-sqlmode> List available sql modes. =item B<--multiple> Multiple database connections (required by some specific modes). =item B<--pass-manager> Use a password manager. =back =head1 DESCRIPTION B<>. =cut centreon-plugins-20220113/centreon/plugins/script_wsman.pm000066400000000000000000000174011417000230700236040ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::script_wsman; use strict; use warnings; use centreon::plugins::wsman; use centreon::plugins::misc; sub new { my ($class, %options) = @_; my $self = {}; bless $self, $class; $self->{options} = $options{options}; $self->{output} = $options{output}; $self->{options}->add_options( arguments => { 'mode:s' => { name => 'mode_name' }, 'dyn-mode:s' => { name => 'dynmode_name' }, 'list-mode' => { name => 'list_mode' }, 'mode-version:s' => { name => 'mode_version' }, 'no-sanity-options' => { name => 'no_sanity_options' }, 'pass-manager:s' => { name => 'pass_manager' }, } ); $self->{version} = '1.0'; %{$self->{modes}} = (); $self->{default} = undef; $self->{options}->parse_options(); $self->{option_results} = $self->{options}->get_options(); foreach (keys %{$self->{option_results}}) { $self->{$_} = $self->{option_results}->{$_}; } $self->{options}->clean(); $self->{options}->add_help(package => $options{package}, sections => 'PLUGIN DESCRIPTION'); $self->{options}->add_help(package => __PACKAGE__, sections => 'GLOBAL OPTIONS'); $self->{output}->mode(name => $self->{mode_name}); return $self; } sub init { my ($self, %options) = @_; # add meta mode $self->{modes}->{multi} = 'centreon::plugins::multi'; if (defined($options{help}) && !defined($self->{mode_name}) && !defined($self->{dynmode_name})) { $self->{options}->display_help(); $self->{output}->option_exit(); } if (defined($options{version}) && !defined($self->{mode_name}) && !defined($self->{dynmode_name})) { $self->version(); } if (defined($self->{list_mode})) { $self->list_mode(); } $self->{options}->set_sanity() if (!defined($self->{no_sanity_options})); # Output HELP $self->{options}->add_help(package => 'centreon::plugins::output', sections => 'OUTPUT OPTIONS'); $self->load_password_mgr(); # WSMAN $self->{wsman} = centreon::plugins::wsman->new(options => $self->{options}, output => $self->{output}); # Load mode if (defined($self->{mode_name}) && $self->{mode_name} ne '') { $self->is_mode(mode => $self->{mode_name}); centreon::plugins::misc::mymodule_load(output => $self->{output}, module => $self->{modes}{$self->{mode_name}}, error_msg => "Cannot load module --mode."); $self->{mode} = $self->{modes}{$self->{mode_name}}->new(options => $self->{options}, output => $self->{output}, mode => $self->{mode_name}); } elsif (defined($self->{dynmode_name}) && $self->{dynmode_name} ne '') { (undef, $self->{dynmode_name}) = centreon::plugins::misc::mymodule_load(output => $self->{output}, module => $self->{dynmode_name}, error_msg => "Cannot load module --dyn-mode."); $self->{mode} = $self->{dynmode_name}->new(options => $self->{options}, output => $self->{output}, mode => $self->{dynmode_name}); } else { $self->{output}->add_option_msg(short_msg => "Need to specify '--mode' or '--dyn-mode' option."); $self->{output}->option_exit(); } if (defined($options{help})) { $self->{options}->add_help(package => $self->{modes}{$self->{mode_name}}, sections => 'MODE'); $self->{options}->display_help(); $self->{output}->option_exit(); } if (defined($options{version})) { $self->{mode}->version(); $self->{output}->option_exit(nolabel => 1); } if (centreon::plugins::misc::minimal_version($self->{mode}->{version}, $self->{mode_version}) == 0) { $self->{output}->add_option_msg(short_msg => "Not good version for plugin mode. Excepted at least: " . $self->{mode_version} . ". Get: ". $self->{mode}->{version}); $self->{output}->option_exit(); } $self->{options}->parse_options(); $self->{option_results} = $self->{options}->get_options(); $self->{pass_mgr}->manage_options(option_results => $self->{option_results}) if (defined($self->{pass_mgr})); $self->{wsman}->check_options(option_results => $self->{option_results}); $self->{mode}->check_options( option_results => $self->{option_results}, default => $self->{default}, modes => $self->{modes} # for meta mode multi ); } sub load_password_mgr { my ($self, %options) = @_; return if (!defined($self->{option_results}->{pass_manager}) || $self->{option_results}->{pass_manager} eq ''); (undef, my $pass_mgr_name) = centreon::plugins::misc::mymodule_load( output => $self->{output}, module => "centreon::plugins::passwordmgr::" . $self->{option_results}->{pass_manager}, error_msg => "Cannot load module 'centreon::plugins::passwordmgr::" . $self->{option_results}->{pass_manager} . "'" ); $self->{pass_mgr} = $pass_mgr_name->new(options => $self->{options}, output => $self->{output}); } sub run { my $self = shift; if ($self->{output}->is_disco_format()) { $self->{mode}->disco_format(); $self->{output}->display_disco_format(); $self->{output}->exit(exit_litteral => 'ok'); } $self->{wsman}->connect(); if ($self->{output}->is_disco_show()) { $self->{mode}->disco_show(wsman => $self->{wsman}); $self->{output}->display_disco_show(); $self->{output}->exit(exit_litteral => 'ok'); } else { $self->{mode}->run(wsman => $self->{wsman}); } } sub is_mode { my ($self, %options) = @_; # $options->{mode} = mode if (!defined($self->{modes}{$options{mode}})) { $self->{output}->add_option_msg(short_msg => "mode '" . $options{mode} . "' doesn't exist (use --list-mode option to show available modes)."); $self->{output}->option_exit(); } } sub version { my $self = shift; $self->{output}->add_option_msg(short_msg => "Plugin Version: " . $self->{version}); $self->{output}->option_exit(nolabel => 1); } sub list_mode { my $self = shift; $self->{options}->display_help(); $self->{output}->add_option_msg(long_msg => 'Modes Meta:'); $self->{output}->add_option_msg(long_msg => ' multi'); $self->{output}->add_option_msg(long_msg => ''); $self->{output}->add_option_msg(long_msg => 'Modes Available:'); foreach (sort keys %{$self->{modes}}) { next if ($_ eq 'multi'); $self->{output}->add_option_msg(long_msg => ' ' . $_); } $self->{output}->option_exit(nolabel => 1); } 1; __END__ =head1 NAME - =head1 SYNOPSIS - =head1 GLOBAL OPTIONS =over 8 =item B<--mode> Choose a mode. =item B<--dyn-mode> Specify a mode with the path (separated by '::'). =item B<--list-mode> List available modes. =item B<--mode-version> Check minimal version of mode. If not, unknown error. =item B<--version> Display plugin version. =item B<--pass-manager> Use a password manager. =back =head1 DESCRIPTION B<>. =cut centreon-plugins-20220113/centreon/plugins/snmp.pm000066400000000000000000001101051417000230700220430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::snmp; use strict; use warnings; use SNMP; use Socket; use POSIX; sub new { my ($class, %options) = @_; my $self = {}; bless $self, $class; # $options{options} = options object # $options{output} = output object # $options{exit_value} = integer if (!defined($options{output})) { print "Class SNMP: Need to specify 'output' argument.\n"; exit 3; } if (!defined($options{options})) { $options{output}->add_option_msg(short_msg => "Class SNMP: Need to specify 'options' argument."); $options{output}->option_exit(); } if (!defined($options{noptions})) { $options{options}->add_options(arguments => { 'hostname|host:s' => { name => 'host' }, 'snmp-community:s' => { name => 'snmp_community', default => 'public' }, 'snmp-version:s' => { name => 'snmp_version', default => 1 }, 'snmp-port:s' => { name => 'snmp_port', default => 161 }, 'snmp-timeout:s' => { name => 'snmp_timeout', default => 1 }, 'snmp-retries:s' => { name => 'snmp_retries', default => 5 }, 'maxrepetitions:s' => { name => 'maxrepetitions', default => 50 }, 'subsetleef:s' => { name => 'subsetleef', default => 50 }, 'subsettable:s' => { name => 'subsettable', default => 100 }, 'snmp-autoreduce:s' => { name => 'snmp_autoreduce' }, 'snmp-force-getnext' => { name => 'snmp_force_getnext' }, 'snmp-username:s' => { name => 'snmp_security_name' }, 'authpassphrase:s' => { name => 'snmp_auth_passphrase' }, 'authprotocol:s' => { name => 'snmp_auth_protocol' }, 'privpassphrase:s' => { name => 'snmp_priv_passphrase' }, 'privprotocol:s' => { name => 'snmp_priv_protocol' }, 'contextname:s' => { name => 'snmp_context_name' }, 'contextengineid:s' => { name => 'snmp_context_engine_id' }, 'securityengineid:s' => { name => 'snmp_security_engine_id' }, 'snmp-errors-exit:s' => { name => 'snmp_errors_exit', default => 'unknown' }, }); $options{options}->add_help(package => __PACKAGE__, sections => 'SNMP OPTIONS'); } ##### $self->{session} = undef; $self->{output} = $options{output}; $self->{snmp_params} = {}; # Dont load MIB $SNMP::auto_init_mib = 0; $ENV{MIBS} = ''; # For snmpv v1 - get request retries when you have "NoSuchName" $self->{RetryNoSuch} = 1; # Dont try to translate OID (we keep value) $self->{UseNumeric} = 1; $self->{error_msg} = undef; $self->{error_status} = 0; return $self; } sub connect { my ($self, %options) = @_; $self->{snmp_params}->{RetryNoSuch} = $self->{RetryNoSuch}; $self->{snmp_params}->{UseNumeric} = $self->{UseNumeric}; if (!$self->{output}->is_litteral_status(status => $self->{snmp_errors_exit})) { $self->{output}->add_option_msg(short_msg => "Unknown value '" . $self->{snmp_errors_exit} . "' for --snmp-errors-exit."); $self->{output}->option_exit(exit_litteral => 'unknown'); } $self->{session} = new SNMP::Session(%{$self->{snmp_params}}); if (!defined($self->{session})) { if (defined($options{dont_quit}) && $options{dont_quit} == 1) { $self->set_error(error_status => -1, error_msg => 'SNMP Session : unable to create'); return 1; } $self->{output}->add_option_msg(short_msg => 'SNMP Session : unable to create'); $self->{output}->option_exit(exit_litteral => $self->{snmp_errors_exit}); } if ($self->{session}->{ErrorNum}) { if (defined($options{dont_quit}) && $options{dont_quit} == 1) { $self->set_error(error_status => -1, error_msg => 'SNMP Session : ' . $self->{session}->{ErrorStr}); return 1; } $self->{output}->add_option_msg(short_msg => 'SNMP Session : ' . $self->{session}->{ErrorStr}); $self->{output}->option_exit(exit_litteral => $self->{snmp_errors_exit}); } return 0; } sub load { my ($self, %options) = @_; # $options{oids} = ref to array of oids (example: ['.1.2', '.1.2']) # $options{instances} = ref to array of oids instances # $options{begin}, $args->{end} = integer instance end # $options{instance_regexp} = str # 3 way to use: with instances, with end, none if (defined($options{end})) { for (my $i = $options{begin}; $i <= $options{end}; $i++) { foreach (@{$options{oids}}) { push @{$self->{oids_loaded}}, $_ . "." . $i; } } return ; } if (defined($options{instances})) { $options{instance_regexp} = defined($options{instance_regexp}) ? $options{instance_regexp} : '(\d+)$'; foreach my $instance (@{$options{instances}}) { $instance =~ /$options{instance_regexp}/; foreach (@{$options{oids}}) { push @{$self->{oids_loaded}}, $_ . "." . $1; } } return ; } push @{$self->{oids_loaded}}, @{$options{oids}}; } sub autoreduce_table { my ($self, %options) = @_; return 1 if (defined($self->{snmp_force_getnext}) || $self->is_snmpv1()); if ($self->{snmp_params}->{Retries} > 1) { $self->{snmp_params}->{Retries} = 1; $self->connect(); } return 1 if (${$options{repeat_count}} == 1); ${$options{repeat_count}} = int(${$options{repeat_count}} / $self->{snmp_autoreduce_divisor}); ${$options{repeat_count}} = 1 if (${$options{repeat_count}} < 1); return 0; } sub autoreduce_multiple_table { my ($self, %options) = @_; if ($self->{snmp_params}->{Retries} > 1) { $self->{snmp_params}->{Retries} = 1; $self->connect(); } return 1 if (${$options{repeat_count}} == 1); ${$options{repeat_count}} = int(${$options{repeat_count}} / $self->{snmp_autoreduce_divisor}); $self->{subsettable} = int($self->{subsettable} / $self->{snmp_autoreduce_divisor}); ${$options{repeat_count}} = 1 if (${$options{repeat_count}} < 1); return 0; } sub autoreduce_leef { my ($self, %options) = @_; if ($self->{snmp_params}->{Retries} > 1) { $self->{snmp_params}->{Retries} = 1; $self->connect(); } return 1 if ($self->{subsetleef} == 1); $self->{subsetleef} = int($self->{subsetleef} / $self->{snmp_autoreduce_divisor}); $self->{subsetleef} = 1 if ($self->{subsetleef} < 1); my $array_ref = []; my $subset_current = 0; my $subset_construct = []; foreach ([@{$options{current}}], @{$self->{array_ref_ar}}) { foreach my $entry (@$_) {; push @$subset_construct, [$entry->[0], $entry->[1]]; $subset_current++; if ($subset_current == $self->{subsetleef}) { push @$array_ref, \@$subset_construct; $subset_construct = []; $subset_current = 0; } } } if ($subset_current) { push @$array_ref, \@$subset_construct; } $self->{array_ref_ar} = \@$array_ref; return 0; } sub get_leef { my ($self, %options) = @_; # $options{dont_quit} = integer # $options{nothing_quit} = integer # $options{oids} = ref to array of oids (example: ['.1.2', '.1.2']) # Returns array # 'undef' value for an OID means NoSuchValue my ($dont_quit) = (defined($options{dont_quit}) && $options{dont_quit} == 1) ? 1 : 0; my ($nothing_quit) = (defined($options{nothing_quit}) && $options{nothing_quit} == 1) ? 1 : 0; $self->set_error(); if (!defined($options{oids})) { if ($#{$self->{oids_loaded}} < 0) { if ($dont_quit == 1) { $self->set_error(error_status => -1, error_msg => "Need to specify OIDs"); return undef; } $self->{output}->add_option_msg(short_msg => 'Need to specify OIDs'); $self->{output}->option_exit(exit_litteral => $self->{snmp_errors_exit}); } push @{$options{oids}}, @{$self->{oids_loaded}}; @{$self->{oids_loaded}} = (); } my $results = {}; $self->{array_ref_ar} = []; my $subset_current = 0; my $subset_construct = []; foreach my $oid (@{$options{oids}}) { # Get last value next if ($oid !~ /(.*)\.(\d+)([\.\s]*)$/); my ($oid, $instance) = ($1, $2); $results->{$oid . "." . $instance} = undef; push @$subset_construct, [$oid, $instance]; $subset_current++; if ($subset_current == $self->{subsetleef}) { push @{$self->{array_ref_ar}}, \@$subset_construct; $subset_construct = []; $subset_current = 0; } } if ($subset_current) { push @{$self->{array_ref_ar}}, \@$subset_construct; } ############################ # If wrong oid with SNMP v1, packet resent (2 packets more). Not the case with SNMP > 1. # Can have "NoSuchName", if nothing works... # = v1: wrong oid # bless( [ # '.1.3.6.1.2.1.1.3', # '0', # '199720062', # 'TICKS' # ], 'SNMP::Varbind' ), # bless( [ # '.1.3.6.1.2.1.1.999', # '0' # ], 'SNMP::Varbind' ), # bless( [ # '.1.3.6.1.2.1.1', # '1000' # ], 'SNMP::Varbind' ) # > v1: wrong oid # bless( [ # '.1.3.6.1.2.1.1.3', # '0', # '199728713', # 'TICKS' # ], 'SNMP::Varbind' ), # bless( [ # '.1.3.6.1.2.1.1', # '3', # 'NOSUCHINSTANCE', # 'TICKS' # ], 'SNMP::Varbind' ) # bless( [ # '.1.3.6.1.2.1.1.999', # '0', # 'NOSUCHOBJECT', # 'NOSUCHOBJECT' # ], 'SNMP::Varbind' ), # bless( [ # '.1.3.6.1.2.1.1', # '1000', # 'NOSUCHOBJECT', # 'NOSUCHOBJECT' # ], 'SNMP::Varbind' ) ############################ my $total = 0; while (my $entry = shift(@{$self->{array_ref_ar}})) { my $vb = new SNMP::VarList(@{$entry}); $self->{session}->get($vb); if ($self->{session}->{ErrorNum}) { # 0 noError Pas d'erreurs. # 1 tooBig Reponse de taille trop grande. # 2 noSuchName Variable inexistante. # -24 Timeout if ($self->{session}->{ErrorNum} == 2) { # We are at the end with snmpv1. We next. next; } if ($self->{snmp_autoreduce} == 1 && ($self->{session}->{ErrorNum} == 1 || $self->{session}->{ErrorNum} == 5 || $self->{session}->{ErrorNum} == -24)) { next if ($self->autoreduce_leef(current => $entry) == 0); } my $msg = 'SNMP GET Request : ' . $self->{session}->{ErrorStr}; if ($dont_quit == 0) { $self->{output}->add_option_msg(short_msg => $msg); $self->{output}->option_exit(exit_litteral => $self->{snmp_errors_exit}); } $self->set_error(error_status => -1, error_msg => $msg); return undef; } # Some equipments gives a partial response and no error. # We look the last value if it's empty or not # In snmpv1 we have the retryNoSuch if (((scalar(@$vb) != scalar(@{$entry})) || (scalar(@{@$vb[-1]}) < 3)) && !$self->is_snmpv1()) { next if ($self->{snmp_autoreduce} == 1 && $self->autoreduce_leef(current => $entry) == 0); if ($dont_quit == 0) { $self->{output}->add_option_msg(short_msg => 'SNMP partial response. Please try --snmp-autoreduce option'); $self->{output}->option_exit(exit_litteral => $self->{snmp_errors_exit}); } $self->set_error(error_status => -1, error_msg => 'SNMP partial response'); return undef; } foreach my $entry (@$vb) { if ($#$entry < 3) { # Can be snmpv1 not find next; } if (${$entry}[2] eq 'NOSUCHOBJECT' || ${$entry}[2] eq 'NOSUCHINSTANCE') { # Error in snmp > 1 next; } $total++; $results->{${$entry}[0] . "." . ${$entry}[1]} = ${$entry}[2]; } } if ($nothing_quit == 1 && $total == 0) { $self->{output}->add_option_msg(short_msg => 'SNMP GET Request : Cant get a single value.'); $self->{output}->option_exit(exit_litteral => $self->{snmp_errors_exit}); } return $results; } sub multiple_find_bigger { my ($self, %options) = @_; my $getting = {}; my @values = (); foreach my $key (keys %{$options{working_oids}}) { push @values, $options{working_oids}->{$key}->{start}; $getting->{ $options{working_oids}->{$key}->{start} } = $key; } @values = $self->oid_lex_sort(@values); return $getting->{pop(@values)}; } sub get_multiple_table { my ($self, %options) = @_; # $options{dont_quit} = integer # $options{oids} = refs array # [ { oid => 'x.x.x.x', start => '', end => ''}, { oid => 'y.y.y.y', start => '', end => ''} ] # $options{return_type} = integer my ($return_type) = (defined($options{return_type}) && $options{return_type} == 1) ? 1 : 0; my ($dont_quit) = (defined($options{dont_quit}) && $options{dont_quit} == 1) ? 1 : 0; my ($nothing_quit) = (defined($options{nothing_quit}) && $options{nothing_quit} == 1) ? 1 : 0; $self->set_error(); my $working_oids = {}; my $results = {}; # Check overlap foreach my $entry (@{$options{oids}}) { # Transform asking if ($entry->{oid} !~ /(.*)\.(\d+)([\.\s]*)$/) { if ($dont_quit == 1) { $self->set_error(error_status => -1, error_msg => "Method 'get_multiple_table': Wrong OID '" . $entry->{oid} . "'."); return undef; } $self->{output}->add_option_msg(short_msg => "Method 'get_multiple_table': Wrong OID '" . $entry->{oid} . "'."); $self->{output}->option_exit(exit_litteral => $self->{snmp_errors_exit}); } if (defined($entry->{start})) { $working_oids->{$entry->{oid}} = { start => $entry->{start}, end => $entry->{end} }; # last in it } else { $working_oids->{$entry->{oid}} = { start => $entry->{oid}, end => $entry->{end} }; } if ($return_type == 0) { $results->{$entry->{oid}} = {}; } } # we use a medium (UDP have a PDU limit. SNMP protcol cant send multiples for one request) # So we need to manage # It's for "bulk". We ask 50 next values. If you set 1, it's like a getnext (snmp v1) my $repeat_count = 50; if (defined($self->{maxrepetitions}) && $self->{maxrepetitions} =~ /^\d+$/) { $repeat_count = $self->{maxrepetitions}; } # Quit if base not the same or 'ENDOFMIBVIEW' value. Need all oid finish otherwise we continue :) while (1) { my $current_oids = 0; my @bindings = (); my @bases = (); foreach my $key (keys %{$working_oids}) { $working_oids->{$key}->{start} =~ /(.*)\.(\d+)([\.\s]*)$/; push @bindings, [$1, $2]; push @bases, $key; $current_oids++; last if ($current_oids > $self->{subsettable}); } # Nothing more to check. We quit last if ($current_oids == 0); my $vb = new SNMP::VarList(@bindings); if ($self->is_snmpv1() || defined($self->{snmp_force_getnext})) { $self->{session}->getnext($vb); } else { my $current_repeat_count = floor($repeat_count / $current_oids); $current_repeat_count = 1 if ($current_repeat_count == 0); $self->{session}->getbulk(0, $current_repeat_count, $vb); } # Error if ($self->{session}->{ErrorNum}) { # 0 noError Pas d'erreurs. # 1 tooBig Reponse de taille trop grande. # 2 noSuchName Variable inexistante. if ($self->{session}->{ErrorNum} == 2) { # We are at the end with snmpv1. Need to find the most up oid ;) my $oid_base = $self->multiple_find_bigger(working_oids => $working_oids); delete $working_oids->{$oid_base}; next; } if ($self->{snmp_autoreduce} == 1 && ($self->{session}->{ErrorNum} == 1 || $self->{session}->{ErrorNum} == 5 || $self->{session}->{ErrorNum} == -24)) { next if ($self->autoreduce_multiple_table(repeat_count => \$repeat_count) == 0); } my $msg = 'SNMP Table Request : ' . $self->{session}->{ErrorStr}; if ($dont_quit == 0) { $self->{output}->add_option_msg(short_msg => $msg); $self->{output}->option_exit(exit_litteral => $self->{snmp_errors_exit}); } $self->set_error(error_status => -1, error_msg => $msg); return undef; } # Manage # step by step: [ 1 => 1, 2 => 1, 3 => 1 ], [ 1 => 2, 2 => 2, 3 => 2 ],... my $pos = -1; foreach my $entry (@$vb) { $pos++; # Already destruct. we continue next if (!defined($working_oids->{ $bases[$pos % $current_oids] })); # ENDOFMIBVIEW is on each iteration. So we need to delete and skip after that if (${$entry}[2] eq 'ENDOFMIBVIEW') { delete $working_oids->{ $bases[$pos % $current_oids] }; # END mib next; } # Not in same table my $complete_oid = ${$entry}[0] . "." . ${$entry}[1]; my $base = $bases[$pos % $current_oids]; if ($complete_oid !~ /^$base\./ || (defined($working_oids->{ $bases[$pos % $current_oids] }->{end}) && $self->check_oid_up(current => $complete_oid, end => $working_oids->{ $bases[$pos % $current_oids] }->{end}))) { delete $working_oids->{ $bases[$pos % $current_oids] }; next; } if ($return_type == 0) { $results->{$bases[$pos % $current_oids]}->{$complete_oid} = ${$entry}[2]; } else { $results->{$complete_oid} = ${$entry}[2]; } $working_oids->{ $bases[$pos % $current_oids] }->{start} = $complete_oid; } # infinite loop. Some equipments it returns nothing!!?? if ($pos == -1) { $self->{output}->add_option_msg(short_msg => 'SNMP Table Request: problem to get values (try --snmp-force-getnext option)'); $self->{output}->option_exit(exit_litteral => $self->{snmp_errors_exit}); } } my $total = 0; if ($nothing_quit == 1) { if ($return_type == 1) { $total = scalar(keys %{$results}); } else { foreach (keys %{$results}) { $total += scalar(keys %{$results->{$_}}); } } if ($total == 0) { $self->{output}->add_option_msg(short_msg => 'SNMP Table Request: Cant get a single value.'); $self->{output}->option_exit(exit_litteral => $self->{snmp_errors_exit}); } } return $results; } sub get_table { my ($self, %options) = @_; # $options{dont_quit} = integer # $options{oid} = string (example: '.1.2') # $options{start} = string (example: '.1.2') # $options{end} = string (example: '.1.2') my ($dont_quit) = (defined($options{dont_quit}) && $options{dont_quit} == 1) ? 1 : 0; my ($nothing_quit) = (defined($options{nothing_quit}) && $options{nothing_quit} == 1) ? 1 : 0; $self->set_error(); if (defined($options{start})) { $options{start} = $self->clean_oid($options{start}); } if (defined($options{end})) { $options{end} = $self->clean_oid($options{end}); } # we use a medium (UDP have a PDU limit. SNMP protcol cant send multiples for one request) # So we need to manage # It's for "bulk". We ask 50 next values. If you set 1, it's like a getnext (snmp v1) my $repeat_count = 50; if (defined($self->{maxrepetitions}) && $self->{maxrepetitions} =~ /^\d+$/) { $repeat_count = $self->{maxrepetitions}; } # Transform asking if ($options{oid} !~ /(.*)\.(\d+)([\.\s]*)$/) { if ($dont_quit == 1) { $self->set_error(error_status => -1, error_msg => "Method 'get_table': Wrong OID '" . $options{oid} . "'."); return undef; } $self->{output}->add_option_msg(short_msg => "Method 'get_table': Wrong OID '" . $options{oid} . "'."); $self->{output}->option_exit(exit_litteral => $self->{snmp_errors_exit}); } my $main_indice = $1 . "." . $2; my $results = {}; # Quit if base not the same or 'ENDOFMIBVIEW' value my $leave = 1; my $last_oid; if (defined($options{start})) { $last_oid = $options{start}; } else { $last_oid = $options{oid}; } while ($leave) { $last_oid =~ /(.*)\.(\d+)([\.\s]*)$/; my $vb = new SNMP::VarList([$1, $2]); if ($self->is_snmpv1() || defined($self->{snmp_force_getnext})) { $self->{session}->getnext($vb); } else { $self->{session}->getbulk(0, $repeat_count, $vb); } # Error if ($self->{session}->{ErrorNum}) { # 0 noError Pas d'erreurs. # 1 tooBig Reponse de taille trop grande. # 2 noSuchName Variable inexistante. # -24 Timeout if ($self->{session}->{ErrorNum} == 2) { # We are at the end with snmpv1. We quit. last; } if ($self->{snmp_autoreduce} == 1 && ($self->{session}->{ErrorNum} == 1 || $self->{session}->{ErrorNum} == 5 || $self->{session}->{ErrorNum} == -24)) { next if ($self->autoreduce_table(repeat_count => \$repeat_count) == 0); } my $msg = 'SNMP Table Request : ' . $self->{session}->{ErrorStr}; if ($dont_quit == 0) { $self->{output}->add_option_msg(short_msg => $msg); $self->{output}->option_exit(exit_litteral => $self->{snmp_errors_exit}); } $self->set_error(error_status => -1, error_msg => $msg); return undef; } # Manage foreach my $entry (@$vb) { if (${$entry}[2] eq 'ENDOFMIBVIEW') { # END mib $leave = 0; last; } # Not in same table my $complete_oid = ${$entry}[0] . "." . ${$entry}[1]; if ($complete_oid !~ /^$main_indice\./ || (defined($options{end}) && $self->check_oid_up(current => $complete_oid, end => $options{end}))) { $leave = 0; last; } $results->{$complete_oid} = ${$entry}[2]; $last_oid = $complete_oid; } } if ($nothing_quit == 1 && scalar(keys %$results) == 0) { $self->{output}->add_option_msg(short_msg => 'SNMP Table Request: Cant get a single value.'); $self->{output}->option_exit(exit_litteral => $self->{snmp_errors_exit}); } return $results; } sub set { my ($self, %options) = @_; # $options{dont_quit} = integer # $options{oids} = ref to hash table my ($dont_quit) = (defined($options{dont_quit}) && $options{dont_quit} == 1) ? 1 : 0; $self->set_error(); my $vars = []; foreach my $oid (keys %{$options{oids}}) { # Get last value next if ($oid !~ /(.*)\.(\d+)([\.\s]*)$/); my $value = $options{oids}->{$oid}->{value}; my $type = $options{oids}->{$oid}->{type}; my ($oid, $instance) = ($1, $2); push @$vars, [$oid, $instance, $value, $type]; } $self->{session}->set($vars); if ($self->{session}->{ErrorNum}) { # 0 noError Pas d'erreurs. # 1 tooBig Reponse de taille trop grande. # 2 noSuchName Variable inexistante. my $msg = 'SNMP SET Request : ' . $self->{session}->{ErrorStr}; if ($dont_quit == 0) { $self->{output}->add_option_msg(short_msg => $msg); $self->{output}->option_exit(exit_litteral => $self->{snmp_errors_exit}); } $self->set_error(error_status => -1, error_msg => $msg); return undef; } return 0; } sub is_snmpv1 { my ($self) = @_; if ($self->{snmp_params}->{Version} eq '1') { return 1; } return 0; } sub clean_oid { my ($self, $oid) = @_; $oid =~ s/\.$//; $oid =~ s/^(\d)/\.$1/; return $oid; } sub check_oid_up { my ($self, %options) = @_; my $current_oid = $options{current}; my $end_oid = $options{end}; my @current_oid_splitted = split /\./, $current_oid; my @end_oid_splitted = split /\./, $end_oid; # Skip first value (before first '.' empty) for (my $i = 1; $i <= $#current_oid_splitted && $i <= $#end_oid_splitted; $i++) { if (int($current_oid_splitted[$i]) > int($end_oid_splitted[$i])) { return 1; } } return 0; } sub check_options { my ($self, %options) = @_; # $options{option_results} = ref to options result if (!defined($options{option_results}->{host})) { $self->{output}->add_option_msg(short_msg => 'Missing parameter --hostname.'); $self->{output}->option_exit(); } $options{option_results}->{snmp_version} =~ s/^v//; if ($options{option_results}->{snmp_version} !~ /1|2c|2|3/) { $self->{output}->add_option_msg(short_msg => 'Unknown snmp version.'); $self->{output}->option_exit(); } $self->{snmp_force_getnext} = $options{option_results}->{snmp_force_getnext}; $self->{maxrepetitions} = $options{option_results}->{maxrepetitions}; $self->{subsetleef} = (defined($options{option_results}->{subsetleef}) && $options{option_results}->{subsetleef} =~ /^[0-9]+$/) ? $options{option_results}->{subsetleef} : 50; $self->{subsettable} = (defined($options{option_results}->{subsettable}) && $options{option_results}->{subsettable} =~ /^[0-9]+$/) ? $options{option_results}->{subsettable} : 100; $self->{snmp_errors_exit} = $options{option_results}->{snmp_errors_exit}; $self->{snmp_autoreduce} = 0; $self->{snmp_autoreduce_divisor} = 2; if (defined($options{option_results}->{snmp_autoreduce})) { $self->{snmp_autoreduce} = 1; $self->{snmp_autoreduce_divisor} = $1 if ($options{option_results}->{snmp_autoreduce} =~ /(\d+(\.\d+)?)/ && $1 > 1); } %{$self->{snmp_params}} = ( DestHost => $options{option_results}->{host}, Community => $options{option_results}->{snmp_community}, Version => $options{option_results}->{snmp_version}, RemotePort => $options{option_results}->{snmp_port}, Retries => 5 ); if (defined($options{option_results}->{snmp_timeout}) && $options{option_results}->{snmp_timeout} =~ /^[0-9]+$/) { $self->{snmp_params}->{Timeout} = $options{option_results}->{snmp_timeout} * (10**6); } if (defined($options{option_results}->{snmp_retries}) && $options{option_results}->{snmp_retries} =~ /^[0-9]+$/) { $self->{snmp_params}->{Retries} = $options{option_results}->{snmp_retries}; } if ($options{option_results}->{snmp_version} eq '3') { delete $self->{snmp_params}->{Community}; $self->{snmp_params}->{Context} = $options{option_results}->{snmp_context_name} if (defined($options{option_results}->{snmp_context_name})); $self->{snmp_params}->{ContextEngineId} = $options{option_results}->{snmp_context_engine_id} if (defined($options{option_results}->{snmp_context_engine_id})); $self->{snmp_params}->{SecEngineId} = $options{option_results}->{snmp_security_engine_id} if (defined($options{option_results}->{snmp_security_engine_id})); $self->{snmp_params}->{SecName} = $options{option_results}->{snmp_security_name} if (defined($options{option_results}->{snmp_security_name})); # Certificate SNMPv3. Need net-snmp > 5.6 if ($options{option_results}->{host} =~ /^(dtls|tls|ssh).*:/) { $self->{snmp_params}->{OurIdentity} = $options{option_results}->{snmp_our_identity} if (defined($options{option_results}->{snmp_our_identity})); $self->{snmp_params}->{TheirIdentity} = $options{option_results}->{snmp_their_identity} if (defined($options{option_results}->{snmp_their_identity})); $self->{snmp_params}->{TheirHostname} = $options{option_results}->{snmp_their_hostname} if (defined($options{option_results}->{snmp_their_hostname})); $self->{snmp_params}->{TrustCert} = $options{option_results}->{snmp_trust_cert} if (defined($options{option_results}->{snmp_trust_cert})); $self->{snmp_params}->{SecLevel} = 'authPriv'; return ; } if (!defined($options{option_results}->{snmp_security_name}) || $options{option_results}->{snmp_security_name} eq '') { $self->{output}->add_option_msg(short_msg => 'Missing parameter Security Name.'); $self->{output}->option_exit(); } # unauthenticated and unencrypted $self->{snmp_params}->{SecLevel} = 'noAuthNoPriv'; my $user_activate = 0; if (defined($options{option_results}->{snmp_auth_passphrase}) && $options{option_results}->{snmp_auth_passphrase} ne '') { if (!defined($options{option_results}->{snmp_auth_protocol})) { $self->{output}->add_option_msg(short_msg => 'Missing parameter authenticate protocol.'); $self->{output}->option_exit(); } $options{option_results}->{snmp_auth_protocol} = uc($options{option_results}->{snmp_auth_protocol}); if ($options{option_results}->{snmp_auth_protocol} !~ /^(?:MD5|SHA|SHA224|SHA256|SHA384|SHA512)$/) { $self->{output}->add_option_msg(short_msg => 'Wrong authentication protocol.'); $self->{output}->option_exit(); } $self->{snmp_params}->{SecLevel} = 'authNoPriv'; $self->{snmp_params}->{AuthProto} = $options{option_results}->{snmp_auth_protocol}; $self->{snmp_params}->{AuthPass} = $options{option_results}->{snmp_auth_passphrase}; $user_activate = 1; } if (defined($options{option_results}->{snmp_priv_passphrase}) && $options{option_results}->{snmp_priv_passphrase} ne '') { if (!defined($options{option_results}->{snmp_priv_protocol})) { $self->{output}->add_option_msg(short_msg => 'Missing parameter privacy protocol.'); $self->{output}->option_exit(); } $options{option_results}->{snmp_priv_protocol} = uc($options{option_results}->{snmp_priv_protocol}); if ($options{option_results}->{snmp_priv_protocol} !~ /^(?:DES|AES|AES192|AES192C|AES256|AES256C)$/) { $self->{output}->add_option_msg(short_msg => 'Wrong privacy protocol.'); $self->{output}->option_exit(); } if ($user_activate == 0) { $self->{output}->add_option_msg(short_msg => 'Cannot use snmp v3 privacy option without snmp v3 authentification options.'); $self->{output}->option_exit(); } $self->{snmp_params}->{SecLevel} = 'authPriv'; $self->{snmp_params}->{PrivPass} = $options{option_results}->{snmp_priv_passphrase}; $self->{snmp_params}->{PrivProto} = $options{option_results}->{snmp_priv_protocol}; } } } sub set_snmp_connect_params { my ($self, %options) = @_; foreach (keys %options) { $self->{snmp_params}->{$_} = $options{$_}; } } sub set_snmp_params { my ($self, %options) = @_; foreach (keys %options) { $self->{$_} = $options{$_}; } } sub set_error { my ($self, %options) = @_; # $options{error_msg} = string error # $options{error_status} = integer status $self->{error_status} = defined($options{error_status}) ? $options{error_status} : 0; $self->{error_msg} = defined($options{error_msg}) ? $options{error_msg} : undef; } sub error_status { my ($self) = @_; return $self->{error_status}; } sub error { my ($self) = @_; return $self->{error_msg}; } sub get_hostname { my ($self) = @_; my $host = $self->{snmp_params}->{DestHost}; $host =~ s/.*://; return $host; } sub get_port { my ($self) = @_; return $self->{snmp_params}->{RemotePort}; } sub map_instance { my ($self, %options) = @_; my $results = {}; my $instance = ''; $instance = '.' . $options{instance} if (defined($options{instance})); foreach my $name (keys %{$options{mapping}}) { my $entry = $options{mapping}->{$name}->{oid} . $instance; if (defined($options{results}->{$entry})) { $results->{$name} = $options{results}->{$entry}; } elsif (defined($options{results}->{$options{mapping}->{$name}->{oid}}->{$entry})) { $results->{$name} = $options{results}->{$options{mapping}->{$name}->{oid}}->{$entry}; } else { $results->{$name} = defined($options{default}) ? $options{default} : undef; } if (defined($options{mapping}->{$name}->{map})) { if (defined($results->{$name})) { $results->{$name} = defined($options{mapping}->{$name}->{map}->{$results->{$name}}) ? $options{mapping}->{$name}->{map}->{$results->{$name}} : (defined($options{default}) ? $options{default} : 'unknown'); } } } return $results; } sub oid_lex_sort { my $self = shift; if (@_ <= 1) { return @_; } return map { $_->[0] } sort { $a->[1] cmp $b->[1] } map { my $oid = $_; $oid =~ s/^\.//; $oid =~ s/ /\.0/g; [$_, pack 'N*', split m/\./, $oid] } @_; } 1; __END__ =head1 NAME SNMP global =head1 SYNOPSIS snmp class =head1 SNMP OPTIONS =over 8 =item B<--hostname> Hostname to query (required). =item B<--snmp-community> Read community (defaults to public). =item B<--snmp-version> Version: 1 for SNMP v1 (default), 2 for SNMP v2c, 3 for SNMP v3. =item B<--snmp-port> Port (default: 161). =item B<--snmp-timeout> Timeout in secondes (default: 1) before retries. =item B<--snmp-retries> Set the number of retries (default: 5) before failure. =item B<--maxrepetitions> Max repetitions value (default: 50) (only for SNMP v2 and v3). =item B<--subsetleef> How many oid values per SNMP request (default: 50) (for get_leef method. Be cautious whe you set it. Prefer to let the default value). =item B<--snmp-autoreduce> Auto reduce SNMP request size in case of SNMP errors (By default, the divisor is 2). =item B<--snmp-force-getnext> Use snmp getnext function (even in snmp v2c and v3). =item B<--snmp-username> Security name (only for SNMP v3). =item B<--authpassphrase> Authentication protocol pass phrase. =item B<--authprotocol> Authentication protocol: MD5|SHA. Since net-snmp 5.9.1: SHA224|SHA256|SHA384|SHA512. =item B<--privpassphrase> Privacy protocol pass phrase =item B<--privprotocol> Privacy protocol: DES|AES. Since net-snmp 5.9.1: AES192|AES192C|AES256|AES256C. =item B<--contextname> Context name =item B<--contextengineid> Context engine ID =item B<--securityengineid> Security engine ID =item B<--snmp-errors-exit> Exit code for SNMP Errors (default: unknown) =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/centreon/plugins/ssh.pm000066400000000000000000000075411417000230700216740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::ssh; use strict; use warnings; sub new { my ($class, %options) = @_; my $self = {}; bless $self, $class; if (!defined($options{noptions}) || $options{noptions} != 1) { $options{options}->add_options(arguments => { 'ssh-backend:s' => { name => 'ssh_backend', default => 'sshcli' }, 'ssh-port:s' => { name => 'ssh_port' }, 'ssh-priv-key:s' => { name => 'ssh_priv_key' }, 'ssh-username:s' => { name => 'ssh_username' }, 'ssh-password:s' => { name => 'ssh_password' } }); $options{options}->add_help(package => __PACKAGE__, sections => 'SSH GLOBAL OPTIONS'); } centreon::plugins::misc::mymodule_load( output => $options{output}, module => 'centreon::plugins::backend::ssh::sshcli', error_msg => "Cannot load module 'centreon::plugins::backend::ssh::sshcli'." ); $self->{backend_sshcli} = centreon::plugins::backend::ssh::sshcli->new(%options); centreon::plugins::misc::mymodule_load( output => $options{output}, module => 'centreon::plugins::backend::ssh::plink', error_msg => "Cannot load module 'centreon::plugins::backend::ssh::plink'." ); $self->{backend_plink} = centreon::plugins::backend::ssh::plink->new(%options); centreon::plugins::misc::mymodule_load( output => $options{output}, module => 'centreon::plugins::backend::ssh::libssh', error_msg => "Cannot load module 'centreon::plugins::backend::ssh::libssh'." ); $self->{backend_libssh} = centreon::plugins::backend::ssh::libssh->new(%options); $self->{output} = $options{output}; return $self; } sub check_options { my ($self, %options) = @_; $self->{ssh_backend} = $options{option_results}->{ssh_backend}; $self->{ssh_port} = defined($options{option_results}->{ssh_port}) && $options{option_results}->{ssh_port} =~ /(\d+)/ ? $1 : 22; $self->{ssh_backend} = 'sshcli' if (!defined($options{option_results}->{ssh_backend}) || $options{option_results}->{ssh_backend} eq ''); if (!defined($self->{'backend_' . $self->{ssh_backend}})) { $self->{output}->add_option_msg(short_msg => 'unknown ssh backend: ' . $self->{ssh_backend}); $self->{output}->option_exit(); } $self->{'backend_' . $self->{ssh_backend}}->check_options(%options); } sub get_port { my ($self, %options) = @_; return $self->{ssh_port}; } sub execute { my ($self, %options) = @_; return $self->{'backend_' . $self->{ssh_backend}}->execute(%options); } 1; __END__ =head1 NAME SSH abstraction layer. =head1 SYNOPSIS SSH abstraction layer for sscli, plink and libssh backends =head1 SSH GLOBAL OPTIONS =over 8 =item B<--ssh-backend> Set the backend used (Default: 'sshcli') Can be: sshcli, plink, libssh. =item B<--ssh-username> Connect with specified username. =item B<--ssh-password> Login with specified password. Cannot be used with sshcli backend. =item B<--ssh-port> Connect to specified port. =item B<--ssh-priv-key> Private key file for user authentication. =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/centreon/plugins/statefile.pm000066400000000000000000000260611417000230700230550ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::statefile; use strict; use warnings; use Data::Dumper; use vars qw($datas); use centreon::plugins::misc; my $default_dir = '/var/lib/centreon/centplugins'; if ($^O eq 'MSWin32') { $default_dir = 'C:/Windows/Temp'; } sub new { my ($class, %options) = @_; my $self = {}; bless $self, $class; if (defined($options{options})) { $options{options}->add_options(arguments => { 'memcached:s' => { name => 'memcached' }, 'redis-server:s' => { name => 'redis_server' }, 'redis-attribute:s%' => { name => 'redis_attribute' }, 'redis-db:s' => { name => 'redis_db' }, 'memexpiration:s' => { name => 'memexpiration', default => 86400 }, 'statefile-dir:s' => { name => 'statefile_dir', default => $default_dir }, 'statefile-suffix:s' => { name => 'statefile_suffix', default => '' }, 'statefile-concat-cwd' => { name => 'statefile_concat_cwd' }, 'statefile-storable' => { name => 'statefile_storable' }, 'failback-file' => { name => 'failback_file' } }); $options{options}->add_help(package => __PACKAGE__, sections => 'RETENTION OPTIONS', once => 1); } $self->{error} = 0; $self->{output} = $options{output}; $self->{datas} = {}; $self->{storable} = 0; $self->{memcached_ok} = 0; $self->{memcached} = undef; $self->{statefile_dir} = undef; $self->{statefile_suffix} = undef; return $self; } sub check_options { my ($self, %options) = @_; if (defined($options{option_results}) && defined($options{option_results}->{memcached})) { centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'Memcached::libmemcached', error_msg => "Cannot load module 'Memcached::libmemcached'." ); $self->{memcached} = Memcached::libmemcached->new(); Memcached::libmemcached::memcached_server_add($self->{memcached}, $options{option_results}->{memcached}); } # Check redis if (defined($options{option_results}->{redis_server})) { $self->{redis_attributes} = ''; if (defined($options{option_results}->{redis_attribute})) { foreach (keys %{$options{option_results}->{redis_attribute}}) { $self->{redis_attributes} .= "$_ => " . $options{option_results}->{redis_attribute}->{$_} . ', '; } } centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'Redis', error_msg => "Cannot load module 'Redis'." ); eval { $options{option_results}->{redis_server} .= ':6379' if ($options{option_results}->{redis_server} !~ /:\d+$/); $self->{redis_cnx} = Redis->new( server => $options{option_results}->{redis_server}, eval $self->{redis_attributes} ); if (defined($self->{redis_cnx}) && defined($options{option_results}->{redis_db}) && $options{option_results}->{redis_db} ne '' ) { $self->{redis_cnx}->select($options{option_results}->{redis_db}); } }; if (!defined($self->{redis_cnx}) && !defined($options{option_results}->{failback_file})) { $self->{output}->add_option_msg(short_msg => "redis connection issue: $@"); $self->{output}->option_exit(); } } $self->{statefile_dir} = $options{option_results}->{statefile_dir}; if ($self->{statefile_dir} ne $default_dir && defined($options{option_results}->{statefile_concat_cwd})) { centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'Cwd', error_msg => "Cannot load module 'Cwd'." ); $self->{statefile_dir} = Cwd::cwd() . '/' . $self->{statefile_dir}; } if (defined($options{option_results}->{statefile_storable})) { centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'Storable', error_msg => "Cannot load module 'Storable'." ); $self->{storable} = 1; } $self->{statefile_suffix} = $options{option_results}->{statefile_suffix}; $self->{memexpiration} = $options{option_results}->{memexpiration}; } sub error { my ($self) = shift; if (@_) { $self->{error} = $_[0]; } return $self->{error}; } sub read { my ($self, %options) = @_; $self->{statefile_suffix} = defined($options{statefile_suffix}) ? $options{statefile_suffix} : $self->{statefile_suffix}; $self->{statefile_dir} = defined($options{statefile_dir}) ? $options{statefile_dir} : $self->{statefile_dir}; $self->{statefile} = defined($options{statefile}) ? $options{statefile} . $self->{statefile_suffix} : $self->{statefile}; $self->{no_quit} = defined($options{no_quit}) && $options{no_quit} == 1 ? 1 : 0; if (defined($self->{memcached})) { # if "SUCCESS" or "NOT FOUND" is ok. Other with use the file my $val = Memcached::libmemcached::memcached_get($self->{memcached}, $self->{statefile_dir} . '/' . $self->{statefile}); if (defined($self->{memcached}->errstr) && $self->{memcached}->errstr =~ /^SUCCESS|NOT FOUND$/i) { $self->{memcached_ok} = 1; if (defined($val)) { eval( $val ); $self->{datas} = $datas; $datas = {}; return 1; } return 0; } } if (defined($self->{redis_cnx})) { my $val = $self->{redis_cnx}->get($self->{statefile_dir} . "/" . $self->{statefile}); if (defined($val)) { eval($val); $self->{datas} = $datas; $datas = {}; return 1; } return 0; } if (! -e $self->{statefile_dir} . '/' . $self->{statefile}) { if (! -w $self->{statefile_dir} || ! -x $self->{statefile_dir}) { $self->error(1); $self->{output}->add_option_msg(short_msg => "Cannot write statefile '" . $self->{statefile_dir} . "/" . $self->{statefile} . "'. Need write/exec permissions on directory."); if ($self->{no_quit} == 0) { $self->{output}->option_exit(); } } return 0; } elsif (! -w $self->{statefile_dir} . '/' . $self->{statefile}) { $self->error(1); $self->{output}->add_option_msg(short_msg => "Cannot write statefile '" . $self->{statefile_dir} . "/" . $self->{statefile} . "'. Need write permissions on file."); if ($self->{no_quit} == 0) { $self->{output}->option_exit(); } return 1; } elsif (! -s $self->{statefile_dir} . '/' . $self->{statefile}) { # Empty file. Not a problem. Maybe plugin not manage not values return 0; } if ($self->{storable} == 1) { open FILE, '<', $self->{statefile_dir} . '/' . $self->{statefile}; eval { $self->{datas} = Storable::fd_retrieve(*FILE); }; # File is corrupted surely. We'll reset it if ($@) { close FILE; return 0; } close FILE; } else { unless (my $return = do $self->{statefile_dir} . '/' . $self->{statefile}) { # File is corrupted surely. We'll reset it return 0; #if ($@) { # $self->{output}->add_option_msg(short_msg => "Couldn't parse '" . $self->{statefile_dir} . "/" . $self->{statefile} . "': $@"); # $self->{output}->option_exit(); #} #unless (defined($return)) { # $self->{output}->add_option_msg(short_msg => "Couldn't do '" . $self->{statefile_dir} . "/" . $self->{statefile} . "': $!"); # $self->{output}->option_exit(); #} #unless ($return) { # $self->{output}->add_option_msg(short_msg => "Couldn't run '" . $self->{statefile_dir} . "/" . $self->{statefile} . "': $!"); # $self->{output}->option_exit(); } $self->{datas} = $datas; $datas = {}; } return 1; } sub get_string_content { my ($self, %options) = @_; return Data::Dumper::Dumper($self->{datas}); } sub get { my ($self, %options) = @_; if (defined($self->{datas}->{$options{name}})) { return $self->{datas}->{$options{name}}; } return undef; } sub write { my ($self, %options) = @_; if ($self->{memcached_ok} == 1) { Memcached::libmemcached::memcached_set( $self->{memcached}, $self->{statefile_dir} . '/' . $self->{statefile}, Data::Dumper->Dump([$options{data}], ['datas']), $self->{memexpiration} ); if (defined($self->{memcached}->errstr) && $self->{memcached}->errstr =~ /^SUCCESS$/i) { return ; } } if (defined($self->{redis_cnx})) { return if (defined($self->{redis_cnx}->set( $self->{statefile_dir} . '/' . $self->{statefile}, Data::Dumper->Dump([$options{data}], ['datas']), 'EX', $self->{memexpiration})) ); } open FILE, '>', $self->{statefile_dir} . '/' . $self->{statefile}; if ($self->{storable} == 1) { Storable::store_fd($options{data}, *FILE); } else { print FILE Data::Dumper->Dump([$options{data}], ['datas']); } close FILE; } 1; __END__ =head1 NAME Statefile class =head1 SYNOPSIS - =head1 RETENTION OPTIONS =over 8 =item B<--memcached> Memcached server to use (only one server). =item B<--redis-server> Redis server to use (only one server). SYntax: address[:port] =item B<--redis-attribute> Set Redis Options (--redis-attribute="cnx_timeout=5"). =item B<--redis-db> Set Redis database index. =item B<--failback-file> Failback on a local file if redis connection failed. =item B<--memexpiration> Time to keep data in seconds (Default: 86400). =item B<--statefile-dir> Directory for statefile (Default: '/var/lib/centreon/centplugins'). =item B<--statefile-suffix> Add a suffix for the statefile name (Default: ''). =item B<--statefile-concat-cwd> Concat current working directory with option '--statefile-dir'. Useful on Windows when plugin is compiled. =item B<--statefile-storable> Use Perl Module 'Storable' (instead Data::Dumper) to store datas. =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/centreon/plugins/templates/000077500000000000000000000000001417000230700225305ustar00rootroot00000000000000centreon-plugins-20220113/centreon/plugins/templates/catalog_functions.pm000066400000000000000000000070221417000230700265710ustar00rootroot00000000000000# # Copyright 2018 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::plugins::templates::catalog_functions; use strict; use warnings; use Exporter; our @ISA = qw(Exporter); our @EXPORT_OK = qw(catalog_status_threshold catalog_status_threshold_ng catalog_status_calc); sub catalog_status_threshold { my ($self, %options) = @_; my $status = 'ok'; my $label = $self->{label}; $label =~ s/-/_/g; if (defined($self->{instance_mode}->{option_results}->{'ok_' . $label}) && $self->{instance_mode}->{option_results}->{'ok_' . $label} ne '' && $self->eval(value => $self->{instance_mode}->{option_results}->{'ok_' . $label})) { $status = 'ok'; } elsif (defined($self->{instance_mode}->{option_results}->{'critical_' . $label}) && $self->{instance_mode}->{option_results}->{'critical_' . $label} ne '' && $self->eval(value => $self->{instance_mode}->{option_results}->{'critical_' . $label})) { $status = 'critical'; } elsif (defined($self->{instance_mode}->{option_results}->{'warning_' . $label}) && $self->{instance_mode}->{option_results}->{'warning_' . $label} ne '' && $self->eval(value => $self->{instance_mode}->{option_results}->{'warning_' . $label})) { $status = 'warning'; } elsif (defined($self->{instance_mode}->{option_results}->{'unknown_' . $label}) && $self->{instance_mode}->{option_results}->{'unknown_' . $label} ne '' && $self->eval(value => $self->{instance_mode}->{option_results}->{'unknown_' . $label})) { $status = 'unknown'; } return $status; } sub catalog_status_threshold_ng { my ($self, %options) = @_; my $status = 'ok'; my $message; if (defined($self->{instance_mode}->{option_results}->{'critical-' . $self->{label}}) && $self->{instance_mode}->{option_results}->{'critical-' . $self->{label}} ne '' && $self->eval(value => $self->{instance_mode}->{option_results}->{'critical-' . $self->{label}})) { $status = 'critical'; } elsif (defined($self->{instance_mode}->{option_results}->{'warning-' . $self->{label}}) && $self->{instance_mode}->{option_results}->{'warning-' . $self->{label}} ne '' && $self->eval(value => $self->{instance_mode}->{option_results}->{'warning-' . $self->{label}})) { $status = 'warning'; } elsif (defined($self->{instance_mode}->{option_results}->{'unknown-' . $self->{label}}) && $self->{instance_mode}->{option_results}->{'unknown-' . $self->{label}} ne '' && $self->eval(value => $self->{instance_mode}->{option_results}->{'unknown-' . $self->{label}})) { $status = 'unknown'; } return $status; } sub catalog_status_calc { my ($self, %options) = @_; foreach (keys %{$options{new_datas}}) { if (/^\Q$self->{instance}\E_(.*)/) { $self->{result_values}->{$1} = $options{new_datas}->{$_}; } } } 1; __END__ centreon-plugins-20220113/centreon/plugins/templates/counter.pm000066400000000000000000001022441417000230700245500ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::templates::counter; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::values; use centreon::plugins::misc; my $sort_subs = { num => sub { $a <=> $b }, cmp => sub { $a cmp $b }, }; sub set_counters { my ($self, %options) = @_; if (!defined($self->{maps_counters})) { $self->{maps_counters} = {}; } $self->{maps_counters_type} = []; # 0 = mode total # 1 = mode instances #push @{$self->{maps_counters_type}}, { # name => 'global', type => 0, message_separator => ', ', cb_prefix_output => undef, cb_init => undef, #}; #$self->{maps_counters}->{global} = [ # { label => 'client', set => { # key_values => [ { name => 'client' } ], # output_template => 'Current client connections : %s', # perfdatas => [ # { label => 'Client', value => 'client', template => '%s', # min => 0, unit => 'con' }, # ], # } # }, #]; # Example for instances #push @{$self->{maps_counters_type}}, { # name => 'cpu', type => 1, message_separator => ', ', cb_prefix_output => undef, cb_init => undef, # message_multiple => 'All CPU usages are ok', #}; } sub get_callback { my ($self, %options) = @_; if (defined($options{method_name})) { return $self->can($options{method_name}); } return undef; } sub call_object_callback { my ($self, %options) = @_; if (defined($options{method_name})) { my $method = $self->can($options{method_name}); if ($method) { return $self->$method(%options); } } return undef; } sub get_threshold_prefix { my ($self, %options) = @_; my $prefix = ''; END_LOOP: foreach (@{$self->{maps_counters_type}}) { if ($_->{name} eq $options{name}) { $prefix = 'instance-' if ($_->{type} == 1); last; } if ($_->{type} == 3) { foreach (@{$_->{group}}) { if ($_->{name} eq $options{name}) { $prefix = 'instance-' if ($_->{type} == 0); $prefix = 'subinstance-' if ($_->{type} == 1); last END_LOOP; } } } } return $prefix; } 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-counters-block:s' => { name => 'filter_counters_block' }, 'filter-counters:s' => { name => 'filter_counters' }, 'display-ok-counters:s' => { name => 'display_ok_counters' }, 'list-counters' => { name => 'list_counters' } }); $self->{statefile_value} = undef; if (defined($options{statefile}) && $options{statefile}) { centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'centreon::plugins::statefile', error_msg => "Cannot load module 'centreon::plugins::statefile'." ); $self->{statefile_value} = centreon::plugins::statefile->new(%options); } $self->{maps_counters} = {} if (!defined($self->{maps_counters})); $self->set_counters(%options); foreach my $key (keys %{$self->{maps_counters}}) { foreach (@{$self->{maps_counters}->{$key}}) { my $label = $_->{label}; my $thlabel = $label; if ($self->{output}->use_new_perfdata() && defined($_->{nlabel})) { $label = $_->{nlabel}; $thlabel = $self->get_threshold_prefix(name => $key) . $label; } $thlabel =~ s/\./-/g; if (!defined($_->{threshold}) || $_->{threshold} != 0) { $options{options}->add_options(arguments => { 'unknown-' . $thlabel . ':s' => { name => 'unknown-' . $thlabel, default => $_->{unknown_default} }, 'warning-' . $thlabel . ':s' => { name => 'warning-' . $thlabel, default => $_->{warning_default} }, 'critical-' . $thlabel . ':s' => { name => 'critical-' . $thlabel, default => $_->{critical_default} } }); if (defined($_->{nlabel})) { $options{options}->add_options(arguments => { 'unknown-' . $_->{label} . ':s' => { name => 'unknown-' . $_->{label}, redirect => 'unknown-' . $thlabel }, 'warning-' . $_->{label} . ':s' => { name => 'warning-' . $_->{label}, redirect => 'warning-' . $thlabel }, 'critical-' . $_->{label} . ':s' => { name => 'critical-' . $_->{label}, redirect => 'critical-' . $thlabel } }); } } $_->{obj} = centreon::plugins::values->new( statefile => $self->{statefile_value}, output => $self->{output}, perfdata => $self->{perfdata}, label => $_->{label}, nlabel => $_->{nlabel}, thlabel => $thlabel ); $_->{obj}->set(%{$_->{set}}); } } return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (defined($self->{option_results}->{list_counters})) { my $list_counter = 'counter list:'; my $th_counter = ''; foreach my $key (keys %{$self->{maps_counters}}) { foreach (@{$self->{maps_counters}->{$key}}) { my $label = $_->{label}; $label =~ s/-//g; $list_counter .= " " . $_->{label}; $th_counter .= " --warning-$_->{label}='\$_SERVICEWARNING" . uc($label) . "\$' --critical-$_->{label}='\$_SERVICECRITICAL" . uc($label) . "\$'"; } } $self->{output}->output_add(short_msg => $list_counter); $self->{output}->output_add(long_msg => 'configuration: ' . $th_counter); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } my $change_macros_opt = []; foreach my $key (keys %{$self->{maps_counters}}) { foreach (@{$self->{maps_counters}->{$key}}) { push @$change_macros_opt, 'unknown-' . $_->{label}, 'warning-' . $_->{label}, 'critical-' . $_->{label} if (defined($_->{type}) && $_->{type} == 2); $_->{obj}->{instance_mode} = $self; $_->{obj}->init(option_results => $self->{option_results}) if (!defined($_->{type}) || $_->{type} != 2); } } $self->change_macros(macros => $change_macros_opt) if (scalar(@$change_macros_opt) > 0); if (defined($self->{statefile_value})) { $self->{statefile_value}->check_options(%options); } } sub run_global { my ($self, %options) = @_; return undef if (defined($self->{option_results}->{filter_counters_block}) && $self->{option_results}->{filter_counters_block} ne '' && $options{config}->{name} =~ /$self->{option_results}->{filter_counters_block}/); return undef if (defined($options{config}->{cb_init}) && $self->call_object_callback(method_name => $options{config}->{cb_init}) == 1); my $resume = defined($options{resume}) && $options{resume} == 1 ? 1 : 0; my $display_short = (!defined($options{config}->{display_short}) || $options{config}->{display_short} != 0) ? 1 : 0; # Can be set when it comes from type 3 counters my $called_multiple = defined($options{called_multiple}) && $options{called_multiple} == 1 ? 1 : 0; my $multiple_parent = defined($options{multiple_parent}) && $options{multiple_parent} == 1 ? 1 : 0; my $force_instance = defined($options{force_instance}) ? $options{force_instance} : undef; my $message_separator = defined($options{config}->{message_separator}) ? $options{config}->{message_separator}: ', '; my ($short_msg, $short_msg_append, $long_msg, $long_msg_append) = ('', '', '', ''); my @exits; foreach (@{$self->{maps_counters}->{$options{config}->{name}}}) { my $obj = $_->{obj}; next if (defined($self->{option_results}->{filter_counters}) && $self->{option_results}->{filter_counters} ne '' && $_->{label} !~ /$self->{option_results}->{filter_counters}/); $obj->set(instance => defined($force_instance) ? $force_instance : $options{config}->{name}); my ($value_check) = $obj->execute(new_datas => $self->{new_datas}, values => $self->{$options{config}->{name}}); next if (defined($options{config}->{skipped_code}) && defined($options{config}->{skipped_code}->{$value_check})); if ($value_check != 0) { $long_msg .= $long_msg_append . $obj->output_error(); $long_msg_append = $message_separator; next; } my $exit2 = $obj->threshold_check(); push @exits, $exit2; my $output = $obj->output(); if (!defined($_->{display_ok}) || $_->{display_ok} != 0 || (defined($self->{option_results}->{display_ok_counters}) && $self->{option_results}->{display_ok_counters} ne '' && $_->{label} =~ /$self->{option_results}->{display_ok_counters}/)) { $long_msg .= $long_msg_append . $output; $long_msg_append = $message_separator; } if (!$self->{output}->is_status(litteral => 1, value => $exit2, compare => 'ok')) { $short_msg .= $short_msg_append . $output; $short_msg_append = $message_separator; } $obj->perfdata(extra_instance => $multiple_parent); } my ($prefix_output, $suffix_output); $prefix_output = $self->call_object_callback(method_name => $options{config}->{cb_prefix_output}, instance_value => $self->{$options{config}->{name}}) if (defined($options{config}->{cb_prefix_output})); $prefix_output = '' if (!defined($prefix_output)); $suffix_output = $self->call_object_callback(method_name => $options{config}->{cb_suffix_output}, instance_value => $self->{$options{config}->{name}}) if (defined($options{config}->{cb_suffix_output})); $suffix_output = '' if (!defined($suffix_output)); if ($called_multiple == 1 && $long_msg ne '') { $self->{output}->output_add(long_msg => $options{indent_long_output} . $prefix_output. $long_msg . $suffix_output); } my $exit = $self->{output}->get_most_critical(status => [ @exits ]); if (!$self->{output}->is_status(litteral => 1, value => $exit, compare => 'ok')) { if ($called_multiple == 0) { $self->{output}->output_add( severity => $exit, short_msg => $prefix_output . $short_msg . $suffix_output ); } else { $self->run_multiple_prefix_output( severity => $exit, short_msg => $prefix_output . $short_msg . $suffix_output ); } } else { if ($long_msg ne '' && $multiple_parent == 0) { if ($called_multiple == 0) { $self->{output}->output_add(short_msg => $prefix_output . $long_msg . $suffix_output) if ($display_short == 1); } else { $self->run_multiple_prefix_output( severity => 'ok', short_msg => $prefix_output . $long_msg . $suffix_output ) if ($display_short == 1); } } } } sub run_instances { my ($self, %options) = @_; return undef if (defined($self->{option_results}->{filter_counters_block}) && $self->{option_results}->{filter_counters_block} ne '' && $options{config}->{name} =~ /$self->{option_results}->{filter_counters_block}/); return undef if (defined($options{config}->{cb_init}) && $self->call_object_callback(method_name => $options{config}->{cb_init}) == 1); my $cb_init_counters = $self->get_callback(method_name => $options{config}->{cb_init_counters}); my $display_status_lo = defined($options{display_status_long_output}) && $options{display_status_long_output} == 1 ? 1 : 0; my $display_short = (!defined($options{config}->{display_short}) || $options{config}->{display_short} != 0) ? 1 : 0; my $display_long = (!defined($options{config}->{display_long}) || $options{config}->{display_long} != 0) ? 1 : 0; my $resume = defined($options{resume}) && $options{resume} == 1 ? 1 : 0; my $no_message_multiple = 1; $self->{lproblems} = 0; $self->{multiple} = 1; if (scalar(keys %{$self->{$options{config}->{name}}}) <= 1) { $self->{multiple} = 0; } my $message_separator = defined($options{config}->{message_separator}) ? $options{config}->{message_separator}: ', '; my $sort_method = 'cmp'; $sort_method = $options{config}->{sort_method} if (defined($options{config}->{sort_method})); foreach my $id (sort { $sort_subs->{$sort_method}->() } keys %{$self->{$options{config}->{name}}}) { my ($short_msg, $short_msg_append, $long_msg, $long_msg_append) = ('', '', '', ''); my @exits = (); foreach (@{$self->{maps_counters}->{$options{config}->{name}}}) { my $obj = $_->{obj}; next if (defined($self->{option_results}->{filter_counters}) && $self->{option_results}->{filter_counters} ne '' && $_->{label} !~ /$self->{option_results}->{filter_counters}/); next if ($cb_init_counters && $self->$cb_init_counters(%$_) == 1); $no_message_multiple = 0; $obj->set(instance => $id); my ($value_check) = $obj->execute( new_datas => $self->{new_datas}, values => $self->{$options{config}->{name}}->{$id} ); next if (defined($options{config}->{skipped_code}) && defined($options{config}->{skipped_code}->{$value_check})); if ($value_check != 0) { $long_msg .= $long_msg_append . $obj->output_error(); $long_msg_append = $message_separator; next; } my $exit2 = $obj->threshold_check(); push @exits, $exit2; my $output = $obj->output(); if (!defined($_->{display_ok}) || $_->{display_ok} != 0 || (defined($self->{option_results}->{display_ok_counters}) && $self->{option_results}->{display_ok_counters} ne '' && $_->{label} =~ /$self->{option_results}->{display_ok_counters}/)) { $long_msg .= $long_msg_append . $output; $long_msg_append = $message_separator; } if (!$self->{output}->is_status(litteral => 1, value => $exit2, compare => 'ok')) { $self->{lproblems}++; $short_msg .= $short_msg_append . $output; $short_msg_append = $message_separator; } $obj->perfdata(extra_instance => $self->{multiple}); } my ($prefix_output, $suffix_output); $prefix_output = $self->call_object_callback(method_name => $options{config}->{cb_prefix_output}, instance => $id, instance_value => $self->{$options{config}->{name}}->{$id}) if (defined($options{config}->{cb_prefix_output})); $prefix_output = '' if (!defined($prefix_output)); $suffix_output = $self->call_object_callback(method_name => $options{config}->{cb_suffix_output}) if (defined($options{config}->{cb_suffix_output})); $suffix_output = '' if (!defined($suffix_output)); my $exit = $self->{output}->get_most_critical(status => [ @exits ]); # in mode grouped, we don't display 'ok' my $debug = 0; $debug = 1 if ($display_status_lo == 1 && $self->{output}->is_status(value => $exit, compare => 'OK', litteral => 1)); if (scalar @{$self->{maps_counters}->{$options{config}->{name}}} > 0 && $long_msg ne '') { $self->{output}->output_add(long_msg => ($display_status_lo == 1 ? lc($exit) . ': ' : '') . $prefix_output . $long_msg . $suffix_output, debug => $debug) if ($display_long == 1); } if ($resume == 1) { $self->{most_critical_instance} = $self->{output}->get_most_critical(status => [ $self->{most_critical_instance}, $exit ]); next; } if (!$self->{output}->is_status(litteral => 1, value => $exit, compare => 'ok')) { $self->{output}->output_add( severity => $exit, short_msg => $prefix_output . $short_msg . $suffix_output ); } if ($self->{multiple} == 0) { $self->{output}->output_add(short_msg => $prefix_output . $long_msg . $suffix_output) if ($display_short == 1); } } if ($no_message_multiple == 0 && $self->{multiple} == 1 && $resume == 0) { $self->{output}->output_add(short_msg => $options{config}->{message_multiple}) if ($display_short == 1); } } sub run_group { my ($self, %options) = @_; my $multiple = 1; return if (scalar(keys %{$self->{$options{config}->{name}}}) <= 0); if (scalar(keys %{$self->{$options{config}->{name}}}) <= 1) { $multiple = 0; } if ($multiple == 1) { $self->{output}->output_add( severity => 'OK', short_msg => $options{config}->{message_multiple} ); } my $format_output = defined($options{config}->{format_output}) ? $options{config}->{format_output} : '%s problem(s) detected'; my ($global_exit, $total_problems) = ([], 0); foreach my $id (sort keys %{$self->{$options{config}->{name}}}) { $self->{most_critical_instance} = 'ok'; if (defined($options{config}->{cb_long_output})) { $self->{output}->output_add( long_msg => $self->call_object_callback( method_name => $options{config}->{cb_long_output}, instance => $id, instance_value => $self->{$options{config}->{name}}->{$id} ) ); } foreach my $group (@{$options{config}->{group}}) { $self->{$group->{name}} = $self->{$options{config}->{name}}->{$id}->{$group->{name}}; # we resume datas $self->run_instances(config => $group, display_status_long_output => 1, resume => 1); push @{$global_exit}, $self->{most_critical_instance}; $total_problems += $self->{lproblems}; my $prefix_output; $prefix_output = $self->call_object_callback(method_name => $options{config}->{cb_prefix_output}, instance => $id, instance_value => $self->{$options{config}->{name}}->{$id}) if (defined($options{config}->{cb_prefix_output})); $prefix_output = '' if (!defined($prefix_output)); if ($multiple == 0 && (!defined($group->{display}) || $group->{display} != 0)) { $self->{output}->output_add( severity => $self->{most_critical_instance}, short_msg => sprintf("${prefix_output}" . $format_output, $self->{lproblems}) ); } } } if ($multiple == 1) { my $exit = $self->{output}->get_most_critical(status => [ @{$global_exit} ]); if (!$self->{output}->is_status(litteral => 1, value => $exit, compare => 'ok')) { $self->{output}->output_add( severity => $exit, short_msg => sprintf($format_output, $total_problems) ); } } if (defined($options{config}->{display_counter_problem})) { $self->{output}->perfdata_add( label => $options{config}->{display_counter_problem}->{label}, nlabel => $options{config}->{display_counter_problem}->{nlabel}, unit => $options{config}->{display_counter_problem}->{unit}, value => $total_problems, min => $options{config}->{display_counter_problem}->{min}, max => $options{config}->{display_counter_problem}->{max} ); } } sub run_multiple_instances { my ($self, %options) = @_; return undef if (defined($self->{option_results}->{filter_counters_block}) && $self->{option_results}->{filter_counters_block} ne '' && $options{config}->{name} =~ /$self->{option_results}->{filter_counters_block}/); return undef if (defined($options{config}->{cb_init}) && $self->call_object_callback(method_name => $options{config}->{cb_init}) == 1); my $use_new_perfdata = $self->{output}->use_new_perfdata(); my $multiple_parent = defined($options{multiple_parent}) && $options{multiple_parent} == 1 ? $options{multiple_parent} : 0; my $indent_long_output = defined($options{indent_long_output}) ? $options{indent_long_output} : ''; my $no_message_multiple = 1; my $display_long = (!defined($options{config}->{display_long}) || $options{config}->{display_long} != 0) ? 1 : 0; my $display_short = (!defined($options{config}->{display_short}) || $options{config}->{display_short} != 0) ? 1 : 0; my $multiple = 1; if (scalar(keys %{$self->{$options{config}->{name}}}) <= 1) { $multiple = 0; } my $message_separator = defined($options{config}->{message_separator}) ? $options{config}->{message_separator} : ', '; my $sort_method = 'cmp'; $sort_method = $options{config}->{sort_method} if (defined($options{config}->{sort_method})); foreach my $id (sort { $sort_subs->{$sort_method}->() } keys %{$self->{$options{config}->{name}}}) { my ($short_msg, $short_msg_append, $long_msg, $long_msg_append) = ('', '', '', ''); my @exits = (); foreach (@{$self->{maps_counters}->{$options{config}->{name}}}) { my $obj = $_->{obj}; next if (defined($self->{option_results}->{filter_counters}) && $self->{option_results}->{filter_counters} ne '' && $_->{label} !~ /$self->{option_results}->{filter_counters}/); my $instance = $id; if ($use_new_perfdata || ($multiple_parent == 1 && $multiple == 1)) { $instance = $options{instance_parent} . ($self->{output}->get_instance_perfdata_separator()) . $id; } elsif ($multiple_parent == 1 && $multiple == 0) { $instance = $options{instance_parent}; } $no_message_multiple = 0; $obj->set(instance => $instance); my ($value_check) = $obj->execute( new_datas => $self->{new_datas}, values => $self->{$options{config}->{name}}->{$id} ); next if (defined($options{config}->{skipped_code}) && defined($options{config}->{skipped_code}->{$value_check})); if ($value_check != 0) { $long_msg .= $long_msg_append . $obj->output_error(); $long_msg_append = $message_separator; next; } my $exit2 = $obj->threshold_check(); push @exits, $exit2; my $output = $obj->output(); if (!defined($_->{display_ok}) || $_->{display_ok} != 0 || (defined($self->{option_results}->{display_ok_counters}) && $self->{option_results}->{display_ok_counters} ne '' && $_->{label} =~ /$self->{option_results}->{display_ok_counters}/)) { $long_msg .= $long_msg_append . $output; $long_msg_append = $message_separator; } if (!$self->{output}->is_status(litteral => 1, value => $exit2, compare => 'ok')) { $short_msg .= $short_msg_append . $output; $short_msg_append = $message_separator; } if ($multiple_parent == 1 && $multiple == 0) { $obj->perfdata(extra_instance => 1); } else { $obj->perfdata(extra_instance => $multiple); } } my ($prefix_output, $suffix_output); $prefix_output = $self->call_object_callback(method_name => $options{config}->{cb_prefix_output}, instance => $id, instance_value => $self->{$options{config}->{name}}->{$id}) if (defined($options{config}->{cb_prefix_output})); $prefix_output = '' if (!defined($prefix_output)); $suffix_output = $self->call_object_callback(method_name => $options{config}->{cb_suffix_output}) if (defined($options{config}->{cb_suffix_output})); $suffix_output = '' if (!defined($suffix_output)); my $exit = $self->{output}->get_most_critical(status => [ @exits ]); if (scalar @{$self->{maps_counters}->{$options{config}->{name}}} > 0 && $long_msg ne '') { $self->{output}->output_add(long_msg => $indent_long_output . $prefix_output . $long_msg . $suffix_output) if ($display_long == 1); } if (!$self->{output}->is_status(litteral => 1, value => $exit, compare => 'ok')) { $self->run_multiple_prefix_output( severity => $exit, short_msg => $prefix_output . $short_msg . $suffix_output ); } if ($multiple == 0 && $multiple_parent == 0) { $self->run_multiple_prefix_output(severity => 'ok', short_msg => $prefix_output . $long_msg . $suffix_output) if ($display_short == 1); } } if ($no_message_multiple == 0 && $multiple == 1 && $multiple_parent == 0) { $self->run_multiple_prefix_output(severity => 'ok', short_msg => $options{config}->{message_multiple}) if ($display_short == 1); } } sub run_multiple_prefix_output { my ($self, %options) = @_; my %separator; if ($self->{prefix_multiple_output_done}->{lc($options{severity})} == 0) { $self->{output}->output_add(severity => $options{severity}, short_msg => $self->{prefix_multiple_output}); $self->{prefix_multiple_output_done}->{lc($options{severity})} = 1; $separator{separator} = ''; } $self->{output}->output_add(severity => $options{severity}, short_msg => $options{short_msg}, %separator); } sub run_multiple { my ($self, %options) = @_; my $multiple = 1; if (scalar(keys %{$self->{$options{config}->{name}}}) <= 1) { $multiple = 0; } if ($multiple == 1) { $self->{output}->output_add( severity => 'OK', short_msg => $options{config}->{message_multiple} ); } foreach my $instance (sort keys %{$self->{$options{config}->{name}}}) { if (defined($options{config}->{cb_long_output})) { $self->{output}->output_add( long_msg => $self->call_object_callback( method_name => $options{config}->{cb_long_output}, instance => $instance, instance_value => $self->{$options{config}->{name}}->{$instance} ) ); } $self->{prefix_multiple_output} = ''; $self->{prefix_multiple_output_done} = { ok => 0, warning => 0, critical => 0, unknown => 0 }; $self->{prefix_multiple_output} = $self->call_object_callback(method_name => $options{config}->{cb_prefix_output}, instance => $instance, instance_value => $self->{$options{config}->{name}}->{$instance}) if (defined($options{config}->{cb_prefix_output})); my $indent_long_output = ''; $indent_long_output = $options{config}->{indent_long_output} if (defined($options{config}->{indent_long_output})); foreach my $group (@{$options{config}->{group}}) { next if (!defined($self->{$options{config}->{name}}->{$instance}->{$group->{name}})); $self->{$group->{name}} = $self->{$options{config}->{name}}->{$instance}->{$group->{name}}; if ($group->{type} == 1) { $self->run_multiple_instances(config => $group, multiple_parent => $multiple, instance_parent => $instance, indent_long_output => $indent_long_output); } elsif ($group->{type} == 0) { $self->run_global( config => $group, multiple_parent => $multiple, called_multiple => 1, force_instance => $instance, indent_long_output => $indent_long_output ); } } } } sub read_statefile_key { my ($self, %options) = @_; $self->{statefile_value}->read(statefile => $self->{cache_name}); return $self->{statefile_value}->get(name => $options{key}); } sub set_timestamp { my ($self, %options) = @_; $self->{override_timestamp} = $options{timestamp}; } sub run { my ($self, %options) = @_; $self->manage_selection(%options); $self->{new_datas} = undef; if (defined($self->{statefile_value})) { $self->{new_datas} = {}; $self->{statefile_value}->read(statefile => $self->{cache_name}) if (defined($self->{cache_name})); $self->{new_datas}->{last_timestamp} = defined($self->{override_timestamp}) ? $self->{override_timestamp} : time(); } foreach my $entry (@{$self->{maps_counters_type}}) { if ($entry->{type} == 0) { $self->run_global(config => $entry); } elsif ($entry->{type} == 1) { $self->run_instances(config => $entry); } elsif ($entry->{type} == 2) { $self->run_group(config => $entry); } elsif ($entry->{type} == 3) { $self->run_multiple(config => $entry); } } if (defined($self->{statefile_value})) { $self->{statefile_value}->write(data => $self->{new_datas}); } $self->{output}->display(); $self->{output}->exit(); } sub manage_selection { my ($self, %options) = @_; # example for snmp #use Digest::MD5 qw(md5_hex); #$self->{cache_name} = "choose_name_" . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . $self->{mode} . '_' . # (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } sub compat_threshold_counter { my ($self, %options) = @_; foreach ('warning', 'critical') { foreach my $th (@{$options{compat}->{th}}) { next if (!defined($options{option_results}->{$_ . '-' . $th->[0]}) || $options{option_results}->{$_ . '-' . $th->[0]} eq ''); my $src_threshold = $options{option_results}->{$_ . '-' . $th->[0]}; if (defined($options{compat}->{units}) && $options{compat}->{units} eq '%') { $options{option_results}->{$_ . '-' . $th->[0]} = undef; if (defined($options{compat}->{free})) { $options{option_results}->{$_ . '-' . $th->[0]} = undef; my ($status, $result) = centreon::plugins::misc::parse_threshold(threshold => $src_threshold); next if ($status == 0); my $tmp = { arobase => $result->{arobase}, infinite_pos => 0, infinite_neg => 0, start => $result->{start}, end => $result->{end} }; $tmp->{infinite_neg} = 1 if ($result->{infinite_pos} == 1); $tmp->{infinite_pos} = 1 if ($result->{infinite_neg} == 1); if ($result->{start} ne '' && $result->{infinite_neg} == 0) { $tmp->{end} = 100 - $result->{start}; } if ($result->{end} ne '' && $result->{infinite_pos} == 0) { $tmp->{start} = 100 - $result->{end}; } $options{option_results}->{$_ . '-' . $th->[1]->{prct}} = centreon::plugins::misc::get_threshold_litteral(%$tmp); } else { $options{option_results}->{$_ . '-' . $th->[1]->{prct}} = $src_threshold; } } elsif (defined($options{compat}->{free})) { $options{option_results}->{$_ . '-' . $th->[1]->{free}} = $options{option_results}->{$_ . '-' . $th->[0]}; $options{option_results}->{$_ . '-' . $th->[0]} = undef; } } } } sub change_macros { my ($self, %options) = @_; foreach (@{$options{macros}}) { if (defined($self->{option_results}->{$_}) && $self->{option_results}->{$_} ne '') { $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$values->{$1}/g; } } } 1; __END__ =head1 MODE Default template for counters. Should be extended. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example to check SSL connections only : --filter-counters='^xxxx|yyyy$' =item B<--warning-*> Threshold warning. Can be: 'xxx', 'xxx'. =item B<--critical-*> Threshold critical. Can be: 'xxx', 'xxx'. =back =cut centreon-plugins-20220113/centreon/plugins/templates/hardware.pm000066400000000000000000000467251417000230700247010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::templates::hardware; use base qw(centreon::plugins::mode); use strict; use warnings; sub set_system { my ($self, %options) = @_; #$self->{regexp_threshold_numeric_check_section_option} = ''; #$self->{cb_threshold_numeric_check_section_option} = 'callbackname'; # Some callbacks #$self->{cb_hook1} = 'callbackname'; # before the loads #$self->{cb_hook2} = 'callbackname'; # between loads and requests #$self->{cb_hook3} = 'callbackname'; # after requests #$self->{cb_hook4} = 'callbackname'; # after output # Example for threshold: #$self->{thresholds} = { # fan => [ # ['bad', 'CRITICAL'], # ['good', 'OK'], # ['notPresent', 'OK'], # ], #}; # Unset the call to load components #$self->{components_exec_load} = 0; # Set the path_info #$self->{components_path} = 'network::xxxx::mode::components'; # Set the components #$self->{components_module} = ['cpu', 'memory', ...]; } sub call_object_callback { my ($self, %options) = @_; if (defined($options{method_name})) { my $method = $self->can($options{method_name}); if ($method) { return $self->$method(%options); } } return undef; } 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 => { 'component:s' => { name => 'component', default => '.*' }, 'no-component:s' => { name => 'no_component' }, 'threshold-overload:s@' => { name => 'threshold_overload' }, 'add-name-instance' => { name => 'add_name_instance' }, 'no-component-count' => { name => 'no_component_count' } }); $self->{performance} = (defined($options{no_performance}) && $options{no_performance} == 1) ? 0 : 1; if ($self->{performance} == 1) { $options{options}->add_options(arguments => { 'warning:s@' => { name => 'warning' }, 'critical:s@' => { name => 'critical' } }); } $self->{filter_exclude} = (defined($options{no_filter_exclude}) && $options{no_filter_exclude} == 1) ? 0 : 1; if ($self->{filter_exclude} == 1) { $options{options}->add_options(arguments => { 'exclude:s' => { name => 'exclude' }, 'filter:s@' => { name => 'filter' } }); } $self->{absent} = (defined($options{no_absent}) && $options{no_absent} == 1) ? 0 : 1; if ($self->{absent} == 1) { $options{options}->add_options(arguments => { 'absent-problem:s@' => { name => 'absent_problem' } }); } $self->{load_components} = (defined($options{no_load_components}) && $options{no_load_components} == 1) ? 0 : 1; $self->{components} = {}; $self->{no_components} = undef; $self->{components_module} = []; $self->{components_exec_load} = 1; $self->set_system(); $self->{count} = (defined($options{no_count}) && $options{no_count} == 1) ? 0 : 1; if ($self->{count} == 1) { foreach my $component (@{$self->{components_module}}) { $options{options}->add_options(arguments => { 'unknown-count-' . $component . ':s' => { name => 'unknown_count_' . $component }, 'warning-count-' . $component . ':s' => { name => 'warning_count_' . $component }, 'critical-count-' . $component . ':s' => { name => 'critical_count_' . $component } }); } } $self->{request} = []; 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'; } } if ($self->{filter_exclude} == 1) { $self->{filter} = []; foreach my $val (@{$self->{option_results}->{filter}}) { next if (!defined($val) || $val eq ''); my @values = split (/,/, $val); push @{$self->{filter}}, { filter => $values[0], instance => $values[1] }; } } if ($self->{absent} == 1) { $self->{absent_problem} = []; foreach my $val (@{$self->{option_results}->{absent_problem}}) { next if (!defined($val) || $val eq ''); my @values = split (/,/, $val); push @{$self->{absent_problem}}, { filter => $values[0], instance => $values[1] }; } } $self->{overload_th} = []; foreach my $val (@{$self->{option_results}->{threshold_overload}}) { next if (!defined($val) || $val eq ''); my @values = split (/,/, $val); if (scalar(@values) < 3) { $self->{output}->add_option_msg(short_msg => "Wrong threshold-overload option '" . $val . "'."); $self->{output}->option_exit(); } my ($section, $instance, $status, $filter); if (scalar(@values) == 3) { ($section, $status, $filter) = @values; $instance = '.*'; } else { ($section, $instance, $status, $filter) = @values; } 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(); } push @{$self->{overload_th}}, { section => $section, filter => $filter, status => $status, instance => $instance }; } if ($self->{performance} == 1) { $self->{numeric_threshold} = {}; foreach my $option (('warning', 'critical')) { foreach my $val (@{$self->{option_results}->{$option}}) { next if (!defined($val) || $val eq ''); if ($val !~ /^(.*?),(.*?),(.*)$/) { $self->{output}->add_option_msg(short_msg => "Wrong $option option '" . $val . "'."); $self->{output}->option_exit(); } my ($section, $instance, $value) = ($1, $2, $3); if (defined($self->{regexp_threshold_numeric_check_section_option}) && $section !~ /$self->{regexp_threshold_numeric_check_section_option}/) { $self->{output}->add_option_msg(short_msg => "Wrong $option option '" . $val . "'."); $self->{output}->option_exit(); } $self->call_object_callback( method_name => $self->{cb_threshold_numeric_check_section_option}, section => $section, option_name => $option, option_value => $val ); 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, instance => $instance }; } } } if ($self->{count} == 1) { foreach my $comp (@{$self->{components_module}}) { foreach my $threshold (('warning', 'critical', 'unknown')) { if (($self->{perfdata}->threshold_validate(label => $threshold . '-count-' . $comp, value => $self->{option_results}->{$threshold . '_count_' . $comp})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong " . $threshold . " threshold '" . $self->{option_results}->{$threshold . '_count_' . $comp} . "'."); $self->{output}->option_exit(); } } } } } sub load_components { my ($self, %options) = @_; foreach (@{$self->{components_module}}) { if (/$self->{option_results}->{component}/) { my $mod_name = $self->{components_path} . "::$_"; centreon::plugins::misc::mymodule_load( output => $self->{output}, module => $mod_name, error_msg => "Cannot load module '$mod_name'.") if ($self->{load_components} == 1); $self->{loaded} = 1; if ($self->{components_exec_load} == 1) { my $func = $mod_name->can('load'); $func->($self); } } } } sub exec_components { my ($self, %options) = @_; foreach (@{$self->{components_module}}) { if (/$self->{option_results}->{component}/) { my $mod_name = $self->{components_path} . "::$_"; my $func = $mod_name->can('check'); $func->($self); } } } sub display { my ($self, %options) = @_; my $total_components = 0; my $display_by_component = ''; my $display_by_component_append = ''; my $exit = 'OK'; my $exits = []; my ($warn, $crit); foreach my $comp (sort(keys %{$self->{components}})) { # Skipping short msg when no components next if (!defined($self->{option_results}->{no_component_count}) && $self->{components}->{$comp}->{total} == 0 && $self->{components}->{$comp}->{skip} == 0); if ($self->{count} == 1) { ($exit, $warn, $crit) = $self->get_severity_count(label => $comp, value => $self->{components}->{$comp}->{total}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "'%s' components '%s' checked", $self->{components}->{$comp}->{total}, $comp ) ); } $self->{output}->perfdata_add( label => 'count_' . $comp, nlabel => 'hardware.' . $comp . '.count', value => $self->{components}->{$comp}->{total}, warning => $warn, critical => $crit ); push @{$exits}, $exit; } $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 = ', '; } $exit = $self->{output}->get_most_critical(status => $exits) if (scalar(@{$exits}) > 0); if ($self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( 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.' ); } } sub run { my ($self, %options) = @_; $self->{loaded} = 0; $self->call_object_callback(method_name => $self->{cb_hook1}, %options); $self->load_components(%options); if ($self->{loaded} == 0) { $self->{output}->add_option_msg(short_msg => "Wrong option. Cannot find component '" . $self->{option_results}->{component} . "'."); $self->{output}->option_exit(); } $self->call_object_callback(method_name => $self->{cb_hook2}, %options); $self->exec_components(%options); $self->call_object_callback(method_name => $self->{cb_hook3}, %options); $self->display(); $self->call_object_callback(method_name => $self->{cb_hook4}, %options); $self->{output}->display(); $self->{output}->exit(); } sub check_filter { my ($self, %options) = @_; # Old compatibility variable. We'll be deleted if (defined($self->{option_results}->{exclude})) { if (defined($options{instance})) { if ($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; } } $options{instance} .= '#' . $options{name} if (defined($self->{option_results}->{add_name_instance}) && defined($options{name})); foreach (@{$self->{filter}}) { if ($options{section} =~ /$_->{filter}/) { if (!defined($options{instance}) && !defined($_->{instance})) { $self->{output}->output_add(long_msg => sprintf("skipping $options{section} section.")); return 1; } elsif (defined($options{instance}) && $options{instance} =~ /$_->{instance}/) { $self->{output}->output_add(long_msg => sprintf("skipping $options{section} section $options{instance} instance.")); return 1; } } } return 0; } sub absent_problem { my ($self, %options) = @_; $options{instance} .= '#' . $options{name} if (defined($self->{option_results}->{add_name_instance}) && defined($options{name})); foreach (@{$self->{absent_problem}}) { if ($options{section} =~ /$_->{filter}/) { if (!defined($_->{instance}) || $options{instance} =~ /$_->{instance}/) { $self->{output}->output_add( severity => 'CRITICAL', short_msg => sprintf( "Component '%s' instance '%s' is not present", $options{section}, $options{instance} ) ); $self->{output}->output_add(long_msg => sprintf("Skipping $options{section} section $options{instance} instance (not present)")); $self->{components}->{$options{section}}->{skip}++; return 1; } } } return 0; } sub get_severity_count { my ($self, %options) = @_; my $status = 'OK'; # default my $thresholds = { warning => undef, critical => undef }; $status = $self->{perfdata}->threshold_check( value => $options{value}, threshold => [ { label => 'critical-count-' . $options{label}, exit_litteral => 'critical' }, { label => 'warning-count-' . $options{label}, exit_litteral => 'warning' }, { label => 'unknown-count-' . $options{label}, exit_litteral => 'unknown' }, ] ); $thresholds->{critical} = $self->{perfdata}->get_perfdata_for_output(label => 'critical-count-' . $options{label}); $thresholds->{warning} = $self->{perfdata}->get_perfdata_for_output(label => 'warning-count-' . $options{label}); return ($status, $thresholds->{warning}, $thresholds->{critical}); } sub get_severity_numeric { my ($self, %options) = @_; my $status = 'OK'; # default my $thresholds = { warning => undef, critical => undef }; my $checked = 0; $options{instance} .= '#' . $options{name} if (defined($self->{option_results}->{add_name_instance}) && defined($options{name})); if (defined($self->{numeric_threshold}->{$options{section}})) { my $exits = []; foreach (@{$self->{numeric_threshold}->{$options{section}}}) { if ($options{instance} =~ /$_->{instance}/) { 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 foreach (@{$self->{overload_th}}) { if ($options{section} =~ /$_->{section}/i) { if ($options{value} =~ /$_->{filter}/i && (!defined($options{instance}) || $options{instance} =~ /$_->{instance}/)) { $status = $_->{status}; return $status; } } } my $label = defined($options{label}) ? $options{label} : $options{section}; foreach (@{$self->{thresholds}->{$label}}) { if ($options{value} =~ /$$_[0]/i) { $status = $$_[1]; return $status; } } return $status; } 1; __END__ =head1 MODE Default template for hardware. Should be extended. =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'xxx', 'yyy'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=xxx --filter=yyyy) Can also exclude specific instance: --filter=xxxxx,instancevalue =item B<--absent-problem> Return an error if an entity is not 'present' (default is skipping) (comma seperated list) Can be specific or global: --absent-problem=xxxx,instancevalue =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='xxxxx,CRITICAL,^(?!(normal)$)' =item B<--warning> Set warning threshold for temperatures (syntax: type,instance,threshold) Example: --warning='xxxxx,.*,30' =item B<--critical> Set critical threshold for temperatures (syntax: type,instance,threshold) Example: --critical='xxxxx,.*,40' =item B<--warning-count-xxxx> Set warning threshold for component count. =item B<--critical-count-xxxx> Set critical threshold for component count. =back =cut centreon-plugins-20220113/centreon/plugins/values.pm000066400000000000000000000320361417000230700223730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::values; use strict; use warnings; use centreon::plugins::misc; # Warning message with sprintf and too much arguments. # Really annoying. Need to disable that warning no if ($^V gt v5.22.0), 'warnings' => 'redundant'; sub new { my ($class, %options) = @_; my $self = {}; bless $self, $class; $self->{statefile} = $options{statefile}; $self->{output} = $options{output}; $self->{perfdata} = $options{perfdata}; $self->{label} = $options{label}; $self->{nlabel} = $options{nlabel}; $self->{thlabel} = defined($options{thlabel}) ? $options{thlabel} : $self->{label}; $self->{perfdatas} = []; $self->{output_template} = $self->{label} . ' : %s'; $self->{output_use} = undef; $self->{output_change_bytes} = 0; $self->{output_error_template} = $self->{label} . ' : %s'; $self->{threshold_use} = undef; $self->{threshold_warn} = undef; $self->{threshold_crit} = undef; $self->{per_second} = 0; $self->{manual_keys} = 0; $self->{last_timestamp} = undef; $self->{result_values} = {}; $self->{safe_test} = 0; return $self; } sub init { my ($self, %options) = @_; my $unkn = defined($self->{threshold_unkn}) ? $self->{threshold_unkn} : 'unknown-' . $self->{thlabel}; my $warn = defined($self->{threshold_warn}) ? $self->{threshold_warn} : 'warning-' . $self->{thlabel}; my $crit = defined($self->{threshold_crit}) ? $self->{threshold_crit} : 'critical-' . $self->{thlabel}; if (($self->{perfdata}->threshold_validate(label => $unkn, value => $options{option_results}->{$unkn})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong $unkn threshold '" . $options{option_results}->{$unkn} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => $warn, value => $options{option_results}->{$warn})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong $warn threshold '" . $options{option_results}->{$warn} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => $crit, value => $options{option_results}->{$crit})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong $crit threshold '" . $options{option_results}->{$crit} . "'."); $self->{output}->option_exit(); } } sub set { my ($self, %options) = @_; foreach (keys %options) { $self->{$_} = $options{$_}; } } sub calc { my ($self, %options) = @_; # manage only one value ;) foreach my $value (@{$self->{key_values}}) { if (defined($value->{diff}) && $value->{diff} == 1) { $self->{result_values}->{$value->{name}} = $options{new_datas}->{$self->{instance} . '_' . $value->{name}} - $options{old_datas}->{$self->{instance} . '_' . $value->{name}}; } elsif (defined($value->{per_second}) && $value->{per_second} == 1) { $self->{result_values}->{$value->{name}} = ($options{new_datas}->{$self->{instance} . '_' . $value->{name}} - $options{old_datas}->{$self->{instance} . '_' . $value->{name}}) / $options{delta_time}; } elsif (defined($value->{per_minute}) && $value->{per_minute} == 1) { $self->{result_values}->{$value->{name}} = ($options{new_datas}->{$self->{instance} . '_' . $value->{name}} - $options{old_datas}->{$self->{instance} . '_' . $value->{name}}) / ($options{delta_time} / 60); } else { $self->{result_values}->{$value->{name}} = $options{new_datas}->{$self->{instance} . '_' . $value->{name}}; } } return 0; } sub threshold_check { my ($self, %options) = @_; if (defined($self->{closure_custom_threshold_check})) { return &{$self->{closure_custom_threshold_check}}($self, %options); } my $unkn = defined($self->{threshold_unkn}) ? $self->{threshold_unkn} : 'unknown-' . $self->{thlabel}; my $warn = defined($self->{threshold_warn}) ? $self->{threshold_warn} : 'warning-' . $self->{thlabel}; my $crit = defined($self->{threshold_crit}) ? $self->{threshold_crit} : 'critical-' . $self->{thlabel}; my $value = ''; if (defined($self->{threshold_use})) { $value = $self->{result_values}->{ $self->{threshold_use} }; } else { $value = defined($self->{key_values}->[0]) ? $self->{result_values}->{ $self->{key_values}->[0]->{name} } : ''; } return $self->{perfdata}->threshold_check( value => $value, threshold => [ { label => $crit, exit_litteral => 'critical' }, { label => $warn, exit_litteral => 'warning' }, { label => $unkn, exit_litteral => 'unknown' } ] ); } sub output_error { my ($self, %options) = @_; return sprintf($self->{output_error_template}, $self->{error_msg}); } sub output { my ($self, %options) = @_; if (defined($self->{closure_custom_output})) { return $self->{closure_custom_output}->($self); } my ($value, $unit, $name) = ('', ''); if (defined($self->{output_use})) { $name = $self->{output_use}; } else { $name = defined($self->{key_values}->[0]) ? $self->{key_values}->[0]->{name} : undef; } if (defined($name)) { $value = $self->{result_values}->{$name}; if ($self->{output_change_bytes} == 1) { ($value, $unit) = $self->{perfdata}->change_bytes(value => $value); } elsif ($self->{output_change_bytes} == 2) { ($value, $unit) = $self->{perfdata}->change_bytes(value => $value, network => 1); } } return sprintf($self->{output_template}, $value, $unit); } sub use_instances { my ($self, %options) = @_; if (!defined($options{extra_instance}) || $options{extra_instance} != 0 || $self->{output}->use_new_perfdata()) { return 1; } return 0; } sub perfdata { my ($self, %options) = @_; if (defined($self->{closure_custom_perfdata})) { return &{$self->{closure_custom_perfdata}}($self, %options); } my $warn = defined($self->{threshold_warn}) ? $self->{threshold_warn} : 'warning-' . $self->{thlabel}; my $crit = defined($self->{threshold_crit}) ? $self->{threshold_crit} : 'critical-' . $self->{thlabel}; foreach my $perf (@{$self->{perfdatas}}) { my ($label, $extra_label, $min, $max, $th_total) = ($self->{label}, ''); my $cast_int = (defined($perf->{cast_int}) && $perf->{cast_int} == 1) ? 1 : 0; my $template = '%s'; $template = $perf->{template} if (defined($perf->{template})); $label = $perf->{label} if (defined($perf->{label})); if (defined($perf->{min})) { $min = ($perf->{min} =~ /[^0-9.-]/) ? $self->{result_values}->{$perf->{min}} : $perf->{min}; } if (defined($perf->{max})) { $max = ($perf->{max} =~ /[^0-9.-]/) ? $self->{result_values}->{$perf->{max}} : $perf->{max}; } if (defined($perf->{threshold_total})) { $th_total = ($perf->{threshold_total} =~ /[^0-9.-]/) ? $self->{result_values}->{$perf->{threshold_total}} : $perf->{threshold_total}; } my $instances; if (defined($perf->{label_extra_instance}) && $perf->{label_extra_instance} == 1) { my $instance = ''; if (defined($perf->{instance_use})) { $instance = $self->{result_values}->{$perf->{instance_use}}; } else { $instance = $self->{instance}; } if (!defined($options{extra_instance}) || $options{extra_instance} != 0 || $self->{output}->use_new_perfdata()) { $instances = $instance; } } my $value = defined($perf->{value}) ? $perf->{value} : $self->{key_values}->[0]->{name}; $self->{output}->perfdata_add( label => $label, instances => $instances, nlabel => $self->{nlabel}, unit => $perf->{unit}, value => $cast_int == 1 ? int($self->{result_values}->{$value}) : sprintf($template, $self->{result_values}->{$value}), warning => $self->{perfdata}->get_perfdata_for_output(label => $warn, total => $th_total, cast_int => $cast_int), critical => $self->{perfdata}->get_perfdata_for_output(label => $crit, total => $th_total, cast_int => $cast_int), min => $min, max => $max ); } } sub eval { my ($self, %options) = @_; if ($self->{safe_test} == 0) { my ($code) = centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'Safe', no_quit => 1 ); if ($code == 0) { $self->{safe} = Safe->new(); $self->{safe}->share('$values'); } $self->{safe_test} = 1; } my $result; if (defined($self->{safe})) { our $values = $self->{result_values}; $result = $self->{safe}->reval($options{value}, 1); if ($@) { die 'Unsafe code evaluation: ' . $@; } } else { my $values = $self->{result_values}; { local $SIG{__WARN__} = sub {}; # ignore $result = eval "$options{value}"; if ($@) { die 'Code evaluation error: ' . $@; } } } return $result; } sub execute { my ($self, %options) = @_; my $old_datas = {}; $self->{result_values} = {}, $self->{error_msg} = undef; my $quit = 0; $options{new_datas} = {} if (!defined($options{new_datas})); foreach my $value (@{$self->{key_values}}) { if (!defined($options{values}->{$value->{name}}) || defined($value->{no_value}) && $options{values}->{$value->{name}} eq $value->{no_value}) { $quit = 2; last; } if ((defined($value->{diff}) && $value->{diff} == 1) || (defined($value->{per_minute}) && $value->{per_minute} == 1) || (defined($value->{per_second}) && $value->{per_second} == 1)) { $options{new_datas}->{$self->{instance} . '_' . $value->{name}} = $options{values}->{$value->{name}}; $old_datas->{$self->{instance} . '_' . $value->{name}} = $self->{statefile}->get(name => $self->{instance} . '_' . $value->{name}); if (!defined($old_datas->{$self->{instance} . '_' . $value->{name}})) { $quit = 1; next; } if ($old_datas->{$self->{instance} . '_' . $value->{name}} > $options{new_datas}->{$self->{instance} . '_' . $value->{name}}) { $old_datas->{$self->{instance} . '_' . $value->{name}} = 0; } } else { $options{new_datas}->{$self->{instance} . '_' . $value->{name}} = $options{values}->{$value->{name}}; if (defined($self->{statefile})) { $old_datas->{$self->{instance} . '_' . $value->{name}} = $self->{statefile}->get(name => $self->{instance} . '_' . $value->{name}); } } } # Very manual if ($self->{manual_keys} == 1) { foreach my $name (keys %{$options{values}}) { $options{new_datas}->{$self->{instance} . '_' . $name} = $options{values}->{$name}; if (defined($self->{statefile})) { $old_datas->{$self->{instance} . '_' . $name} = $self->{statefile}->get(name => $self->{instance} . '_' . $name); } } } if ($quit == 2) { $self->{error_msg} = 'skipped (no value(s))'; return -10; } if (defined($self->{statefile})) { $self->{last_timestamp} = $self->{statefile}->get(name => 'last_timestamp'); } if ($quit == 1) { $self->{error_msg} = 'Buffer creation'; return -1; } my $delta_time; if (defined($self->{statefile}) && defined($self->{last_timestamp})) { $delta_time = $options{new_datas}->{last_timestamp} - $self->{last_timestamp}; if ($delta_time <= 0) { $delta_time = 1; } } if (defined($self->{closure_custom_calc})) { return $self->{closure_custom_calc}->( $self, old_datas => $old_datas, new_datas => $options{new_datas}, delta_time => $delta_time, extra_options => $self->{closure_custom_calc_extra_options} ); } return $self->calc(old_datas => $old_datas, new_datas => $options{new_datas}, delta_time => $delta_time); } 1; __END__ centreon-plugins-20220113/centreon/plugins/wsman.pm000066400000000000000000000544761417000230700222350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package centreon::plugins::wsman; use strict; use warnings; use openwsman; use MIME::Base64; my %auth_method_map = ( noauth => $openwsman::NO_AUTH_STR, basic => $openwsman::BASIC_AUTH_STR, digest => $openwsman::DIGEST_AUTH_STR, pass => $openwsman::PASS_AUTH_STR, ntlm => $openwsman::NTLM_AUTH_STR, gssnegotiate => $openwsman::GSSNEGOTIATE_AUTH_STR, ); sub new { my ($class, %options) = @_; my $self = {}; bless $self, $class; # $options{options} = options object # $options{output} = output object # $options{exit_value} = integer if (!defined($options{output})) { print "Class wsman: Need to specify 'output' argument.\n"; exit 3; } if (!defined($options{options})) { $options{output}->add_option_msg(short_msg => "Class wsman: Need to specify 'options' argument."); $options{output}->option_exit(); } $options{options}->add_options(arguments => { "hostname|host:s" => { name => 'host' }, "wsman-port:s" => { name => 'wsman_port', default => 5985 }, "wsman-path:s" => { name => 'wsman_path', default => '/wsman' }, "wsman-scheme:s" => { name => 'wsman_scheme', default => 'http' }, "wsman-username:s" => { name => 'wsman_username' }, "wsman-password:s" => { name => 'wsman_password' }, "wsman-timeout:s" => { name => 'wsman_timeout', default => 30 }, "wsman-proxy-url:s" => { name => 'wsman_proxy_url', }, "wsman-proxy-username:s" => { name => 'wsman_proxy_username', }, "wsman-proxy-password:s" => { name => 'wsman_proxy_password', }, "wsman-debug" => { name => 'wsman_debug', }, "wsman-auth-method:s" => { name => 'wsman_auth_method', default => 'basic' }, "wsman-errors-exit:s" => { name => 'wsman_errors_exit', default => 'unknown' }, }); $options{options}->add_help(package => __PACKAGE__, sections => 'WSMAN OPTIONS'); ##### $self->{client} = undef; $self->{output} = $options{output}; $self->{wsman_params} = {}; $self->{error_msg} = undef; $self->{error_status} = 0; return $self; } sub connect { my ($self, %options) = @_; if (!$self->{output}->is_litteral_status(status => $self->{wsman_errors_exit})) { $self->{output}->add_option_msg(short_msg => "Unknown value '" . $self->{wsman_errors_exit} . "' for --wsman-errors-exit."); $self->{output}->option_exit(exit_litteral => 'unknown'); } openwsman::set_debug(1) if (defined($self->{wsman_params}->{wsman_debug})); $self->{client} = new openwsman::Client::($self->{wsman_params}->{host}, $self->{wsman_params}->{wsman_port}, $self->{wsman_params}->{wsman_path}, $self->{wsman_params}->{wsman_scheme}, $self->{wsman_params}->{wsman_username}, $self->{wsman_params}->{wsman_password}); if (!defined($self->{client})) { $self->{output}->add_option_msg(short_msg => 'Could not create client handler'); $self->{output}->option_exit(exit_litteral => $self->{wsman_errors_exit}); } if ($self->{wsman_params}->{wsman_scheme} eq 'https') { # Dont verify $self->{client}->transport()->set_verify_peer(0); $self->{client}->transport()->set_verify_host(0); } $self->{client}->transport()->set_auth_method($auth_method_map{$self->{wsman_params}->{wsman_auth_method}}); $self->{client}->transport()->set_timeout($self->{wsman_params}->{wsman_timeout}); if (defined($self->{wsman_params}->{wsman_proxy_url})) { $self->{client}->transport()->set_proxy($self->{wsman_params}->{wsman_proxy_url}); if (defined($self->{wsman_params}->{wsman_proxy_username}) && defined($self->{wsman_params}->{wsman_proxy_password})) { $self->{client}->transport()->set_proxyauth($self->{wsman_params}->{wsman_proxy_username} . ':' . $self->{wsman_params}->{wsman_proxy_password}); } } } sub execute_winshell_commands { my ($self, %options) = @_; # $options{keep_open} = integer # $options{commands} = ref array of hash ([{label => 'myipconfig', value => 'ipconfig /all' }]) my ($dont_quit) = (defined($options{dont_quit}) && $options{dont_quit} == 1) ? 1 : 0; $self->set_error(); my $uri = 'http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd'; my $namespace = 'http://schemas.microsoft.com/wbem/wsman/1/windows/shell'; my $command_result = {}; my ($command_id, $client_options, $data, $result, $node); # Init result foreach my $command (@{$options{commands}}) { $command_result->{$command->{label}} = {stdout => undef, stderr => undef, exit_code => undef}; } if (!defined($self->{shell_id})) { $self->{shell_id} = undef; ###### # Start Shell $client_options = new openwsman::ClientOptions::() or $self->internal_exit(msg => 'Could not create client options handler'); $client_options->set_timeout(30 * 1000); # 30sec $client_options->add_selector('Name', 'Themes'); $client_options->add_option('WINRS_NOPROFILE', 'FALSE'); $client_options->add_option('WINRS_CODEPAGE', '437'); # utf-8 $data = new openwsman::XmlDoc::('Shell', $namespace) or $self->internal_exit(msg => 'Could not create XmlDoc'); $data->root()->add($namespace, 'InputStreams', 'stdin'); $data->root()->add($namespace, 'OutputStreams', 'stdout stderr'); $result = $self->{client}->create($client_options, $uri, $data->string(), length($data->string()), "utf-8"); return undef if ($self->handle_dialog_fault(result => $result, msg => 'Create failed: ', dont_quit => $dont_quit)); $node = $result->root()->find(undef, 'Selector') or $self->internal_exit(msg => 'No shell id returned'); $self->{shell_id} = $node->text(); } foreach my $command (@{$options{commands}}) { ####### # Issue command $client_options = new openwsman::ClientOptions::() or $self->internal_exit(msg => 'Could not create client options handler'); $client_options->set_timeout(30 * 1000); # 30sec $client_options->add_option('WINRS_CONSOLEMODE_STDIN', 'TRUE'); $client_options->add_option('WINRS_SKIP_CMD_SHELL', 'FALSE'); $client_options->add_selector('ShellId', $self->{shell_id}); $data = new openwsman::XmlDoc::('CommandLine', $namespace) or $self->internal_exit(msg => 'Could not create XmlDoc'); $data->root()->add($namespace, 'Command', $command->{value}); $result = $self->{client}->invoke($client_options, $uri, 'http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Command', $data); return undef if ($self->handle_dialog_fault(result => $result, msg => 'Invoke failed: ', dont_quit => $dont_quit)); $node = $result->root()->find(undef, 'CommandId') or $self->internal_exit(msg => 'No command id returned'); $command_id = $node->text(); ####### # Request stdout/stderr $client_options = new openwsman::ClientOptions::() or $self->internal_exit(msg => 'Could not create client options handler'); $client_options->set_timeout(30 * 1000); # 30sec $client_options->add_selector('ShellId', $self->{shell_id}); $data = new openwsman::XmlDoc::('Receive', $namespace); $node = $data->root()->add($namespace, 'DesiredStream', 'stdout stderr') or $self->internal_exit(msg => 'Could not create XmlDoc'); $node->attr_add(undef, 'CommandId', $command_id); my $timeout_global = 30; #seconds my $wait_timeout_done = 0; my $loop_out = 1; my ($current_stdout, $current_stderr) = ('', ''); while ($loop_out == 1 && $wait_timeout_done < $timeout_global) { $result = $self->{client}->invoke($client_options, $uri, 'http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Receive', $data); return undef if ($self->handle_dialog_fault(result => $result, msg => 'Invoke failed: ', dont_quit => $dont_quit)); my $response = $result->root()->find($namespace, 'ReceiveResponse') or $self->internal_exit(msg => 'No ReceiveResponse'); ###### # Parsing Reponse for (my $cnt = 0; $cnt < $response->size(); $cnt++) { my $node = $response->get($cnt); my $node_command = $node->attr_find(undef, 'CommandId') or $self->internal_exit(msg => 'No CommandId in ReceiveResponse'); if ($node_command->value() ne $command_id) { $self->internal_exit(msg => 'Wrong CommandId in ReceiveResponse node'); } if ($node->name() eq 'Stream') { my $node_tmp = $node->attr_find(undef, 'Name'); if (!defined($node_tmp)) { next; } my $stream_type = $node_tmp->value(); my $output = decode_base64($node->text()); next if (!defined($output) || $output eq ''); if ($stream_type eq 'stderr') { $current_stderr .= $output; } if ($stream_type eq 'stdout') { $current_stdout .= $output; } } if ($node->name() eq 'CommandState') { my $node_tmp = $node->attr_find(undef, 'State'); if (!defined($node_tmp)) { next; } my $state = $node_tmp->value(); if ($state eq 'http://schemas.microsoft.com/wbem/wsman/1/windows/shell/CommandState/Done') { my $exit_code = $node->find(undef, 'ExitCode'); if (defined($exit_code)) { $command_result->{$command->{label}}->{exit_code} = $exit_code->text(); } else { $self->internal_exit(msg => "No exit code for 'done' command"); } $loop_out = 0; } elsif ($state eq 'http://schemas.microsoft.com/wbem/wsman/1/windows/shell/CommandState/Running') { # we wait $wait_timeout_done += 3; sleep 3; } elsif ($state eq 'http://schemas.microsoft.com/wbem/wsman/1/windows/shell/CommandState/Pending') { # no-op # WinRM 1.1 sends this with ExitCode:0 $loop_out = 0; } else { # unknown $self->internal_exit(msg => 'Unknown command state: ' . $state); } } } } if ($loop_out == 1) { $self->internal_exit(msg => 'Command to long to execute...'); } $current_stderr =~ s/\r//mg; $current_stdout =~ s/\r//mg; $command_result->{$command->{label}}->{stderr} = $current_stderr if ($current_stderr ne ''); $command_result->{$command->{label}}->{stdout} = $current_stdout if ($current_stdout ne ''); # # terminate shell command # # not strictly needed for WinRM 2.0, but WinRM 1.1 requires this # $data = new openwsman::XmlDoc::('Signal', $namespace) or $self->internal_exit(msg => 'Could not create XmlDoc'); $data->root()->attr_add(undef, 'CommandId', $command_id); $data->root()->add($namespace, 'Code', 'http://schemas.microsoft.com/wbem/wsman/1/windows/shell/signal/terminate'); $result = $self->{client}->invoke($client_options, $uri, 'http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Signal', $data); return undef if ($self->handle_dialog_fault(result => $result, msg => 'Invoke failed: ', dont_quit => $dont_quit)); } # Delete Shell resource if (defined($self->{shell_id}) && !(defined($options{keep_open}) && $options{keep_open} == 1)) { my $client_options = new openwsman::ClientOptions::() or die print "[ERROR] Could not create client options handler.\n"; $client_options->set_timeout(30 * 1000); # 30sec $client_options->add_selector('ShellId', $self->{shell_id}); $self->{shell_id} = undef; $result = $self->{client}->invoke($client_options, $uri, 'http://schemas.xmlsoap.org/ws/2004/09/transfer/Delete', undef); return undef if ($self->handle_dialog_fault(result => $result, msg => 'Invoke failed: ', dont_quit => $dont_quit)); } return $command_result; } sub request { my ($self, %options) = @_; # $options{nothing_quit} = integer # $options{dont_quit} = integer # $options{uri} = string # $options{wql_filter} = string # $options{result_type} = string ('array' or 'hash' with a key) # $options{hash_key} = string my ($dont_quit) = (defined($options{dont_quit}) && $options{dont_quit} == 1) ? 1 : 0; my ($nothing_quit) = (defined($options{nothing_quit}) && $options{nothing_quit} == 1) ? 1 : 0; my ($result_type) = (defined($options{result_type}) && $options{result_type} =~ /^(array|hash)$/) ? $options{result_type} : 'array'; $self->set_error(); ###### # Check options if (!defined($options{uri})) { $self->{output}->add_option_msg(short_msg => 'Need to specify uri option'); $self->{output}->option_exit(exit_litteral => $self->{wsman_errors_exit}); } ###### # ClientOptions object my $client_options = new openwsman::ClientOptions::() or $self->internal_exit(msg => 'Could not create client options handler'); # Optimization $client_options->set_flags($openwsman::FLAG_ENUMERATION_OPTIMIZATION); $client_options->set_max_elements(999); ###### # Filter/Enumerate my $filter; if (defined($options{wql_filter})) { $filter = new openwsman::Filter::() or $self->internal_exit(msg => 'Could not create filter'); $filter->wql($options{wql_filter}); } my $result = $self->{client}->enumerate($client_options, $filter, $options{uri}); return undef if ($self->handle_dialog_fault(result => $result, msg => 'Could not enumerate instances: ', dont_quit => $dont_quit)); ###### # Fetch values my ($array_return, $hash_return); $array_return = [] if ($result_type eq 'array'); $hash_return = {} if ($result_type eq 'hash'); my $context; my $total = 0; while (1) { my $nodes = $result->body()->find(undef, "Items"); # Get items. my $items; for (my $cnt = 0; defined($nodes) && ($cnt<$nodes->size()); $cnt++) { my $row_return = {}; for (my $cnt2 = 0; ($cnt2<$nodes->get($cnt)->size()); $cnt2++) { $row_return->{$nodes->get($cnt)->get($cnt2)->name()} = $nodes->get($cnt)->get($cnt2)->text(); } $total++; push @{$array_return}, $row_return if ($result_type eq 'array'); $hash_return->{$row_return->{$options{hash_key}}} = $row_return if ($result_type eq 'hash'); } $context = $result->context() or last; $result = $self->{client}->pull($client_options, $filter, $options{uri}, $context) or last; } # Release context. $self->{client}->release($client_options, $options{uri}, $context) if($context); if ($nothing_quit == 1 && $total == 0) { $self->{output}->add_option_msg(short_msg => "Cant get a single value."); $self->{output}->option_exit(exit_litteral => $self->{option_results}->{wsman_errors_exit}); } if ($result_type eq 'array') { return $array_return; } return $hash_return; } sub check_options { my ($self, %options) = @_; # $options{option_results} = ref to options result $self->{wsman_errors_exit} = $options{option_results}->{wsman_errors_exit}; if (!defined($options{option_results}->{host})) { $self->{output}->add_option_msg(short_msg => "Missing parameter --hostname."); $self->{output}->option_exit(); } $self->{wsman_params}->{host} = $options{option_results}->{host}; if (!defined($options{option_results}->{wsman_scheme}) || $options{option_results}->{wsman_scheme} !~ /^(http|https)$/) { $self->{output}->add_option_msg(short_msg => "Wrong scheme parameter. Must be 'http' or 'https'."); $self->{output}->option_exit(); } $self->{wsman_params}->{wsman_scheme} = $options{option_results}->{wsman_scheme}; if (!defined($options{option_results}->{wsman_auth_method}) || !defined($auth_method_map{$options{option_results}->{wsman_auth_method}})) { $self->{output}->add_option_msg(short_msg => "Wrong wsman auth method parameter. Must be 'basic', 'noauth', 'digest', 'pass', 'ntlm' or 'gssnegotiate'."); $self->{output}->option_exit(); } $self->{wsman_params}->{wsman_auth_method} = $options{option_results}->{wsman_auth_method}; if (!defined($options{option_results}->{wsman_port}) || $options{option_results}->{wsman_port} !~ /^([0-9]+)$/) { $self->{output}->add_option_msg(short_msg => "Wrong wsman port parameter. Must be an integer."); $self->{output}->option_exit(); } $self->{wsman_params}->{wsman_port} = $options{option_results}->{wsman_port}; $self->{wsman_params}->{wsman_path} = $options{option_results}->{wsman_path}; $self->{wsman_params}->{wsman_username} = $options{option_results}->{wsman_username}; $self->{wsman_params}->{wsman_password} = $options{option_results}->{wsman_password}; $self->{wsman_params}->{wsman_timeout} = $options{option_results}->{wsman_timeout}; $self->{wsman_params}->{wsman_proxy_url} = $options{option_results}->{wsman_proxy_url}; $self->{wsman_params}->{wsman_proxy_username} = $options{option_results}->{wsman_proxy_username}; $self->{wsman_params}->{wsman_proxy_password} = $options{option_results}->{wsman_proxy_password}; $self->{wsman_params}->{wsman_debug} = $options{option_results}->{wsman_debug}; } sub handle_dialog_fault { my ($self, %options) = @_; my $result = $options{result}; my $msg = $options{msg}; unless($result && $result->is_fault eq 0) { my $fault_string = $self->{client}->fault_string(); my $msg = 'Could not enumerate instances: ' . ((defined($fault_string)) ? $fault_string : 'use debug option to have details'); if ($options{dont_quit} == 1) { $self->set_error(error_status => -1, error_msg => $msg); return 1; } $self->{output}->add_option_msg(short_msg => $msg); $self->{output}->option_exit(exit_litteral => $self->{wsman_errors_exit}); } return 0; } sub internal_exit { my ($self, %options) = @_; $self->{output}->add_option_msg(short_msg => $options{msg}); $self->{output}->option_exit(exit_litteral => $self->{wsman_errors_exit}); } sub set_error { my ($self, %options) = @_; # $options{error_msg} = string error # $options{error_status} = integer status $self->{error_status} = defined($options{error_status}) ? $options{error_status} : 0; $self->{error_msg} = defined($options{error_msg}) ? $options{error_msg} : undef; } sub error_status { my ($self) = @_; return $self->{error_status}; } sub error { my ($self) = @_; return $self->{error_msg}; } sub get_hostname { my ($self) = @_; my $host = $self->{wsman_params}->{host}; return $host; } sub get_port { my ($self) = @_; return $self->{wsman_params}->{wsman_port}; } 1; __END__ =head1 NAME WSMAN global =head1 SYNOPSIS wsman class =head1 WSMAN OPTIONS Need at least openwsman-perl version >= 2.4.0 =over 8 =item B<--hostname> Hostname to query (required). =item B<--wsman-port> Port (default: 5985). =item B<--wsman-path> Set path of URL (default: '/wsman'). =item B<--wsman-scheme> Set transport scheme (default: 'http'). =item B<--wsman-username> Set username for authentification. =item B<--wsman-password> Set username password for authentification. =item B<--wsman-timeout> Set HTTP Transport Timeout in seconds (default: 30). =item B<--wsman-auth-method> Set the authentification method (default: 'basic'). =item B<--wsman-proxy-url> Set HTTP proxy URL. =item B<--wsman-proxy-username> Set the proxy username. =item B<--wsman-proxy-password> Set the proxy password. =item B<--wsman-debug> Set openwsman debug on (Only for test purpose). =item B<--wsman-errors-exit> Exit code for wsman Errors (default: unknown) =back =head1 DESCRIPTION B. =cutcentreon-plugins-20220113/centreon_plugins.pl000077500000000000000000000017351417000230700211600ustar00rootroot00000000000000#!/usr/bin/perl # # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # use strict; use warnings; # Not perl embedded compliant at all use FindBin; use lib "$FindBin::Bin"; # use lib '/usr/lib/nagios/plugins/'; use centreon::plugins::script; centreon::plugins::script->new()->run(); centreon-plugins-20220113/changelog000066400000000000000000001140021417000230700171040ustar00rootroot000000000000002022-01-13 Quentin Garnier * Plugin added: AWS FSx * Plugin added: Azure Virtual Machine Scale Sets * Plugin added: Barracuda Message Archiver SNMP * Plugin added: Dell OME-M SNMP * Plugin added: Fortinet FortiSwitch SNMP * Plugin added: Hikvision NVR ISAPI * Plugin added: Hikvision NVR SNMP * Plugin added: HPE Simplivity Rest API * Plugin added: Lenovo RackSwitch SNMP * Plugin added: Microsens G6 SNMP * Plugin added: Redis Sentinel * Break: [mssql] 'backup-age' 2021-12-15 Quentin Garnier * Plugin added: IBM DB2 * Plugin added: Wallix Bastion SNMP * Plugin added: pdu Gude SNMP * Plugin added: Nvidia gpu smi * Plugin added: Ericsson ENMP API * Plugin added: Netgear Sseries SNMP * Core: add strong snmp authentication (net-snmp 5.9.1) * Core: add HashiCorpVault password manager * Mode added: [fortigate/snmp] 'sdwan' * Break: [redis] refactoring * Break: [netapp/ontap/snmp] 'qtree-usage' mode renamed 'quotas' 2021-11-02 Quentin Garnier * Plugin added: IBM MQ Rest API * Plugin added: HP Moonshot SNMP * Plugin added: Dell PowerStore Rest API * Plugin added: Cisco ESA Rest API * Plugin added: Azure Compute Disks * Plugin added: Azure Insights Metrics * Plugin added: AS400 Connector * Break: [fritzbox] refactoring 2021-09-15 Quentin Garnier * Plugin added: Fortinet Fortiweb SNMP * Plugin added: Tplink SNMP * Plugin added: Grafana * Plugin added: Symbolg Wing SNMP * Plugin added: Jvm actuator * Plugin added: Azure Container Registry * Plugin added: Barco ClickShare Rest API * Plugin added: HashiCorp Vault Rest API * Core: passmanager change library for keepass v4 * Break: [infoblox/snmp] remove cpu/memory modes - add system mode * Break: [qnap/snmp] es serie managed, rename volume-usage 2021-05-20 Quentin Garnier * Plugin added: Azure MySQL * Plugin added: Azure EventGrid * Plugin added: Azure ServiceBus * Plugin added: Azure AutomationAccount * Plugin added: Azure SignalR * Plugin added: Azure FrontDoor * Plugin added: Azure App Service * Plugin added: Azure EventHub * Plugin added: Azure Functions * Plugin added: Azure Application Gateway * Plugin added: Azure Application Insights * Plugin added: Azure Cosmos DB * Plugin added: Azure App Service Plan * Plugin added: Cisco WAP SNMP * Plugin added: Huawei OceanStor SNMP * Plugin added: Proxmox MG API * Plugin added: Ubiquiti Unifi SNMP * Core: secure plugins options * Core: use package Pod::Simple::Search * Mode added: [linux/local] 'check-plugin' * Mode added: [protocol/snmp] 'collection' * Mode added: [veeam] 'licenses' 2021-02-18 Quentin Garnier * Plugin added: Google Cloud CloudSQL MySQL * Plugin added: Google Cloud Storage * Plugin added: Azure Load Balancer * Plugin added: Azure Firewall * Plugin added: Azure Public IPs * Plugin added: Azure Key Vaults * Plugin added: Notification Jasmin SMS * Plugin added: Athonet ePC SNMP * Plugin added: Meru SNMP * Plugin added: Ubiquiti Airfiber SNMP * Plugin added: EMC PPMA Rest API * Plugin added: DenyALL SNMP * Mode added: [cisco/standard/snmp] 'aaa-servers' * Break: refactoring for protocol x509 2021-01-13 Quentin Garnier * Plugin added: Hitachi HCP SNMP * Plugin added: Aruba AOS-CX Rest API * Plugin added: Aruba AOS-CX SNMP * Plugin added: Fortinet Fortiauthenticator SNMP * Plugin added: Cisco DNAC Rest API * Plugin added: Oracle OVM Rest API * Plugin added: Cisco Firepower FMC API * Plugin added: Cisco Firepower Fxos SNMP * Plugin added: Rubrik Rest API * Plugin added: AWS SES * Plugin added: AWS TransitGateway * Plugin added: Commvault Commserve Rest API * Plugin added: Alyvix Rest API * Plugin added: SmarterMail Rest API * Plugin added: Cyberpower UPS SNMP * Plugin added: Cyberpower PDU SNMP * Plugin added: Cisco CTS SNMP * Plugin added: Microsoft DHCP SNMP * Plugin added: FiberStore SNMP * Plugin added: Socomec NetVision SNMP * Plugin added: HMS Ewon SNMP * Plugin added: GSuite * Plugin added: RRDtool * Plugin added: Notification Microsoft Teams * Core: add option --insecure for backend http * Core: option --list-plugin working with Par::Packer * Mode added: [cisco/standard/snmp] 'vpc' * Mode added: [emc/celerra/local] 'filesystems' * Mode added: [emc/celerra/local] 'pools' * Mode added: [synology/snmp] 'upgrade' * Mode added: [mikrotik/snmp] 'firmware' * Break: move microsoft applications 2020-10-08 Quentin Garnier * Plugin added: Cisco CUCM SXML * Plugin added: DRBD * Plugin added: Pexip Infinity Management API * Plugin added: Polycom RPRM SNMP * Plugin added: Polycom DMA SNMP * Plugin added: Polycom HDX SNMP * Plugin added: Aws SQS * Plugin added: Aws SNS 2020-08-03 Quentin Garnier * Plugin added: Netapp Ontap Rest API * Plugin added: Netdata Rest API * Plugin added: Gorgone Rest API * Plugin added: Nimble Rest API * Plugin added: Cisco SSMS Rest API * Plugin added: Loggly * Plugin added: Nginx Plus Rest API * Plugin added: IP-Label newtest Rest API * Plugin added: Aws Health * Core: add option --no-component-count (#2062) * Core: can use unknown thresholds for counter modes * Mode added: [cisco/standard/snmp] 'vss' * Mode added: [paloalto/standard/snmp] 'signatures' * Mode added: [checkpoint/snmp] 'ra-users' * Break: [linux/local] refactoring * Break: [iis/local] refactoring * Break: [ansible/tower] refactoring 2020-06-02 Quentin Garnier * Plugin added: pfsense FauxAPI * Plugin added: IIS Rest API * Plugin added: Amazon EBS * Plugin added: IP-Label datametrie API * Plugin added: ActiveMQ JMX * Plugin added: VerneMQ Rest API * Plugin added: Ruckus SmartZone SNMP * Plugin added: Ruckus ZoneDirector SNMP * Plugin added: Ruckus ICX SNMP * Plugin added: Dell Xseries SNMP * Plugin added: Adva FSP150 SNMP * Plugin added: Lenovo Iomega SNMP * Plugin added: Netapp Santricity Rest API * Plugin added: Timelinkmicro tms6001 SNMP * Plugin added: Bluemind * Plugin added: Mulesoft Rest API * Plugin added: Salesforce Rest API * Plugin added: Versa SNMP * Break: [netapp/snmp] move directory * Break: [netapp/restapi] move directory 2020-04-10 Quentin Garnier * Plugin added: Dell OS10 SNMP * Plugin added: Sirportly notification * Plugin added: Mobotix Camera SNMP * Plugin added: Ibm MQ MQI * Plugin added: Supermicro BMC SNMP * Plugin added: Eltek Enexus SNMP * Plugin added: Cisco Meraki Rest API * Plugin added: Aws EFS * Core: add backend ssh system (plink, ssh and libssh) * Mode added: [azure] 'alert' * Mode added: [checkpoint/snmp] 'vsx' * Mode added: [synology/snmp] 'ha' * Mode added: [cisco/standard/snmp] 'wan3g' * Break: [fortigate/snmp] 'cpu', 'memory', 'vdom' (merge) * Break: [supermicro/snmp] move directory 2020-02-04 Quentin Garnier * Plugin added: Allied Telesis SNMP * Plugin added: UPS HP SNMP * Plugin added: HP ILO Rest API * Plugin added: UPS Phoenixtec SNMP * Plugin added: AWS Cloudwatch logs * Plugin added: Cisco Collaboration Endpoint Rest API * Plugin added: Polycom Trio Rest API * Plugin added: Libraesva SNMP * Plugin added: Dynatrace Rest API * Plugin added: Hyperledger Exporter * Plugin added: Prowl notification * Mode added: [paloalto/snmp] 'gp-usage' * Mode added: [centreon/local] 'centengine-stats' * Mode added: [oracle] 'dataguard' * Mode added: [netapp/snmp] 'failover' 2019-12-19 Quentin Garnier * Plugin added: CouchDB Rest API * Plugin added: Maltem Insight Performance Rest API * Plugin added: Hikvision camera SNMP * Plugin added: Avaya CM SNMP * Plugin added: Palo Alto SSH * Plugin added: Rapid Recovery Quest SNMP * Mode added: [linux/snmp] 'udpcon' * Mode added: [cisco/standard/snmp] 'load' * Mode added: [3cx/restapi] 'extensions' * Mode added: [aix/local] 'cmd-return' * Fix: Ctrl+F "Fix" on commits page 2019-10-16 Colin Gagnaire * Plugin added: ABB CMS700 SNMP * Mode added: [linux/local] 'discovery-nmap' * Mode added: [hp/procurve] 'virtual-chassis' * Mode added: [azure] 'health' * Enhancement: [emerson/liebert] merge plugins * Enhancement: [fortigate] enhance vpn mode * Enhancement: [extreme/snmp] refacto modes * Enhancement: [core] add mode status in openmetrics output * Enhancement: [netapp/snmp] enhance snapmirrorlag * Enhancement: [linux/local] refacto diskio mode * Break: [f5/bigip] use status thresholds in virtual-server-status * Fix: [nrpe] fix SSL context * Fix: Ctrl+F "Fix" on commits page 2019-10-02 Quentin Garnier * Plugin added: Warp10 Sensision * Plugin added: OpenMetrics * Plugin added: AWS API Gateway Api * Plugin added: AWS Kinesis Api * Plugin added: Hanwha Camera SNMP * Plugin added: Perle IDS SNMP * Plugin added: Scom Rest API * Plugin added: Wazuh Rest API * Plugin added: Zoom Rest API * Plugin added: VMWare VCSA Rest API * Plugin added: EMC Unisphere Rest API * Plugin added: Nitram UPS SNMP * Plugin added: Quanta.io Rest API * Plugin added: HP OneView * Plugin added: Geist * Mode added: [oracle] 'fra-usage' * Mode added: [oracle] 'tablespace-usage' * Mode added: [hp p2000] 'vdisks' * Mode added: [windows] 'list-services' * Mode added: [os] 'list-processes' * Enhancement: [core] add global timeout option * Enhancement: [cisco/standard/snmp] add err disable interfaces * Enhancement: [oracle] add container option * Enhancement: [snmp_standard] 'memory' add option for redhat * Enhancement: [nsclient] handle new rest api * Enhancement: [aruba/standard] enhance modes to use ap name * Enhancement: [azure] allow multiple metrics in monitor getmetrics mode * Enhancement: [aws/paws] add proxyurl option * Break: [ucopia] modes refactoring * Break: [aws] metrics forced to new format for billing, cloudfront, elb, ec2, lambda breaks thresholds * Break: [oracle] merged modes temp-tablespace and undo-tablespace into tablespace-usage * Fix: Ctrl+F "Fix" on commits page 2019-07-04 Quentin Garnier * Plugin added: RabbitMQ Rest API * Plugin added: VMware VeloCloud Rest API * Plugin added: InfluxDB * Plugin added: MongoDB * Plugin added: Aruba Instant SNMP * Plugin added: Cisco ACI APIC Rest API * Plugin added: OpenLDAP * Plugin added: SCCM * Plugin added: Cisco ESA XML API * Plugin added: Protocol NRPE * Plugin added: Ovirt Rest API * Plugin added: Keepalived SNMP * Plugin added: Openweathermap Rest API * Plugin added: 3CX Rest API * Plugin added: Atto FiberBridge SNMP * Plugin added: Buffalo TeraStation SNMP * Plugin added: PDU Schleifenbauer Gateway SNMP * Plugin added: Ansible Tower * Plugin added: Dell ME4 Rest API * Plugin added: Avaya AES SNMP * Plugin added: Arcseve UDP MSSQL * Mode added: [oracle] 'librarycacheusage' * Mode added: [oracle] 'dictionarycacheusage' * Mode added: [oracle] 'redologusage' * Enhancement: [haproxy/snmp] manage oss mib (#1475) * Enhancement: [oracle] Fix segfault with last DBD::Oracle * Break: [elasticsearch] plugin refactoring * Break: [pdu/apc] modes refactoring * Break: [pdu/eaton] modes refactoring * Break: [apps/lmsensors] modes refactoring * Break: [cisco/standard] 'cpu', 'memory' refactoring * Break: [3par/ssh] modes refactoring * Break: [mysql] 'threads-connected' refactoring * Break: [snmp_standard] 'swap' refactoring * Fix: Ctrl+F "Fix" on commits page 2019-04-12 Quentin Garnier * Plugin added: Google Cloud Platform Compute Engine API * Plugin added: Prometheus NGINX Ingress Controller * Plugin added: Bind9 Web * Plugin added: Rudder Rest API * Plugin added: Kubernetes API * Plugin added: Protocol TFTP * Plugin added: Rad Airmux SNMP * Plugin added: Alvarion Breezeaccess SNMP * Plugin added: Riverbed Interceptor SNMP * Plugin added: WSUS * Plugin added: Sahipro * Mode added: [linux/local] 'ntp' * Mode added: [macafee/webgateway] 'versions' * Mode added: [ups/apc] 'input-lines' * Mode added: [oracle] 'password-expiration' * Mode added: [fortigate] 'ap-usage' * Mode added: [centreon/local] 'bam-services' * Mode added: [linux/local] 'discovery' * Mode added: [aws] 'discovery' * Mode added: [azure] 'discovery' * Mode added: [vmware] 'discovery' * Enhancement: [core] add float-precision option * Enhancement: [core] add --extend-perfdata-group option * Enhancement: [core/http] add curl backend support * Enhancement: [core/http] add debug for lwp backend * Enhancement: [oracle] add servicename support * Enhancement: [snmp_standard] 'storage' (#1042) * Enhancement: [snmp_standard] 'interfaces' (#712) * Enhancement: [snmp_standard] 'list-interfaces' (#713) * Enhancement: [f5/bigip] 'list-virtualservers' (#1252) * Enhancement: [linux/local] 'traffic' 'packet-errors' (#916) * Enhancement: [protocols/http] 'expected-content' * Enhancement: [linux/local] 'process' (#1438) * Enhancement: [cisco/snmp] 'interfaces' (#454) * Enhancement: [hwgste/snmp] 'sensors' (#585) * Enhancement: [azure] better apis responses handling * Fix: Ctrl+F "Fix" on commits page * Break: [dell/equallogic] modes refactoring * Break: [snmp_standard] mode memory refactoring changes thresholds 2019-02-21 Quentin Garnier * Plugin added: Microsoft Azure Recovery and Backup * Plugin added: Microsoft Azure ExpressRoute * Plugin added: Microsoft Azure VPN Gateway * Plugin added: Microsoft Azure Virtual Network * Plugin added: Microsoft Azure SQL Server and Database * Plugin added: Squid SNMP * Plugin added: Informix Database SNMP * Plugin added: Lenovo XCC SNMP * Plugin added: Peplink Pepwave SNMP * Plugin added: Centreon MAP JMX (>= 18.10) * Plugin added: Adder AIM SNMP * Plugin added: Kafka JMX * Plugin added: Cassandra JMX * Plugin added: Office 365 Teams * Plugin added: Office 365 Skype for Business * Plugin added: Skype 2015 MSSQL * Plugin added: HP Standard SNMP * Plugin added: Mac OS SNMP * Mode added: [snmp_standard] 'listspanningtrees' * Mode added: [quantum dxi] 'dedupvtl' * Mode added: [protocols/snmp] 'response-time' * Enhancement: [vmware/connector] compatibility with VMware connector 3.x with enhancement * Enhancement: [azure] many improvements in Azure plugins (tags, dates format) * Enhancement: [office] change metrics behaviour, more global * Enhancement: [core] add password management system * Enhancement: [core/template] add catalog template method * Enhancement: [core/template] enhance counter type 3 * Enhancement: [core/snmp] change snmpv3 management parameters * Enhancement: [core/exec] change exit behaviour in case of failure * Enhancement: [protocols/http] refacto expected-content mode, add possibility to extract data * Enhancement: [database/oracle] add sqlpluscmd connection method * Enhancement: [snmp_standard] spanningtree mode * Enhancement: [centreon/sql] pollerdelay mode * Enhancement: [mssql] 'failed-jobs' (#1365) * Enhancement: [snmp_standard] 'interfaces' (#553) * Enhancement: [prometheus/api] add headers handling * Enhancement: [centreon/sql] add filter for broker stats * Fix: [fortinet/fortigate] enhance cluster status mode * Fix: [core/http] fix get-param option (#1355) * Fix: [ilo xmlapi] fix nic management (#1358 #1213) * Break: [informix/sql] change informix sql plugin path * Break: [vmware/connector] several options changement 2019-01-11 Colin Gagnaire * Plugin added: Office 365 (PR #1288) * Plugin added: IBM Cloud SoftLayer (PR #1224, #1226, #1241, #1273) * Plugin added: PVX API (PR #1246) * Plugin added: Quantum DXI SSH (PR #1280, #1322) * Plugin added: Proxmox VE API (PR #1269, #1270) * Plugin added: cAdvisor API (PR #1299, #1300) * Plugin added: McAfee Web Gateway SNMP (PR #1304) * Plugin added: Netgear ReadyNAS SNMP (PR #1174) * Plugin added: Cisco CMS (PR #1309) * Plugin added: Cisco ISE (PR #1312) * Plugin added: Cisco VCS (PR #1317) * Plugin added: OpenVPN OMI * Plugin added: Avid ISIS SNMP (PR #1174) * Plugin added: MRV OptiSwitch SNMP (PR #1215) * Plugin added: Mikrotik SNMP (PR #1077) * Plugin added: OHV SMS notification (PR #1263) * Plugin added: Telegram notification (PR #1266) * Mode added: [azure] API custom mode (PR #1248, #1276) * Mode added: [fortigate] virtual domains modes (PR #1293) * Mode added: [juniper/mseries] 'ldpsessionstatus', 'lspstatus', 'rsvpsessionstatus' (PR #1297) * Mode added: [purestorage] 'pgroup-replication' (PR #1221) * Mode added: [cisco standard] 'configuration' (#1102, PR #1236) * Mode added: [centreon] 'dummy' (PR #1258) * Mode added: [protocols/x509] 'certificate' (replace 'validity' mode) (PR #1306) * Enhancement: [core/snmp] add requests size autoreducing (PR #1301) * Enhancement: [core/snmp] harden snmp request (#880, PR #1325) * Enhancement: [core] perfdata extension system (PR #1313) * Enhancement: [aws] add proxy and endpoint URL handling (PR #1249) * Enhancement: [windows/snmp] pending reboot output (PR #1222) * Enhancement: [cisco standard] refactor stack mode (PR #1227) * Enhancement: [snmp_standard] refactor diskusage mode (PR #1233) * Enhancement: [fortigate] refactor clusterstatus mode (#343, PR #1238) * Enhancement: [prometheus/cadvisor] allow using % for working memory (PR #1240) * Enhancement: [juniper/mseries] add cache to improve performances (PR #1298) * Enhancement: [cisco standard] enhance cisco environment sensor filter (PR #1303) * Enhancement: [idrac] add SMART alert for disk s * Fix: [core/snmp] fix snmp lib start/end checkup function (PR #1292) * Fix: [core/counter] fix template counter short output handling (PR #1295, #1305) * Fix: [cisco cm/phoneusage] fix typo in long outputs (PR #1230, #1231) * Fix: [storeonce/clusterusage] handling multiple API versions (#1162, PR #1237) * Fix: [silverpeak/loadaverage] wrong OIDs (#1256, PR #1272) * Fix: [mssql] fix MSSQL version bug (#1038) * Fix: [windows/memory] fix real SWAP bug * Fix: [apc/devicestatus] fix empty values bug (#1127) * Fix: [protocols/smtp] better error handling (#1172) * Fix: [huawei/ibmc] fix huawei ibmc raidcontroller bug (#1244, PR #1315) * Fix: [silverpeak] fix alarms mode * Break: [snmp_standard/diskusage] refactoring of diskusage mode breaks thresholds (PR #1233) * Break: [cisco standard] enhance cisco environment sensor filter (PR #1303) 2018-10-31 Colin Gagnaire * Plugin added: Prometheus for cAdvisor (PR #1199) * Plugin added: Axis Video SNMP (PR #1196) * Mode added: [prometheus] 'expression' (PR #1205) * Enhancement: [prometheus] target status mode filtering (PR #1206, #1207) * Enhancement: [prometheus/nodeexporter] nodeexporter filtering (PR #1201) * Enhancement: [prometheus/kubernetes] kubernetes filtering (PR #1197, #1200) * Enhancement: [azure] add subscription option (PR #1189) * Enhancement: [prometheus/api] enh prometheus timeframe/step options (PR #1190) * Fix: [idrac/pdisk] fix typo in long outputs (PR #1194) * Fix: [netapp/qtreeusage] fix qtreeusage mode thresholds (#1193, PR #1195) * Fix: [hyperv2012/nodesnapshot] fix negative timestamp (PR #1192) * Break: [masterclock/ntp] change masterclock plugin path (PR #1191) 2018-10-19 Colin Gagnaire * Plugin added: Prometheus (PR #1168, #1169) * Plugin added: Prometheus for Node Exporter (PR #1168, #1169, #1179) * Plugin added: Prometheus for Kubernetes (PR #1181) * Plugin added: Masterclock NTP GPS (PR #1182) * Plugin added: Moxa EDS/IKS switches (PR #1183) * Enhancement: [counter] add type 3 (instances of instances) (PR #1167, #1178) * Fix: [cloud/azure] fix azure plugin typos, helpers and other (PR #1159) * Fix: [hyperv/nodesnapshot] bug with comma on french Windows OS (PR #1175) * Fix: [slack/alert] host and service not printed (PR #1177) 2018-09-28 Colin Gagnaire * Plugin added: Huawei iBMC (PR #1098, #1108, #1112, #1114) * Plugin added: Huawei HMM (PR #1098, #1113) * Plugin added: Barracuda CloudGen (PR #1109) * Plugin added: Mitel 3300 ICP (PR #1146) * Plugin added: AEG ACM (PR #1147) * Plugin added: Ruckus SmartCell Gateway (PR #1141) * Enhancement: [snmp_standard/cpu] add per core thresholds (PR #1107) * Enhancement: [protocols/dns] add CNAME to possible search type (PR #1143) * Enhancement: [azure] add proxyurl option, update cli installation process (PR #1154) * Enhancement: [snmp_standard/interfaces] add --add-volume option (PR #1157) * Enhancement: [os/freebsd] add standard ntp mode (PR #1152) * Fix: [hp/ilo/pdrive] handle pdrive xml variants (#1087, PR #1105) * Fix: [watchguard/cpu] fix watchguard cpu usage calcul (#1078, PR #1105) * Break: [snmp_standard/cpu] option declaration --(critical|warning)-average instead of --(warning|critical) (PR #1107) * Break: [azure] change paths to providers/services (PR #1154) 2018-08-21 Colin Gagnaire * Plugin added: Microsoft Azure API (PR #1097) * Plugin added: Slack RestAPI (PR #1076) * Plugin added: Peplink Balance SNMP (PR #1015, #1045) * Plugin added: Silverpeak SNMP (PR #1037, #1045) * Plugin added: Cloudfoundry RestAPI (PR #1031) * Mode added: [linux/local] add upgrade mode (PR #1034, #1068) * Mode added: [linux/local] add mountpoint mode (PR #1036, #1043) * Mode added: [hpux/local] add storage and inode modes (PR #955, #1058) * Mode added: [aix/local] add inode modes (PR #956, #1056, #1057) * Mode added: [postgres] add databasesize mode (PR #870, #1046, #1047) * Mode added: [selenium] add seleniumkatalon mode (PR #1039) * Enhancement: [activedirectory/local] add receiving-member option to dfsrbacklog mode (#1088, PR #1089) * Enhancement: [h3c/snmp] enhance h3c hardware mode to allow count thresholds (PR #1080) * Enhancement: [hardware] enhance template hardware to count checked components (PR #1079) * Enhancement: [mssql] enhance database-size mode, add list-database mode (PR #1091) * Enhancement: [common/sql] enhance sqlstring for dual tables (#936, PR #1075) * Enhancement: [windows/snmp] enhance swap mode virtual memory (#928, #929, PR #1069, #1072, #1073) * Enhancement: [mssql] convert blockedprocesses mode to counters (PR #938, #1055, #1066) * Enhancement: [paloalto/snmp] enhance clusterstatus output (PR #1054) * Enhancement: [h3c/snmp] enhance hardware cache (#1005, PR #1049) * Fix: [centreon/database] several bugs on multiservice mode (PR #1094) * Fix: [netapp/restapi] fix netapp restapi volumeusage typo (PR #1074) * Fix: [kaspersky/snmp] fix kaspersky snmp deployment devision by zero (PR #1070) * Fix: [mssql] fix transactions mode case issue (#1059, PR #1067) * Fix: [protocols/radius] correct login mode helper (PR #1060) * Fix: [protocols/http] using a file as JSON source did not work (PR #979) * Fix: [tomcat/web] fix sessions mode regexp (#864, PR #1053) * Fix: [hirschmann/snmp] fix memory mode division by 0 (#999, PR #1052) * Fix: [dell/fastpath] fix temperature mode loop (#1026, PR #1051) * Fix: [fortimanager/snmp] fix devicestatus mode helper (#1009, PR #1050) * Fix: [arista/snmp] fix memory mode output (#1018, PR #1048) * Fix: [idrac/snmp] report idrac installed CPUs only (PR #1017) * Fix: [qnap/hardware] add smartdisk section to allow threshold overload (#1008, PR #1017) * Fix: [netapp/snmp] refactor qtreeusage mode, add not-kbytes option (#1006, PR #1029) * Fix: [snmp_standard/processcount] fix processcount perfdata output typos (PR #1003) * Fix: [windows/snmp] fix physical memory informations (#994, PR #1000) * Break: [mssql] databasesize mode parfdata labels (PR #1091) 2018-05-28 Colin Gagnaire * Enhancement: [http] handle hidden basic authent (#974) * Enhancement: add basic option to mode using http lib (#975) * Enhancement: [sonicwall] enhance modes outputs and thresholds (#978) * Enhancement: [quadstor]{vtltapeusage} add tapes count (#987) * Fix: [f5/bigip]{trunks} div by 0 error (#964) * Fix: [hirschmann]{hardware/psu} wrong oid (#985) * Fix: [cisco/standard]{qosusage} calcul of total and child (#792) 2018-04-27 Colin Gagnaire * Plugin added: Sonicwall SNMP (#914) * Mode added: [juniper/ssg] 'vpnstatus' (#891) * Mode added: [juniper/ssg] 'vpnusage' (#891) * Mode added: [juniper/ssg] 'listvpn' (#891) * Enhancement: [snmp_standard/ntp] improve ntp mode empty ntp_hostname option * Enhancement: [windows/local] improve liststorages * Enhancement: add --ssl-opt on plugin using http library (#961) * Enhancement: [snmp_standard/interfaces] add interfaces speed check (#762, #954) * Enhancement: [riverbed/steelhead/snmp] refactor plugin to handle EX series (#970) * Fix: [netapp/restapi] fix uri uninitialized option in custom mode * Fix: [netapp/restapi] fix snapmiror modes debug output * Fix: [aws/ec2] fix perl 5.10/el6 compatibility (#945) * Fix: [f5/bigip] fix failover warning thresholds (#964) * Fix: [f5/bigip] fix trunks thresholds management (#964) * Doc: correcting mode formely named 'traffic' to 'interfaces' 2018-04-09 Colin Gagnaire * Plugin added: IBM FS900 SNMP * Plugin added: Kaspersky SNMP * Plugin added: NetApp Rest Api * Plugin added: AWS EC2 Api * Plugin added: AWS RDS Api * Plugin added: AWS S3 Api * Plugin added: AWS ELB Api * Plugin added: AWS Cloudfront Api * Plugin added: AWS Billing Api * Plugin added: AWS Elasticache Api * Plugin added: AWS Lambda Api * Mode added: [windows/local] 'liststorages' * Mode added: [mssql] 'logsize' * Mode added: [f5/bigip] 'trunks' * Mode added: [f5/bigip] 'listtrunks' * Enhancement: [vmware]{nethost} add dropped packets * Enhancement: [snmp_standard]{processcount} add per process options, refactor code * Enhancement: [hyperv]{scvmmintegrationservice} add some status * Enhancement: [http] add new useragent.pm library to handle Basic, Digest, Ntlm and Ntlm v2 authentification * Enhancement: [snmp_standard]{spanningtree} add filtering options, refactor code (#780) * Enhancement: [ups/apc]{sensors} show temp in long output (#849) * Fix: [nsclient/restapi] use of uninitialized value issue (#825) * Fix: [hp]{procurve} temperature sensor not present issue (#847) * Fix: [veeam]{jobstatus} argument isn't numeric issue (#863) * Fix: [centreon]{metaservice} use metric name defined in Meta-Service configuration (#874) * Fix: [oracle]{eventwaitusage} event-count option * Fix: [redis/restapi]{*} hashes deref issues * Fix: [activedirectory]{dcdiag} wrong option issue (#902) * Fix: [bluecoat]{hardware} typo in sensor state * Fix: [stormshield]{hanodes} mapping issue * Fix: [f5/bigip]{poolstatus,virtualserverstatus} bad character (#930) 2017-12-22 Quentin Garnier * Plugin added: Pure Storage SNMP * Plugin added: Pure Storage Rest API * Plugin added: Amazon AWS API * Plugin added: Comet P8000 series SNMP * Plugin added: Veeam local * Plugin added: Colubris SNMP * Plugin added: Alpha ups SNMP * Plugin added: Infoblox SNMP * Plugin added: Redis Rest API * Plugin added: Cisco Call Manager SNMP 2017-12-08 Quentin Garnier * Plugin added: Kingdee Rest API * Plugin added: Redis Cli * Plugin added: Ubiquiti Edge SNMP * Plugin added: Arista SNMP * Plugin added: Haproxy SNMP * Plugin added: JBoss JMX * Plugin added: NSClient Query * Break: Renamed Asterisk AMI * Break: Renamed Dell n4000 * Break: Renamed Dell 62000 2017-11-23 Quentin Garnier * Plugin added: Freebox Rest API * Plugin added: Netgear Mseries SNMP * Plugin added: Zyxel SNMP * Add redis support for temporary datas 2017-10-13 Quentin Garnier * Plugin added: Kaminario Rest API * Plugin added: Protocol SSH * Plugin added: Tivoli Storage Manager * Plugin added: Toshiba Storemate * Mode added: [windows] 'pending-reboot' * Mode added: [storeonce] 'nas-usage' * Mode added: [tomcat] 'connector-usage' 2017-09-13 Quentin Garnier * Plugin added: Zookeeper JMX * Plugin added: Solr JMX * Plugin added: Automic Workload Automation JMX * Plugin added: Fujitsu Server SNMP * Plugin added: Foxbox Notification * Break: Netasq renamed to Stormshield 2017-08-11 Quentin Garnier * Plugin added: Ruckus AP SNMP * Plugin added: Adva FSP3000 SNMP * Plugin added: Nokia Timos SNMP * Plugin added: Huawei SNMP * Plugin added: Hibernate JMX * Plugin added: Raisecom SNMP * Break: mode change for Pfsense SNMP * Break: mode change for HP MSL SNMP * Break: mode change for Juniper ISG SNMP * Break: mode change for Digi Standard (sarian now) SNMP 2017-07-13 Quentin Garnier * Plugin added: Supermicro SNMP * Plugin added: QuadStor VTL Local * Plugin added: Docker Rest API * Mode added: [linux] directlvm-usage * Mode added: [oracle] rollback-segment-usage * Mode added: [oracle] event-waits-usage 2017-06-13 Quentin Garnier * Plugin added: HP Eva CLI * Plugin added: Acme Packet SNMP * Plugin added: A10 AX SNMP * Plugin added: OpenHeadend SNMP * Plugin added: Zixi Rest API * Plugin added: Various Evertz SNMP * Plugin added: Qsan Nas SNMP * Plugin added: Citrix SDX SNMP * Plugin added: IBM TS2900 SNMP * Plugin added: Fortinet Fortimanager SNMP * Mode added: [pacemaker] clustat * Break: path change for Alcatel Omniswitch SNMP 2017-05-19 Quentin Garnier * Plugin added: Alteon SNMP * Plugin added: Nutanix SNMP * Plugin added: Citrix Cloudbridge SNMP * Plugin added: Protocol Modbus * Plugin added: Notification HighSMS * Plugin added: Jmeter Scenario * Plugin added: AppearTV SNMP * Plugin added: QSan NAS SNMP * Mode added: [linux] systemd services * Break: path change for Alcatel Omniswitch 2017-03-29 Quentin Garnier * Plugin added: Watchguard SNMP * Plugin added: Intelligence Interactive SNMP * Plugin added: Oracle Infiniband SNMP * Plugin added: Beeware SNMP * Plugin added: Oracle ZFS Storage ZS SNMP * Plugin added: Safenet Keysecure SNMP * Plugin added: Oracle OTD SNMP * Break: path change for Alteon SNMP 2017-03-10 Quentin Garnier * Plugin added: Dell FluidFS SNMP * Plugin added: Clamav * Plugin added: Sendmail SNMP * Plugin added: Centreon DSM * Plugin added: Audiocodes SNMP * Mode added: [snmp_standard] 'vrrp-status' * Mode added: [centreon] 'virtualservice' * Break: path change for Netscaler SNMP * Fix: perl connector issue 2017-02-16 Quentin Garnier * Plugin added: Hyper-v 2012 * Plugin added: Avocent ACS 6000 SNMP * Plugin added: Alcatel PSS 1830 * Mode added:: [hp lefthand] 'volume-usage' * Mode added:: [checkpoint] 'vpn-status' * Mode added:: [f-5 bigip] 'tmm-usage' * Break: path change for F-5 BigIp * Break: path change for Checkpoint 2017-01-20 Quentin Garnier * Plugin added: SAP Hana DB * Plugin added: Efficient IP * Plugin added: IBM TS3500 * Plugin added: Sophos Email Security appliance * Mode added: [hmc] 'led-status' * Add a special mode to send SNMP trap * Break: path changed for IBM TS3100 and TS3200 2016-12-12 Quentin Garnier * Plugin added: to check Cisco Meraki Cloud Ctrl SNMP * Plugin added: to check Polycom RMX SNMP * Plugin added: to check Exagrid SNMP * Plugin added: to check Cisco Prime Wireless SNMP * Mode added: [snmp_standard] 'numeric-value' * Mode added: [fortigate] 'signatures' * Mode added: [cisco standard] 'qos-usage' * Mode added: [cisco standard] 'ipsec-tunnel' * Enhancement: [checkpoint] major update * Enhancement: [protocol bgp] major update 2016-11-21 Quentin Garnier * Plugin added: to check Jacarta Sensor SNMP * Plugin added: to check Safenet HSM * Plugin added: to check HP ILO XML API * Plugin added: to check EMC Isilon SNMP * Plugin added: to check APC NetBotz SNMP * Enhancement: [apc ats] major update * Enhancement: [hwgste] update * Fix: [sonus] namespace issue (#532) * Fix: [snmp_standard]{storage} cache issue (#523) 2016-10-14 Quentin Garnier * Plugin added: to check StorageTek SLxxx * Plugin added: to check HP Storeonce Rest API * Plugin added: to check Gorgy ntpserver SNMP * Plugin added: to check Nortel/Avaya SNMP * Plugin added: to check Vtom Rest API * Plugin added: to check Sybase * Plugin added: to check Cyberoam SNMP (#517) * Minor fixes and enhancement 2016-09-02 Quentin Garnier * Plugin added: to check HP-UX SNMP (#13) * Plugin added: to check Hitachi HNAS * Plugin added: to check Overland Neo Series * Plugin added: to check Quantum Scalar * Plugin added: to check HP Storeonce SSH * Fix: [pdu emerson]{global-status} wrong status 2016-08-03 Quentin Garnier * Plugin added: to check IBM Storwize (#438) * Plugin added: to check Sonus SBC * Plugin added: to check Aerohive * Plugin added: to check Digi routers * Plugin added: to check telnet sessions * Plugin added: to check china clever PDU * Plugin added: to check Cisco Voice Gateway * Some minor fix and enhancement 2016-06-27 Quentin Garnier * Update FAQ: build a standalone perl script * Plugin added: to check Lenovo S Series (#412) * Plugin added: to check Digi AnywhereUSB * Mode added: [netasq] 'ha-nodes' * Mode removed: [netasq] 'ha-status' * Fix: [dell n4000]{environment} wrong temperature (#397) * Fix: [netapp]{cache-age} not working (#422) * Fix: [cisco wlc]{ap-users} wrong total * Fix: [tomcat]{memory} problem with java 8 * Fix: [netapp]{filesys} no values (#415) 2016-05-24 Quentin Garnier * Can use '/' instead '::' for plugin option (#380) * Mode added: [pacemaker] 'constraints' * Mode added: [netbackup] 'tape-usage' * Mode added: [oracle] 'data-files-status' * Mode added: [netasq] 'connections' * Enhancement: [cisco wlc]{ap-users} get users by AP (#375) * Enhancement: [oracle]{tablespace} can use free size left * Fix: [pdu apc]{load} incorrect values (#408) * Fix: [mscs] Issue with old versions * Fix: [postgres]{timesync} threshold issue * Fix: [ntp]{offset} time formula issue * Fix: [github]{issues} Get only issue * Fix: [netasq]{memory} Use BSD memory check * Fix: [tomcat]{applications} Issue on Windows (#356) 2016-03-24 Quentin Garnier * Plugin added: to check AKCP SensorProbe * Plugin added: to check Juniper ISG * Plugin added: to check OSPF protocol * Plugin added: to check Microsoft Cluster Service * Plugin added: to check Dell Compellent in SNMP and Powershell SDK * Enhancement: [snmp_standard]{string-value} Many changes (#228) * Fix: [raritan] OnOff sending errors (#348) 2016-02-20 Quentin Garnier * Add a class for FatPacker system 2016-02-17 Quentin Garnier * Plugin added: to check Kemp * Plugin added: to check Netbackup * Plugin added: to check Ucopia Wireless Controller * Plugin added: to check Emerson Liebert PDU * Plugin added: to check Microsoft Lync 2013 * Plugin added: to check TemPERHum sensors * Mode added: [mysql] 'table-size' * Mode added: [centreon] 'count-services' * Mode added: [iDrac] 'hardware' (for iDrac 8) * Enhancement: [xtremio] hardened code * Enhancement: [cisco asa]{sessions} better metrics (#315) * Enhancement: [freebsd]{memory} More real values * Fix: [oracle]{tablespace-usage} Usage more than 100% * Fix: [clariion]{disks} Last disks was missing * Fix: [mssql]{failed-jobs} wrong thresholds 2016-01-22 Quentin Garnier * Plugin added: Add a plugin to check Juniper Trapeze in SNMP * Plugin added: Add a plugin to check Dell ML6000 in SNMP * Plugin added: Add a plugin to check UPS APC in SNMP * Plugin added: Add a plugin to check HP VC in SNMP * Major fix on sanity mechanism for options * Add option '--filter-uom' in core library (#220) * Add some new classes for code refactoring * Add 'get_header' method in http library * Fix 'proxypac' in http library (#263) * Mode added: [github] 'stats' * Mode added: [netapp] 'cache-age' * Mode added: [datadomain] 'replication' * Enhancement: [cisco standard]{ipsla} hardened code * Enhancement: [github]{issues} change api call method (#257) * Enhancement: [selenium]{scenario} add echo command (#258) * Enhancement: [protocol x509]{validity} add SNI support (#241) * Enhancement: [snmp_standard]{interfaces} add option '--force-counters32' (#213) * Enhancement: [protocol x509]{validity} add support for alternative subject names (#277) * Enhancement: [juniper sa]{users} add filter (#192) * Enhancement: [cisco wlc]{ap-users} add users by ssid (#227) * Enhancement: [juniper ssg]{sessions} better counters (#233) * Enhancement: [vmware connector]{time-host} new options * Enhancement: [extreme]{hardware} add poe status * Enhancement: [vplex]{directors} hardened code * Fix: [bluecoat]{hardware} problem with sensor * Fix: [cisco ucs]{equipment} fix severity for iocard (#283) * Fix: [exchange 2010]{queues} perdata infinity not raising anymore 2015-12-18 Quentin Garnier * Plugin added: Add a plugin to check VMWare ESX with WSMAN * Configuration: centreon-plugins don't use GetOptions anymore (custom library instead) * Add option '--snmp-force-getnext' in core snmp library * Mode added: [F5 BigIP] 'failover' * Mode added: [vmware connector] for centreon-vmware 2.1.0 * Enhancement: [extreme]{cpu} 'n/a' value managed (#223) * Enhancement: [snmp standard]{inodes} add filter type option (#224) * Enhancement: [netapp]{filesys} add inodes usage * Enhancement: [snmp_standard]{ntp} change output (#232) * Enhancement: [snmp_standard]{processcount} improve performance * Enhancement: [cisco standard]{ipsla} manage no tag name * Enhancement: [snmp_standard]{loadaverage} manage load with coma * Enhancement: [oracle]{tablespaces} manage 'UNDO' tablespaces (#242) * Enhancement: [cisco ucs]{equipment} add cpu, memory and localdisk monitoring * Enhancement: [cisco wlc]{ap-status} can monitor the number of APs * Enhancement: [F5 BigIP]{hardware} refactoring * Enhancement: [cisco standard]{environment} add sensors monitoring (#160) * Enhancement: [aws]{list} add exclude service (#248) * Fix: [protocol x509]{validity} add default port (#240) * Fix: [ups standard]{battery-status} hardened code (#225) * Fix: [cisco standard]{environment} voltage threshold value issue * Fix: [kayako api]{ticketcount} mode crash * Fix: [elasticsearch] Crash without some values in command line (#243) 2015-11-26 Quentin Garnier * initial release centreon-plugins-20220113/cloud/000077500000000000000000000000001417000230700163425ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/000077500000000000000000000000001417000230700171345ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/apigateway/000077500000000000000000000000001417000230700212675ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/apigateway/mode/000077500000000000000000000000001417000230700222135ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/apigateway/mode/discovery.pm000066400000000000000000000054051417000230700245640ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::apigateway::mode::discovery; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "prettify" => { name => 'prettify' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my @disco_data; my $disco_stats; $disco_stats->{start_time} = time(); my $apis = $options{custom}->discovery( service => 'apigateway', command => 'get-rest-apis' ); foreach my $api (@{$apis->{items}}) { my %api; $api{type} = "apigateway"; $api{id} = $api->{id}; $api{name} = $api->{name}; $api{description} = $api->{description}; $api{version} = $api->{version}; foreach my $type (@{$api->{endpointConfiguration}->{types}}) { push @{$api{types}}, $type; } push @disco_data, \%api; } $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; $disco_stats->{discovered_items} = @disco_data; $disco_stats->{results} = \@disco_data; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE API Gateway discovery. =over 8 =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/aws/apigateway/mode/latency.pm000066400000000000000000000145601417000230700242160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::apigateway::mode::latency; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my %metrics_mapping = ( 'Latency' => { 'output' => 'Client Latency', 'output_unit' => 'ms', 'perfdata_unit' => 'ms', 'label' => 'client-latency', 'nlabel' => 'apigateway.client.latency.milliseconds' }, 'IntegrationLatency' => { 'output' => 'Integration Latency', 'output_unit' => 'ms', 'perfdata_unit' => 'ms', 'label' => 'backend-latency', 'nlabel' => 'apigateway.backend.latency.milliseconds' }, ); sub prefix_metric_output { my ($self, %options) = @_; return ucfirst("'" . $options{instance_value}->{display} . "' "); } sub prefix_statistics_output { my ($self, %options) = @_; return "Statistic: '" . $options{instance_value}->{display} . "' "; } sub long_output { my ($self, %options) = @_; return "Checking " . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metrics', type => 3, cb_prefix_output => 'prefix_metric_output', cb_long_output => 'long_output', message_multiple => 'All API latency metrics are ok', indent_long_output => ' ', group => [ { name => 'statistics', display_long => 1, cb_prefix_output => 'prefix_statistics_output', message_multiple => 'All metrics are ok', type => 1, skipped_code => { -10 => 1 } }, ] } ]; foreach my $metric (keys %metrics_mapping) { my $entry = { label => $metrics_mapping{$metric}->{label}, nlabel => $metrics_mapping{$metric}->{nlabel}, set => { key_values => [ { name => $metric }, { name => 'display' } ], output_template => $metrics_mapping{$metric}->{output} . ': %.2f ' . $metrics_mapping{$metric}->{output_unit}, perfdatas => [ { value => $metric , template => '%.2f', label_extra_instance => 1, perfdata_unit => $metrics_mapping{$metric}->{perfdata_unit} } ], } }; push @{$self->{maps_counters}->{statistics}}, $entry; } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, force_new_perfdata => 1, %options); bless $self, $class; $options{options}->add_options(arguments => { 'api-name:s@' => { name => 'api_name' }, 'filter-metric:s' => { name => 'filter_metric' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); foreach my $instance (@{$self->{option_results}->{api_name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Average']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %metrics_mapping) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/ApiGateway', dimensions => [ { Name => 'ApiName', Value => $instance } ], metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period}, ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{$instance}->{display} = $instance; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{display} = $statistic; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{$metric} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check metrics related to ApiGateway latencies Default statistic: 'sum' =over 8 =item B<--api-name> Set the API name (Required) (Can be multiple). =item B<--filter-metric> Filter metrics (Can be: 'Latency', 'IntegrationLatency') =item B<--warning-*> B<--critical-*> Thresholds warning star substitution possibilities: client-latency, backend-latency =back =cut centreon-plugins-20220113/cloud/aws/apigateway/mode/requests.pm000066400000000000000000000144111417000230700244250ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::apigateway::mode::requests; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my %metrics_mapping = ( 'Count' => { 'output' => 'Client Requests', 'label' => 'requests-client', 'nlabel' => 'apigateway.requests.client.count' }, '4XXError' => { 'output' => 'HTTP 4XX Errors', 'label' => 'requests-errors-4xx', 'nlabel' => 'apigateway.requests.errors.4xx.count' }, '5XXError' => { 'output' => 'HTTP 5XX Errors', 'label' => 'requests-errors-5xx', 'nlabel' => 'apigateway.requests.errors.5xx.count' }, ); sub prefix_metric_output { my ($self, %options) = @_; return " '" . $options{instance_value}->{display} . "' "; } sub prefix_statistics_output { my ($self, %options) = @_; return "Statistic '" . $options{instance_value}->{display} . "' Metrics "; } sub long_output { my ($self, %options) = @_; return "Checking '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metrics', type => 3, cb_prefix_output => 'prefix_metric_output', cb_long_output => 'long_output', message_multiple => 'All requests metrics are ok', indent_long_output => ' ', group => [ { name => 'statistics', display_long => 1, cb_prefix_output => 'prefix_statistics_output', message_multiple => 'All requests are ok', type => 1, skipped_code => { -10 => 1 } }, ] } ]; foreach my $metric (keys %metrics_mapping) { my $entry = { label => $metrics_mapping{$metric}->{label}, nlabel => $metrics_mapping{$metric}->{nlabel}, set => { key_values => [ { name => $metric }, { name => 'display' } ], output_template => $metrics_mapping{$metric}->{output} . ': %.2f', perfdatas => [ { value => $metric , template => '%.2f', label_extra_instance => 1 } ], } }; push @{$self->{maps_counters}->{statistics}}, $entry; } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, force_new_perfdata => 1, %options); bless $self, $class; $options{options}->add_options(arguments => { 'api-name:s@' => { name => 'api_name' }, 'filter-metric:s' => { name => 'filter_metric' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); foreach my $instance (@{$self->{option_results}->{api_name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Sum']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %metrics_mapping) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/ApiGateway', dimensions => [ { Name => 'ApiName', Value => $instance } ], metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period}, ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{$instance}->{display} = $instance; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{display} = $statistic; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{$metric} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check metrics related to ApiGateway requests Default statistic: 'sum' =over 8 =item B<--api-name> Set the api name (Required) (Can be multiple). =item B<--filter-metric> Filter metrics (Can be: 'Count', '4XXError', '5XXError') =item B<--warning-*> B<--critical-*> Thresholds warning star substitusion possibilities: requests-client, requests-errors-4xx, requests-errors-5xx =back =cut centreon-plugins-20220113/cloud/aws/apigateway/plugin.pm000066400000000000000000000027711417000230700231320ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::apigateway::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} } = ( 'discovery' => 'cloud::aws::apigateway::mode::discovery', 'latency' => 'cloud::aws::apigateway::mode::latency', 'requests' => 'cloud::aws::apigateway::mode::requests', ); $self->{custom_modes}{paws} = 'cloud::aws::custom::paws'; $self->{custom_modes}{awscli} = 'cloud::aws::custom::awscli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Amazon API Gateway (AmazonApiGateway). =cut centreon-plugins-20220113/cloud/aws/billing/000077500000000000000000000000001417000230700205545ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/billing/mode/000077500000000000000000000000001417000230700215005ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/billing/mode/estimatedcharges.pm000066400000000000000000000106711417000230700253570ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::billing::mode::estimatedcharges; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_charges_output { my ($self, %options) = @_; return "Service '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'services', type => 1, cb_prefix_output => 'prefix_charges_output', message_multiple => 'All services estimated charges are ok' }, ]; $self->{maps_counters}->{services} = [ { label => 'billing', nlabel => 'billing.estimatedcharges.usd', set => { key_values => [ { name => 'estimated_charges' }, { name => 'display' } ], output_template => 'Estimated Charges: %.2f USD', perfdatas => [ { value => 'estimated_charges', template => '%.2f', unit => 'USD', label_extra_instance => 1 }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { "service:s@" => { name => 'service' }, "currency:s" => { name => 'currency', default => 'USD' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{service}) || $self->{option_results}->{service} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --service option."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{currency}) || $self->{option_results}->{currency} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --currency option."); $self->{output}->option_exit(); } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 86400; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; } sub manage_selection { my ($self, %options) = @_; foreach my $service (@{$self->{option_results}->{service}}) { my $metric_results = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/Billing', dimensions => [ { Name => 'ServiceName', Value => $service }, { Name => 'Currency', Value => $self->{option_results}->{currency} } ], metrics => ['EstimatedCharges'], statistics => ['Maximum'], timeframe => $self->{aws_timeframe}, period => $self->{aws_period}, ); $self->{services}->{$service}->{estimated_charges} = $metric_results->{'EstimatedCharges'}->{'maximum'} if defined($metric_results->{'EstimatedCharges'}->{'maximum'}); $self->{services}->{$service}->{display} = $service; } if (scalar(keys %{$self->{services}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No value.'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check Billing estimated charges for a service. Example: perl centreon_plugins.pl --plugin=cloud::aws::billing::plugin --custommode=paws --mode=estimated-charges --region='us-east-1' --service='AWSService' --verbose See 'https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/billing-metricscollected.html' for more informations. =over 8 =item B<--service> Set the Amazon service (Required) (Can be multiple). =item B<--warning-billing> Thresholds warning. =item B<--critical-billing> Thresholds critical. =back =cut centreon-plugins-20220113/cloud/aws/billing/mode/listservices.pm000066400000000000000000000063011417000230700245550ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::billing::mode::listservices; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{dimensions} = $options{custom}->cloudwatch_list_metrics( namespace => 'AWS/Billing' ); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); my %already; foreach my $dimension (@{$self->{dimensions}}) { my $servicename = ''; my $currency = ''; foreach my $name (@{$dimension->{Dimensions}}) { $servicename = $name->{Value} if ($name->{Name} =~ m/ServiceName/ && $name->{Value} ne ''); $currency = $name->{Value} if ($name->{Name} =~ m/Currency/ && $name->{Value} ne ''); } next if (defined($already{$servicename}) || $servicename eq ''); $self->{output}->output_add(long_msg => sprintf("[ServiceName = %s][Currency = %s]", $servicename, $currency)); $already{$servicename} = 1; } $self->{output}->output_add(severity => 'OK', short_msg => 'List services:'); $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 => ['servicename', 'currency']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); my %already; foreach my $dimension (@{$self->{dimensions}}) { my $servicename = ''; my $currency = ''; foreach my $name (@{$dimension->{Dimensions}}) { $servicename = $name->{Value} if ($name->{Name} =~ m/ServiceName/ && $name->{Value} ne ''); $currency = $name->{Value} if ($name->{Name} =~ m/Currency/ && $name->{Value} ne ''); } next if (defined($already{$servicename}) || $servicename eq ''); $self->{output}->add_disco_entry( servicename => $servicename, currency => $currency, ); $already{$servicename} = 1; } } 1; __END__ =head1 MODE List billed Amazon services. =over 8 =back =cut centreon-plugins-20220113/cloud/aws/billing/plugin.pm000066400000000000000000000031121417000230700224050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::billing::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} = { 'estimated-charges' => 'cloud::aws::billing::mode::estimatedcharges', 'list-services' => 'cloud::aws::billing::mode::listservices' }; $self->{customdefault} = { paws => { region => 'us-east-1' }, awscli => { region => 'us-east-1' } }; $self->{custom_modes}->{paws} = 'cloud::aws::custom::paws'; $self->{custom_modes}->{awscli} = 'cloud::aws::custom::awscli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Amazon Billing. Works for 'us-east-1' region only. =cut centreon-plugins-20220113/cloud/aws/cloudfront/000077500000000000000000000000001417000230700213135ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/cloudfront/mode/000077500000000000000000000000001417000230700222375ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/cloudfront/mode/errors.pm000066400000000000000000000126361417000230700241210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::cloudfront::mode::errors; use base qw(cloud::aws::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { extra_params => { message_multiple => 'All instances metrics are ok' }, metrics => { TotalErrorRate => { output => 'Total Error Rate', label => 'errorrate-total', nlabel => { absolute => 'cloudfront.errorrate.total.percentage' }, unit => '%' }, '4xxErrorRate' => { output => '4xx Error Rate', label => 'errorrate-4xx', nlabel => { absolute => 'cloudfront.errorrate.4xx.percentage' }, unit => '%' }, '5xxErrorRate' => { output => '5xx Error Rate', label => 'errorrate-5xx', nlabel => { absolute => 'cloudfront.errorrate.5xx.percentage' }, unit => '%' } } }; return $metrics_mapping; } sub prefix_metric_output { my ($self, %options) = @_; return "Instance '" . $options{instance_value}->{display} . "' "; } sub long_output { my ($self, %options) = @_; return "Checking Instance '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'id:s@' => { name => 'id' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{id}) || $self->{option_results}->{id} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --id option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{id}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/CloudFront', dimensions => [ { Name => 'Region', Value => 'Global' }, { Name => 'DistributionId', Value => $instance } ], metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period}, ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{$instance}->{display} = $instance; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{display} = $statistic; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{timeframe} = $self->{aws_timeframe}; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{$metric} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check CloudFront instances errors. Example: perl centreon_plugins.pl --plugin=cloud::aws::cloudfront::plugin --custommode=paws --mode=errors --region='eu-west-1' --id='E8T734E1AF1L4' --statistic='average' --critical-totalerrorsrate='10' --verbose See 'https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/monitoring-using-cloudwatch.html' for more informations. Default statistic: 'average' / Valid statistic: 'average'. =over 8 =item B<--id> Set the instance id (Required) (Can be multiple). =item B<--filter-metric> Filter metrics (Can be: 'TotalErrorRate', '4xxErrorRate', '5xxErrorRate') (Can be a regexp). =item B<--warning-*> Thresholds warning (Can be: 'errorrate-total', 'errorrate-4xx', 'errorrate-5xx'). =item B<--critical-*> Thresholds critical (Can be: 'errorrate-total', 'errorrate-4xx', 'errorrate-5xx'). =back =cut centreon-plugins-20220113/cloud/aws/cloudfront/mode/requests.pm000066400000000000000000000121271417000230700244530ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::cloudfront::mode::requests; use base qw(cloud::aws::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { extra_params => { message_multiple => 'All instances metrics are ok' }, metrics => { Requests => { output => 'Requests', label => 'requests', nlabel => { absolute => 'cloudfront.requests.count', per_second => 'cloudfront.requests.persecond' }, unit => 'requests' } } }; return $metrics_mapping; } sub prefix_metric_output { my ($self, %options) = @_; return "Instance '" . $options{instance_value}->{display} . "' "; } sub long_output { my ($self, %options) = @_; return "Checking Instance '" . $options{instance_value}->{display} . "' "; } 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 => { 'id:s@' => { name => 'id' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{id}) || $self->{option_results}->{id} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --id option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{id}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_statistics} = ['Sum']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/CloudFront', dimensions => [ { Name => 'Region', Value => 'Global' }, { Name => 'DistributionId', Value => $instance } ], metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period}, ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{$instance}->{display} = $instance; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{display} = $statistic; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{timeframe} = $self->{aws_timeframe}; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{$metric} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check CloudFront instances requests. Example: perl centreon_plugins.pl --plugin=cloud::aws::cloudfront::plugin --custommode=paws --mode=requests --region='eu-west-1' --id='E8T734E1AF1L4' --statistic='sum' --critical-requests='10' --verbose See 'https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/monitoring-using-cloudwatch.html' for more informations. Default statistic: 'sum' / Valid statistic: 'sum'. =over 8 =item B<--id> Set the instance id (Required) (Can be multiple). =item B<--warning-requests> Thresholds warning. =item B<--critical-requests> Thresholds critical. =item B<--per-sec> Change the data to be unit/sec. =back =cut centreon-plugins-20220113/cloud/aws/cloudfront/mode/throughput.pm000066400000000000000000000132261417000230700250120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::cloudfront::mode::throughput; use base qw(cloud::aws::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { extra_params => { message_multiple => 'All instances metrics are ok' }, metrics => { BytesDownloaded => { output => 'Bytes Downloaded', label => 'bytes-downloaded', nlabel => { absolute => 'cloudfront.bytes.downloaded.bytes', per_second => 'cloudfront.bytes.downloaded.persecond' }, unit => 'B' }, BytesUploaded => { output => 'Bytes Uploaded', label => 'bytes-uploaded', nlabel => { absolute => 'cloudfront.bytes.uploaded.bytes', per_second => 'cloudfront.bytes.uploaded.persecond', }, unit => 'B' } } }; return $metrics_mapping; } sub prefix_metric_output { my ($self, %options) = @_; return "Instance '" . $options{instance_value}->{display} . "' "; } sub long_output { my ($self, %options) = @_; return "Checking Instance '" . $options{instance_value}->{display} . "' "; } 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 => { 'id:s@' => { name => 'id' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{id}) || $self->{option_results}->{id} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --id option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{id}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_statistics} = ['Sum']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/CloudFront', dimensions => [ { Name => 'Region', Value => 'Global' }, { Name => 'DistributionId', Value => $instance } ], metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period} ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{$instance}->{display} = $instance; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{display} = $statistic; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{timeframe} = $self->{aws_timeframe}; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{$metric} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check CloudFront instances throughput. Example: perl centreon_plugins.pl --plugin=cloud::aws::cloudfront::plugin --custommode=paws --mode=throughput --region='eu-west-1' --id='E8T734E1AF1L4' --statistic='sum' --critical-bytes-downloaded='10' --verbose See 'https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/monitoring-using-cloudwatch.html' for more informations. Default statistic: 'sum' / Valid statistic: 'sum'. =over 8 =item B<--id> Set the instance id (Required) (Can be multiple). =item B<--filter-metric> Filter metrics (Can be: 'BytesDownloaded', 'BytesUploaded') (Can be a regexp). =item B<--warning-*> Thresholds warning (Can be: 'bytes-downloaded', 'bytes-uploaded'). =item B<--critical-*> Thresholds critical (Can be: 'bytes-downloaded', 'bytes-uploaded') =item B<--per-sec> Change the data to be unit/sec. =back =cut centreon-plugins-20220113/cloud/aws/cloudfront/plugin.pm000066400000000000000000000030411417000230700231450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::cloudfront::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} } = ( 'errors' => 'cloud::aws::cloudfront::mode::errors', 'requests' => 'cloud::aws::cloudfront::mode::requests', 'throughput' => 'cloud::aws::cloudfront::mode::throughput', ); $self->{custom_modes}{paws} = 'cloud::aws::custom::paws'; $self->{custom_modes}{awscli} = 'cloud::aws::custom::awscli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Amazon CloudFront. Works for 'us-east-1' region only. =cut centreon-plugins-20220113/cloud/aws/cloudwatch/000077500000000000000000000000001417000230700212715ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/cloudwatch/mode/000077500000000000000000000000001417000230700222155ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/cloudwatch/mode/discovery.pm000066400000000000000000000241231417000230700245640ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::cloudwatch::mode::discovery; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "service:s@" => { name => 'service' }, "prettify" => { name => 'prettify' }, }); $self->{services} = { VPC => $self->can('discover_vpc'), EC2 => $self->can('discover_ec2'), RDS => $self->can('discover_rds'), ELB => $self->can('discover_elb'), VPN => $self->can('discover_vpn'), KINESIS => $self->can('discover_kinesis_stream'), DYNAMODB => $self->can('discover_dynamodb_table'), APIGATEWAY => $self->can('discover_api'), S3 => $self->can('discover_s3_bucket') }; return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{service}) || $self->{option_results}->{service} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --service option."); $self->{output}->option_exit(); } } sub discover_vpc { my (%options) = @_; my @disco_data; my $vpcs = $options{custom}->discovery(region => $options{region}, service => 'ec2', command => 'describe-vpcs'); foreach my $vpc (@{$vpcs->{Vpcs}}) { next if (!defined($vpc->{VpcId})); my %vpc; $vpc{type} = "vpc"; $vpc{id} = $vpc->{VpcId}; $vpc{state} = $vpc->{State}; $vpc{cidr} = $vpc->{CidrBlock}; foreach my $tag (@{$vpc->{Tags}}) { if ($tag->{Key} eq "Name" && defined($tag->{Value})) { $vpc{name} = $tag->{Value}; } push @{$vpc{tags}}, { key => $tag->{Key}, value => $tag->{Value} }; } push @disco_data, \%vpc; } return @disco_data; } sub discover_ec2 { my (%options) = @_; my @disco_data; my %asgs; my $instances = $options{custom}->discovery(region => $options{region}, service => 'ec2', command => 'describe-instances'); foreach my $reservation (@{$instances->{Reservations}}) { foreach my $instance (@{$reservation->{Instances}}) { next if (!defined($instance->{InstanceId})); my %asg; $asg{type} = "asg"; my %ec2; $ec2{type} = "ec2"; $ec2{id} = $instance->{InstanceId}; $ec2{state} = $instance->{State}->{Name}; $ec2{key_name} = $instance->{KeyName}; $ec2{private_ip} = $instance->{PrivateIpAddress}; $ec2{private_dns_name} = $instance->{PrivateDnsName}; $ec2{public_dns_name} = $instance->{PublicDnsName}; $ec2{instance_type} = $instance->{InstanceType}; $ec2{vpc_id} = $instance->{VpcId}; foreach my $tag (@{$instance->{Tags}}) { if ($tag->{Key} eq "aws:autoscaling:groupName" && defined($tag->{Value})) { $ec2{asg} = $tag->{Value}; next if (defined($asgs{$tag->{Value}})); $asg{name} = $tag->{Value}; $asgs{$tag->{Value}} = 1; } if ($tag->{Key} eq "Name" && defined($tag->{Value})) { $ec2{name} = $tag->{Value}; } push @{$ec2{tags}}, { key => $tag->{Key}, value => $tag->{Value} }; } push @disco_data, \%ec2; push @disco_data, \%asg if (defined($asg{name}) && $asg{name} ne ''); } } return @disco_data; } sub discover_rds { my (%options) = @_; my @disco_data; my $db_instances = $options{custom}->discovery(region => $options{region}, service => 'rds', command => 'describe-db-instances'); foreach my $db_instance (@{$db_instances->{DBInstances}}) { next if (!defined($db_instance->{DbiResourceId})); my %rds; $rds{type} = "rds"; $rds{id} = $db_instance->{DbiResourceId}; $rds{name} = $db_instance->{DBInstanceIdentifier}; $rds{status} = $db_instance->{DBInstanceStatus}; $rds{storage_type} = $db_instance->{StorageType}; $rds{instance_class} = $db_instance->{DBInstanceClass}; $rds{availability_zone} = $db_instance->{AvailabilityZone}; $rds{vpc_id} = $db_instance->{DBSubnetGroup}->{VpcId}; push @disco_data, \%rds; } return @disco_data; } sub discover_elb { my (%options) = @_; my @disco_data; my $load_balancers = $options{custom}->discovery(region => $options{region}, service => 'elb', command => 'describe-load-balancers'); foreach my $load_balancer (@{$load_balancers->{LoadBalancerDescriptions}}) { next if (!defined($load_balancer->{LoadBalancerName})); my %elb; $elb{type} = "elb"; $elb{name} = $load_balancer->{LoadBalancerName}; $elb{dns_name} = $load_balancer->{DNSName}; $elb{availability_zones} = $load_balancer->{AvailabilityZones}; $elb{vpc_id} = $load_balancer->{VPCId}; push @disco_data, \%elb; } return @disco_data; } sub discover_vpn { my (%options) = @_; my @disco_data; my $vpns = $options{custom}->discovery(region => $options{region}, service => 'ec2', command => 'describe-vpn-connections'); foreach my $connection (@{$vpns->{VpnConnections}}) { next if (!defined($connection->{VpnConnectionId})); my %vpn; $vpn{type} = "vpn"; $vpn{id} = $connection->{VpnConnectionId}; $vpn{connection_type} = $connection->{Type}; $vpn{state} = $connection->{State}; $vpn{category} = $connection->{Category}; foreach my $tag (@{$connection->{Tags}}) { if ($tag->{Key} eq "Name" && defined($tag->{Value})) { $vpn{name} = $tag->{Value}; } push @{$vpn{tags}}, { key => $tag->{Key}, value => $tag->{Value} }; } push @disco_data, \%vpn; } return @disco_data; } sub discover_kinesis_stream { my (%options) = @_; my @disco_data; my $streams = $options{custom}->discovery(region => $options{region}, service => 'kinesis', command => 'list-streams'); foreach my $stream (@{$streams->{StreamNames}}) { my %stream; $stream{type} = "kinesis_stream"; $stream{name} = $stream; push @disco_data, \%stream; } return @disco_data; } sub discover_s3_bucket { my (%options) = @_; my @disco_data; my $buckets = $options{custom}->discovery(region => $options{region}, service => 's3api', command => 'list-buckets'); foreach my $bucket (@{$buckets->{Buckets}}) { my %bucket; $bucket{type} = "s3_bucket"; $bucket{name} = $bucket->{Name}; $bucket{creation_date} = $bucket->{CreationDate}; push @disco_data, \%bucket; } return @disco_data; } sub discover_dynamodb_table { my (%options) = @_; my @disco_data; my $tables = $options{custom}->discovery(region => $options{region}, service => 'dynamodb', command => 'list-tables'); foreach my $table (@{$tables->{TableNames}}) { my %table; $table{type} = "dynamodb_table"; $table{name} = $table; push @disco_data, \%table; } return @disco_data; } sub discover_api { my (%options) = @_; my @disco_data; my $apis = $options{custom}->discovery(region => $options{region}, service => 'apigateway', command => 'get-rest-apis'); foreach my $api (@{$apis->{items}}) { my %api; $api{id} = $api->{id}; $api{name} = $api->{name}; $api{description} = $api->{description}; $api{version} = $api->{version}; foreach my $type (@{$api->{endpointConfiguration}->{types}}) { push @{$api{types}}, $type; } push @disco_data, \%api; } return @disco_data; } sub run { my ($self, %options) = @_; my @disco_data; my $disco_stats; $disco_stats->{start_time} = time(); foreach my $service (@{$self->{option_results}->{service}}) { push @disco_data, $self->{services}->{uc($service)}->(custom => $options{custom}, region => $self->{option_results}->{region}) if (defined($self->{services}->{uc($service)})); } $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; $disco_stats->{discovered_items} = @disco_data; $disco_stats->{results} = \@disco_data; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE Resources discovery. =over 8 =item B<--service> Choose the service from which discover resources (Can be: 'VPC', 'EC2', 'RDS', 'ELB', 'VPN') (Mandatory). =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/aws/cloudwatch/mode/getalarms.pm000066400000000000000000000143331417000230700245360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::cloudwatch::mode::getalarms; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::statefile; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf( 'alarm [name: %s] [state: %s] [metric: %s] [reason: %s] %s', $self->{result_values}->{alarm_name}, $self->{result_values}->{state_value}, $self->{result_values}->{metric_name}, $self->{result_values}->{state_reason}, centreon::plugins::misc::change_seconds(value => $self->{result_values}->{last_update}) ); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{alarm_name} = $options{new_datas}->{$self->{instance} . '_AlarmName'}; $self->{result_values}->{state_value} = $options{new_datas}->{$self->{instance} . '_StateValue'}; $self->{result_values}->{metric_name} = $options{new_datas}->{$self->{instance} . '_MetricName'}; $self->{result_values}->{last_update} = $options{new_datas}->{$self->{instance} . '_LastUpdate'}; $self->{result_values}->{state_reason} = $options{new_datas}->{$self->{instance} . '_StateReason'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'alarms', type => 2, message_multiple => '0 problem(s) detected', display_counter_problem => { label => 'alerts', min => 0 }, group => [ { name => 'alarm', skipped_code => { -11 => 1 } } ] } ]; $self->{maps_counters}->{alarm} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'AlarmName' }, { name => 'StateValue' }, { name => 'MetricName' }, { name => 'StateReason' }, { name => 'LastUpdate' } ], 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 => \&catalog_status_threshold, } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-alarm-name:s' => { name => 'filter_alarm_name' }, 'warning-status:s' => { name => 'warning_status', default => '%{state_value} =~ /INSUFFICIENT_DATA/i' }, 'critical-status:s' => { name => 'critical_status', default => '%{state_value} =~ /ALARM/i' }, 'memory' => { name => 'memory' }, }); centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'Date::Parse', error_msg => "Cannot load module 'Date::Parse'." ); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->check_options(%options); } } sub manage_selection { my ($self, %options) = @_; $self->{alarms}->{global} = { alarm => {} }; my $alarm_results = $options{custom}->cloudwatch_get_alarms(); my $last_time; if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->read(statefile => 'cache_aws_' . $self->{mode} . '_' . $self->{option_results}->{region}); $last_time = $self->{statefile_cache}->get(name => 'last_time'); } my ($i, $current_time) = (1, time()); foreach my $alarm (@{$alarm_results}) { my $create_time = Date::Parse::str2time($alarm->{StateUpdatedTimestamp}); if (!defined($create_time)) { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => "Can't Parse date '" . $alarm->{StateUpdatedTimestamp} . "'" ); next; } next if (defined($self->{option_results}->{memory}) && defined($last_time) && $last_time > $create_time); if (defined($self->{option_results}->{filter_alarm_name}) && $self->{option_results}->{filter_alarm_name} ne '' && $alarm->{AlarmName} !~ /$self->{option_results}->{filter_alarm_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $alarm->{AlarmName} . "': no matching filter.", debug => 1); next; } my $diff_time = $current_time - $create_time; $self->{alarms}->{global}->{alarm}->{$i} = { %$alarm, LastUpdate => $diff_time, }; $i++; } if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->write(data => { last_time => $current_time }); } } 1; __END__ =head1 MODE Check cloudwatch alarms. =over 8 =item B<--filter-alarm-name> Filter by alarm name (can be a regexp). =item B<--warning-status> Set warning threshold for status (Default: '%{state_value} =~ /INSUFFICIENT_DATA/i') Can used special variables like: %{alarm_name}, %{state_value}, %{metric_name}, %{last_update} =item B<--critical-status> Set critical threshold for status (Default: '%{state_value} =~ /ALARM/i'). Can used special variables like: %{alarm_name}, %{state_value}, %{metric_name}, %{last_update} =item B<--memory> Only check new alarms. =back =cut centreon-plugins-20220113/cloud/aws/cloudwatch/mode/getmetrics.pm000066400000000000000000000167641417000230700247370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::cloudwatch::mode::getmetrics; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_metric_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => $self->{result_values}->{perf_label}, value => $self->{result_values}->{value}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-metric'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-metric'), ); } sub custom_metric_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check( value => $self->{result_values}->{value}, threshold => [ { label => 'critical-metric', exit_litteral => 'critical' }, { label => 'warning-metric', exit_litteral => 'warning' } ] ); return $exit; } sub custom_metric_output { my ($self, %options) = @_; my $msg = "Metric '" . $self->{result_values}->{display} . "' value is " . $self->{result_values}->{value}; return $msg; } sub custom_metric_calc { my ($self, %options) = @_; $self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_value'}; $self->{result_values}->{perf_label} = $options{new_datas}->{$self->{instance} . '_perf_label'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metrics', type => 1, message_multiple => 'All metrics are ok' }, ]; $self->{maps_counters}->{metrics} = [ { label => 'metric', set => { key_values => [ { name => 'value' }, { name => 'perf_label' }, { name => 'display' } ], 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; $options{options}->add_options(arguments => { 'namespace:s' => { name => 'namespace' }, 'dimension:s%' => { name => 'dimension' }, 'metric:s@' => { name => 'metric' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{namespace}) || $self->{option_results}->{namespace} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --namespace option."); $self->{output}->option_exit(); } $self->{aws_metrics} = []; if (defined($self->{option_results}->{metric})) { $self->{aws_metrics} = [@{$self->{option_results}->{metric}}]; } if (scalar(@{$self->{aws_metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => "Need to specify --metric option."); $self->{output}->option_exit(); } $self->{dimension_name} = ''; my $append = ''; $self->{aws_dimensions} = []; if (defined($self->{option_results}->{dimension})) { foreach (keys %{$self->{option_results}->{dimension}}) { push @{$self->{aws_dimensions}}, { Name => $_, Value => $self->{option_results}->{dimension}->{$_} }; $self->{dimension_name} .= $append . $_ . '.' . $self->{option_results}->{dimension}->{$_}; $append = '-'; } } if ($self->{dimension_name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --dimension option."); $self->{output}->option_exit(); } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Average']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } foreach my $metric_name ($self->{aws_metrics}) { foreach my $statistic ($self->{aws_statistics}) { my $entry = { label => lc($metric_name) . '-' . $statistic, set => { key_values => [ { name => $metric_name . '_' . $statistic }, { name => 'display' } ], output_template => $metric_name . ' ' . ucfirst($statistic) . ' : %s', perfdatas => [ { label => lc($metric_name) . '_' . $statistic, value => $metric_name . '_' . $statistic , template => '%s', label_extra_instance => 1, instance_use => 'display' }, ], } }; push @{$self->{maps_counters}->{dimensions}}, $entry; } } } sub manage_selection { my ($self, %options) = @_; my $metric_results = $options{custom}->cloudwatch_get_metrics( namespace => $self->{option_results}->{namespace}, dimensions => $self->{aws_dimensions}, metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period}, ); $self->{metrics} = {}; foreach my $label (keys %{$metric_results}) { foreach my $stat (('minimum', 'maximum', 'average', 'sum')) { next if (!defined($metric_results->{$label}->{$stat})); $self->{metrics}->{$self->{dimension_name} . '_' . $label . '_' . $stat} = { display => $self->{dimension_name} . '_' . $label . '_' . $stat, value => $metric_results->{$label}->{$stat}, perf_label => $label . '_' . $stat, }; } } } 1; __END__ =head1 MODE Check cloudwatch metrics (same dimension and namespace). Example: perl centreon_plugins.pl --plugin=cloud::aws::plugin --custommode=paws --mode=cloudwatch-get-metrics --region=eu-west-1 --namespace=AWS/EC2 --dimension=InstanceId=i-01622936185e32a45 --metric=CPUUtilization --metric=CPUCreditUsage --statistic=average --statistic=max –-period=60 --timeframe=600 --warning-metric= --critical-metric= =over 8 =item B<--namespace> Set cloudwatch namespace (Required). =item B<--dimension> Set cloudwatch dimensions (Required). =item B<--metric> Set cloudwatch metrics (Required). =item B<--warning-metric> Threshold warning. =item B<--critical-metric> Threshold critical. =back =cut centreon-plugins-20220113/cloud/aws/cloudwatch/mode/listmetrics.pm000066400000000000000000000057241417000230700251250ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::cloudwatch::mode::listmetrics; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'namespace:s' => { name => 'namespace' }, 'metric:s' => { name => 'metric' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{metrics} = $options{custom}->cloudwatch_list_metrics( namespace => $self->{option_results}->{namespace}, metric => $self->{option_results}->{metric} ); } sub get_dimensions_str { my ($self, %options) = @_; my $dimensions = ''; my $append = ''; foreach (@{$options{dimensions}}) { $dimensions .= $append . "Name=$_->{Name},Value=$_->{Value}"; $append = ','; } return $dimensions; } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach (@{$self->{metrics}}) { $self->{output}->output_add(long_msg => sprintf("[Namespace = %s][Dimensions = %s][Metric = %s]", $_->{Namespace}, $self->get_dimensions_str(dimensions => $_->{Dimensions}), $_->{MetricName})); } $self->{output}->output_add( severity => 'OK', short_msg => 'List metrics:' ); $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 => ['namespace', 'metric', 'dimensions']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach (@{$self->{metrics}}) { $self->{output}->add_disco_entry( namespace => $_->{Namespace}, metric => $_->{MetricName}, dimensions => $self->get_dimensions_str(dimensions => $_->{Dimensions}), ); } } 1; __END__ =head1 MODE List cloudwatch metrics. =over 8 =item B<--namespace> Set cloudwatch namespace. =item B<--metric> Set cloudwatch metric. =back =cut centreon-plugins-20220113/cloud/aws/cloudwatch/plugin.pm000066400000000000000000000030611417000230700231250ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::cloudwatch::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} } = ( 'discovery' => 'cloud::aws::cloudwatch::mode::discovery', 'get-alarms' => 'cloud::aws::cloudwatch::mode::getalarms', 'get-metrics' => 'cloud::aws::cloudwatch::mode::getmetrics', 'list-metrics' => 'cloud::aws::cloudwatch::mode::listmetrics', ); $self->{custom_modes}{paws} = 'cloud::aws::custom::paws'; $self->{custom_modes}{awscli} = 'cloud::aws::custom::awscli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Amazon CloudWatch. =cut centreon-plugins-20220113/cloud/aws/cloudwatchlogs/000077500000000000000000000000001417000230700221565ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/cloudwatchlogs/mode/000077500000000000000000000000001417000230700231025ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/cloudwatchlogs/mode/getlogs.pm000066400000000000000000000143261417000230700251120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::cloudwatchlogs::mode::getlogs; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::statefile; use Digest::MD5 qw(md5_hex); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; return sprintf( 'log [created: %s] [stream: %s] [message: %s] ', centreon::plugins::misc::change_seconds(value => $self->{result_values}->{since}), $self->{result_values}->{stream_name}, $self->{result_values}->{message} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'alarms', type => 2, message_multiple => '0 logs detected', display_counter_problem => { label => 'logs', min => 0 }, group => [ { name => 'alarm', skipped_code => { -11 => 1 } } ] } ]; $self->{maps_counters}->{alarm} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'message' }, { name => 'stream_name' }, { name => 'since' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'group-name:s' => { name => 'group_name' }, 'stream-name:s@' => { name => 'stream_name' }, 'start-time-since:s' => { name => 'start_time_since' }, 'unknown-status:s' => { name => 'unknown_status', default => '' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '' } }); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{group_name}) || $self->{option_results}->{group_name} eq '') { $self->{output}->add_option_msg(short_msg => 'please set --group-name option'); $self->{output}->option_exit(); } if (defined($self->{option_results}->{start_time_since}) && $self->{option_results}->{start_time_since} =~ /(\d+)/) { $self->{start_time} = time() - $1; } $self->{stream_names} = undef; if (defined($self->{option_results}->{stream_name})) { foreach my $stream_name (@{$self->{option_results}->{stream_name}}) { if ($stream_name ne '') { $self->{stream_names} = [] if (!defined($self->{stream_names})); push @{$self->{stream_names}}, $stream_name; } } } $self->change_macros(macros => ['unknown_status', 'warning_status', 'critical_status']); if (!defined($self->{start_time})) { $self->{statefile_cache}->check_options(%options); } } sub manage_selection { my ($self, %options) = @_; my $current_time = time(); if (!defined($self->{start_time})) { $self->{statefile_cache}->read( statefile => 'cache_aws_' . $self->{mode} . '_' . $options{custom}->get_region() . (defined($self->{option_results}->{group_name}) ? md5_hex($self->{option_results}->{group_name}) : md5_hex('all')) . '_' . (defined($self->{stream_names}) ? md5_hex(join('-', @{$self->{stream_names}})) : md5_hex('all')) ); $self->{start_time} = $self->{statefile_cache}->get(name => 'last_time'); $self->{statefile_cache}->write(data => { last_time => $current_time }); if (!defined($self->{start_time})) { $self->{output}->output_add( severity => 'OK', short_msg => 'first execution. create cache' ); $self->{output}->display(); $self->{output}->exit(); } } $self->{alarms}->{global} = { alarm => {} }; my $results = $options{custom}->cloudwatchlogs_filter_log_events( group_name => $self->{option_results}->{group_name}, stream_names => $self->{stream_names}, start_time => $self->{start_time} * 1000 ); my $i = 1; foreach my $entry (@$results) { $entry->{message} =~ s/[\|\n]/ -- /msg; $self->{alarms}->{global}->{alarm}->{$i} = { message => $entry->{message}, stream_name => $entry->{logStreamName}, since => int($current_time - ($entry->{timestamp} / 1000)) }; $i++; } } 1; __END__ =head1 MODE Check cloudwatch logs. =over 8 =item B<--group-name> Set log group name (Required). =item B<--stream-name> Filters the results to only logs from the log stream (multiple option). =item B<--start-time-since> Lookup logs last X seconds ago. If not set: lookup logs since the last execution. =item B<--unknown-status> Set unknown threshold for status (Default: '') Can used special variables like: %{message}, %{stream_name}, %{since} =item B<--warning-status> Set warning threshold for status (Default: '') Can used special variables like: %{message}, %{stream_name}, %{since} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{message}, %{stream_name}, %{since} =back =cut centreon-plugins-20220113/cloud/aws/cloudwatchlogs/mode/listgroups.pm000066400000000000000000000043621417000230700256600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::cloudwatchlogs::mode::listgroups; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; return $options{custom}->cloudwatchlogs_describe_log_groups(); } sub run { my ($self, %options) = @_; my $log_groups = $self->manage_selection(%options); foreach (@$log_groups) { $self->{output}->output_add( long_msg => sprintf( '[group name = %s]', $_->{logGroupName} ) ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List log groups:' ); $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 => ['group_name']); } sub disco_show { my ($self, %options) = @_; my $log_groups = $self->manage_selection(%options); foreach (@$log_groups) { $self->{output}->add_disco_entry( group_name => $_->{logGroupName} ); } } 1; __END__ =head1 MODE List cloudwatch logs groups. =over 8 =back =cut centreon-plugins-20220113/cloud/aws/cloudwatchlogs/plugin.pm000066400000000000000000000026551417000230700240220ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::cloudwatchlogs::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} } = ( 'list-groups' => 'cloud::aws::cloudwatchlogs::mode::listgroups', 'get-logs' => 'cloud::aws::cloudwatchlogs::mode::getlogs', ); $self->{custom_modes}{paws} = 'cloud::aws::custom::paws'; $self->{custom_modes}{awscli} = 'cloud::aws::custom::awscli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Amazon CloudWatchLogs. =cut centreon-plugins-20220113/cloud/aws/custom/000077500000000000000000000000001417000230700204465ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/custom/awscli.pm000066400000000000000000000765211417000230700223010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::custom::awscli; use strict; use warnings; use DateTime; use JSON::XS; 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 => { 'aws-secret-key:s' => { name => 'aws_secret_key' }, 'aws-access-key:s' => { name => 'aws_access_key' }, 'aws-session-token:s' => { name => 'aws_session_token' }, 'aws-profile:s' => { name => 'aws_profile' }, 'endpoint-url:s' => { name => 'endpoint_url' }, 'region:s' => { name => 'region' }, 'timeframe:s' => { name => 'timeframe' }, 'period:s' => { name => 'period' }, 'statistic:s@' => { name => 'statistic' }, 'zeroed' => { name => 'zeroed' }, 'timeout:s' => { name => 'timeout', default => 50 }, 'sudo' => { name => 'sudo' }, 'command:s' => { name => 'command', default => 'aws' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '' }, 'proxyurl:s' => { name => 'proxyurl' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'AWSCLI OPTIONS', once => 1); $self->{output} = $options{output}; $self->{custommode_name} = $options{custommode_name}; return $self; } sub get_region { my ($self, %options) = @_; return $self->{option_results}->{region}; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults { my ($self, %options) = @_; foreach (keys %{$options{default}}) { if ($_ eq $self->{custommode_name}) { if (ref($options{default}->{$_}) eq 'ARRAY') { 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}; } } } } if (ref($options{default}->{$_}) eq 'HASH') { foreach my $opt (keys %{$options{default}->{$_}}) { if (!defined($self->{option_results}->{$opt})) { $self->{option_results}->{$opt} = $options{default}->{$_}->{$opt}; } } } } } } sub check_options { my ($self, %options) = @_; if (defined($self->{option_results}->{proxyurl}) && $self->{option_results}->{proxyurl} ne '') { $ENV{HTTP_PROXY} = $self->{option_results}->{proxyurl}; $ENV{HTTPS_PROXY} = $self->{option_results}->{proxyurl}; } if (defined($self->{option_results}->{aws_secret_key}) && $self->{option_results}->{aws_secret_key} ne '') { $ENV{AWS_SECRET_ACCESS_KEY} = $self->{option_results}->{aws_secret_key}; } if (defined($self->{option_results}->{aws_access_key}) && $self->{option_results}->{aws_access_key} ne '') { $ENV{AWS_ACCESS_KEY_ID} = $self->{option_results}->{aws_access_key}; } if (defined($self->{option_results}->{aws_session_token}) && $self->{option_results}->{aws_session_token} ne '') { $ENV{AWS_SESSION_TOKEN} = $self->{option_results}->{aws_session_token}; } if (defined($self->{option_results}->{aws_profile}) && $self->{option_results}->{aws_profile} ne '') { $ENV{AWS_PROFILE} = $self->{option_results}->{aws_profile}; } if (!defined($self->{option_results}->{region}) || $self->{option_results}->{region} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --region option."); $self->{output}->option_exit(); } if (defined($self->{option_results}->{statistic})) { foreach my $statistic (@{$self->{option_results}->{statistic}}) { if ($statistic !~ /minimum|maximum|average|sum/) { $self->{output}->add_option_msg(short_msg => "Statistic '" . $statistic . "' is not handled"); $self->{output}->option_exit(); } } } $self->{endpoint_url} = (defined($self->{option_results}->{endpoint_url})) ? $self->{option_results}->{endpoint_url} : undef; return 0; } sub execute { my ($self, %options) = @_; my $cmd_options = $options{cmd_options}; $cmd_options .= " --debug" if ($self->{output}->is_debug()); $self->{output}->output_add(long_msg => "Command line: '" . $self->{option_results}->{command} . " " . $cmd_options . "'", debug => 1); my ($response) = 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 => $cmd_options, redirect_stderr => ($self->{output}->is_debug()) ? 0 : 1 ); my $raw_results; eval { $raw_results = JSON::XS->new->utf8->decode($response); }; if ($@) { $self->{output}->output_add(long_msg => $response, debug => 1); $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } return $raw_results; } sub cloudwatch_get_metrics_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "cloudwatch get-metric-statistics --region $self->{option_results}->{region} --namespace $options{namespace}" . " --metric-name '$options{metric_name}' --start-time $options{start_time} --end-time $options{end_time}" . " --period $options{period} --statistics " . join(' ', @{$options{statistics}}) . " --output json --dimensions"; foreach my $entry (@{$options{dimensions}}) { $cmd_options .= " 'Name=$entry->{Name},Value=$entry->{Value}'"; } $cmd_options .= " --endpoint-url $self->{endpoint_url}" if (defined($self->{endpoint_url}) && $self->{endpoint_url} ne ''); return $cmd_options; } sub cloudwatch_get_metrics { my ($self, %options) = @_; my $metric_results = {}; my $start_time = DateTime->now->subtract(seconds => $options{timeframe})->iso8601; my $end_time = DateTime->now->iso8601; foreach my $metric_name (@{$options{metrics}}) { my $cmd_options = $self->cloudwatch_get_metrics_set_cmd(%options, metric_name => $metric_name, start_time => $start_time, end_time => $end_time); my $raw_results = $self->execute(cmd_options => $cmd_options); $metric_results->{$raw_results->{Label}} = { points => 0 }; foreach my $point (@{$raw_results->{Datapoints}}) { if (defined($point->{Average})) { $metric_results->{$raw_results->{Label}}->{average} = 0 if (!defined($metric_results->{$raw_results->{Label}}->{average})); $metric_results->{$raw_results->{Label}}->{average} += $point->{Average}; } if (defined($point->{Minimum})) { $metric_results->{$raw_results->{Label}}->{minimum} = $point->{Minimum} if (!defined($metric_results->{$raw_results->{Label}}->{minimum}) || $point->{Minimum} < $metric_results->{$raw_results->{Label}}->{minimum}); } if (defined($point->{Maximum})) { $metric_results->{$raw_results->{Label}}->{maximum} = $point->{Maximum} if (!defined($metric_results->{$raw_results->{Label}}->{maximum}) || $point->{Maximum} > $metric_results->{$raw_results->{Label}}->{maximum}); } if (defined($point->{Sum})) { $metric_results->{$raw_results->{Label}}->{sum} = 0 if (!defined($metric_results->{$raw_results->{Label}}->{sum})); $metric_results->{$raw_results->{Label}}->{sum} += $point->{Sum}; } $metric_results->{$raw_results->{Label}}->{points}++; } if (defined($metric_results->{$raw_results->{Label}}->{average})) { $metric_results->{$raw_results->{Label}}->{average} /= $metric_results->{$raw_results->{Label}}->{points}; } } return $metric_results; } sub discovery_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = $options{service} . " " . $options{command} . " --region $self->{option_results}->{region} --output json"; $cmd_options .= " --endpoint-url $self->{endpoint_url}" if (defined($self->{endpoint_url}) && $self->{endpoint_url} ne ''); return $cmd_options; } sub discovery { my ($self, %options) = @_; my $cmd_options = $self->discovery_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); return $raw_results; } sub cloudwatch_get_alarms_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "cloudwatch describe-alarms --region $self->{option_results}->{region} --output json"; $cmd_options .= " --endpoint-url $self->{endpoint_url}" if (defined($self->{endpoint_url}) && $self->{endpoint_url} ne ''); return $cmd_options; } sub cloudwatch_get_alarms { my ($self, %options) = @_; my $cmd_options = $self->cloudwatch_get_alarms_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); my $alarm_results = []; foreach my $alarm (@{$raw_results->{MetricAlarms}}) { push @$alarm_results, { AlarmName => $alarm->{AlarmName}, StateValue => $alarm->{StateValue}, MetricName => $alarm->{MetricName}, StateReason => $alarm->{StateReason}, StateUpdatedTimestamp => $alarm->{StateUpdatedTimestamp}, }; } return $alarm_results; } sub cloudwatch_list_metrics_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "cloudwatch list-metrics --region $self->{option_results}->{region} --output json"; $cmd_options .= " --namespace $options{namespace}" if (defined($options{namespace})); $cmd_options .= " --metric-name $options{metric}" if (defined($options{metric})); $cmd_options .= " --endpoint-url $self->{endpoint_url}" if (defined($self->{endpoint_url}) && $self->{endpoint_url} ne ''); return $cmd_options; } sub cloudwatch_list_metrics { my ($self, %options) = @_; my $cmd_options = $self->cloudwatch_list_metrics_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); return $raw_results->{Metrics}; } sub cloudwatchlogs_describe_log_groups_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "logs describe-log-groups --region $self->{option_results}->{region} --output json"; $cmd_options .= " --endpoint-url $self->{endpoint_url}" if (defined($self->{endpoint_url}) && $self->{endpoint_url} ne ''); return $cmd_options; } sub cloudwatchlogs_describe_log_groups { my ($self, %options) = @_; my $cmd_options = $self->cloudwatchlogs_describe_log_groups_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); return $raw_results->{logGroups}; } sub cloudwatchlogs_filter_log_events_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "logs filter-log-events --region $self->{option_results}->{region} --output json --log-group-name '$options{group_name}'"; $cmd_options .= " --start-time $options{start_time}" if (defined($options{start_time})); if (defined($options{stream_names})) { $cmd_options .= " --log-stream-names"; foreach (@{$options{stream_names}}) { $cmd_options .= " '$_'"; } } $cmd_options .= " --endpoint-url $self->{endpoint_url}" if (defined($self->{endpoint_url}) && $self->{endpoint_url} ne ''); return $cmd_options; } sub cloudwatchlogs_filter_log_events { my ($self, %options) = @_; my $cmd_options = $self->cloudwatchlogs_filter_log_events_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); return $raw_results->{events}; } sub ebs_list_volumes_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "ec2 describe-volumes --no-dry-run --region $self->{option_results}->{region} --output json"; $cmd_options .= " --endpoint-url $self->{endpoint_url}" if (defined($self->{endpoint_url}) && $self->{endpoint_url} ne ''); return $cmd_options; } sub ebs_list_volumes { my ($self, %options) = @_; my $cmd_options = $self->ebs_list_volumes_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); my $resource_results = []; foreach my $volume_request (@{$raw_results->{Volumes}}) { my @name_tags; foreach my $tag (@{$volume_request->{Tags}}) { if ($tag->{Key} eq "Name" && defined($tag->{Value})) { push @name_tags, $tag->{Value}; } }; push @{$resource_results}, { VolumeId => $volume_request->{VolumeId}, VolumeName => join(",", @name_tags), VolumeType => $volume_request->{VolumeType}, VolumeState => $volume_request->{State} }; } return $resource_results; } sub ec2_get_instances_status_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "ec2 describe-instance-status --include-all-instances --no-dry-run --region $self->{option_results}->{region} --output json"; $cmd_options .= " --endpoint-url $self->{endpoint_url}" if (defined($self->{endpoint_url}) && $self->{endpoint_url} ne ''); return $cmd_options; } sub ec2_get_instances_status { my ($self, %options) = @_; my $cmd_options = $self->ec2_get_instances_status_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); my $instance_results = {}; foreach (@{$raw_results->{InstanceStatuses}}) { $instance_results->{$_->{InstanceId}} = { state => $_->{InstanceState}->{Name}, status => $_->{InstanceStatus}->{Status} }; } return $instance_results; } sub ec2spot_get_active_instances_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "ec2 describe-spot-fleet-instances --no-dry-run --region $self->{option_results}->{region} --output json"; $cmd_options .= " --endpoint-url $self->{endpoint_url}" if (defined($self->{endpoint_url}) && $self->{endpoint_url} ne ''); $cmd_options .= " --spot-fleet-request-id " . $options{spot_fleet_request_id}; return $cmd_options; } sub ec2spot_get_active_instances_status { my ($self, %options) = @_; my $cmd_options = $self->ec2spot_get_active_instances_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); my $instance_results = {}; foreach (@{$raw_results->{ActiveInstances}}) { $instance_results->{$_->{InstanceId}} = { health => $_->{InstanceHealth}, type => $_->{InstanceType}, request_id => $_->{SpotInstanceRequestId} }; } return $instance_results; } sub ec2spot_list_fleet_requests_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "ec2 describe-spot-fleet-requests --no-dry-run --region $self->{option_results}->{region} --output json"; $cmd_options .= " --endpoint-url $self->{endpoint_url}" if (defined($self->{endpoint_url}) && $self->{endpoint_url} ne ''); return $cmd_options; } sub ec2spot_list_fleet_requests { my ($self, %options) = @_; my $cmd_options = $self->ec2spot_list_fleet_requests_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); my $resource_results = []; foreach my $fleet_request (@{$raw_results->{SpotFleetRequestConfigs}}) { push @{$resource_results}, { SpotFleetRequestState => $fleet_request->{SpotFleetRequestState}, SpotFleetRequestId => $fleet_request->{SpotFleetRequestId}, ActivityStatus => $fleet_request->{ActivityStatus} }; } return $resource_results; } sub ec2_list_resources_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "ec2 describe-instances --no-dry-run --region $self->{option_results}->{region} --output json"; $cmd_options .= " --endpoint-url $self->{endpoint_url}" if (defined($self->{endpoint_url}) && $self->{endpoint_url} ne ''); return $cmd_options; } sub ec2_list_resources { my ($self, %options) = @_; my $cmd_options = $self->ec2_list_resources_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); my $resource_results = []; foreach my $reservation (@{$raw_results->{Reservations}}) { foreach my $instance (@{$reservation->{Instances}}) { my @instance_tags; foreach my $tag (@{$instance->{Tags}}) { my %already = map { $_->{Name} => $_ } @{$resource_results}; if ($tag->{Key} eq "aws:autoscaling:groupName") { next if (defined($already{$tag->{Value}})); push @{$resource_results}, { Name => $tag->{Value}, Type => 'asg', }; } elsif ($tag->{Key} eq "Name" && defined($tag->{Value})) { push @instance_tags, $tag->{Value}; } } push @{$resource_results}, { Name => $instance->{InstanceId}, Type => 'instance', AvailabilityZone => $instance->{Placement}->{AvailabilityZone}, InstanceType => $instance->{InstanceType}, State => $instance->{State}->{Name}, Tags => join(',', @instance_tags), KeyName => $instance->{KeyName} }; } } return $resource_results; } sub ec2_get_instances { my ($self, %options) = @_; my $cmd_options = $self->ec2_list_resources_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); my $instance_results = {}; foreach my $reservation (@{$raw_results->{Reservations}}) { foreach my $instance (@{$reservation->{Instances}}) { $instance_results->{ $instance->{InstanceId} } = { State => $instance->{State}->{Name}, InstanceType => $instance->{InstanceType}, LaunchTime => $instance->{LaunchTime} }; } } return $instance_results; } sub asg_get_resources_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "autoscaling describe-auto-scaling-groups --region $self->{option_results}->{region} --output json"; $cmd_options .= " --endpoint-url $self->{endpoint_url}" if (defined($self->{endpoint_url}) && $self->{endpoint_url} ne ''); return $cmd_options; } sub asg_get_resources { my ($self, %options) = @_; my $cmd_options = $self->asg_get_resources_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); return \@{$raw_results->{AutoScalingGroups}}; } sub rds_get_instances_status_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "rds describe-db-instances --region $self->{option_results}->{region} --output json"; $cmd_options .= " --endpoint-url $self->{endpoint_url}" if (defined($self->{endpoint_url}) && $self->{endpoint_url} ne ''); return $cmd_options; } sub rds_get_instances_status { my ($self, %options) = @_; my $cmd_options = $self->rds_get_instances_status_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); my $instance_results = {}; foreach (@{$raw_results->{DBInstances}}) { $instance_results->{$_->{DBInstanceIdentifier}} = { state => $_->{DBInstanceStatus} }; } return $instance_results; } sub rds_list_instances_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "rds describe-db-instances --region $self->{option_results}->{region} --output json"; $cmd_options .= " --endpoint-url $self->{endpoint_url}" if (defined($self->{endpoint_url}) && $self->{endpoint_url} ne ''); return $cmd_options; } sub rds_list_instances { my ($self, %options) = @_; my $cmd_options = $self->rds_list_instances_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); my $instance_results = []; foreach my $instance (@{$raw_results->{DBInstances}}) { push @{$instance_results}, { Name => $instance->{DBInstanceIdentifier}, AvailabilityZone => $instance->{AvailabilityZone}, Engine => $instance->{Engine}, StorageType => $instance->{StorageType}, DBInstanceStatus => $instance->{DBInstanceStatus}, AllocatedStorage => $instance->{AllocatedStorage} }; } return $instance_results; } sub rds_list_clusters_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "rds describe-db-clusters --region $self->{option_results}->{region} --output json"; $cmd_options .= " --endpoint-url $self->{endpoint_url}" if (defined($self->{endpoint_url}) && $self->{endpoint_url} ne ''); return $cmd_options; } sub rds_list_clusters { my ($self, %options) = @_; my $cmd_options = $self->rds_list_clusters_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); my $cluster_results = []; foreach my $cluster (@{$raw_results->{DBClusters}}) { push @{$cluster_results}, { Name => $cluster->{DBClusterIdentifier}, DatabaseName => $cluster->{DatabaseName}, Engine => $cluster->{Engine}, Status => $cluster->{Status}, AllocatedStorage => $cluster->{AllocatedStorage} }; } return $cluster_results; } sub vpn_list_connections_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "ec2 describe-vpn-connections --region $self->{option_results}->{region} --output json"; $cmd_options .= " --endpoint-url $self->{endpoint_url}" if (defined($self->{endpoint_url}) && $self->{endpoint_url} ne ''); return $cmd_options; } sub vpn_list_connections { my ($self, %options) = @_; my $cmd_options = $self->vpn_list_connections_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); my $connections_results = []; foreach my $connection (@{$raw_results->{VpnConnections}}) { my @name_tags; foreach my $tag (@{$connection->{Tags}}) { if ($tag->{Key} eq "Name" && defined($tag->{Value})) { push @name_tags, $tag->{Value}; } } push @{$connections_results}, { id => $connection->{VpnConnectionId}, name => join(",", @name_tags), state => $connection->{State} } }; return $connections_results; } sub health_describe_events_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "health describe-events --region $self->{option_results}->{region} --output json"; my ($filter, $filter_append) = ('', ''); foreach ((['service', 'services'], ['region', 'regions'], ['entity_value', 'entityValues'], ['event_status', 'eventStatusCodes'], ['event_category', 'eventTypeCategories'])) { next if (!defined($options{ 'filter_' . $_->[0] })); $filter .= $filter_append . $_->[1] . '=' . join(',', @{$options{ 'filter_' . $_->[0] }}); $filter_append = ','; } $cmd_options .= " --filter '$filter'" if ($filter ne ''); $cmd_options .= " --endpoint-url $self->{endpoint_url}" if (defined($self->{endpoint_url}) && $self->{endpoint_url} ne ''); return $cmd_options; } sub health_describe_events { my ($self, %options) = @_; my $cmd_options = $self->health_describe_events_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); return $raw_results->{events}; } sub health_describe_affected_entities_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "health describe-affected-entities --region $self->{option_results}->{region} --output json"; my $filter = ''; if (defined($options{filter_event_arns})) { $filter = 'eventArns=' . join(',', @{$options{filter_event_arns}}); } $cmd_options .= " --filter '$filter'" if ($filter ne ''); $cmd_options .= " --endpoint-url $self->{endpoint_url}" if (defined($self->{endpoint_url}) && $self->{endpoint_url} ne ''); return $cmd_options; } sub health_describe_affected_entities { my ($self, %options) = @_; my $all_results = []; while (my @elements = splice(@{$options{filter_event_arns}}, 0, 10)) { my $cmd_options = $self->health_describe_affected_entities_set_cmd(filter_event_arns => \@elements); my $raw_results = $self->execute(cmd_options => $cmd_options); push @$all_results, @{$raw_results->{entities}}; } return $all_results; } sub sqs_list_queues_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "sqs list-queues --region $self->{option_results}->{region} --output json"; $cmd_options .= " --endpoint-url $self->{endpoint_url}" if (defined($self->{endpoint_url}) && $self->{endpoint_url} ne ''); return $cmd_options; } sub sqs_list_queues { my ($self, %options) = @_; my $cmd_options = $self->sqs_list_queues_set_cmd(%options); my $queues_results = $self->execute(cmd_options => $cmd_options); return $queues_results->{QueueUrls}; } sub sns_list_topics_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "sns list-topics --region $self->{option_results}->{region} --output json"; $cmd_options .= " --endpoint-url $self->{endpoint_url}" if (defined($self->{endpoint_url}) && $self->{endpoint_url} ne ''); return $cmd_options; } sub sns_list_topics { my ($self, %options) = @_; my $cmd_options = $self->sns_list_topics_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); my $topics_results = []; foreach my $topic (@{$raw_results->{Topics}}) { push @{$topics_results}, { name => $topic->{TopicArn} }; }; return $topics_results; } sub tgw_list_gateways_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "ec2 describe-transit-gateways --region $self->{option_results}->{region} --output json"; $cmd_options .= " --endpoint-url $self->{endpoint_url}" if (defined($self->{endpoint_url}) && $self->{endpoint_url} ne ''); return $cmd_options; } sub tgw_list_gateways { my ($self, %options) = @_; my $cmd_options = $self->tgw_list_gateways_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); my $gateway_results = []; foreach my $gateway (@{$raw_results->{TransitGateways}}) { push @{$gateway_results}, { id => $gateway->{TransitGatewayId}, name => $gateway->{Description} }; }; return $gateway_results; } 1; __END__ =head1 NAME Amazon AWS =head1 AWSCLI OPTIONS Amazon AWS CLI =over 8 =item B<--aws-secret-key> Set AWS secret key. =item B<--aws-access-key> Set AWS access key. =item B<--aws-session-token> Set AWS session token. =item B<--aws-profile> Set AWS profile. =item B<--endpoint-url> Override AWS service endpoint URL if necessary. =item B<--region> Set the region name (Required). =item B<--period> Set period in seconds. =item B<--timeframe> Set timeframe in seconds. =item B<--statistic> Set cloudwatch statistics (Can be: 'minimum', 'maximum', 'average', 'sum'). =item B<--zeroed> Set metrics value to 0 if none. Usefull when CloudWatch does not return value when not defined. =item B<--timeout> Set timeout in seconds (Default: 50). =item B<--sudo> Use 'sudo' to execute the command. =item B<--command> Command to get information (Default: 'aws'). 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: none). =item B<--proxyurl> Proxy URL if any =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/cloud/aws/custom/mode.pm000066400000000000000000000172511417000230700217360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::custom::mode; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_metric_calc { my ($self, %options) = @_; $self->{result_values}->{timeframe} = $options{new_datas}->{$self->{instance} . '_timeframe'}; $self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{metric}}; $self->{result_values}->{value_per_sec} = $self->{result_values}->{value} / $self->{result_values}->{timeframe}; $self->{result_values}->{metric} = $options{extra_options}->{metric}; return 0; } sub custom_metric_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check( value => defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}, threshold => [ { label => 'critical-' . $self->{instance_mode}->{metrics_mapping}->{ $self->{result_values}->{metric} }->{label} , exit_litteral => 'critical' }, { label => 'warning-' . $self->{instance_mode}->{metrics_mapping}->{ $self->{result_values}->{metric} }->{label}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_metric_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( instances => $self->{instance}, nlabel => defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{instance_mode}->{metrics_mapping}->{ $self->{result_values}->{metric} }->{nlabel}->{per_second} : $self->{instance_mode}->{metrics_mapping}->{ $self->{result_values}->{metric} }->{nlabel}->{absolute}, unit => defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{instance_mode}->{metrics_mapping}->{ $self->{result_values}->{metric} }->{unit} . '/s' : $self->{instance_mode}->{metrics_mapping}->{ $self->{result_values}->{metric} }->{unit}, value => sprintf("%.2f", defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{instance_mode}->{metrics_mapping}->{ $self->{result_values}->{metric} }->{label}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{instance_mode}->{metrics_mapping}->{ $self->{result_values}->{metric} }->{label}), ); } sub custom_metric_output { my ($self, %options) = @_; my $msg = ''; if (defined($self->{instance_mode}->{option_results}->{per_sec})) { my ($value, $unit) = ($self->{instance_mode}->{metrics_mapping}->{ $self->{result_values}->{metric} }->{unit} eq 'B') ? $self->{perfdata}->change_bytes(value => $self->{result_values}->{value_per_sec}) : ($self->{result_values}->{value_per_sec}, $self->{instance_mode}->{metrics_mapping}->{ $self->{result_values}->{metric} }->{unit}); $msg = sprintf("%s: %.2f %s", $self->{instance_mode}->{metrics_mapping}->{ $self->{result_values}->{metric} }->{output}, $value, $unit . '/s'); } else { my ($value, $unit) = ($self->{instance_mode}->{metrics_mapping}->{ $self->{result_values}->{metric} }->{unit} eq 'B') ? $self->{perfdata}->change_bytes(value => $self->{result_values}->{value}) : ($self->{result_values}->{value}, $self->{instance_mode}->{metrics_mapping}->{ $self->{result_values}->{metric} }->{unit}); $msg = sprintf("%s: %.2f %s", $self->{instance_mode}->{metrics_mapping}->{ $self->{result_values}->{metric} }->{output}, $value, $unit); } return $msg; } sub prefix_metric_output { my ($self, %options) = @_; return "'" . $options{instance_value}->{display} . "' "; } sub prefix_statistics_output { my ($self, %options) = @_; return "Statistic '" . $options{instance_value}->{display} . "' Metrics "; } sub long_output { my ($self, %options) = @_; return "Checking '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; my $data = $self->get_metrics_mapping(); $self->{metrics_mapping} = $data->{metrics}; $self->{maps_counters_type} = [ { name => 'metrics', type => 3, cb_prefix_output => 'prefix_metric_output', cb_long_output => 'long_output', message_multiple => defined($data->{extra_params}->{message_mutiple}) ? $data->{extra_params}->{message_mutiple} : 'All metrics are ok', indent_long_output => ' ', group => [ { name => 'statistics', display_long => 1, cb_prefix_output => 'prefix_statistics_output', message_multiple => 'All metrics are ok', type => 1, skipped_code => { -10 => 1 } }, ] } ]; foreach my $metric (keys %{$self->{metrics_mapping}}) { my $entry = { label => $self->{metrics_mapping}->{$metric}->{label}, set => { key_values => [ { name => $metric }, { name => 'timeframe' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_metric_calc'), closure_custom_calc_extra_options => { metric => $metric }, 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') } }; push @{$self->{maps_counters}->{statistics}}, $entry; } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-metric:s' => { name => 'filter_metric' }, 'per-sec' => { name => 'per_sec' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Average']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } }; $self->{aws_metrics} = []; foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; }; } 1; __END__ centreon-plugins-20220113/cloud/aws/custom/paws.pm000066400000000000000000000651411417000230700217650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::custom::paws; use strict; use warnings; use Paws; use DateTime; 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 => { 'aws-secret-key:s' => { name => 'aws_secret_key' }, 'aws-access-key:s' => { name => 'aws_access_key' }, 'aws-session-token:s' => { name => 'aws_session_token' }, 'aws-role-arn:s' => { name => 'aws_role_arn' }, 'region:s' => { name => 'region' }, 'timeframe:s' => { name => 'timeframe' }, 'period:s' => { name => 'period' }, 'statistic:s@' => { name => 'statistic' }, 'zeroed' => { name => 'zeroed' }, 'proxyurl:s' => { name => 'proxyurl' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'PAWS OPTIONS', once => 1); $self->{output} = $options{output}; $self->{custommode_name} = $options{custommode_name}; return $self; } sub get_region { my ($self, %options) = @_; return $self->{option_results}->{region}; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults { my ($self, %options) = @_; foreach (keys %{$options{default}}) { if ($_ eq $self->{custommode_name}) { if (ref($options{default}->{$_}) eq 'ARRAY') { 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}; } } } } if (ref($options{default}->{$_}) eq 'HASH') { foreach my $opt (keys %{$options{default}->{$_}}) { if (!defined($self->{option_results}->{$opt})) { $self->{option_results}->{$opt} = $options{default}->{$_}->{$opt}; } } } } } } sub check_options { my ($self, %options) = @_; if (defined($self->{option_results}->{aws_secret_key}) && $self->{option_results}->{aws_secret_key} ne '') { $ENV{AWS_SECRET_KEY} = $self->{option_results}->{aws_secret_key}; } if (defined($self->{option_results}->{aws_access_key}) && $self->{option_results}->{aws_access_key} ne '') { $ENV{AWS_ACCESS_KEY} = $self->{option_results}->{aws_access_key}; } if (defined($self->{option_results}->{aws_session_token}) && $self->{option_results}->{aws_session_token} ne '') { $ENV{AWS_SESSION_TOKEN} = $self->{option_results}->{aws_session_token}; } if (!defined($self->{option_results}->{region}) || $self->{option_results}->{region} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --region option.'); $self->{output}->option_exit(); } if (defined($self->{option_results}->{statistic})) { foreach my $statistic (@{$self->{option_results}->{statistic}}) { if ($statistic !~ /minimum|maximum|average|sum/) { $self->{output}->add_option_msg(short_msg => "Statistic '" . $statistic . "' is not handled"); $self->{output}->option_exit(); } } } my $config = {}; if (defined($self->{option_results}->{proxyurl}) && $self->{option_results}->{proxyurl} ne '') { $ENV{HTTP_PROXY} = $self->{option_results}->{proxyurl}; $ENV{HTTPS_PROXY} = $self->{option_results}->{proxyurl}; centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'Paws::Net::LWPCaller', error_msg => "Cannot load module 'Paws::Net::LWPCaller'." ); $config->{caller} = Paws::Net::LWPCaller->new(); } if (defined($self->{option_results}->{aws_role_arn}) && $self->{option_results}->{aws_role_arn} ne '') { centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'Paws::Credential::AssumeRole', error_msg => "Cannot load module 'Paws::Credential::AssumeRole'." ); $config->{credentials} = Paws::Credential::AssumeRole->new( RoleArn => $self->{option_results}->{aws_role_arn}, RoleSessionName => 'centreon-plugins' ); } $self->{paws} = Paws->new(config => $config); return 0; } sub cloudwatch_get_metrics { my ($self, %options) = @_; my $metric_results = {}; eval { my $cw = $self->{paws}->service('CloudWatch', region => $self->{option_results}->{region}); my $start_time = DateTime->now->subtract(seconds => $options{timeframe})->iso8601; my $end_time = DateTime->now->iso8601; foreach my $metric_name (@{$options{metrics}}) { my $metric_result = $cw->GetMetricStatistics( MetricName => $metric_name, Namespace => $options{namespace}, Statistics => $options{statistics}, #ExtendedStatistics => ['p100'], EndTime => $end_time, StartTime => $start_time, Period => $options{period}, #Unit => $unit, Dimensions => $options{dimensions}, ); $metric_results->{$metric_result->{Label}} = { points => 0 }; foreach my $point (@{$metric_result->{Datapoints}}) { if (defined($point->{Average})) { $metric_results->{$metric_result->{Label}}->{average} = 0 if (!defined($metric_results->{$metric_result->{Label}}->{average})); $metric_results->{$metric_result->{Label}}->{average} += $point->{Average}; } if (defined($point->{Minimum})) { $metric_results->{$metric_result->{Label}}->{minimum} = $point->{Minimum} if (!defined($metric_results->{$metric_result->{Label}}->{minimum}) || $point->{Minimum} < $metric_results->{$metric_result->{Label}}->{minimum}); } if (defined($point->{Maximum})) { $metric_results->{$metric_result->{Label}}->{maximum} = $point->{Maximum} if (!defined($metric_results->{$metric_result->{Label}}->{maximum}) || $point->{Maximum} > $metric_results->{$metric_result->{Label}}->{maximum}); } if (defined($point->{Sum})) { $metric_results->{$metric_result->{Label}}->{sum} = 0 if (!defined($metric_results->{$metric_result->{Label}}->{sum})); $metric_results->{$metric_result->{Label}}->{sum} += $point->{Sum}; } $metric_results->{$metric_result->{Label}}->{points}++; } if (defined($metric_results->{$metric_result->{Label}}->{average})) { $metric_results->{$metric_result->{Label}}->{average} /= $metric_results->{$metric_result->{Label}}->{points}; } } }; if ($@) { $self->{output}->add_option_msg(short_msg => "error: $@"); $self->{output}->option_exit(); } return $metric_results; } sub cloudwatch_get_alarms { my ($self, %options) = @_; my $alarm_results = []; eval { my $cw = $self->{paws}->service('CloudWatch', region => $self->{option_results}->{region}); my $alarms = $cw->DescribeAlarms(); foreach my $alarm (@{$alarms->{MetricAlarms}}) { push @$alarm_results, { AlarmName => $alarm->{AlarmName}, StateValue => $alarm->{StateValue}, MetricName => $alarm->{MetricName}, StateReason => $alarm->{StateReason}, StateUpdatedTimestamp => $alarm->{StateUpdatedTimestamp}, }; } }; if ($@) { $self->{output}->add_option_msg(short_msg => "error: $@"); $self->{output}->option_exit(); } return $alarm_results; } sub cloudwatch_list_metrics { my ($self, %options) = @_; my $metric_results = []; eval { my $cw = $self->{paws}->service('CloudWatch', region => $self->{option_results}->{region}); my %cw_options = (); $cw_options{Namespace} = $options{namespace} if (defined($options{namespace})); $cw_options{MetricName} = $options{metric} if (defined($options{metric})); while ((my $list_metrics = $cw->ListMetrics(%cw_options))) { foreach (@{$list_metrics->{Metrics}}) { my $dimensions = []; foreach my $dimension (@{$_->{Dimensions}}) { push @$dimensions, { Name => $dimension->{Name}, Value => $dimension->{Value} }; } push @{$metric_results}, { Namespace => $_->{Namespace}, MetricName => $_->{MetricName}, Dimensions => $dimensions, }; } last if (!defined($list_metrics->{NextToken})); $cw_options{NextToken} = $list_metrics->{NextToken}; } }; if ($@) { $self->{output}->add_option_msg(short_msg => "error: $@"); $self->{output}->option_exit(); } return $metric_results; } sub cloudwatchlogs_describe_log_groups { my ($self, %options) = @_; my $log_groups_results = []; eval { my $cw = $self->{paws}->service('CloudWatchLogs', region => $self->{option_results}->{region}); my %cw_options = (); while ((my $list_log_groups = $cw->DescribeLogGroups(%cw_options))) { foreach (@{$list_log_groups->{logGroups}}) { push @$log_groups_results, $_; } last if (!defined($list_log_groups->{NextToken})); $cw_options{NextToken} = $list_log_groups->{NextToken}; } }; if ($@) { $self->{output}->add_option_msg(short_msg => "error: $@"); $self->{output}->option_exit(); } return $log_groups_results; } sub cloudwatchlogs_filter_log_events { my ($self, %options) = @_; my $log_groups_results = []; eval { my $cw = $self->{paws}->service('CloudWatchLogs', region => $self->{option_results}->{region}); my %cw_options = (); $cw_options{StartTime} = $options{start_time} if (defined($options{start_time})); $cw_options{LogStreamNames} = [@{$options{LogStreamNames}}] if (defined($options{LogStreamNames})); while ((my $list_log_groups = $cw->FilterLogEvents(%cw_options))) { foreach (@{$list_log_groups->{logGroups}}) { push @$log_groups_results, $_; } last if (!defined($list_log_groups->{NextToken})); $cw_options{NextToken} = $list_log_groups->{NextToken}; } }; if ($@) { $self->{output}->add_option_msg(short_msg => "error: $@"); $self->{output}->option_exit(); } return $log_groups_results; } sub ebs_list_volumes { my ($self, %options) = @_; my $volume_results = []; eval { my $ebsvolume = $self->{paws}->service('EC2', region => $self->{option_results}->{region}); my $ebsvolume_requests = $ebsvolume->DescribeVolumes(DryRun => 0); foreach my $request (@{$ebsvolume_requests->{Volumes}}) { my @name_tags; foreach my $tag (@{$request->{Tags}}) { if ($tag->{Key} eq "Name" && defined($tag->{Value})) { push @name_tags, $tag->{Value}; } }; push @{$volume_results}, { VolumeId => $request->{VolumeId}, VolumeName => join(",", @name_tags), VolumeType => $request->{VolumeType}, VolumeState => $request->{State} }; } }; if ($@) { $self->{output}->add_option_msg(short_msg => "error: $@"); $self->{output}->option_exit(); } return $volume_results; } sub ec2_get_instances_status { my ($self, %options) = @_; my $instance_results = {}; eval { my $ec2 = $self->{paws}->service('EC2', region => $self->{option_results}->{region}); my $instances = $ec2->DescribeInstanceStatus(DryRun => 0, IncludeAllInstances => 1); foreach (@{$instances->{InstanceStatuses}}) { $instance_results->{$_->{InstanceId}} = { state => $_->{InstanceState}->{Name}, status => $_->{InstanceStatus}->{Status} }; } }; if ($@) { $self->{output}->add_option_msg(short_msg => "error: $@"); $self->{output}->option_exit(); } return $instance_results; } sub ec2_get_instances { my ($self, %options) = @_; my $instance_results = {}; eval { my $ec2 = $self->{paws}->service('EC2', region => $self->{option_results}->{region}); my $list_instances = $ec2->DescribeInstances(DryRun => 0); foreach my $reservation (@{$list_instances->{Reservations}}) { foreach my $instance (@{$reservation->{Instances}}) { $instance_results->{ $instance->{InstanceId} } = { Name => $instance->{InstanceId}, InstanceType => $instance->{InstanceType}, State => $instance->{State}->{Name}, LaunchTime => $instance->{LaunchTime} }; } } }; if ($@) { $self->{output}->add_option_msg(short_msg => "error: $@"); $self->{output}->option_exit(); } return $instance_results; } sub ec2spot_get_active_instances { my ($self, %options) = @_; my $instance_results = {}; eval { my $ec2 = $self->{paws}->service('EC2', region => $self->{option_results}->{region}); my $instances = $ec2->DescribeSpotFleetInstances('SpotFleetRequestId' => $options{spot_fleet_request_id}, DryRun => 0, IncludeAllInstances => 1); foreach (@{$instances->{ActiveInstances}}) { $instance_results->{$_->{InstanceId}} = { health => $_->{InstanceHealth}, type => $_->{InstanceType}, request_id => $_->{SpotInstanceRequestId} }; } }; if ($@) { $self->{output}->add_option_msg(short_msg => "error: $@"); $self->{output}->option_exit(); } return $instance_results; } sub ec2spot_list_fleet_requests { my ($self, %options) = @_; my $resource_results = []; eval { my $ec2spot = $self->{paws}->service('EC2', region => $self->{option_results}->{region}); my $spot_fleet_requests = $ec2spot->DescribeSpotFleetRequests(DryRun => 0); foreach (@{$spot_fleet_requests->{SpotFleetRequestConfigs}}) { push @{$resource_results}, { SpotFleetRequestState => $_->{SpotFleetRequestState}, SpotFleetRequestId => $_->{SpotFleetRequestId}, ActivityStatus => $_->{ActivityStatus} }; } }; if ($@) { $self->{output}->add_option_msg(short_msg => "error: $@"); $self->{output}->option_exit(); } return $resource_results; } sub ec2_list_resources { my ($self, %options) = @_; my $resource_results = []; eval { my $ec2 = $self->{paws}->service('EC2', region => $self->{option_results}->{region}); my $list_instances = $ec2->DescribeInstances(DryRun => 0); foreach my $reservation (@{$list_instances->{Reservations}}) { foreach my $instance (@{$reservation->{Instances}}) { my @instance_tags; foreach my $tag (@{$instance->{Tags}}) { my %already = map { $_->{Name} => $_ } @{$resource_results}; if ($tag->{Key} eq "aws:autoscaling:groupName") { next if (defined($already{$tag->{Value}})); push @{$resource_results}, { Name => $tag->{Value}, Type => 'asg', }; } elsif (defined($tag->{Key}) && defined($tag->{Value})) { push @instance_tags, $tag->{Key} . ":" . $tag->{Value}; } } push @{$resource_results}, { Name => $instance->{InstanceId}, Type => 'instance', AvailabilityZone => $instance->{Placement}->{AvailabilityZone}, InstanceType => $instance->{InstanceType}, State => $instance->{State}->{Name}, Tags => join(",", @instance_tags), }; } } }; if ($@) { $self->{output}->add_option_msg(short_msg => "error: $@"); $self->{output}->option_exit(); } return $resource_results; } sub asg_get_resources { my ($self, %options) = @_; my $autoscaling_groups = {}; eval { my $asg = $self->{paws}->service('AutoScaling', region => $self->{option_results}->{region}); $autoscaling_groups = $asg->DescribeAutoScalingGroups(); }; if ($@) { $self->{output}->add_option_msg(short_msg => "error: $@"); $self->{output}->option_exit(); } return \@{$autoscaling_groups->{AutoScalingGroups}}; } sub rds_get_instances_status { my ($self, %options) = @_; my $instance_results = {}; eval { my $rds = $self->{paws}->service('RDS', region => $self->{option_results}->{region}); my $instances = $rds->DescribeDBInstances(); foreach (@{$instances->{DBInstances}}) { $instance_results->{$_->{DBInstanceIdentifier}} = { state => $_->{DBInstanceStatus} }; } }; if ($@) { $self->{output}->add_option_msg(short_msg => "error: $@"); $self->{output}->option_exit(); } return $instance_results; } sub rds_list_instances { my ($self, %options) = @_; my $instance_results = []; eval { my $rds = $self->{paws}->service('RDS', region => $self->{option_results}->{region}); my $list_instances = $rds->DescribeDBInstances(); foreach my $instance (@{$list_instances->{DBInstances}}) { push @{$instance_results}, { Name => $instance->{DBInstanceIdentifier}, AvailabilityZone => $instance->{AvailabilityZone}, Engine => $instance->{Engine}, StorageType => $instance->{StorageType}, DBInstanceStatus => $instance->{DBInstanceStatus}, AllocatedStorage => $instance->{AllocatedStorage} }; } }; if ($@) { $self->{output}->add_option_msg(short_msg => "error: $@"); $self->{output}->option_exit(); } return $instance_results; } sub rds_list_clusters { my ($self, %options) = @_; my $cluster_results = []; eval { my $rds = $self->{paws}->service('RDS', region => $self->{option_results}->{region}); my $list_clusters = $rds->DescribeDBClusters(); foreach my $cluster (@{$list_clusters->{DBClusters}}) { push @{$cluster_results}, { Name => $cluster->{DBClusterIdentifier}, DatabaseName => $cluster->{DatabaseName}, Engine => $cluster->{Engine}, Status => $cluster->{Status}, AllocatedStorage => $cluster->{AllocatedStorage} }; } }; if ($@) { $self->{output}->add_option_msg(short_msg => "error: $@"); $self->{output}->option_exit(); } return $cluster_results; } sub vpn_list_connections { my ($self, %options) = @_; my $connections_results = []; eval { my $vpn = $self->{paws}->service('EC2', region => $self->{option_results}->{region}); my $list_vpn = $vpn->DescribeVpnConnections(); foreach my $connection (@{$list_vpn->{VpnConnections}}) { my @name_tags; foreach my $tag (@{$connection->{Tags}}) { if ($tag->{Key} eq "Name" && defined($tag->{Value})) { push @name_tags, $tag->{Value}; } } push @{$connections_results}, { id => $connection->{VpnConnectionId}, name => join(",", @name_tags), state => $connection->{State} } }; }; if ($@) { $self->{output}->add_option_msg(short_msg => "error: $@"); $self->{output}->option_exit(); } return $connections_results; } sub health_describe_events { my ($self, %options) = @_; my $event_results = []; eval { my $health = $self->{paws}->service('Health', region => $self->{option_results}->{region}); my $health_options = { Filter => {} }; foreach ((['service', 'Services'], ['region', 'Regions'], ['entity_value', 'EntityValues'], ['event_status', 'EventStatusCodes'], ['event_category', 'EventTypeCategories'])) { next if (!defined($options{ 'filter_' . $_->[0] })); $health_options->{Filter}->{ $_->[1] } = $options{ 'filter_' . $_->[0] }; } while ((my $events = $health->DescribeEvents(%$health_options))) { foreach (@{$events->{Events}}) { push @$event_results, { arn => $_->{Arn}, service => $_->{Service}, eventTypeCode => $_->{EventTypeCode}, eventTypeCategory => $_->{EventTypeCategory}, region => $_->{Region}, startTime => $_->{StartTime}, lastUpdatedTime => $_->{LastUpdatedTime}, statusCode => $_->{StatusCode} }; } last if (!defined($events->{NextToken})); $health_options->{NextToken} = $events->{NextToken}; } }; if ($@) { $self->{output}->add_option_msg(short_msg => "error: $@"); $self->{output}->option_exit(); } return $event_results; } sub health_describe_affected_entities { my ($self, %options) = @_; my $entities_results = []; eval { my $health = $self->{paws}->service('Health', region => $self->{option_results}->{region}); while (my @events = splice(@{$options{filter_event_arns}}, 0, 10)) { my $health_options = { Filter => { EventArns => \@events } }; while ((my $entities = $health->DescribeAffectedEntities(%$health_options))) { foreach (@{$entities->{Entities}}) { push @$entities_results, { entityArn => $_->{EntityArn}, eventArn => $_->{EventArn}, entityValue => $_->{EntityValue}, awsAccountId => $_->{AwsAccountId}, lastUpdatedTime => $_->{LastUpdatedTime}, statusCode => $_->{StatusCode} }; } last if (!defined($entities->{NextToken})); $health_options->{NextToken} = $entities->{NextToken}; } } }; if ($@) { $self->{output}->add_option_msg(short_msg => "error: $@"); $self->{output}->option_exit(); } return $entities_results; } sub sqs_list_queues { my ($self, %options) = @_; my $queues_results = []; eval { my $queues = $self->{paws}->service('SQS', region => $self->{option_results}->{region}); my $list_queues = $queues->ListQueues(); foreach my $queue (@{$list_queues->{QueueUrls}}) { push @{$queues_results}, $queue; }; }; if ($@) { $self->{output}->add_option_msg(short_msg => "error: $@"); $self->{output}->option_exit(); } return $queues_results; } sub sns_list_topics { my ($self, %options) = @_; my $topics_results = []; eval { my $topics = $self->{paws}->service('SNS', region => $self->{option_results}->{region}); my $raw_results = $topics->ListTopics(); foreach my $topic (@{$raw_results->{Topics}}) { push @{$topics_results}, { name => $topic->{TopicArn} }; }; }; if ($@) { $self->{output}->add_option_msg(short_msg => "error: $@"); $self->{output}->option_exit(); } return $topics_results; } sub tgw_list_gateways { my ($self, %options) = @_; my $gateway_results = []; eval { my $gateways = $self->{paws}->service('EC2', region => $self->{option_results}->{region}); my $raw_results = $gateways->DescribeTransitGateways(); foreach my $gateway (@{$raw_results->{TransitGateways}}) { push @{$gateway_results}, { id => $gateway->{TransitGatewayId}, name => $gateway->{Description} }; }; }; if ($@) { $self->{output}->add_option_msg(short_msg => "error: $@"); $self->{output}->option_exit(); } return $gateway_results; } 1; __END__ =head1 NAME Amazon AWS =head1 SYNOPSIS Amazon AWS =head1 PAWS OPTIONS =over 8 =item B<--aws-secret-key> Set AWS secret key. =item B<--aws-access-key> Set AWS access key. =item B<--aws-session-token> Set AWS session token. =item B<--aws-role-arn> Set arn of the role to be assumed. =item B<--region> Set the region name (Required). =item B<--period> Set period in seconds. =item B<--timeframe> Set timeframe in seconds. =item B<--statistic> Set cloudwatch statistics (Can be: 'minimum', 'maximum', 'average', 'sum'). =item B<--zeroed> Set metrics value to 0 if none. Usefull when CloudWatch does not return value when not defined. =item B<--proxyurl> Proxy URL if any =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/cloud/aws/ebs/000077500000000000000000000000001417000230700177055ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/ebs/mode/000077500000000000000000000000001417000230700206315ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/ebs/mode/discovery.pm000066400000000000000000000057171417000230700232100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::ebs::mode::discovery; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "prettify" => { name => 'prettify' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my @disco_data; my $disco_stats; $disco_stats->{start_time} = time(); my $volumes = $options{custom}->discovery( service => 'ec2', command => 'describe-volumes' ); foreach my $volume (@{$volumes->{Volumes}}) { my %volume; my @name_tags; foreach my $tag (@{$volume->{Tags}}) { if ($tag->{Key} eq "Name" && defined($tag->{Value})) { push @name_tags, $tag->{Value}; } } $volume{id} = $volume->{VolumeId}; $volume{name} = join(",", @name_tags); $volume{type} = $volume->{VolumeType}; $volume{state} = $volume->{State}; $volume{snapshotid} = $volume->{SnapshotId}; $volume{encrypted} = $volume->{Encrypted}; push @disco_data, \%volume; } $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; $disco_stats->{discovered_items} = @disco_data; $disco_stats->{results} = \@disco_data; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE Amazon EBS volumes discovery. =over 8 =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/aws/ebs/mode/listvolumes.pm000066400000000000000000000046111417000230700235570ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::ebs::mode::listvolumes; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{volume} = $options{custom}->ebs_list_volumes(); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach (@{$self->{volume}}) { $self->{output}->output_add( long_msg => sprintf("[Name = %s][Id = %s][Type = %s][State = %s]", $_->{VolumeName}, $_->{VolumeId}, $_->{VolumeType}, $_->{VolumeState} )); } $self->{output}->output_add( severity => 'OK', short_msg => 'List EBS volumes:' ); $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', 'Id', 'Type', 'State']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach (@{$self->{volume}}) { $self->{output}->add_disco_entry( VolumeName => $_->{VolumeName}, VolumeId => $_->{VolumeId}, VolumeType => $_->{VolumeType}, VolumeState => $_->{VolumeState}, ); }; } 1; __END__ =head1 MODE List Amazon Elastic Block Store volumes. =over 8 =back =cut centreon-plugins-20220113/cloud/aws/ebs/mode/volumeio.pm000066400000000000000000000123331417000230700230300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::ebs::mode::volumeio; use base qw(cloud::aws::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { extra_params => { message_multiple => 'All EBS metrics are ok' }, metrics => { 'VolumeReadBytes' => { 'output' => 'Volume Read Bytes', 'label' => 'volume-read-bytes', 'nlabel' => { 'absolute' => 'ebs.volume.bytes.read.bytes', 'per_second' => 'ebs.volume.bytes.read.bytespersecond' }, 'unit' => 'B' }, 'VolumeWriteBytes' => { 'output' => 'Volume Write Bytes', 'label' => 'volume-write-bytes', 'nlabel' => { 'absolute' => 'ebs.volume.bytes.write.bytes', 'per_second' => 'ebs.volume.bytes.write.bytespersecond' }, 'unit' => 'B' } } }; return $metrics_mapping; } sub long_output { my ($self, %options) = @_; return "AWS EBS Volume '" . $options{instance_value}->{display} . "' "; } 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 => { 'volume-id:s@' => { name => 'volume_id' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{volume_id}) || $self->{option_results}->{volume_id} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --volume-id option."); $self->{output}->option_exit(); }; foreach my $instance (@{$self->{option_results}->{volume_id}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; }; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/EBS', dimensions => [ { Name => 'VolumeId', Value => $instance } ], metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period} ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{$instance}->{display} = $instance; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{display} = $statistic; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{timeframe} = $self->{aws_timeframe}; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{$metric} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check Amazon Elastic Block Store volumes IO usage. Example: perl centreon_plugins.pl --plugin=cloud::aws::ebs::plugin --custommode=awscli --mode=volumeio --region='eu-west-1' --volumeid='vol-1234abcd' --warning-write-bytes='100000' --critical-write-bytes='200000' --warning --verbose See 'https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using_cloudwatch_ebs.html' for more information. =over 8 =item B<--volume-id> Set the VolumeId (Required). =item B<--filter-metric> Filter on a specific metric. Can be: VolumeReadBytes, VolumeWriteBytes =item B<--warning-$metric$> Warning thresholds ($metric$ can be: 'volume-read-bytes', 'volume-write-bytes'). =item B<--critical-$metric$> Critical thresholds ($metric$ can be: 'volume-read-bytes', 'volume-write-bytes'). =item B<--per-sec> Change the data to be unit/sec. =back =cut centreon-plugins-20220113/cloud/aws/ebs/mode/volumeiops.pm000066400000000000000000000146641417000230700234040ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::ebs::mode::volumeiops; use base qw(cloud::aws::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { extra_params => { message_multiple => 'All EBS metrics are ok' }, metrics => { VolumeReadOps => { output => 'IOPS Read', label => 'iops-read', nlabel => { absolute => 'ebs.volume.iops.read.count', per_second => 'ebs.volume.iops.read.countpersecond' }, unit => '' }, VolumeWriteOps => { output => 'IOPS Write', label => 'iops-write', nlabel => { absolute => 'ebs.volume.iops.write.count', per_second => 'ebs.volume.iops.write.countpersecond' }, unit => '' }, VolumeThroughputPercentage => { output => 'IOPS Throughput', label => 'iops-throughput', nlabel => { absolute => 'ebs.volume.iops.throughput.percentage', per_second => 'ebs.volume.iops.throughput.percentagepersecond' }, unit => '%' }, VolumeConsumedReadWriteOps => { output => 'IOPS Consumed', label => 'iops-consumed', nlabel => { absolute => 'ebs.volume.iops.consumed.count', per_second => 'ebs.volume.iops.consumed.countpersecond' }, unit => '' }, VolumeQueueLength => { output => 'IOPS Queue Length', label => 'iops-queue-length', nlabel => { absolute => 'ebs.volume.iops.queuelength.count', per_second => 'ebs.volume.iops.queuelength.countpersecond' }, unit => '' } } }; return $metrics_mapping; } sub long_output { my ($self, %options) = @_; return "AWS EBS Volume'" . $options{instance_value}->{display} . "' "; } 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 => { 'volume-id:s@' => { name => 'volume_id' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{volume_id}) || $self->{option_results}->{volume_id} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --volumeid option."); $self->{output}->option_exit(); }; foreach my $instance (@{$self->{option_results}->{volume_id}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; }; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/EBS', dimensions => [ { Name => 'VolumeId', Value => $instance } ], metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period} ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{$instance}->{display} = $instance; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{display} = $statistic; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{timeframe} = $self->{aws_timeframe}; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{$metric} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check Amazon Elastic Block Store volumes IOPS. Example: perl centreon_plugins.pl --plugin=cloud::aws::ebs::plugin --custommode=awscli --mode=volumeiops --region='eu-west-1' --volumeid='vol-1234abcd' --warning-iops-queue-length='100' --critical-iops-queue-length='200' --warning --verbose See 'https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using_cloudwatch_ebs.html' for more information. =over 8 =item B<--volume-id> Set the VolumeId (Required). =item B<--filter-metric> Filter on a specific metric. Can be: VolumeReadOps, VolumeWriteOps, VolumeThroughputPercentage, VolumeConsumedReadWriteOps =item B<--warning-$metric$> Warning thresholds ($metric$ can be: 'iops-read', 'iops-write', 'iops-throughput', 'iops-consumed', 'iops-queue-length'). =item B<--critical-$metric$> Critical thresholds ($metric$ can be: 'iops-read', 'iops-write', 'iops-throughput', 'iops-consumed', 'iops-queue-length'). =item B<--per-sec> Change the data to be unit/sec. =back =cut centreon-plugins-20220113/cloud/aws/ebs/mode/volumetime.pm000066400000000000000000000242011417000230700233540ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::ebs::mode::volumetime; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my %metrics_mapping = ( 'VolumeTotalReadTime' => { 'output' => 'Total Read Time', 'label' => 'total-read-time', 'nlabel' => { 'absolute' => 'ebs.volume.totalread.time.second' }, 'unit' => 's' }, 'VolumeTotalWriteTime' => { 'output' => 'Total Write Time', 'label' => 'total-write-time', 'nlabel' => { 'absolute' => 'ebs.volume.totalwrite.time.second' }, 'unit' => 's' }, 'VolumeIdleTime' => { 'output' => 'Idle Time', 'label' => 'idle-time', 'nlabel' => { 'absolute' => 'ebs.volume.idle.time.second' }, 'unit' => 's', 'display_percent' => 1 } ); sub custom_metric_calc { my ($self, %options) = @_; $self->{result_values}->{timeframe} = $options{new_datas}->{$self->{instance} . '_timeframe'}; $self->{result_values}->{period} = $options{new_datas}->{$self->{instance} . '_period'}; $self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{metric}}; $self->{result_values}->{metric} = $options{extra_options}->{metric}; return 0; } sub custom_metric_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check( value => $self->{result_values}->{value}, threshold => [ { label => 'critical-' . $metrics_mapping{$self->{result_values}->{metric}}->{label} , exit_litteral => 'critical' }, { label => 'warning-' . $metrics_mapping{$self->{result_values}->{metric}}->{label}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_metric_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( instances => $self->{instance}, label => $metrics_mapping{$self->{result_values}->{metric}}->{label}, nlabel => $metrics_mapping{$self->{result_values}->{metric}}->{nlabel}->{absolute}, unit => $metrics_mapping{$self->{result_values}->{metric}}->{unit}, value => $self->{result_values}->{value}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $metrics_mapping{$self->{result_values}->{metric}}->{label}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $metrics_mapping{$self->{result_values}->{metric}}->{label}), ); } sub custom_metric_output { my ($self, %options) = @_; my $msg = ""; my ($value, $unit) = ($metrics_mapping{$self->{result_values}->{metric}}->{unit} eq 'B') ? $self->{perfdata}->change_bytes(value => $self->{result_values}->{value}) : ($self->{result_values}->{value}, $metrics_mapping{$self->{result_values}->{metric}}->{unit}); if (defined($metrics_mapping{$self->{result_values}->{metric}}->{display_percent})) { my $percent = ($self->{result_values}->{value} / $self->{result_values}->{period} * 100); $msg = sprintf("%s: %.2f%s (%.2f%)", $metrics_mapping{$self->{result_values}->{metric}}->{output}, $value, $unit, $percent); } else { $msg = sprintf("%s: %.2f%s", $metrics_mapping{$self->{result_values}->{metric}}->{output}, $value, $unit); }; return $msg; } sub prefix_metric_output { my ($self, %options) = @_; return "'" . $options{instance_value}->{display} . "' "; } sub prefix_statistics_output { my ($self, %options) = @_; return "Statistic '" . $options{instance_value}->{display} . "' Metrics "; } sub long_output { my ($self, %options) = @_; return "AWS EBS Volume'" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metrics', type => 3, cb_prefix_output => 'prefix_metric_output', cb_long_output => 'long_output', message_multiple => 'All EBS metrics are ok', indent_long_output => ' ', group => [ { name => 'statistics', display_long => 1, cb_prefix_output => 'prefix_statistics_output', message_multiple => 'All metrics are ok', type => 1, skipped_code => { -10 => 1 } }, ] } ]; foreach my $metric (keys %metrics_mapping) { my $entry = { label => $metrics_mapping{$metric}->{label}, set => { key_values => [ { name => $metric }, { name => 'timeframe' }, { name => 'display' }, { name => 'period'} ], closure_custom_calc => $self->can('custom_metric_calc'), closure_custom_calc_extra_options => { metric => $metric }, 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') } }; push @{$self->{maps_counters}->{statistics}}, $entry; } } 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 => { 'volume-id:s@' => { name => 'volume_id' }, 'filter-metric:s' => { name => 'filter_metric' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{volume_id}) || $self->{option_results}->{volume_id} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --volume-id option."); $self->{output}->option_exit(); }; foreach my $instance (@{$self->{option_results}->{volume_id}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; }; } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Average']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } }; foreach my $metric (keys %metrics_mapping) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; }; } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/EBS', dimensions => [ { Name => 'VolumeId', Value => $instance } ], metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period} ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{$instance}->{display} = $instance; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{display} = $statistic; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{timeframe} = $self->{aws_timeframe}; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{period} = $self->{aws_period}; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{$metric} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check Amazon Elastic Block Store volumes operations time. Example: perl centreon_plugins.pl --plugin=cloud::aws::ebs::plugin --custommode=awscli --mode=volumetime --region='eu-west-1' --volumeid='vol-1234abcd' --warning-write-time='40' --critical-write-time='50' --warning --verbose See 'https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using_cloudwatch_ebs.html' for more information. =over 8 =item B<--volume-id> Set the VolumeId (Required). =item B<--filter-metric> Filter on a specific metric. Can be: VolumeTotalReadTime, VolumeTotalWriteTime, VolumeIdleTime =item B<--warning-$metric$> Warning thresholds ($metric$ can be: 'total-read-time', 'total-write-time', 'idle-time'). =item B<--critical-$metric$> Critical thresholds ($metric$ can be: 'total-read-time', 'total-write-time', 'idle-time'). =back =cut centreon-plugins-20220113/cloud/aws/ebs/plugin.pm000066400000000000000000000031541417000230700215440ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::ebs::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} = '1.0'; %{ $self->{modes} } = ( 'discovery' => 'cloud::aws::ebs::mode::discovery', 'list-volumes' => 'cloud::aws::ebs::mode::listvolumes', 'volumeio' => 'cloud::aws::ebs::mode::volumeio', 'volumeiops' => 'cloud::aws::ebs::mode::volumeiops', 'volumetime' => 'cloud::aws::ebs::mode::volumetime' ); $self->{custom_modes}{paws} = 'cloud::aws::custom::paws'; $self->{custom_modes}{awscli} = 'cloud::aws::custom::awscli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Amazon Elastic Block Store (Amazon EBS). =cut centreon-plugins-20220113/cloud/aws/ec2/000077500000000000000000000000001417000230700176055ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/ec2/mode/000077500000000000000000000000001417000230700205315ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/ec2/mode/asgstatus.pm000066400000000000000000000171021417000230700231060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::ec2::mode::asgstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = "[Health: " . $self->{result_values}->{health} . " - Lifecycle: " . $self->{result_values}->{lifecycle} . "]"; return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{health} = $options{new_datas}->{$self->{instance} . '_health'}; $self->{result_values}->{lifecycle} = $options{new_datas}->{$self->{instance} . '_lifecycle'}; $self->{result_values}->{asg} = $options{new_datas}->{$self->{instance} . '_asg'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub custom_asg_output { my ($self, %options) = @_; my $msg = sprintf('Instance current count: %s (config: min=%d max=%d)', $self->{result_values}->{count}, $self->{result_values}->{min_size}, $self->{result_values}->{max_size}); return $msg; } sub custom_asg_calc { my ($self, %options) = @_; $self->{result_values}->{count} = $options{new_datas}->{$self->{instance} . '_count'}; $self->{result_values}->{min_size} = $options{new_datas}->{$self->{instance} . '_min_size'}; $self->{result_values}->{max_size} = $options{new_datas}->{$self->{instance} . '_max_size'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub prefix_awsasg_output { my ($self, %options) = @_; return "AutoScalingGroup '" . $options{instance_value}->{display} . "' "; } sub prefix_awsinstance_output { my ($self, %options) = @_; return "Instance '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'aws_asg', type => 1, cb_prefix_output => 'prefix_awsasg_output', message_multiple => 'All Auto Scaling Groups are ok' }, { name => 'aws_instances', type => 1, cb_prefix_output => 'prefix_awsinstance_output', message_multiple => 'All instances are ok' }, ]; $self->{maps_counters}->{aws_asg} = [ { label => 'asg-instance-current', nlabel => 'ec2.asg.instance.current.count', set => { key_values => [ { name => 'display' }, { name => 'count' }, { name => 'min_size' }, { name => 'max_size' } ], threshold_use => 'count', closure_custom_calc => $self->can('custom_asg_calc'), closure_custom_output => $self->can('custom_asg_output'), perfdatas => [ { value => 'count', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; $self->{maps_counters}->{aws_instances} = [ { label => 'instances', set => { key_values => [ { name => 'health' }, { name => 'lifecycle' }, { name => 'asg' }, { 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 => \&catalog_status_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 => { "filter-asg:s" => { name => 'filter_asg', default => '' }, "warning-instances:s" => { name => 'warning_instances', default => '' }, "critical-instances:s" => { name => 'critical_instances', default => '%{health} =~ /Healthy/ && %{lifecycle} !~ /InService/' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_instances', 'critical_instances']); } sub manage_selection { my ($self, %options) = @_; $self->{aws_autoscaling_groups} = {}; my $result = $options{custom}->asg_get_resources(); foreach my $asg (@{$result}) { my $instance_count = 0; if (defined($self->{option_results}->{filter_asg}) && $self->{option_results}->{filter_asg} ne '' && $asg->{AutoScalingGroupName} !~ /$self->{option_results}->{filter_asg}/) { $self->{output}->output_add(long_msg => "skipping asg '" . $asg->{AutoScalingGroupName} . "': no matching filter.", debug => 1); next; } foreach my $instance (@{$asg->{Instances}}) { $self->{aws_instances}->{$instance->{InstanceId}} = { display => $instance->{InstanceId}, asg => $asg->{AutoScalingGroupName}, health => $instance->{HealthStatus}, lifecycle => $instance->{LifecycleState} }; $instance_count++; } $self->{aws_asg}->{$asg->{AutoScalingGroupName}} = { display => $asg->{AutoScalingGroupName}, min_size => $asg->{MinSize}, max_size => $asg->{MaxSize}, count => $instance_count }; } if (scalar(keys %{$self->{aws_instances}}) <= 0 && $self->{aws_asg} <= 0) { $self->{output}->add_option_msg(short_msg => "Didn't check anything, are your filters correct ?"); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check EC2 Auto Scaling Groups and related instances status (number of instances within, state of each instances) Example: perl centreon_plugins.pl --plugin=cloud::aws::ec2::plugin --custommode=paws --mode=asg-status --region='eu-west-1' --critical-instances='%{health} =~ /Healthy/ && %{lifecycle} !~ /InService/' --warning-count 10 --verbose See 'https://docs.aws.amazon.com/autoscaling/ec2/APIReference/API_DescribeAutoScalingGroups.html' for more informations. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Possible values: asg / instances =item B<--filter-asg> Filter by autoscaling group name (can be a regexp). =item B<--warning-instances> Set warning threshold for status (Default: ''). Can use special variables like: %{health}, %{lifecycle} =item B<--critical-instances> Set critical threshold for instances states (Default: '%{health} =~ /Healthy/ && %{lifecycle} !~ /InService/'). Can use special variables like: %{health}, %{lifecycle} =item B<--warning-asg-instance-current> Threshold warning about number of instances in the autoscaling group =item B<--critical-asg-instance-current> Threshold critical about number of instances in the autoscaling group =back =cut centreon-plugins-20220113/cloud/aws/ec2/mode/cpu.pm000066400000000000000000000157211417000230700216640ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::ec2::mode::cpu; use base qw(cloud::aws::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { extra_params => { message_multiple => 'All CPU metrics are ok' }, metrics => { CPUUtilization => { output => 'CPU Utilization', label => 'cpu-utilization', nlabel => { absolute => 'ec2.cpu.utilization.percentage' }, unit => '' }, CPUCreditBalance => { output => 'CPU Credit Balance', label => 'cpu-credit-balance', nlabel => { absolute => 'ec2.cpu.credit.balance.count' }, unit => '' }, CPUCreditUsage => { output => 'CPU Credit Usage', label => 'cpu-credit-usage', nlabel => { absolute => 'ec2.cpu.credit.usage.count' }, unit => '' }, CPUSurplusCreditBalance => { output => 'CPU Surplus Credit Balance', label => 'cpu-credit-surplus-balance', nlabel => { absolute => 'ec2.cpu.credit.surplus.balance.count' }, unit => '' }, CPUSurplusCreditsCharged => { output => 'CPU Surplus Credit Charged', label => 'cpu-credit-surplus-charged', nlabel => { absolute => 'ec2.cpu.credit.surplus.charged.count' }, unit => '' } } }; return $metrics_mapping; } sub prefix_metric_output { my ($self, %options) = @_; return ucfirst($options{instance_value}->{type}) . " '" . $options{instance_value}->{display} . "' "; } sub long_output { my ($self, %options) = @_; return "Checking " . ucfirst($self->{option_results}->{type}) . " '" . $options{instance_value}->{display} . "' "; } 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 => { 'type:s' => { name => 'type' }, 'name:s@' => { name => 'name' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{type}) || $self->{option_results}->{type} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --type option."); $self->{output}->option_exit(); } if ($self->{option_results}->{type} ne 'asg' && $self->{option_results}->{type} ne 'instance') { $self->{output}->add_option_msg(short_msg => "Instance type '" . $self->{option_results}->{type} . "' is not handled for this mode"); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } } my %map_type = ( 'instance' => "InstanceId", 'asg' => "AutoScalingGroupName" ); sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/EC2', dimensions => [ { Name => $map_type{$self->{option_results}->{type}}, Value => $instance } ], metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period} ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{$instance}->{display} = $instance; $self->{metrics}->{$instance}->{type} = $self->{option_results}->{type}; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{display} = $statistic; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{timeframe} = $self->{aws_timeframe}; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{$metric} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check EC2 instances CPU metrics. Example: perl centreon_plugins.pl --plugin=cloud::aws::ec2::plugin --custommode=paws --mode=cpu --region='eu-west-1' --type='asg' --name='centreon-middleware' --filter-metric='Credit' --statistic='average' --critical-cpu-credit-usage='10' --verbose See 'https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/viewing_metrics_with_cloudwatch.html' for more informations. Default statistic: 'average' / All satistics are valid. =over 8 =item B<--type> Set the instance type (Required) (Can be: 'asg', 'instance'). =item B<--name> Set the instance name (Required) (Can be multiple). =item B<--filter-metric> Filter metrics (Can be: 'CPUCreditBalance', 'CPUCreditUsage', 'CPUSurplusCreditBalance', 'CPUSurplusCreditsCharged', 'CPUUtilization') (Can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds warning (Can be 'cpu-credit-usage', 'cpu-credit-balance', 'cpu-credit-surplus-balance', 'cpu-credit-surplus-charged', 'cpu-utilization'). =back =cut centreon-plugins-20220113/cloud/aws/ec2/mode/discovery.pm000066400000000000000000000102501417000230700230740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::ec2::mode::discovery; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "prettify" => { name => 'prettify' }, "filter-type:s" => { name => 'filter_type' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my @disco_data; my $disco_stats; $disco_stats->{start_time} = time(); my %asgs; my $instances = $options{custom}->discovery( service => 'ec2', command => 'describe-instances' ); foreach my $reservation (@{$instances->{Reservations}}) { foreach my $instance (@{$reservation->{Instances}}) { next if (!defined($instance->{InstanceId})); my %asg; $asg{type} = "asg"; my %ec2; $ec2{type} = "ec2"; $ec2{id} = $instance->{InstanceId}; $ec2{state} = $instance->{State}->{Name}; $ec2{key_name} = $instance->{KeyName}; $ec2{private_ip} = $instance->{PrivateIpAddress}; $ec2{private_dns_name} = $instance->{PrivateDnsName}; $ec2{public_dns_name} = $instance->{PublicDnsName}; $ec2{instance_type} = $instance->{InstanceType}; $ec2{vpc_id} = $instance->{VpcId}; foreach my $tag (@{$instance->{Tags}}) { if ($tag->{Key} eq "aws:autoscaling:groupName" && defined($tag->{Value})) { $ec2{asg} = $tag->{Value}; next if (defined($asgs{$tag->{Value}})); $asg{name} = $tag->{Value}; $asgs{$tag->{Value}} = 1; } if ($tag->{Key} eq "Name" && defined($tag->{Value})) { $ec2{name} = $tag->{Value}; } push @{$ec2{tags}}, { key => $tag->{Key}, value => $tag->{Value} }; } push @disco_data, \%ec2 unless (defined($self->{option_results}->{filter_type}) && $ec2{type} !~ /$self->{option_results}->{filter_type}/); push @disco_data, \%asg unless ((defined($self->{option_results}->{filter_type}) && $asg{type} !~ /$self->{option_results}->{filter_type}/) || !defined($asg{name}) || $asg{name} eq ''); } } $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; $disco_stats->{discovered_items} = @disco_data; $disco_stats->{results} = \@disco_data; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE EC2/ASG discovery. =over 8 =item B<--filter-type> Filter type. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/aws/ec2/mode/discoveryspotfleetrequests.pm000066400000000000000000000057631417000230700266330ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::ec2::mode::discoveryspotfleetrequests; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "prettify" => { name => 'prettify' }, "filter-state:s" => { name => 'filter_state' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my @disco_data; my $disco_stats; $disco_stats->{start_time} = time(); my %asgs; my $spot_fleet_requests = $options{custom}->discovery( service => 'ec2', command => 'describe-spot-fleet-requests' ); foreach my $fleet_request (@{$spot_fleet_requests->{SpotFleetRequestConfigs}}) { my %sfr; $sfr{state} = $fleet_request->{SpotFleetRequestState}; $sfr{id} = $fleet_request->{SpotFleetRequestId}; $sfr{activity_status} = $fleet_request->{ActivityStatus}; push @disco_data, \%sfr unless (defined($self->{option_results}->{filter_state}) && $sfr{state} !~ /$self->{option_results}->{filter_state}/); } $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; $disco_stats->{discovered_items} = @disco_data; $disco_stats->{results} = \@disco_data; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE EC2 Spot Fleet Requests discovery. =over 8 =item B<--filter-state> Filter on Spot Fleet Request state. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/aws/ec2/mode/diskio.pm000066400000000000000000000212761417000230700223610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::ec2::mode::diskio; use base qw(cloud::aws::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { extra_params => { message_multiple => 'All disks metrics are ok' }, metrics => { DiskReadBytes => { output => 'Disk Read Bytes', label => 'disk-bytes-read', nlabel => { absolute => 'ec2.disk.bytes.read.bytes', per_second => 'ec2.disk.bytes.read.bytespersecond' }, unit => 'B' }, DiskWriteBytes => { output => 'Disk Write Bytes', label => 'disk-bytes-write', nlabel => { absolute => 'ec2.disk.bytes.write.bytes', per_second => 'ec2.disk.bytes.write.bytespersecond' }, unit => 'B' }, DiskReadOps => { output => 'Disk Read Ops', label => 'disk-ops-read', nlabel => { absolute => 'ec2.disk.ops.read.count', per_second => 'ec2.disk.ops.read.persecond' }, unit => 'ops' }, DiskWriteOps => { output => 'Disk Write Ops', label => 'disk-ops-write', nlabel => { absolute => 'ec2.disk.ops.write.count', per_second => 'ec2.disk.ops.write.persecond' }, unit => 'ops' }, EBSReadBytes => { output => 'EBS Read Bytes', label => 'ebs-bytes-read', nlabel => { absolute => 'ec2.disk.bytes.read.bytes', per_second => 'ec2.disk.bytes.read.bytespersecond' }, unit => 'B' }, EBSWriteBytes => { output => 'EBS Write Bytes', label => 'ebs-bytes-write', nlabel => { absolute => 'ec2.ebs.bytes.write.bytes', per_second => 'ec2.ebs.bytes.write.bytespersecond' }, unit => 'B' }, EBSReadOps => { output => 'EBS Read Ops', label => 'ebs-ops-read', nlabel => { absolute => 'ec2.ebs.ops.read.count', per_second => 'ec2.ebs.ops.read.persecond' }, unit => 'ops' }, EBSWriteOps => { output => 'EBS Write Ops', label => 'ebs-ops-write', nlabel => { absolute => 'ec2.ebs.ops.write.count', per_second => 'ec2.ebs.ops.write.persecond' }, unit => 'ops' } } }; return $metrics_mapping; } sub prefix_metric_output { my ($self, %options) = @_; return ucfirst($self->{option_results}->{type}) . " '" . $options{instance_value}->{display} . "' "; } sub long_output { my ($self, %options) = @_; return "Checking " . ucfirst($self->{option_results}->{type}) . " '" . $options{instance_value}->{display} . "' "; } 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 => { 'type:s' => { name => 'type' }, 'name:s@' => { name => 'name' }, 'add-ebs-metrics' => { name => 'add_ebs_metrics' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{type}) || $self->{option_results}->{type} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --type option."); $self->{output}->option_exit(); } if ($self->{option_results}->{type} ne 'asg' && $self->{option_results}->{type} ne 'instance') { $self->{output}->add_option_msg(short_msg => "Instance type '" . $self->{option_results}->{type} . "' is not handled for this mode"); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_metrics} = []; foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (!defined($self->{option_results}->{add_ebs_metrics}) && $metric =~ /EBS/); next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } } my %map_type = ( instance => 'InstanceId', asg => 'AutoScalingGroupName' ); sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/EC2', dimensions => [ { Name => $map_type{$self->{option_results}->{type}}, Value => $instance } ], metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period}, ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{$instance}->{display} = $instance; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{display} = $statistic; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{timeframe} = $self->{aws_timeframe}; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{$metric} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check EC2 instances disk IO metrics. Example: perl centreon_plugins.pl --plugin=cloud::aws::ec2::plugin --custommode=paws --mode=diskio --region='eu-west-1' --type='asg' --name='centreon-middleware' --filter-metric='Read' --statistic='sum' --critical-disk-ops-read='10' --verbose See 'https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/ec2-metricscollected.html' for more informations. Default statistic: 'average' / All satistics are valid. =over 8 =item B<--type> Set the instance type (Required) (Can be: 'asg', 'instance'). =item B<--name> Set the instance name (Required) (Can be multiple). =item B<--add-ebs-metrics> Add EBS metrics ('EBSReadOps', 'EBSWriteOps', 'EBSReadBytes', 'EBSWriteBytes'). =item B<--filter-metric> Filter metrics (Can be: 'DiskReadBytes', 'DiskWriteBytes', 'DiskReadOps', 'DiskWriteOps') (Can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds (Can be 'disk-bytes-read', 'disk-bytes-write', 'disk-ops-read', 'disk-ops-write', 'ebs-bytes-read', 'ebs-bytes-write', 'ebs-ops-read', 'ebs-ops-write'). =item B<--per-sec> Change the data to be unit/sec. =back =cut centreon-plugins-20220113/cloud/aws/ec2/mode/instancesstatus.pm000066400000000000000000000242571417000230700243340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::ec2::mode::instancesstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use POSIX; use centreon::plugins::misc; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use DateTime; my $unitdiv = { s => 1, w => 604800, d => 86400, h => 3600, m => 60 }; my $unitdiv_long = { s => 'seconds', w => 'weeks', d => 'days', h => 'hours', m => 'minutes' }; sub custom_uptime_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel} . '.' . $unitdiv_long->{ $self->{instance_mode}->{option_results}->{uptime_unit} }, unit => $self->{instance_mode}->{option_results}->{uptime_unit}, instances => $self->{result_values}->{display}, value => floor($self->{result_values}->{uptime_seconds} / $unitdiv->{ $self->{instance_mode}->{option_results}->{uptime_unit} }), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}), min => 0 ); } sub custom_uptime_threshold { my ($self, %options) = @_; return $self->{perfdata}->threshold_check( value => floor($self->{result_values}->{uptime_seconds} / $unitdiv->{ $self->{instance_mode}->{option_results}->{uptime_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_status_output { my ($self, %options) = @_; return sprintf('state: %s, status: %s', $self->{result_values}->{state}, $self->{result_values}->{status}); } sub prefix_global_output { my ($self, %options) = @_; return 'Total instances '; } sub prefix_awsinstance_output { my ($self, %options) = @_; return "Instance '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }, { name => 'aws_instances', type => 1, cb_prefix_output => 'prefix_awsinstance_output', message_multiple => 'All instances are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'pending', nlabel => 'ec2.instances.status.pending.count', set => { key_values => [ { name => 'pending' } ], output_template => "pending: %s", perfdatas => [ { template => '%d', min => 0 } ] } }, { label => 'running', nlabel => 'ec2.instances.status.running.count', set => { key_values => [ { name => 'running' } ], output_template => "running: %s", perfdatas => [ { template => '%d', min => 0 } ] } }, { label => 'shuttingdown', nlabel => 'ec2.instances.status.shuttingdown.count', set => { key_values => [ { name => 'shutting-down' } ], output_template => "shutting down: %s", perfdatas => [ { template => '%d', min => 0 } ] } }, { label => 'terminated', nlabel => 'ec2.instances.status.terminated.count', set => { key_values => [ { name => 'terminated' } ], output_template => "terminated: %s", perfdatas => [ { template => '%d', min => 0 } ] } }, { label => 'stopping', nlabel => 'ec2.instances.status.stopping.count', set => { key_values => [ { name => 'stopping' } ], output_template => "stopping: %s", perfdatas => [ { template => '%d', min => 0 } ] } }, { label => 'stopped', nlabel => 'ec2.instances.status.stopped.count', set => { key_values => [ { name => 'stopped' } ], output_template => "stopped: %s", perfdatas => [ { template => '%d', min => 0 } ] } } ]; $self->{maps_counters}->{aws_instances} = [ { label => 'status', type => 2, set => { key_values => [ { name => 'state' }, { name => 'status' }, { name => 'display' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'uptime', nlabel => 'ec2.uptime', set => { key_values => [ { name => 'uptime_seconds' }, { name => 'uptime_human' }, { name => 'display' } ], output_template => 'uptime: %s', output_use => 'uptime_human', closure_custom_perfdata => $self->can('custom_uptime_perfdata'), closure_custom_threshold_check => $self->can('custom_uptime_threshold') } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-instanceid:s' => { name => 'filter_instanceid' }, 'add-uptime' => { name => 'add_uptime' }, 'uptime-unit:s' => { name => 'uptime_unit', default => 'd' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if ($self->{option_results}->{uptime_unit} eq '' || !defined($unitdiv->{$self->{option_results}->{uptime_unit}})) { $self->{option_results}->{uptime_unit} = 'd'; } } sub add_uptime { my ($self, %options) = @_; return if (!defined($options{instances}->{ $options{instance_id} })); return if ($options{state} !~ /running|stopping/); # format: "2021-04-16T07:54:33.000Z" return if ($options{instances}->{ $options{instance_id} }->{LaunchTime} !~ /^(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)/); my $dt = DateTime->new( year => $1, month => $2, day => $3, hour => $4, minute => $5, second => $6, time_zone => 'UTC' ); $self->{aws_instances}->{ $options{instance_id} }->{uptime_seconds} = time() - $dt->epoch(); $self->{aws_instances}->{ $options{instance_id} }->{uptime_human} = centreon::plugins::misc::change_seconds( value => $self->{aws_instances}->{ $options{instance_id} }->{uptime_seconds} ); } sub manage_selection { my ($self, %options) = @_; $self->{global} = { pending => 0, running => 0, 'shutting-down' => 0, terminated => 0, stopping => 0, stopped => 0, }; $self->{aws_instances} = {}; my $result = $options{custom}->ec2_get_instances_status(); my $instances; if (defined($self->{option_results}->{add_uptime})) { $instances = $options{custom}->ec2_get_instances(); } foreach my $instance_id (keys %{$result}) { if (defined($self->{option_results}->{filter_instanceid}) && $self->{option_results}->{filter_instanceid} ne '' && $instance_id !~ /$self->{option_results}->{filter_instanceid}/) { $self->{output}->output_add(long_msg => "skipping '" . $instance_id . "': no matching filter.", debug => 1); next; } $self->{aws_instances}->{$instance_id} = { display => $instance_id, state => $result->{$instance_id}->{state}, status => $result->{$instance_id}->{status} }; $self->add_uptime(instances => $instances, instance_id => $instance_id, state => $result->{$instance_id}->{state}) if (defined($self->{option_results}->{add_uptime})); $self->{global}->{ $result->{$instance_id}->{state} }++; } if (scalar(keys %{$self->{aws_instances}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No aws instance found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check EC2 instances status. Example: perl centreon_plugins.pl --plugin=cloud::aws::ec2::plugin --custommode=paws --mode=instances-status --region='eu-west-1' --filter-instanceid='.*' --filter-counters='^running$' --critical-running='10' --verbose See 'https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeInstanceStatus.html' for more informations. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^running$' =item B<--filter-instanceid> Filter by instance id (can be a regexp). =item B<--add-uptime> Monitor instances uptime. =item B<--uptime-unit> Select the unit for uptime threshold. May be 's' for seconds, 'm' for minutes, 'h' for hours, 'd' for days, 'w' for weeks. Default is days. =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-*> B<--critical-*> Thresholds. Can be: 'pending', 'running', 'shuttingdown', 'terminated', 'stopping', 'stopped', 'uptime'. =back =cut centreon-plugins-20220113/cloud/aws/ec2/mode/instancestypes.pm000066400000000000000000000271411417000230700241500ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::ec2::mode::instancestypes; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my %family_mapping = ( 'general' => { 'prefix_output' => 'prefix_general_output', 'types' => [ 'a1.medium', 'a1.large', 'a1.xlarge', 'a1.2xlarge', 'a1.4xlarge', 'm4.large', 'm4.xlarge', 'm4.2xlarge', 'm4.4xlarge', 'm4.10xlarge', 'm4.16xlarge', 'm5.large', 'm5.xlarge', 'm5.2xlarge', 'm5.4xlarge', 'm5.8xlarge', 'm5.12xlarge', 'm5.16xlarge', 'm5.24xlarge', 'm5.metal', 'm5a.large', 'm5a.xlarge', 'm5a.2xlarge', 'm5a.4xlarge', 'm5a.8xlarge', 'm5a.12xlarge', 'm5a.16xlarge', 'm5a.24xlarge', 'm5ad.large', 'm5ad.xlarge', 'm5ad.2xlarge', 'm5ad.4xlarge', 'm5ad.12xlarge', 'm5ad.24xlarge', 'm5d.large', 'm5d.xlarge', 'm5d.2xlarge', 'm5d.4xlarge', 'm5d.8xlarge', 'm5d.12xlarge', 'm5d.16xlarge', 'm5d.24xlarge', 'm5d.metal', 't2.nano', 't2.micro', 't2.small', 't2.medium', 't2.large', 't2.xlarge', 't2.2xlarge', 't3.nano', 't3.micro', 't3.small', 't3.medium', 't3.large', 't3.xlarge', 't3.2xlarge', 't3a.nano', 't3a.micro', 't3a.small', 't3a.medium', 't3a.large', 't3a.xlarge', 't3a.2xlarge' ], }, 'compute' => { 'prefix_output' => 'prefix_compute_output', 'types' => [ 'c4.large', 'c4.xlarge', 'c4.2xlarge', 'c4.4xlarge', 'c4.8xlarge', 'c5.large', 'c5.xlarge', 'c5.2xlarge', 'c5.4xlarge', 'c5.9xlarge', 'c5.12xlarge', 'c5.18xlarge', 'c5.24xlarge', 'c5.metal', 'c5d.large', 'c5d.xlarge', 'c5d.2xlarge', 'c5d.4xlarge', 'c5d.9xlarge', 'c5d.18xlarge', 'c5n.large', 'c5n.xlarge', 'c5n.2xlarge', 'c5n.4xlarge', 'c5n.9xlarge', 'c5n.18xlarge' ], }, 'memory' => { 'prefix_output' => 'prefix_memory_output', 'types' => [ 'r4.large', 'r4.xlarge', 'r4.2xlarge', 'r4.4xlarge', 'r4.8xlarge', 'r4.16xlarge', 'r5.large', 'r5.xlarge', 'r5.2xlarge', 'r5.4xlarge', 'r5.8xlarge', 'r5.12xlarge', 'r5.16xlarge', 'r5.24xlarge', 'r5.metal', 'r5a.large', 'r5a.xlarge', 'r5a.2xlarge', 'r5a.4xlarge', 'r5a.8xlarge', 'r5a.12xlarge', 'r5a.16xlarge', 'r5a.24xlarge', 'r5ad.large', 'r5ad.xlarge', 'r5ad.2xlarge', 'r5ad.4xlarge', 'r5ad.12xlarge', 'r5ad.24xlarge', 'r5d.large', 'r5d.xlarge', 'r5d.2xlarge', 'r5d.4xlarge', 'r5d.8xlarge', 'r5d.12xlarge', 'r5d.16xlarge', 'r5d.24xlarge', 'r5d.metal', 'u-6tb1.metal', 'u-9tb1.metal', 'u-12tb1.metal', 'x1.16xlarge', 'x1.32xlarge', 'x1e.xlarge', 'x1e.2xlarge', 'x1e.4xlarge', 'x1e.8xlarge', 'x1e.16xlarge', 'x1e.32xlarge', 'z1d.large', 'z1d.xlarge', 'z1d.2xlarge', 'z1d.3xlarge', 'z1d.6xlarge', 'z1d.12xlarge', 'z1d.metal' ], }, 'storage' => { 'prefix_output' => 'prefix_storage_output', 'types' => [ 'd2.xlarge', 'd2.2xlarge', 'd2.4xlarge', 'd2.8xlarge', 'h1.2xlarge', 'h1.4xlarge', 'h1.8xlarge', 'h1.16xlarge', 'i3.large', 'i3.xlarge', 'i3.2xlarge', 'i3.4xlarge', 'i3.8xlarge', 'i3.16xlarge', 'i3.metal', 'i3en.large', 'i3en.xlarge', 'i3en.2xlarge', 'i3en.3xlarge', 'i3en.6xlarge', 'i3en.12xlarge', 'i3en.24xlarge' ], }, 'accelerated' => { 'prefix_output' => 'prefix_accelerated_output', 'types' => [ 'f1.2xlarge', 'f1.4xlarge', 'f1.16xlarge', 'g3s.xlarge', 'g3.4xlarge', 'g3.8xlarge', 'g3.16xlarge', 'p2.xlarge', 'p2.8xlarge', 'p2.16xlarge', 'p3.2xlarge', 'p3.8xlarge', 'p3.16xlarge', 'p3dn.24xlarge' ], }, ); sub prefix_general_output { my ($self, %options) = @_; return "Spot family 'General purpose' instances count "; } sub prefix_compute_output { my ($self, %options) = @_; return "Spot family 'Compute optimized' instances count "; } sub prefix_memory_output { my ($self, %options) = @_; return "Spot family 'Memory optimized' instances count "; } sub prefix_storage_output { my ($self, %options) = @_; return "Spot family 'Storage optimized' instances count "; } sub prefix_accelerated_output { my ($self, %options) = @_; return "Spot family 'Accelerated computing' instances count "; } sub set_counters { my ($self, %options) = @_; foreach my $family (keys %family_mapping) { my $counter = { name => $family, type => 0, cb_prefix_output => $family_mapping{$family}->{prefix_output}, skipped_code => { -10 => 1 } }; push @{$self->{maps_counters_type}}, $counter; $self->{maps_counters}->{$family} = []; foreach my $type (@{$family_mapping{$family}->{types}}) { my $entry = { label => $type, nlabel => 'ec2.instances.type.' . $family . '.' . $type . '.count', set => { key_values => [ { name => $type } ], output_template => $type . ": %s", perfdatas => [ { value => $type , template => '%d', min => 0 }, ], } }; push @{$self->{maps_counters}->{$family}}, $entry; } } } 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-family:s" => { name => 'filter_family' }, "filter-type:s" => { name => 'filter_type' }, "running" => { name => 'running' } }); return $self; } sub manage_selection { my ($self, %options) = @_; foreach my $family (keys %family_mapping) { if (defined($self->{option_results}->{filter_family}) && $self->{option_results}->{filter_family} ne '' && $family !~ /$self->{option_results}->{filter_family}/) { $self->{output}->output_add(long_msg => sprintf("skipping family '%s'", $family), debug => 1); $self->{maps_counters}->{$family} = undef; } else { foreach my $type (@{$family_mapping{$family}->{types}}) { if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' && $type !~ /$self->{option_results}->{filter_type}/) { next; } $self->{$family}->{$type} = 0; } } } $self->{instances} = $options{custom}->ec2_list_resources(); foreach my $instance (@{$self->{instances}}) { next if ($instance->{Type} !~ /instance/ || (defined($self->{option_results}->{running}) && $instance->{State} !~ /running/)); if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' && $instance->{InstanceType} !~ /$self->{option_results}->{filter_type}/) { $self->{output}->output_add(long_msg => sprintf("skipping type '%s'", $instance->{InstanceType}), debug => 1); next; } foreach my $family (keys %family_mapping) { $self->{$family}->{$instance->{InstanceType}}++ if (defined($self->{maps_counters}->{$family}) && map(/$instance->{InstanceType}/, @{$family_mapping{$family}->{types}})); } } if (scalar(keys %{$self->{general}}) <= 0 && scalar(keys %{$self->{compute}}) <= 0 && scalar(keys %{$self->{memory}}) <= 0 && scalar(keys %{$self->{storage}}) <= 0 && scalar(keys %{$self->{accelerated}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No result matched with applied filters."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check EC2 instances types count. Example: perl centreon_plugins.pl --plugin=cloud::aws::ec2::plugin --custommode=paws --mode=instances-types --region='eu-west-1' --filter-family='general' --filter-type='medium' --critical-t2.medium='10' --verbose See 'https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.html' for more informations. =over 8 =item B<--filter-family> Filter by instance family (regexp) (Can be: 'general', 'compute', 'memory', 'storage', 'accelerated') =item B<--filter-type> Filter by instance type (regexp) =item B<--warning-*> B<--critical-*> Threshold warning. Can be: 'a1.medium', 'a1.large', 'a1.xlarge', 'a1.2xlarge', 'a1.4xlarge', 'm4.large', 'm4.xlarge', 'm4.2xlarge', 'm4.4xlarge', 'm4.10xlarge', 'm4.16xlarge', 'm5.large', 'm5.xlarge', 'm5.2xlarge', 'm5.4xlarge', 'm5.8xlarge', 'm5.12xlarge', 'm5.16xlarge', 'm5.24xlarge', 'm5.metal', 'm5a.large', 'm5a.xlarge', 'm5a.2xlarge', 'm5a.4xlarge', 'm5a.8xlarge', 'm5a.12xlarge', 'm5a.16xlarge', 'm5a.24xlarge', 'm5ad.large', 'm5ad.xlarge', 'm5ad.2xlarge', 'm5ad.4xlarge', 'm5ad.12xlarge', 'm5ad.24xlarge', 'm5d.large', 'm5d.xlarge', 'm5d.2xlarge', 'm5d.4xlarge', 'm5d.8xlarge', 'm5d.12xlarge', 'm5d.16xlarge', 'm5d.24xlarge', 'm5d.metal', 't2.nano', 't2.micro', 't2.small', 't2.medium', 't2.large', 't2.xlarge', 't2.2xlarge', 't3.nano', 't3.micro', 't3.small', 't3.medium', 't3.large', 't3.xlarge', 't3.2xlarge', 't3a.nano', 't3a.micro', 't3a.small', 't3a.medium', 't3a.large', 't3a.xlarge', 't3a.2xlarge', 'c4.large', 'c4.xlarge', 'c4.2xlarge', 'c4.4xlarge', 'c4.8xlarge', 'c5.large', 'c5.xlarge', 'c5.2xlarge', 'c5.4xlarge', 'c5.9xlarge', 'c5.12xlarge', 'c5.18xlarge', 'c5.24xlarge', 'c5.metal', 'c5d.large', 'c5d.xlarge', 'c5d.2xlarge', 'c5d.4xlarge', 'c5d.9xlarge', 'c5d.18xlarge', 'c5n.large', 'c5n.xlarge', 'c5n.2xlarge', 'c5n.4xlarge', 'c5n.9xlarge', 'c5n.18xlarge', 'r4.large', 'r4.xlarge', 'r4.2xlarge', 'r4.4xlarge', 'r4.8xlarge', 'r4.16xlarge', 'r5.large', 'r5.xlarge', 'r5.2xlarge', 'r5.4xlarge', 'r5.8xlarge', 'r5.12xlarge', 'r5.16xlarge', 'r5.24xlarge', 'r5.metal', 'r5a.large', 'r5a.xlarge', 'r5a.2xlarge', 'r5a.4xlarge', 'r5a.8xlarge', 'r5a.12xlarge', 'r5a.16xlarge', 'r5a.24xlarge', 'r5ad.large', 'r5ad.xlarge', 'r5ad.2xlarge', 'r5ad.4xlarge', 'r5ad.12xlarge', 'r5ad.24xlarge', 'r5d.large', 'r5d.xlarge', 'r5d.2xlarge', 'r5d.4xlarge', 'r5d.8xlarge', 'r5d.12xlarge', 'r5d.16xlarge', 'r5d.24xlarge', 'r5d.metal', 'u-6tb1.metal', 'u-9tb1.metal', 'u-12tb1.metal', 'x1.16xlarge', 'x1.32xlarge', 'x1e.xlarge', 'x1e.2xlarge', 'x1e.4xlarge', 'x1e.8xlarge', 'x1e.16xlarge', 'x1e.32xlarge', 'z1d.large', 'z1d.xlarge', 'z1d.2xlarge', 'z1d.3xlarge', 'z1d.6xlarge', 'z1d.12xlarge', 'z1d.metal', 'd2.xlarge', 'd2.2xlarge', 'd2.4xlarge', 'd2.8xlarge', 'h1.2xlarge', 'h1.4xlarge', 'h1.8xlarge', 'h1.16xlarge', 'i3.large', 'i3.xlarge', 'i3.2xlarge', 'i3.4xlarge', 'i3.8xlarge', 'i3.16xlarge', 'i3.metal', 'i3en.large', 'i3en.xlarge', 'i3en.2xlarge', 'i3en.3xlarge', 'i3en.6xlarge', 'i3en.12xlarge', 'i3en.24xlarge','f1.2xlarge', 'f1.4xlarge', 'f1.16xlarge', 'g3s.xlarge', 'g3.4xlarge', 'g3.8xlarge', 'g3.16xlarge', 'p2.xlarge', 'p2.8xlarge', 'p2.16xlarge', 'p3.2xlarge', 'p3.8xlarge', 'p3.16xlarge', 'p3dn.24xlarge'. =item B<--running> Only check running instances. =back =cut centreon-plugins-20220113/cloud/aws/ec2/mode/listasg.pm000066400000000000000000000043251417000230700225410ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::ec2::mode::listasg; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{instances} = $options{custom}->ec2_list_resources(); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach (@{$self->{instances}}) { next if ($_->{Type} !~ m/asg/); $self->{output}->output_add(long_msg => sprintf("[Name = %s]", $_->{Name})); } $self->{output}->output_add(severity => 'OK', short_msg => 'List autoscaling group:'); $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->manage_selection(%options); foreach (@{$self->{instances}}) { next if ($_->{Type} !~ m/asg/); $self->{output}->add_disco_entry( name => $_->{Name}, ); } } 1; __END__ =head1 MODE List EC2 autoscaling groups. =over 8 =back =cut centreon-plugins-20220113/cloud/aws/ec2/mode/listinstances.pm000066400000000000000000000052251417000230700237560ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::ec2::mode::listinstances; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{instances} = $options{custom}->ec2_list_resources(); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach (@{$self->{instances}}) { next if ($_->{Type} !~ m/instance/); $self->{output}->output_add( long_msg => sprintf("[Id = %s][AvailabilityZone = %s][InstanceType = %s][State = %s][Tags = %s][KeyName = %s]", $_->{Name}, $_->{AvailabilityZone}, $_->{InstanceType}, $_->{State}, $_->{Tags}, $_->{KeyName})); } $self->{output}->output_add(severity => 'OK', short_msg => 'List instances:'); $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 => ['id', 'availabilityzone', 'instancetype', 'state', 'tags', 'keyname']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach (@{$self->{instances}}) { next if ($_->{Type} !~ m/instance/); $self->{output}->add_disco_entry( id => $_->{Name}, availabilityzone => $_->{AvailabilityZone}, instancetype => $_->{InstanceType}, state => $_->{State}, tags => $_->{Tags}, keyname => $_->{KeyName}, ); } } 1; __END__ =head1 MODE List EC2 instances. =over 8 =back =cut centreon-plugins-20220113/cloud/aws/ec2/mode/listspotfleetrequests.pm000066400000000000000000000046531417000230700255740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::ec2::mode::listspotfleetrequests; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{spot_fleet_requests} = $options{custom}->ec2spot_list_fleet_requests(); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach (@{$self->{spot_fleet_requests}}) { $self->{output}->output_add( long_msg => sprintf("[id = %s][state = %s][status = %s]", $_->{SpotFleetRequestId}, $_->{SpotFleetRequestState}, $_->{ActivityStatus})); } $self->{output}->output_add(severity => 'OK', short_msg => 'List spot fleet requests:'); $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 => ['id', 'state', 'status']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach (@{$self->{spot_fleet_requests}}) { $self->{output}->add_disco_entry( id => $_->{SpotFleetRequestId}, state => $_->{SpotFleetRequestState}, status => $_->{ActivityStatus} ); } } 1; __END__ =head1 MODE List EC2 Spot Fleet Requests =over 8 =back =cut centreon-plugins-20220113/cloud/aws/ec2/mode/network.pm000066400000000000000000000154011417000230700225610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::ec2::mode::network; use base qw(cloud::aws::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { extra_params => { message_multiple => 'All network metrics are ok' }, metrics => { NetworkIn => { output => 'Network In', label => 'network-in', nlabel => { absolute => 'ec2.network.in.bytes', per_second => 'ec2.network.in.bytespersecond' }, unit => 'B' }, NetworkOut => { output => 'Network Out', label => 'network-out', nlabel => { absolute => 'ec2.network.out.bytes', per_second => 'ec2.network.out.bytespersecond' }, unit => 'B' }, NetworkPacketsIn => { output => 'Network Packets In', label => 'network-packets-in', nlabel => { absolute => 'ec2.network.packets.in.count', per_second => 'ec2.network.packets.in.persecond' }, unit => 'packets' }, NetworkPacketsOut => { output => 'Network Packets Out', label => 'network-packets-out', nlabel => { absolute => 'ec2.network.packets.out.count', per_second => 'ec2.network.packets.out.persecond' }, unit => 'packets' } } }; return $metrics_mapping; } sub prefix_metric_output { my ($self, %options) = @_; return ucfirst($self->{option_results}->{type}) . " '" . $options{instance_value}->{display} . "' "; } sub long_output { my ($self, %options) = @_; return "Checking " . ucfirst($self->{option_results}->{type}) . " '" . $options{instance_value}->{display} . "' "; } 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 => { 'type:s' => { name => 'type' }, 'name:s@' => { name => 'name' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{type}) || $self->{option_results}->{type} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --type option."); $self->{output}->option_exit(); } if ($self->{option_results}->{type} ne 'asg' && $self->{option_results}->{type} ne 'instance') { $self->{output}->add_option_msg(short_msg => "Instance type '" . $self->{option_results}->{type} . "' is not handled for this mode"); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } } my %map_type = ( 'instance' => "InstanceId", 'asg' => "AutoScalingGroupName" ); sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/EC2', dimensions => [ { Name => $map_type{$self->{option_results}->{type}}, Value => $instance } ], metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period}, ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{$instance}->{display} = $instance; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{display} = $statistic; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{timeframe} = $self->{aws_timeframe}; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{$metric} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check EC2 instances network metrics. Example: perl centreon_plugins.pl --plugin=cloud::aws::ec2::plugin --custommode=paws --mode=network --region='eu-west-1' --type='asg' --name='centreon-middleware' --filter-metric='Packets' --statistic='sum' --critical-network-packets-out='10' --verbose See 'https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/ec2-metricscollected.html' for more informations. Default statistic: 'average' / All satistics are valid. =over 8 =item B<--type> Set the instance type (Required) (Can be: 'asg', 'instance'). =item B<--name> Set the instance name (Required) (Can be multiple). =item B<--filter-metric> Filter metrics (Can be: 'NetworkIn', 'NetworkOut', 'NetworkPacketsIn', 'NetworkPacketsOut') (Can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds warning (Can be 'network-in', 'network-out', 'network-packets-in', 'network-packets-out'. =item B<--per-sec> Change the data to be unit/sec. =back =cut centreon-plugins-20220113/cloud/aws/ec2/mode/spotactiveinstances.pm000066400000000000000000000070701417000230700251640ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::ec2::mode::spotactiveinstances; 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 }, ]; $self->{maps_counters}->{global} = [ { label => 'active', nlabel => 'ec2.spot.instances.active.count', set => { key_values => [ { name => 'active' } ], output_template => 'Active instances : %s', perfdatas => [ { label => 'active', value => 'active', template => '%s', min => 0 }, ], } }, { label => 'healthy', nlabel => 'ec2.spot.instances.healthy.count', set => { key_values => [ { name => 'healthy' } ], output_template => 'Healthy instances : %s', perfdatas => [ { label => 'healthy', value => 'healthy', template => '%s', min => 0 }, ], } }, { label => 'unhealthy', nlabel => 'ec2.spot.instances.unhealthy.count', set => { key_values => [ { name => 'unhealthy' } ], output_template => 'Unhealty instances : %s', perfdatas => [ { label => 'unhealthy', value => 'unhealthy', template => '%s', min => 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 => { 'spot-fleet-request-id:s' => { name => 'spot_fleet_request_id' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{spot_fleet_request_id}) || $self->{option_results}->{spot_fleet_request_id} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --spot-fleet-request-id option."); $self->{output}->option_exit(); } } sub manage_selection { my ($self, %options) = @_; $self->{global} = { active => 0, healthy => 0, unhealthy => 0 }; $self->{instances} = $options{custom}->ec2spot_get_active_instances_status(spot_fleet_request_id => $self->{option_results}->{spot_fleet_request_id}); foreach my $instance_id (keys %{$self->{instances}}) { $self->{global}->{active}++; $self->{global}->{lc($self->{instances}->{$instance_id}->{health})}++; } } 1; __END__ =head1 MODE Check EC2 Spot active instance for a specific fleet =over 8 =item B<--warning-*> B<--critical-*> Warning and Critical thresholds. You can use 'active', 'healthy', 'unhealthy' =back =cut centreon-plugins-20220113/cloud/aws/ec2/mode/status.pm000066400000000000000000000162461417000230700224230ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::ec2::mode::status; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my %map_type = ( 'instance' => 'InstanceId', 'asg' => 'AutoScalingGroupName' ); my %map_status = ( 0 => 'passed', 1 => 'failed' ); sub prefix_metric_output { my ($self, %options) = @_; return ucfirst($options{instance_value}->{type}) . " '" . $options{instance_value}->{display} . "' "; } sub custom_status_threshold { my ($self, %options) = @_; my $status = 'ok'; if (defined($self->{instance_mode}->{option_results}->{critical_status}) && $self->{instance_mode}->{option_results}->{critical_status} ne '' && $self->eval(value => $self->{instance_mode}->{option_results}->{critical_status})) { $status = 'critical'; } elsif (defined($self->{instance_mode}->{option_results}->{warning_status}) && $self->{instance_mode}->{option_results}->{warning_status} ne '' && $self->eval(value => $self->{instance_mode}->{option_results}->{warning_status})) { $status = 'warning'; } return $status; } sub custom_status_output { my ($self, %options) = @_; return $self->{result_values}->{metric} . ": " . $self->{result_values}->{status}; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $map_status{$options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{metric}}}; $self->{result_values}->{metric} = $options{extra_options}->{metric}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All status metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $metric ('StatusCheckFailed_Instance', 'StatusCheckFailed_System') { my $entry = { label => lc($metric), threshold => 0, set => { key_values => [ { name => $metric }, { name => 'display' } ], closure_custom_calc => $self->can('custom_status_calc'), closure_custom_calc_extra_options => { metric => $metric }, closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => $self->can('custom_status_threshold') } }; push @{$self->{maps_counters}->{metric}}, $entry; } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'type:s' => { name => 'type' }, 'name:s@' => { name => 'name' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{status} =~ /failed/i' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{type}) || $self->{option_results}->{type} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --type option."); $self->{output}->option_exit(); } if ($self->{option_results}->{type} ne 'asg' && $self->{option_results}->{type} ne 'instance') { $self->{output}->add_option_msg(short_msg => "Instance type '" . $self->{option_results}->{type} . "' is not handled for this mode"); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 90; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Average']; foreach my $metric ('StatusCheckFailed_Instance', 'StatusCheckFailed_System') { push @{$self->{aws_metrics}}, $metric; } $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/EC2', dimensions => [ { Name => $map_type{$self->{option_results}->{type}}, Value => $instance } ], metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period}, ); foreach my $metric (keys %{$metric_results{$instance}}) { next if (!defined($metric_results{$instance}->{$metric}->{average})); $self->{metric}->{$instance}->{display} = $instance; $self->{metric}->{$instance}->{type} = $self->{option_results}->{type}; $self->{metric}->{$instance}->{$metric} = $metric_results{$instance}->{$metric}->{average}; } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics detected.'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check EC2 instances status metrics. Example: perl centreon_plugins.pl --plugin=cloud::aws::ec2::plugin --custommode=paws --mode=status --region='eu-west-1' --type='asg' --name='centreon-middleware' --verbose See 'https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/ec2-metricscollected.html' for more informations. Default statistic: 'average' / Only valid statistic: 'average'. =over 8 =item B<--type> Set the instance type (Required) (Can be: 'asg', 'instance'). =item B<--name> Set the instance name (Required) (Can be multiple). =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{status}. 'status' can be: 'passed', 'failed'. =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /failed/i'). Can used special variables like: %{status}. 'status' can be: 'passed', 'failed'. =back =cut centreon-plugins-20220113/cloud/aws/ec2/plugin.pm000066400000000000000000000044331417000230700214450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::ec2::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} } = ( 'asg-status' => 'cloud::aws::ec2::mode::asgstatus', 'cpu' => 'cloud::aws::ec2::mode::cpu', 'discovery' => 'cloud::aws::ec2::mode::discovery', 'discovery-fleet-requests' => 'cloud::aws::ec2::mode::discoveryspotfleetrequests', 'diskio' => 'cloud::aws::ec2::mode::diskio', 'instances-status' => 'cloud::aws::ec2::mode::instancesstatus', 'instances-types' => 'cloud::aws::ec2::mode::instancestypes', 'list-asg' => 'cloud::aws::ec2::mode::listasg', 'list-instances' => 'cloud::aws::ec2::mode::listinstances', 'list-spot-fleet-requests' => 'cloud::aws::ec2::mode::listspotfleetrequests', 'network' => 'cloud::aws::ec2::mode::network', 'status' => 'cloud::aws::ec2::mode::status', 'spot-active-instances' => 'cloud::aws::ec2::mode::spotactiveinstances' ); $self->{custom_modes}{paws} = 'cloud::aws::custom::paws'; $self->{custom_modes}{awscli} = 'cloud::aws::custom::awscli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Amazon Elastic Compute Cloud (Amazon EC2). =cut centreon-plugins-20220113/cloud/aws/efs/000077500000000000000000000000001417000230700177115ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/efs/mode/000077500000000000000000000000001417000230700206355ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/efs/mode/connections.pm000066400000000000000000000113351417000230700235200ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::efs::mode::connections; use base qw(cloud::aws::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { extra_params => { message_multiple => 'All FS metrics are ok' }, metrics => { ClientConnections => { output => 'Client Connections', label => 'client-connections', nlabel => { absolute => 'efs.clients.connections.count' }, unit => '' } } }; return $metrics_mapping; } sub long_output { my ($self, %options) = @_; return "EFS FileSystemId '" . $options{instance_value}->{display} . "' "; } 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 => { 'name:s@' => { name => 'name' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 172800; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 86400; $self->{aws_statistics} = ['Sum']; } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/EFS', dimensions => [ { Name => 'FileSystemId', Value => $instance } ], metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period} ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{$instance}->{display} = $instance; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{display} = $statistic; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{timeframe} = $self->{aws_timeframe}; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{$metric} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check EFS FileSystem Connection Count. Example: perl centreon_plugins.pl --plugin=cloud::aws::efs::plugin --custommode=paws --mode=connections --region='eu-west-1' --name='fs-1234abcd' --warning-client-connections='50' --critical-client-connections='100' --verbose See 'https://docs.aws.amazon.com/efs/latest/ug/monitoring-cloudwatch.html' for more information. =over 8 =item B<--name> Set the instance name (Required) (Can be multiple). =item B<--warning-client-connections> Warning threshold. =item B<--critical-client-connections> Critical threshold. =back =cut centreon-plugins-20220113/cloud/aws/efs/mode/datausage.pm000066400000000000000000000146561417000230700231450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::efs::mode::datausage; use base qw(cloud::aws::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { extra_params => { message_multiple => 'All FS metrics are ok' }, metrics => { DataReadIOByte => { output => 'Data Read IO Bytes', label => 'data-iobytes-read', nlabel => { absolute => 'efs.data.iobytes.read.bytes', per_second => 'efs.data.iobytes.read.bytespersecond' }, unit => 'B' }, DataWriteIOBytes => { output => 'Data Write IO Bytes', label => 'data-iobytes-write', nlabel => { absolute => 'efs.data.iobytes.write.bytes', per_second => 'efs.data.iobytes.write.bytespersecond' }, unit => 'B' }, MetaDataIOBytes => { output => 'MetaData IO Bytes', label => 'metadata-iobytes', nlabel => { absolute => 'efs.metadata.iobytes.bytes', per_second => 'efs.metadata.iobytes.bytespersecond' }, unit => 'B' }, TotalIOBytes => { output => 'Total IO Bytes', label => 'total-iobytes', nlabel => { absolute => 'efs.total.iobytes.bytes', per_second => 'efs.total.iobytes.bytespersecond' }, unit => 'B' }, BurstCreditBalance => { output => 'Burst Credit Balance Bytes', label => 'burst-bytes', nlabel => { absolute => 'efs.creditbalance.burst.bytes', per_second => 'efs.creditbalance.burst.bytespersecond' }, unit => 'B' } } }; return $metrics_mapping; } sub long_output { my ($self, %options) = @_; return "EFS FileSystemId '" . $options{instance_value}->{display} . "' "; } 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 => { 'name:s@' => { name => 'name' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/EFS', dimensions => [ { Name => "FileSystemId", Value => $instance } ], metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period} ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{$instance}->{display} = $instance; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{display} = $statistic; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{timeframe} = $self->{aws_timeframe}; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{$metric} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check EFS FileSystem Data IO metrics. Example: perl centreon_plugins.pl --plugin=cloud::aws::efs::plugin --custommode=paws --mode=datausage --region='eu-west-1' --name='fs-1234abcd' --filter-metric='DataReadIOBytes' --warning-data-iobytes-read='5' --critical-data-iobytes-read='10' --verbose See 'https://docs.aws.amazon.com/efs/latest/ug/monitoring-cloudwatch.html' for more information. =over 8 =item B<--name> Set the instance name (Required) (Can be multiple). =item B<--filter-metric> Filter on a specific metric Can be: DataReadIOBytes, DataWriteIOBytes, MetaDataIOBytes, TotalIOBytes, BurstCreditBalance =item B<--statistic> Set the metric calculation method (Default: Average) Can be 'minimum', 'maximum', 'average', 'sum' =item B<--warning-$metric$> Thresholds warning ($metric$ can be: 'data-iobytes-read', 'data-iobytes-write', 'metadata-iobytes', 'total-iobytes', 'burst-bytes'). =item B<--critical-$metric$> Thresholds critical ($metric$ can be: 'data-iobytes-read', 'data-iobytes-write', 'metadata-iobytes', 'total-iobytes', 'burst-bytes'). =back =cut centreon-plugins-20220113/cloud/aws/efs/mode/discovery.pm000066400000000000000000000056541417000230700232140ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::efs::mode::discovery; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'prettify' => { name => 'prettify' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my @disco_data; my $disco_stats; $disco_stats->{start_time} = time(); my $fs_instances = $options{custom}->discovery( service => 'efs', command => 'describe-file-systems' ); foreach my $fs_instance (@{$fs_instances->{FileSystems}}) { next if (!defined($fs_instance->{FileSystemId})); my %efs; $efs{type} = "efs"; $efs{id} = $fs_instance->{FileSystemId}; $efs{name} = $fs_instance->{Name}; $efs{creation_time} = $fs_instance->{CreationTime}; $efs{size} = $fs_instance->{SizeInBytes}->{Value}; $efs{perf_mode} = $fs_instance->{PerformanceMode }; $efs{is_encrypted} = $fs_instance->{Encrypted}; $efs{throughput_mode} = $fs_instance->{ThroughputMode}; push @disco_data, \%efs; } $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; $disco_stats->{discovered_items} = @disco_data; $disco_stats->{results} = \@disco_data; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE EFS discovery. =over 8 =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/aws/efs/plugin.pm000066400000000000000000000027351417000230700215540ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::efs::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} = '1.0'; %{ $self->{modes} } = ( 'connections' => 'cloud::aws::efs::mode::connections', 'datausage' => 'cloud::aws::efs::mode::datausage', 'discovery' => 'cloud::aws::efs::mode::discovery' ); $self->{custom_modes}{paws} = 'cloud::aws::custom::paws'; $self->{custom_modes}{awscli} = 'cloud::aws::custom::awscli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Amazon Elastic File System (Amazon EFS). =cut centreon-plugins-20220113/cloud/aws/elasticache/000077500000000000000000000000001417000230700214015ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/elasticache/mode/000077500000000000000000000000001417000230700223255ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/elasticache/mode/commandsmemcached.pm000066400000000000000000000247121417000230700263210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::elasticache::mode::commandsmemcached; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; my $node_id = ""; if (defined($options{instance_value}->{node_id}) && $options{instance_value}->{node_id} ne '') { $node_id = "[Node: $options{instance_value}->{node_id}] "; } return "Cluster '" . $options{instance_value}->{display} . "' " . $node_id . $options{instance_value}->{stat} . " commands "; } sub custom_metric_calc { my ($self, %options) = @_; $self->{result_values}->{timeframe} = $options{new_datas}->{$self->{instance} . '_timeframe'}; $self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{metric} . '_' . $options{extra_options}->{stat}}; $self->{result_values}->{value_per_sec} = $self->{result_values}->{value} / $self->{result_values}->{timeframe}; $self->{result_values}->{stat} = $options{extra_options}->{stat}; $self->{result_values}->{metric} = $options{extra_options}->{metric}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub custom_metric_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check(value => defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}, threshold => [ { label => 'critical-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat}), exit_litteral => 'critical' }, { label => 'warning-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat}), exit_litteral => 'warning' } ]); return $exit; } sub custom_metric_perfdata { my ($self, %options) = @_; my $extra_label = ''; $extra_label = '_' . lc($self->{result_values}->{display}) if (!defined($options{extra_instance}) || $options{extra_instance} != 0); $self->{output}->perfdata_add(label => lc($self->{result_values}->{metric}) . "_" . lc($self->{result_values}->{stat}) . $extra_label, unit => defined($self->{instance_mode}->{option_results}->{per_sec}) ? 'cmd/s' : 'cmd', value => sprintf("%.2f", defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat})), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat})), ); } sub custom_metric_output { my ($self, %options) = @_; my $msg = ""; if (defined($self->{instance_mode}->{option_results}->{per_sec})) { $msg = sprintf("%s: %.2f cmd/s", $self->{result_values}->{metric}, $self->{result_values}->{value_per_sec}); } else { $msg = sprintf("%s: %.2f cmd", $self->{result_values}->{metric}, $self->{result_values}->{value}); } return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All commands metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $statistic ('minimum', 'maximum', 'average', 'sum') { foreach my $metric ('CmdFlush', 'CmdGet', 'CmdSet', 'CmdConfigGet', 'CmdConfigSet', 'CmdTouch') { my $entry = { label => lc($metric) . '-' . lc($statistic), set => { key_values => [ { name => $metric . '_' . $statistic }, { name => 'display' }, { name => 'stat' }, { name => 'timeframe' } ], closure_custom_calc => $self->can('custom_metric_calc'), closure_custom_calc_extra_options => { metric => $metric, stat => $statistic }, 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'), } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "name:s@" => { name => 'name' }, "node-id:s" => { name => 'node_id' }, "filter-metric:s" => { name => 'filter_metric' }, "per-sec" => { name => 'per_sec' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Average']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } foreach my $metric ('CmdFlush', 'CmdGet', 'CmdSet', 'CmdConfigGet', 'CmdConfigSet', 'CmdTouch') { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { push @{$self->{aws_dimensions}}, { Name => 'CacheClusterId', Value => $instance }; if (defined($self->{option_results}->{node_id}) && $self->{option_results}->{node_id} ne '') { push @{$self->{aws_dimensions}}, { Name => 'CacheNodeId', Value => $self->{option_results}->{node_id} }; } $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/ElastiCache', dimensions => $self->{aws_dimensions}, metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period} ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$instance . "_" . lc($statistic)}->{display} = $instance; $self->{metric}->{$instance . "_" . lc($statistic)}->{stat} = lc($statistic); $self->{metric}->{$instance . "_" . lc($statistic)}->{node_id} = $self->{option_results}->{node_id}; $self->{metric}->{$instance . "_" . lc($statistic)}->{timeframe} = $self->{aws_timeframe}; $self->{metric}->{$instance . "_" . lc($statistic)}->{$metric . "_" . lc($statistic)} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check ElastiCache cluster received commands for Memcached backends (flush, get and set, config get, config set and touch for Memcached 1.4.14). Example: perl centreon_plugins.pl --plugin=cloud::aws::elasticache::plugin --custommode=paws --mode=commands-memcached --region='eu-west-1' --name='centreon-front' --statistic='average' --critical-cmdget-average='50' --verbose --per-sec See 'https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/elasticache-metricscollected.html' for more informations. Default statistic: 'average' / All satistics are valid. =over 8 =item B<--name> Set the cluster name (Required) (Can be multiple). =item B<--node-id> Set the node id (Optional). =item B<--filter-metric> Filter metrics (Can be: 'CmdFlush', 'CmdGet', 'CmdSet', 'CmdConfigGet', 'CmdConfigSet', 'CmdTouch') (Can be a regexp). =item B<--warning-$metric$-$statistic$> Thresholds warning ($metric$ can be: 'cmdflush', 'cmdget', 'cmdset', 'cmdconfigget', 'cmdconfigset', 'cmdtouch', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =item B<--critical-$metric$-$statistic$> Thresholds critical ($metric$ can be: 'cmdflush', 'cmdget', 'cmdset', 'cmdconfigget', 'cmdconfigset', 'cmdtouch', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =item B<--per-sec> Change the data to be unit/sec. =back =cut centreon-plugins-20220113/cloud/aws/elasticache/mode/commandsredis.pm000066400000000000000000000255751417000230700255310ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::elasticache::mode::commandsredis; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; my $node_id = ""; if (defined($options{instance_value}->{node_id}) && $options{instance_value}->{node_id} ne '') { $node_id = "[Node: $options{instance_value}->{node_id}] "; } return "Cluster '" . $options{instance_value}->{display} . "' " . $node_id . $options{instance_value}->{stat} . " commands "; } sub custom_metric_calc { my ($self, %options) = @_; $self->{result_values}->{timeframe} = $options{new_datas}->{$self->{instance} . '_timeframe'}; $self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{metric} . '_' . $options{extra_options}->{stat}}; $self->{result_values}->{value_per_sec} = $self->{result_values}->{value} / $self->{result_values}->{timeframe}; $self->{result_values}->{stat} = $options{extra_options}->{stat}; $self->{result_values}->{metric} = $options{extra_options}->{metric}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub custom_metric_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check(value => defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}, threshold => [ { label => 'critical-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat}), exit_litteral => 'critical' }, { label => 'warning-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat}), exit_litteral => 'warning' } ]); return $exit; } sub custom_metric_perfdata { my ($self, %options) = @_; my $extra_label = ''; $extra_label = '_' . lc($self->{result_values}->{display}) if (!defined($options{extra_instance}) || $options{extra_instance} != 0); $self->{output}->perfdata_add(label => lc($self->{result_values}->{metric}) . "_" . lc($self->{result_values}->{stat}) . $extra_label, unit => defined($self->{instance_mode}->{option_results}->{per_sec}) ? 'cmd/s' : 'cmd', value => sprintf("%.2f", defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat})), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat})), ); } sub custom_metric_output { my ($self, %options) = @_; my $msg = ""; if (defined($self->{instance_mode}->{option_results}->{per_sec})) { $msg = sprintf("%s: %.2f cmd/s", $self->{result_values}->{metric}, $self->{result_values}->{value_per_sec}); } else { $msg = sprintf("%s: %.2f cmd", $self->{result_values}->{metric}, $self->{result_values}->{value}); } return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All commands metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $statistic ('minimum', 'maximum', 'average', 'sum') { foreach my $metric ('GetTypeCmds', 'HashBasedCmds', 'KeyBasedCmds', 'ListBasedCmds', 'SetBasedCmds', 'SetTypeCmds', 'SortedSetBasedCmds', 'StringBasedCmds', 'HyperLogLogBasedCmds') { my $entry = { label => lc($metric) . '-' . lc($statistic), set => { key_values => [ { name => $metric . '_' . $statistic }, { name => 'display' }, { name => 'stat' }, { name => 'timeframe' } ], closure_custom_calc => $self->can('custom_metric_calc'), closure_custom_calc_extra_options => { metric => $metric, stat => $statistic }, 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'), } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "name:s@" => { name => 'name' }, "node-id:s" => { name => 'node_id' }, "filter-metric:s" => { name => 'filter_metric' }, "per-sec" => { name => 'per_sec' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Average']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } foreach my $metric ('GetTypeCmds', 'HashBasedCmds', 'KeyBasedCmds', 'ListBasedCmds', 'SetBasedCmds', 'SetTypeCmds', 'SortedSetBasedCmds', 'StringBasedCmds', 'HyperLogLogBasedCmds') { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { push @{$self->{aws_dimensions}}, { Name => 'CacheClusterId', Value => $instance }; if (defined($self->{option_results}->{node_id}) && $self->{option_results}->{node_id} ne '') { push @{$self->{aws_dimensions}}, { Name => 'CacheNodeId', Value => $self->{option_results}->{node_id} }; } $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/ElastiCache', dimensions => $self->{aws_dimensions}, metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period} ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$instance . "_" . lc($statistic)}->{display} = $instance; $self->{metric}->{$instance . "_" . lc($statistic)}->{stat} = lc($statistic); $self->{metric}->{$instance . "_" . lc($statistic)}->{node_id} = $self->{option_results}->{node_id}; $self->{metric}->{$instance . "_" . lc($statistic)}->{timeframe} = $self->{aws_timeframe}; $self->{metric}->{$instance . "_" . lc($statistic)}->{$metric . "_" . lc($statistic)} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check ElastiCache cluster received commands for Redis backends (get and set, hash, key, list, set, sorted set, string and hyperlog log based). Example: perl centreon_plugins.pl --plugin=cloud::aws::elasticache::plugin --custommode=paws --mode=commands-redis --region='eu-west-1' --name='centreon-front' --statistic='average' --critical-cmdget-average='50' --verbose --per-sec See 'https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/elasticache-metricscollected.html' for more informations. Default statistic: 'average' / All satistics are valid. =over 8 =item B<--name> Set the cluster name (Required) (Can be multiple). =item B<--node-id> Set the node id (Optional). =item B<--filter-metric> Filter metrics (Can be: 'GetTypeCmds', 'HashBasedCmds', 'KeyBasedCmds', 'ListBasedCmds', 'SetBasedCmds', 'SetTypeCmds', 'SortedSetBasedCmds', 'StringBasedCmds', 'HyperLogLogBasedCmds') (Can be a regexp). =item B<--warning-$metric$-$statistic$> Thresholds warning ($metric$ can be: 'gettypecmds', 'hashbasedcmds', 'keybasedcmds', 'listbasedcmds', 'setbasedcmds', 'settypecmds', 'sortedsetbasedcmds', 'stringbasedcmds', 'hyperloglogbasedcmds', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =item B<--critical-$metric$-$statistic$> Thresholds critical ($metric$ can be: 'gettypecmds', 'hashbasedcmds', 'keybasedcmds', 'listbasedcmds', 'setbasedcmds', 'settypecmds', 'sortedsetbasedcmds', 'stringbasedcmds' 'hyperloglogbasedcmds', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =item B<--per-sec> Change the data to be unit/sec. =back =cut centreon-plugins-20220113/cloud/aws/elasticache/mode/connections.pm000066400000000000000000000260231417000230700252100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::elasticache::mode::connections; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; my $node_id = ""; if (defined($options{instance_value}->{node_id}) && $options{instance_value}->{node_id} ne '') { $node_id = "[Node: $options{instance_value}->{node_id}] "; } return "Cluster '" . $options{instance_value}->{display} . "' " . $node_id . $options{instance_value}->{stat} . " "; } sub custom_connection_calc { my ($self, %options) = @_; $self->{result_values}->{timeframe} = $options{new_datas}->{$self->{instance} . '_timeframe'}; $self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{metric} . '_' . $options{extra_options}->{stat}}; $self->{result_values}->{value_per_sec} = $self->{result_values}->{value} / $self->{result_values}->{timeframe}; $self->{result_values}->{stat} = $options{extra_options}->{stat}; $self->{result_values}->{metric} = $options{extra_options}->{metric}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub custom_connection_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check(value => defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}, threshold => [ { label => 'critical-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat}), exit_litteral => 'critical' }, { label => 'warning-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat}), exit_litteral => 'warning' } ]); return $exit; } sub custom_connection_perfdata { my ($self, %options) = @_; my $extra_label = ''; $extra_label = '_' . lc($self->{result_values}->{display}) if (!defined($options{extra_instance}) || $options{extra_instance} != 0); $self->{output}->perfdata_add(label => lc($self->{result_values}->{metric}) . "_" . lc($self->{result_values}->{stat}) . $extra_label, unit => defined($self->{instance_mode}->{option_results}->{per_sec}) ? 'conn/s' : 'conn', value => sprintf("%.2f", defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat})), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat})), ); } sub custom_connection_output { my ($self, %options) = @_; my $msg = ""; if (defined($self->{instance_mode}->{option_results}->{per_sec})) { $msg = sprintf("%s: %.2f connections/s", $self->{result_values}->{metric}, $self->{result_values}->{value_per_sec}); } else { $msg = sprintf("%s: %.2f connections", $self->{result_values}->{metric}, $self->{result_values}->{value}); } return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All connections metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $statistic ('minimum', 'maximum', 'average', 'sum') { foreach my $metric ('CurrConnections') { my $entry = { label => lc($metric) . '-' . lc($statistic), set => { key_values => [ { name => $metric . '_' . $statistic }, { name => 'display' }, { name => 'stat' } ], output_template => $metric . ': %d connections', perfdatas => [ { label => lc($metric) . '_' . lc($statistic), value => $metric . '_' . $statistic , template => '%d', unit => 'conn', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } foreach my $metric ('NewConnections') { my $entry = { label => lc($metric) . '-' . lc($statistic), set => { key_values => [ { name => $metric . '_' . $statistic }, { name => 'display' }, { name => 'stat' }, { name => 'timeframe' } ], closure_custom_calc => $self->can('custom_connection_calc'), closure_custom_calc_extra_options => { metric => $metric, stat => $statistic }, closure_custom_output => $self->can('custom_connection_output'), closure_custom_perfdata => $self->can('custom_connection_perfdata'), closure_custom_threshold_check => $self->can('custom_connection_threshold'), } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "name:s@" => { name => 'name' }, "node-id:s" => { name => 'node_id' }, "filter-metric:s" => { name => 'filter_metric' }, "per-sec" => { name => 'per_sec' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Average']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } foreach my $metric ('CurrConnections', 'NewConnections') { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { push @{$self->{aws_dimensions}}, { Name => 'CacheClusterId', Value => $instance }; if (defined($self->{option_results}->{node_id}) && $self->{option_results}->{node_id} ne '') { push @{$self->{aws_dimensions}}, { Name => 'CacheNodeId', Value => $self->{option_results}->{node_id} }; } $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/ElastiCache', dimensions => $self->{aws_dimensions}, metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period} ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$instance . "_" . lc($statistic)}->{display} = $instance; $self->{metric}->{$instance . "_" . lc($statistic)}->{stat} = lc($statistic); $self->{metric}->{$instance . "_" . lc($statistic)}->{node_id} = $self->{option_results}->{node_id}; $self->{metric}->{$instance . "_" . lc($statistic)}->{timeframe} = $self->{aws_timeframe}; $self->{metric}->{$instance . "_" . lc($statistic)}->{$metric . "_" . lc($statistic)} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check ElastiCache cluster connections (current and new). Works with Memcached and Redis backends. Example: perl centreon_plugins.pl --plugin=cloud::aws::elasticache::plugin --custommode=paws --mode=connections --region='eu-west-1' --name='centreon-front' --statistic='average' --critical-currconnections-average='20' --verbose See 'https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/elasticache-metricscollected.html' for more informations. Default statistic: 'average' / All satistics are valid. =over 8 =item B<--name> Set the cluster name (Required) (Can be multiple). =item B<--node-id> Set the node id (Optional). =item B<--filter-metric> Filter metrics (Can be: 'CurrConnections', 'NewConnections') (Can be a regexp). =item B<--warning-$metric$-$statistic$> Thresholds warning ($metric$ can be: 'currconnections', 'newconnections', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =item B<--critical-$metric$-$statistic$> Thresholds critical ($metric$ can be: 'currconnections', 'newconnections', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =item B<--per-sec> Change the data to be unit/sec. =back =cut centreon-plugins-20220113/cloud/aws/elasticache/mode/cpu.pm000066400000000000000000000147451417000230700234650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::elasticache::mode::cpu; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; my $node_id = ""; if (defined($options{instance_value}->{node_id}) && $options{instance_value}->{node_id} ne '') { $node_id = "[Node: $options{instance_value}->{node_id}] "; } return "Cluster '" . $options{instance_value}->{display} . "' " . $node_id . $options{instance_value}->{stat} . " "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All CPU metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $statistic ('minimum', 'maximum', 'average', 'sum') { foreach my $metric ('CPUUtilization') { my $entry = { label => lc($metric) . '-' . lc($statistic), set => { key_values => [ { name => $metric . '_' . $statistic }, { name => 'display' }, { name => 'stat' } ], output_template => $metric . ': %.2f %%', perfdatas => [ { label => lc($metric) . '_' . lc($statistic), value => $metric . '_' . $statistic , template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1, instance_use => 'display' }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "name:s@" => { name => 'name' }, "node-id:s" => { name => 'node_id' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Average']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } push @{$self->{aws_metrics}}, 'CPUUtilization'; } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { push @{$self->{aws_dimensions}}, { Name => 'CacheClusterId', Value => $instance }; if (defined($self->{option_results}->{node_id}) && $self->{option_results}->{node_id} ne '') { push @{$self->{aws_dimensions}}, { Name => 'CacheNodeId', Value => $self->{option_results}->{node_id} }; } $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/ElastiCache', dimensions => $self->{aws_dimensions}, metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period} ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$instance . "_" . lc($statistic)}->{display} = $instance; $self->{metric}->{$instance . "_" . lc($statistic)}->{stat} = lc($statistic); $self->{metric}->{$instance . "_" . lc($statistic)}->{node_id} = $self->{option_results}->{node_id}; $self->{metric}->{$instance . "_" . lc($statistic)}->{$metric . "_" . lc($statistic)} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check ElastiCache cluster CPU utilization. Works with Memcached and Redis backends. Example: perl centreon_plugins.pl --plugin=cloud::aws::elasticache::plugin --custommode=paws --mode=cpu --region='eu-west-1' --name='centreon-front' --statistic='average' --critical-cpuutilization-average='90' --verbose See 'https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/elasticache-metricscollected.html' for more informations. Default statistic: 'average' / All satistics are valid. =over 8 =item B<--name> Set the cluster name (Required) (Can be multiple). =item B<--node-id> Set the node id (Optional). =item B<--warning-cpuutilization-*> Thresholds warning (* can be: 'minimum', 'maximum', 'average', 'sum'). =item B<--critical-cpuutilization-*> Thresholds critical (* can be: 'minimum', 'maximum', 'average', 'sum'). =back =cut centreon-plugins-20220113/cloud/aws/elasticache/mode/evictions.pm000066400000000000000000000242611417000230700246730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::elasticache::mode::evictions; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; my $node_id = ""; if (defined($options{instance_value}->{node_id}) && $options{instance_value}->{node_id} ne '') { $node_id = "[Node: $options{instance_value}->{node_id}] "; } return "Cluster '" . $options{instance_value}->{display} . "' " . $node_id . $options{instance_value}->{stat} . " "; } sub custom_metric_calc { my ($self, %options) = @_; $self->{result_values}->{timeframe} = $options{new_datas}->{$self->{instance} . '_timeframe'}; $self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{metric} . '_' . $options{extra_options}->{stat}}; $self->{result_values}->{value_per_sec} = $self->{result_values}->{value} / $self->{result_values}->{timeframe}; $self->{result_values}->{stat} = $options{extra_options}->{stat}; $self->{result_values}->{metric} = $options{extra_options}->{metric}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub custom_metric_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check(value => defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}, threshold => [ { label => 'critical-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat}), exit_litteral => 'critical' }, { label => 'warning-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat}), exit_litteral => 'warning' } ]); return $exit; } sub custom_metric_perfdata { my ($self, %options) = @_; my $extra_label = ''; $extra_label = '_' . lc($self->{result_values}->{display}) if (!defined($options{extra_instance}) || $options{extra_instance} != 0); $self->{output}->perfdata_add(label => lc($self->{result_values}->{metric}) . "_" . lc($self->{result_values}->{stat}) . $extra_label, unit => defined($self->{instance_mode}->{option_results}->{per_sec}) ? 'evictions/s' : 'evictions', value => sprintf("%.2f", defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat})), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat})), ); } sub custom_metric_output { my ($self, %options) = @_; my $msg = ""; if (defined($self->{instance_mode}->{option_results}->{per_sec})) { $msg = sprintf("%s: %.2f evictions/s", $self->{result_values}->{metric}, $self->{result_values}->{value_per_sec}); } else { $msg = sprintf("%s: %.2f evictions", $self->{result_values}->{metric}, $self->{result_values}->{value}); } return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All evictions metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $statistic ('minimum', 'maximum', 'average', 'sum') { foreach my $metric ('Evictions', 'Reclaimed') { my $entry = { label => lc($metric) . '-' . lc($statistic), set => { key_values => [ { name => $metric . '_' . $statistic }, { name => 'display' }, { name => 'stat' }, { name => 'timeframe' } ], closure_custom_calc => $self->can('custom_metric_calc'), closure_custom_calc_extra_options => { metric => $metric, stat => $statistic }, 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'), } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "name:s@" => { name => 'name' }, "node-id:s" => { name => 'node_id' }, "filter-metric:s" => { name => 'filter_metric' }, "per-sec" => { name => 'per_sec' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Average']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } foreach my $metric ('Evictions', 'Reclaimed') { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { push @{$self->{aws_dimensions}}, { Name => 'CacheClusterId', Value => $instance }; if (defined($self->{option_results}->{node_id}) && $self->{option_results}->{node_id} ne '') { push @{$self->{aws_dimensions}}, { Name => 'CacheNodeId', Value => $self->{option_results}->{node_id} }; } $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/ElastiCache', dimensions => $self->{aws_dimensions}, metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period} ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$instance . "_" . lc($statistic)}->{display} = $instance; $self->{metric}->{$instance . "_" . lc($statistic)}->{stat} = lc($statistic); $self->{metric}->{$instance . "_" . lc($statistic)}->{node_id} = $self->{option_results}->{node_id}; $self->{metric}->{$instance . "_" . lc($statistic)}->{timeframe} = $self->{aws_timeframe}; $self->{metric}->{$instance . "_" . lc($statistic)}->{$metric . "_" . lc($statistic)} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check ElastiCache cluster evictions to retreive space (evicted and reclaimed). Works with Memcached and Redis backends. Example: perl centreon_plugins.pl --plugin=cloud::aws::elasticache::plugin --custommode=paws --mode=evictions --region='eu-west-1' --name='centreon-front' --statistic='average' --critical-evictions-average='10' --verbose See 'https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/elasticache-metricscollected.html' for more informations. Default statistic: 'average' / All satistics are valid. =over 8 =item B<--name> Set the cluster name (Required) (Can be multiple). =item B<--node-id> Set the node id (Optional). =item B<--filter-metric> Filter metrics (Can be: 'Evictions', 'Reclaimed') (Can be a regexp). =item B<--warning-$metric$-$statistic$> Thresholds warning ($metric$ can be: 'evictions', 'reclaimed', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =item B<--critical-$metric$-$statistic$> Thresholds critical ($metric$ can be: 'evictions', 'reclaimed', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =item B<--per-sec> Change the data to be unit/sec. =back =cut centreon-plugins-20220113/cloud/aws/elasticache/mode/items.pm000066400000000000000000000256311417000230700240130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::elasticache::mode::items; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; my $node_id = ""; if (defined($options{instance_value}->{node_id}) && $options{instance_value}->{node_id} ne '') { $node_id = "[Node: $options{instance_value}->{node_id}] "; } return "Cluster '" . $options{instance_value}->{display} . "' " . $node_id . $options{instance_value}->{stat} . " "; } sub custom_item_calc { my ($self, %options) = @_; $self->{result_values}->{timeframe} = $options{new_datas}->{$self->{instance} . '_timeframe'}; $self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{metric} . '_' . $options{extra_options}->{stat}}; $self->{result_values}->{value_per_sec} = $self->{result_values}->{value} / $self->{result_values}->{timeframe}; $self->{result_values}->{stat} = $options{extra_options}->{stat}; $self->{result_values}->{metric} = $options{extra_options}->{metric}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub custom_item_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check(value => defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}, threshold => [ { label => 'critical-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat}), exit_litteral => 'critical' }, { label => 'warning-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat}), exit_litteral => 'warning' } ]); return $exit; } sub custom_item_perfdata { my ($self, %options) = @_; my $extra_label = ''; $extra_label = '_' . lc($self->{result_values}->{display}) if (!defined($options{extra_instance}) || $options{extra_instance} != 0); $self->{output}->perfdata_add(label => lc($self->{result_values}->{metric}) . "_" . lc($self->{result_values}->{stat}) . $extra_label, unit => defined($self->{instance_mode}->{option_results}->{per_sec}) ? 'items/s' : 'items', value => sprintf("%.2f", defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat})), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat})), ); } sub custom_item_output { my ($self, %options) = @_; my $msg = ""; if (defined($self->{instance_mode}->{option_results}->{per_sec})) { $msg = sprintf("%s: %.2f items/s", $self->{result_values}->{metric}, $self->{result_values}->{value_per_sec}); } else { $msg = sprintf("%s: %.2f items", $self->{result_values}->{metric}, $self->{result_values}->{value}); } return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All items metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $statistic ('minimum', 'maximum', 'average', 'sum') { foreach my $metric ('CurrItems') { my $entry = { label => lc($metric) . '-' . lc($statistic), set => { key_values => [ { name => $metric . '_' . $statistic }, { name => 'display' }, { name => 'stat' }, { name => 'timeframe' } ], output_template => $metric . ': %d items', perfdatas => [ { label => lc($metric) . '_' . lc($statistic), value => $metric . '_' . $statistic , template => '%d', unit => 'items', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } foreach my $metric ('NewItems') { my $entry = { label => lc($metric) . '-' . lc($statistic), set => { key_values => [ { name => $metric . '_' . $statistic }, { name => 'display' }, { name => 'stat' }, { name => 'timeframe' } ], closure_custom_calc => $self->can('custom_item_calc'), closure_custom_calc_extra_options => { metric => $metric, stat => $statistic }, closure_custom_output => $self->can('custom_item_output'), closure_custom_perfdata => $self->can('custom_item_perfdata'), closure_custom_threshold_check => $self->can('custom_item_threshold'), } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "name:s@" => { name => 'name' }, "node-id:s" => { name => 'node_id' }, "filter-metric:s" => { name => 'filter_metric' }, "per-sec" => { name => 'per_sec' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Average']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } foreach my $metric ('CurrItems', 'NewItems') { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { push @{$self->{aws_dimensions}}, { Name => 'CacheClusterId', Value => $instance }; if (defined($self->{option_results}->{node_id}) && $self->{option_results}->{node_id} ne '') { push @{$self->{aws_dimensions}}, { Name => 'CacheNodeId', Value => $self->{option_results}->{node_id} }; } $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/ElastiCache', dimensions => $self->{aws_dimensions}, metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period} ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$instance . "_" . lc($statistic)}->{display} = $instance; $self->{metric}->{$instance . "_" . lc($statistic)}->{stat} = lc($statistic); $self->{metric}->{$instance . "_" . lc($statistic)}->{node_id} = $self->{option_results}->{node_id}; $self->{metric}->{$instance . "_" . lc($statistic)}->{timeframe} = $self->{aws_timeframe}; $self->{metric}->{$instance . "_" . lc($statistic)}->{$metric . "_" . lc($statistic)} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check ElastiCache cluster items number (current and new). Works with Memcached and Redis backends. Example: perl centreon_plugins.pl --plugin=cloud::aws::elasticache::plugin --custommode=paws --mode=items --region='eu-west-1' --name='centreon-front' --statistic='average' --critical-newitems-average='10' --verbose See 'https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/elasticache-metricscollected.html' for more informations. Default statistic: 'average' / All satistics are valid. =over 8 =item B<--name> Set the cluster name (Required) (Can be multiple). =item B<--node-id> Set the node id (Optional). =item B<--filter-metric> Filter metrics (Can be: 'CurrItems', 'NewItems') (Can be a regexp). =item B<--warning-$metric$-$statistic$> Thresholds warning ($metric$ can be: 'curritems', 'newitems', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =item B<--critical-$metric$-$statistic$> Thresholds critical ($metric$ can be: 'curritems', 'newitems', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =item B<--per-sec> Change the data to be unit/sec. =back =cut centreon-plugins-20220113/cloud/aws/elasticache/mode/network.pm000066400000000000000000000245031417000230700243600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::elasticache::mode::network; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; my $node_id = ""; if (defined($options{instance_value}->{node_id}) && $options{instance_value}->{node_id} ne '') { $node_id = "[Node: $options{instance_value}->{node_id}] "; } return "Cluster '" . $options{instance_value}->{display} . "' " . $node_id . $options{instance_value}->{stat} . " "; } sub custom_traffic_calc { my ($self, %options) = @_; $self->{result_values}->{timeframe} = $options{new_datas}->{$self->{instance} . '_timeframe'}; $self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{metric} . '_' . $options{extra_options}->{stat}}; $self->{result_values}->{value_per_sec} = $self->{result_values}->{value} / $self->{result_values}->{timeframe}; $self->{result_values}->{stat} = $options{extra_options}->{stat}; $self->{result_values}->{metric} = $options{extra_options}->{metric}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub custom_traffic_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check(value => defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}, threshold => [ { label => 'critical-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat}), exit_litteral => 'critical' }, { label => 'warning-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat}), exit_litteral => 'warning' } ]); return $exit; } sub custom_traffic_perfdata { my ($self, %options) = @_; my $extra_label = ''; $extra_label = '_' . lc($self->{result_values}->{display}) if (!defined($options{extra_instance}) || $options{extra_instance} != 0); $self->{output}->perfdata_add(label => lc($self->{result_values}->{metric}) . "_" . lc($self->{result_values}->{stat}) . $extra_label, unit => defined($self->{instance_mode}->{option_results}->{per_sec}) ? 'B/s' : 'B', value => sprintf("%.2f", defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat})), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat})), ); } sub custom_traffic_output { my ($self, %options) = @_; my $msg = ""; if (defined($self->{instance_mode}->{option_results}->{per_sec})) { my ($value, $unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{value_per_sec}); $msg = $self->{result_values}->{metric} . ": " . $value . $unit . "/s"; } else { my ($value, $unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{value}); $msg = $self->{result_values}->{metric} . ": " . $value . $unit; } return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All network metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $statistic ('minimum', 'maximum', 'average', 'sum') { foreach my $metric ('NetworkBytesIn', 'NetworkBytesOut') { my $entry = { label => lc($metric) . '-' . lc($statistic), set => { key_values => [ { name => $metric . '_' . $statistic }, { name => 'display' }, { name => 'stat' }, { name => 'timeframe' } ], closure_custom_calc => $self->can('custom_traffic_calc'), closure_custom_calc_extra_options => { metric => $metric, stat => $statistic }, closure_custom_output => $self->can('custom_traffic_output'), closure_custom_perfdata => $self->can('custom_traffic_perfdata'), closure_custom_threshold_check => $self->can('custom_traffic_threshold'), } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "name:s@" => { name => 'name' }, "node-id:s" => { name => 'node_id' }, "filter-metric:s" => { name => 'filter_metric' }, "per-sec" => { name => 'per_sec' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Average']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } foreach my $metric ('NetworkBytesIn', 'NetworkBytesOut') { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { push @{$self->{aws_dimensions}}, { Name => 'CacheClusterId', Value => $instance }; if (defined($self->{option_results}->{node_id}) && $self->{option_results}->{node_id} ne '') { push @{$self->{aws_dimensions}}, { Name => 'CacheNodeId', Value => $self->{option_results}->{node_id} }; } $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/ElastiCache', dimensions => $self->{aws_dimensions}, metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period} ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$instance . "_" . lc($statistic)}->{display} = $instance; $self->{metric}->{$instance . "_" . lc($statistic)}->{stat} = lc($statistic); $self->{metric}->{$instance . "_" . lc($statistic)}->{node_id} = $self->{option_results}->{node_id}; $self->{metric}->{$instance . "_" . lc($statistic)}->{timeframe} = $self->{aws_timeframe}; $self->{metric}->{$instance . "_" . lc($statistic)}->{$metric . "_" . lc($statistic)} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check ElastiCache cluster network usage. Works with Memcached and Redis backends. Example: perl centreon_plugins.pl --plugin=cloud::aws::elasticache::plugin --custommode=paws --mode=network --region='eu-west-1' --name='centreon-front' --statistic='average' --critical-networkbytesin-average='1000' --verbose See 'https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/elasticache-metricscollected.html' for more informations. Default statistic: 'average' / All satistics are valid. =over 8 =item B<--name> Set the cluster name (Required) (Can be multiple). =item B<--node-id> Set the node id (Optional). =item B<--filter-metric> Filter metrics (Can be: 'NetworkBytesIn', 'NetworkBytesOut') (Can be a regexp). =item B<--warning-$metric$-$statistic$> Thresholds warning ($metric$ can be: 'networkbytesin', 'networkbytesout', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =item B<--critical-$metric$-$statistic$> Thresholds critical ($metric$ can be: 'networkbytesin', 'networkbytesout', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =item B<--per-sec> Change the data to be unit/sec. =back =cut centreon-plugins-20220113/cloud/aws/elasticache/mode/replication.pm000066400000000000000000000255721417000230700252070ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::elasticache::mode::replication; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; my $node_id = ""; if (defined($options{instance_value}->{node_id}) && $options{instance_value}->{node_id} ne '') { $node_id = "[Node: $options{instance_value}->{node_id}] "; } return "Cluster '" . $options{instance_value}->{display} . "' " . $node_id . $options{instance_value}->{stat} . " "; } sub custom_metric_calc { my ($self, %options) = @_; $self->{result_values}->{timeframe} = $options{new_datas}->{$self->{instance} . '_timeframe'}; $self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{metric} . '_' . $options{extra_options}->{stat}}; $self->{result_values}->{value_per_sec} = $self->{result_values}->{value} / $self->{result_values}->{timeframe}; $self->{result_values}->{stat} = $options{extra_options}->{stat}; $self->{result_values}->{metric} = $options{extra_options}->{metric}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub custom_metric_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check(value => defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}, threshold => [ { label => 'critical-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat}), exit_litteral => 'critical' }, { label => 'warning-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat}), exit_litteral => 'warning' } ]); return $exit; } sub custom_metric_perfdata { my ($self, %options) = @_; my $extra_label = ''; $extra_label = '_' . lc($self->{result_values}->{display}) if (!defined($options{extra_instance}) || $options{extra_instance} != 0); $self->{output}->perfdata_add( label => lc($self->{result_values}->{metric}) . "_" . lc($self->{result_values}->{stat}) . $extra_label, unit => defined($self->{instance_mode}->{option_results}->{per_sec}) ? 'B/s' : 'B', value => sprintf("%.2f", defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat})), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat})), ); } sub custom_metric_output { my ($self, %options) = @_; my $msg = ""; if (defined($self->{instance_mode}->{option_results}->{per_sec})) { my ($value, $unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{value_per_sec}); $msg = $self->{result_values}->{metric} . ": " . $value . $unit . "/s"; } else { my ($value, $unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{value}); $msg = $self->{result_values}->{metric} . ": " . $value . $unit; } return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All replication metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $statistic ('minimum', 'maximum', 'average', 'sum') { foreach my $metric ('ReplicationBytes') { my $entry = { label => lc($metric) . '-' . lc($statistic), set => { key_values => [ { name => $metric . '_' . $statistic }, { name => 'display' }, { name => 'stat' }, { name => 'timeframe' } ], closure_custom_calc => $self->can('custom_metric_calc'), closure_custom_calc_extra_options => { metric => $metric, stat => $statistic }, 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'), } }; push @{$self->{maps_counters}->{metric}}, $entry; } foreach my $metric ('ReplicationLag') { my $entry = { label => lc($metric) . '-' . lc($statistic), set => { key_values => [ { name => $metric . '_' . $statistic }, { name => 'display' }, { name => 'stat' }, { name => 'timeframe' } ], output_template => $metric . ': %.2f s', perfdatas => [ { label => lc($metric) . '_' . lc($statistic), value => $metric . '_' . $statistic , template => '%.2f', unit => 's', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'name:s@' => { name => 'name' }, 'node-id:s' => { name => 'node_id' }, 'filter-metric:s' => { name => 'filter_metric' }, 'per-sec' => { name => 'per_sec' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Average']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } foreach my $metric ('ReplicationBytes', 'ReplicationLag') { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { push @{$self->{aws_dimensions}}, { Name => 'CacheClusterId', Value => $instance }; if (defined($self->{option_results}->{node_id}) && $self->{option_results}->{node_id} ne '') { push @{$self->{aws_dimensions}}, { Name => 'CacheNodeId', Value => $self->{option_results}->{node_id} }; } $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/ElastiCache', dimensions => $self->{aws_dimensions}, metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period} ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$instance . "_" . lc($statistic)}->{display} = $instance; $self->{metric}->{$instance . "_" . lc($statistic)}->{stat} = lc($statistic); $self->{metric}->{$instance . "_" . lc($statistic)}->{node_id} = $self->{option_results}->{node_id}; $self->{metric}->{$instance . "_" . lc($statistic)}->{timeframe} = $self->{aws_timeframe}; $self->{metric}->{$instance . "_" . lc($statistic)}->{$metric . "_" . lc($statistic)} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check ElastiCache cluster replication performances (throughput and lag). Works with Redis backends only. Example: perl centreon_plugins.pl --plugin=cloud::aws::elasticache::plugin --custommode=paws --mode=replication --region='eu-west-1' --name='centreon-front' --statistic='average' --critical-replicationlag-average='2' --verbose See 'https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/elasticache-metricscollected.html' for more informations. Default statistic: 'average' / All satistics are valid. =over 8 =item B<--name> Set the cluster name (Required) (Can be multiple). =item B<--node-id> Set the node id (Optional). =item B<--filter-metric> Filter metrics (Can be: 'ReplicationBytes', 'ReplicationLag') (Can be a regexp). =item B<--warning-$metric$-$statistic$> Thresholds warning ($metric$ can be: 'replicationbytes', 'replicationlag', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =item B<--critical-$metric$-$statistic$> Thresholds critical ($metric$ can be: 'replicationbytes', 'replicationlag', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =item B<--per-sec> Change the data to be unit/sec. =back =cut centreon-plugins-20220113/cloud/aws/elasticache/mode/requestsmemcached.pm000066400000000000000000000255111417000230700263710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::elasticache::mode::requestsmemcached; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; my $node_id = ""; if (defined($options{instance_value}->{node_id}) && $options{instance_value}->{node_id} ne '') { $node_id = "[Node: $options{instance_value}->{node_id}] "; } return "Cluster '" . $options{instance_value}->{display} . "' " . $node_id . $options{instance_value}->{stat} . " requests "; } sub custom_metric_calc { my ($self, %options) = @_; $self->{result_values}->{timeframe} = $options{new_datas}->{$self->{instance} . '_timeframe'}; $self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{metric} . '_' . $options{extra_options}->{stat}}; $self->{result_values}->{value_per_sec} = $self->{result_values}->{value} / $self->{result_values}->{timeframe}; $self->{result_values}->{stat} = $options{extra_options}->{stat}; $self->{result_values}->{metric} = $options{extra_options}->{metric}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub custom_metric_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check(value => defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}, threshold => [ { label => 'critical-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat}), exit_litteral => 'critical' }, { label => 'warning-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat}), exit_litteral => 'warning' } ]); return $exit; } sub custom_metric_perfdata { my ($self, %options) = @_; my $extra_label = ''; $extra_label = '_' . lc($self->{result_values}->{display}) if (!defined($options{extra_instance}) || $options{extra_instance} != 0); $self->{output}->perfdata_add(label => lc($self->{result_values}->{metric}) . "_" . lc($self->{result_values}->{stat}) . $extra_label, unit => defined($self->{instance_mode}->{option_results}->{per_sec}) ? 'req/s' : 'req', value => sprintf("%.2f", defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat})), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat})), ); } sub custom_metric_output { my ($self, %options) = @_; my $msg = ""; if (defined($self->{instance_mode}->{option_results}->{per_sec})) { $msg = sprintf("%s: %.2f requests/s", $self->{result_values}->{metric}, $self->{result_values}->{value_per_sec}); } else { $msg = sprintf("%s: %.2f requests", $self->{result_values}->{metric}, $self->{result_values}->{value}); } return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All requests metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $statistic ('minimum', 'maximum', 'average', 'sum') { foreach my $metric ('CasHits', 'CasMisses', 'DecrHits', 'DecrMisses', 'DeleteHits', 'DeleteMisses', 'GetHits', 'GetMisses', 'IncrHits', 'IncrMisses', 'TouchHits', 'TouchMisses') { my $entry = { label => lc($metric) . '-' . lc($statistic), set => { key_values => [ { name => $metric . '_' . $statistic }, { name => 'display' }, { name => 'stat' }, { name => 'timeframe' } ], closure_custom_calc => $self->can('custom_metric_calc'), closure_custom_calc_extra_options => { metric => $metric, stat => $statistic }, 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'), } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "name:s@" => { name => 'name' }, "node-id:s" => { name => 'node_id' }, "filter-metric:s" => { name => 'filter_metric' }, "per-sec" => { name => 'per_sec' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Average']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } foreach my $metric ('CasHits', 'CasMisses', 'DecrHits', 'DecrMisses', 'DeleteHits', 'DeleteMisses', 'GetHits', 'GetMisses', 'IncrHits', 'IncrMisses', 'TouchHits', 'TouchMisses') { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { push @{$self->{aws_dimensions}}, { Name => 'CacheClusterId', Value => $instance }; if (defined($self->{option_results}->{node_id}) && $self->{option_results}->{node_id} ne '') { push @{$self->{aws_dimensions}}, { Name => 'CacheNodeId', Value => $self->{option_results}->{node_id} }; } $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/ElastiCache', dimensions => $self->{aws_dimensions}, metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period} ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$instance . "_" . lc($statistic)}->{display} = $instance; $self->{metric}->{$instance . "_" . lc($statistic)}->{stat} = lc($statistic); $self->{metric}->{$instance . "_" . lc($statistic)}->{node_id} = $self->{option_results}->{node_id}; $self->{metric}->{$instance . "_" . lc($statistic)}->{timeframe} = $self->{aws_timeframe}; $self->{metric}->{$instance . "_" . lc($statistic)}->{$metric . "_" . lc($statistic)} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check ElastiCache cluster received requests for Memcached backends (found and not found keys). Example: perl centreon_plugins.pl --plugin=cloud::aws::elasticache::plugin --custommode=paws --mode=requests-memcached --region='eu-west-1' --name='centreon-front' --statistic='average' --critical-getmisses-average='5' --verbose See 'https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/elasticache-metricscollected.html' for more informations. Default statistic: 'average' / All satistics are valid. =over 8 =item B<--name> Set the cluster name (Required) (Can be multiple). =item B<--node-id> Set the node id (Optional). =item B<--filter-metric> Filter metrics (Can be: 'CasHits', 'CasMisses', 'DecrHits', 'DecrMisses', 'DeleteHits', 'DeleteMisses', 'GetHits', 'GetMisses', 'IncrHits', 'IncrMisses', 'TouchHits', 'TouchMisses') (Can be a regexp). =item B<--warning-$metric$-$statistic$> Thresholds warning ($metric$ can be: 'cashits', 'casmisses', 'decrhits', 'decrmisses', 'deletehits', 'deletemisses', 'gethits', 'getmisses', 'incrhits', 'incrmisses', 'touchhits', 'touchmisses', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =item B<--critical-$metric$-$statistic$> Thresholds critical ($metric$ can be: 'cashits', 'casmisses', 'decrhits', 'decrmisses', 'deletehits', 'deletemisses', 'gethits', 'getmisses', 'incrhits', 'incrmisses', 'touchhits', 'touchmisses', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =item B<--per-sec> Change the data to be unit/sec. =back =cut centreon-plugins-20220113/cloud/aws/elasticache/mode/requestsredis.pm000066400000000000000000000242611417000230700255720ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::elasticache::mode::requestsredis; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; my $node_id = ""; if (defined($options{instance_value}->{node_id}) && $options{instance_value}->{node_id} ne '') { $node_id = "[Node: $options{instance_value}->{node_id}] "; } return "Cluster '" . $options{instance_value}->{display} . "' " . $node_id . $options{instance_value}->{stat} . " requests "; } sub custom_metric_calc { my ($self, %options) = @_; $self->{result_values}->{timeframe} = $options{new_datas}->{$self->{instance} . '_timeframe'}; $self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{metric} . '_' . $options{extra_options}->{stat}}; $self->{result_values}->{value_per_sec} = $self->{result_values}->{value} / $self->{result_values}->{timeframe}; $self->{result_values}->{stat} = $options{extra_options}->{stat}; $self->{result_values}->{metric} = $options{extra_options}->{metric}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub custom_metric_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check(value => defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}, threshold => [ { label => 'critical-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat}), exit_litteral => 'critical' }, { label => 'warning-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat}), exit_litteral => 'warning' } ]); return $exit; } sub custom_metric_perfdata { my ($self, %options) = @_; my $extra_label = ''; $extra_label = '_' . lc($self->{result_values}->{display}) if (!defined($options{extra_instance}) || $options{extra_instance} != 0); $self->{output}->perfdata_add(label => lc($self->{result_values}->{metric}) . "_" . lc($self->{result_values}->{stat}) . $extra_label, unit => defined($self->{instance_mode}->{option_results}->{per_sec}) ? 'req/s' : 'req', value => sprintf("%.2f", defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat})), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat})), ); } sub custom_metric_output { my ($self, %options) = @_; my $msg = ""; if (defined($self->{instance_mode}->{option_results}->{per_sec})) { $msg = sprintf("%s: %.2f requests/s", $self->{result_values}->{metric}, $self->{result_values}->{value_per_sec}); } else { $msg = sprintf("%s: %.2f requests", $self->{result_values}->{metric}, $self->{result_values}->{value}); } return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All requests metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $statistic ('minimum', 'maximum', 'average', 'sum') { foreach my $metric ('CacheHits', 'CacheMisses') { my $entry = { label => lc($metric) . '-' . lc($statistic), set => { key_values => [ { name => $metric . '_' . $statistic }, { name => 'display' }, { name => 'stat' }, { name => 'timeframe' } ], closure_custom_calc => $self->can('custom_metric_calc'), closure_custom_calc_extra_options => { metric => $metric, stat => $statistic }, 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'), } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "name:s@" => { name => 'name' }, "node-id:s" => { name => 'node_id' }, "filter-metric:s" => { name => 'filter_metric' }, "per-sec" => { name => 'per_sec' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Average']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } foreach my $metric ('CacheHits', 'CacheMisses') { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { push @{$self->{aws_dimensions}}, { Name => 'CacheClusterId', Value => $instance }; if (defined($self->{option_results}->{node_id}) && $self->{option_results}->{node_id} ne '') { push @{$self->{aws_dimensions}}, { Name => 'CacheNodeId', Value => $self->{option_results}->{node_id} }; } $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/ElastiCache', dimensions => $self->{aws_dimensions}, metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period} ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$instance . "_" . lc($statistic)}->{display} = $instance; $self->{metric}->{$instance . "_" . lc($statistic)}->{stat} = lc($statistic); $self->{metric}->{$instance . "_" . lc($statistic)}->{node_id} = $self->{option_results}->{node_id}; $self->{metric}->{$instance . "_" . lc($statistic)}->{timeframe} = $self->{aws_timeframe}; $self->{metric}->{$instance . "_" . lc($statistic)}->{$metric . "_" . lc($statistic)} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check ElastiCache cluster received requests for Redis backends (successfull and unsuccessful key lookups). Example: perl centreon_plugins.pl --plugin=cloud::aws::elasticache::plugin --custommode=paws --mode=requests-redis --region='eu-west-1' --name='centreon-front' --statistic='average' --critical-cachemisses-average='5' --verbose See 'https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/elasticache-metricscollected.html' for more informations. Default statistic: 'average' / All satistics are valid. =over 8 =item B<--name> Set the cluster name (Required) (Can be multiple). =item B<--node-id> Set the node id (Optional). =item B<--filter-metric> Filter metrics (Can be: 'CacheHits', 'CacheMisses') (Can be a regexp). =item B<--warning-$metric$-$statistic$> Thresholds warning ($metric$ can be: 'cachehits', 'cachemisses', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =item B<--critical-$metric$-$statistic$> Thresholds critical ($metric$ can be: 'cachehits', 'cachemisses', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =item B<--per-sec> Change the data to be unit/sec. =back =cut centreon-plugins-20220113/cloud/aws/elasticache/mode/usagememcached.pm000066400000000000000000000160021417000230700256150ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::elasticache::mode::usagememcached; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; my $node_id = ""; if (defined($options{instance_value}->{node_id}) && $options{instance_value}->{node_id} ne '') { $node_id = "[Node: $options{instance_value}->{node_id}] "; } return "Cluster '" . $options{instance_value}->{display} . "' " . $node_id . $options{instance_value}->{stat} . " "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All usage metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $statistic ('minimum', 'maximum', 'average', 'sum') { foreach my $metric ('BytesUsedForCacheItems') { my $entry = { label => lc($metric) . '-' . lc($statistic), set => { key_values => [ { name => $metric . '_' . $statistic }, { name => 'display' }, { name => 'stat' } ], output_template => $metric . ': %d %s', output_change_bytes => 1, perfdatas => [ { label => lc($metric) . '_' . lc($statistic), value => $metric . '_' . $statistic , template => '%d', unit => 'B', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "name:s@" => { name => 'name' }, "node-id:s" => { name => 'node_id' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Average']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } foreach my $metric ('BytesUsedForCacheItems') { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { push @{$self->{aws_dimensions}}, { Name => 'CacheClusterId', Value => $instance }; if (defined($self->{option_results}->{node_id}) && $self->{option_results}->{node_id} ne '') { push @{$self->{aws_dimensions}}, { Name => 'CacheNodeId', Value => $self->{option_results}->{node_id} }; } $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/ElastiCache', dimensions => $self->{aws_dimensions}, metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period} ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$instance . "_" . lc($statistic)}->{display} = $instance; $self->{metric}->{$instance . "_" . lc($statistic)}->{stat} = lc($statistic); $self->{metric}->{$instance . "_" . lc($statistic)}->{node_id} = $self->{option_results}->{node_id}; $self->{metric}->{$instance . "_" . lc($statistic)}->{$metric . "_" . lc($statistic)} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check ElastiCache cluster space usage for Memcached backends. Example: perl centreon_plugins.pl --plugin=cloud::aws::elasticache::plugin --custommode=paws --mode=usage-memcached --region='eu-west-1' --name='centreon-front' --statistic='average' --critical-bytesusedforcacheitems-average='1614281' --verbose See 'https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/elasticache-metricscollected.html' for more informations. Default statistic: 'average' / All satistics are valid. =over 8 =item B<--name> Set the cluster name (Required) (Can be multiple). =item B<--node-id> Set the node id (Optional). =item B<--warning-$metric$-$statistic$> Thresholds warning ($metric$ can be: 'bytesusedforcacheitems', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =item B<--critical-$metric$-$statistic$> Thresholds critical ($metric$ can be: 'bytesusedforcacheitems', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =back =cut centreon-plugins-20220113/cloud/aws/elasticache/mode/usageredis.pm000066400000000000000000000157351417000230700250310ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::elasticache::mode::usageredis; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; my $node_id = ""; if (defined($options{instance_value}->{node_id}) && $options{instance_value}->{node_id} ne '') { $node_id = "[Node: $options{instance_value}->{node_id}] "; } return "Cluster '" . $options{instance_value}->{display} . "' " . $node_id . $options{instance_value}->{stat} . " "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All usage metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $statistic ('minimum', 'maximum', 'average', 'sum') { foreach my $metric ('BytesUsedForCache') { my $entry = { label => lc($metric) . '-' . lc($statistic), set => { key_values => [ { name => $metric . '_' . $statistic }, { name => 'display' }, { name => 'stat' } ], output_template => $metric . ': %d %s', output_change_bytes => 1, perfdatas => [ { label => lc($metric) . '_' . lc($statistic), value => $metric . '_' . $statistic , template => '%d', unit => 'B', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "name:s@" => { name => 'name' }, "node-id:s" => { name => 'node_id' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Average']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } foreach my $metric ('BytesUsedForCache') { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { push @{$self->{aws_dimensions}}, { Name => 'CacheClusterId', Value => $instance }; if (defined($self->{option_results}->{node_id}) && $self->{option_results}->{node_id} ne '') { push @{$self->{aws_dimensions}}, { Name => 'CacheNodeId', Value => $self->{option_results}->{node_id} }; } $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/ElastiCache', dimensions => $self->{aws_dimensions}, metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period} ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$instance . "_" . lc($statistic)}->{display} = $instance; $self->{metric}->{$instance . "_" . lc($statistic)}->{stat} = lc($statistic); $self->{metric}->{$instance . "_" . lc($statistic)}->{node_id} = $self->{option_results}->{node_id}; $self->{metric}->{$instance . "_" . lc($statistic)}->{$metric . "_" . lc($statistic)} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check ElastiCache cluster space usage for Redis backends. Example: perl centreon_plugins.pl --plugin=cloud::aws::elasticache::plugin --custommode=paws --mode=usage-redis --region='eu-west-1' --name='centreon-front' --statistic='average' --critical-bytesusedforcache-average='1614281' --verbose See 'https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/elasticache-metricscollected.html' for more informations. Default statistic: 'average' / All satistics are valid. =over 8 =item B<--name> Set the cluster name (Required) (Can be multiple). =item B<--node-id> Set the node id (Optional). =item B<--warning-$metric$-$statistic$> Thresholds warning ($metric$ can be: 'bytesusedforcache', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =item B<--critical-$metric$-$statistic$> Thresholds critical ($metric$ can be: 'bytesusedforcache', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =back =cut centreon-plugins-20220113/cloud/aws/elasticache/plugin.pm000066400000000000000000000043421417000230700232400ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::elasticache::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} } = ( 'commands-memcached' => 'cloud::aws::elasticache::mode::commandsmemcached', 'commands-redis' => 'cloud::aws::elasticache::mode::commandsredis', 'connections' => 'cloud::aws::elasticache::mode::connections', 'cpu' => 'cloud::aws::elasticache::mode::cpu', 'evictions' => 'cloud::aws::elasticache::mode::evictions', 'items' => 'cloud::aws::elasticache::mode::items', 'network' => 'cloud::aws::elasticache::mode::network', 'replication' => 'cloud::aws::elasticache::mode::replication', 'requests-memcached' => 'cloud::aws::elasticache::mode::requestsmemcached', 'requests-redis' => 'cloud::aws::elasticache::mode::requestsredis', 'usage-memcached' => 'cloud::aws::elasticache::mode::usagememcached', 'usage-redis' => 'cloud::aws::elasticache::mode::usageredis', ); $self->{custom_modes}{paws} = 'cloud::aws::custom::paws'; $self->{custom_modes}{awscli} = 'cloud::aws::custom::awscli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Amazon ElastiCache. =cut centreon-plugins-20220113/cloud/aws/elb/000077500000000000000000000000001417000230700176765ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/elb/application/000077500000000000000000000000001417000230700222015ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/elb/application/mode/000077500000000000000000000000001417000230700231255ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/elb/application/mode/connections.pm000066400000000000000000000213441417000230700260110ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::elb::application::mode::connections; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my %metrics_mapping = ( 'ActiveConnectionCount' => { # Minimum, Maximum, and Average all return 1. 'output' => 'Active Connection', 'label' => 'connection-active', 'nlabel' => 'elb.connection.active.count', }, 'NewConnectionCount' => { # Minimum, Maximum, and Average all return 1. 'output' => 'New Connection', 'label' => 'connection-new', 'nlabel' => 'elb.connection.new.count', }, 'RejectedConnectionCount' => { # Minimum, Maximum, and Average all return 1. 'output' => 'Rejected Connection', 'label' => 'connection-rejected', 'nlabel' => 'elb.rejected.new.count', }, 'TargetConnectionErrorCount' => { # Minimum, Maximum, and Average all return 1. 'output' => 'Target Connection Error', 'label' => 'target-connection-error', 'nlabel' => 'elb.target.connection.error.count', }, ); sub prefix_metric_output { my ($self, %options) = @_; my $availability_zone = ""; if (defined($options{instance_value}->{availability_zone}) && $options{instance_value}->{availability_zone} ne '') { $availability_zone = "[$options{instance_value}->{availability_zone}] "; } return "ELB '" . $options{instance_value}->{display} . "' " . $availability_zone; } sub prefix_statistics_output { my ($self, %options) = @_; return "Statistic '" . $options{instance_value}->{display} . "' Metrics "; } sub long_output { my ($self, %options) = @_; my $availability_zone = ""; if (defined($options{instance_value}->{availability_zone}) && $options{instance_value}->{availability_zone} ne '') { $availability_zone = "[$options{instance_value}->{availability_zone}] "; } return "Checking '" . $options{instance_value}->{display} . "' " . $availability_zone; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metrics', type => 3, cb_prefix_output => 'prefix_metric_output', cb_long_output => 'long_output', message_multiple => 'All elb metrics are ok', indent_long_output => ' ', group => [ { name => 'statistics', display_long => 1, cb_prefix_output => 'prefix_statistics_output', message_multiple => 'All metrics are ok', type => 1, skipped_code => { -10 => 1 } }, ] } ]; foreach my $metric (keys %metrics_mapping) { my $entry = { label => $metrics_mapping{$metric}->{label}, nlabel => $metrics_mapping{$metric}->{nlabel}, set => { key_values => [ { name => $metric }, { name => 'display' } ], output_template => $metrics_mapping{$metric}->{output} . ': %.2f', perfdatas => [ { value => $metric , template => '%.2f', label_extra_instance => 1 } ], } }; push @{$self->{maps_counters}->{statistics}}, $entry; } } 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 => { "name:s@" => { name => 'name' }, "availability-zone:s" => { name => 'availability_zone' }, "filter-metric:s" => { name => 'filter_metric' }, "statistic:s@" => { name => 'statistic' }, "target-group:s" => { name => 'target_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; if (defined($self->{option_results}->{target_group}) && $self->{option_results}->{target_group} ne '') { push @{$self->{aws_dimensions}}, { Name => 'TargetGroup', Value => $self->{option_results}->{target_group} }; } $self->{aws_statistics} = ['Sum']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %metrics_mapping) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { push @{$self->{aws_dimensions}}, { Name => 'LoadBalancer', Value => $instance }; if (defined($self->{option_results}->{availability_zone}) && $self->{option_results}->{availability_zone} ne '') { push @{$self->{aws_dimensions}}, { Name => 'AvailabilityZone', Value => $self->{option_results}->{availability_zone} }; } $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/ApplicationELB', dimensions => $self->{aws_dimensions}, metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period}, ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{$instance}->{display} = $instance; $self->{metrics}->{$instance}->{availability_zone} = $self->{option_results}->{availability_zone}; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{display} = $statistic; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{$metric} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check Application ELB connections metrics. Example: perl centreon_plugins.pl --plugin=cloud::aws::elb::application::plugin --custommode=paws --mode=connections --region='eu-west-1' --name='app/AppProd/7c8ecfbd1093c5bd' --critical-connection-rejected='10' --verbose See 'https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-cloudwatch-metrics.html' for more informations. Default statistic: 'sum' / Most usefull statistics: 'sum'. =over 8 =item B<--name> Set the instance name (Required) (Can be multiple). =item B<--availability-zone> Add Availability Zone dimension. =item B<--filter-metric> Filter metrics (Can be: ActiveConnectionCount', 'NewConnectionCount', 'RejectedConnectionCount', 'TargetConnectionErrorCount') (Can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds warning (Can be: 'connection-active', 'connection-new', 'connection-rejected', 'target-connection-error'). =back =cut centreon-plugins-20220113/cloud/aws/elb/application/mode/discovery.pm000066400000000000000000000060551417000230700255000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::elb::application::mode::discovery; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "prettify" => { name => 'prettify' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my @disco_data; my $disco_stats; $disco_stats->{start_time} = time(); my $load_balancers = $options{custom}->discovery( service => 'elbv2', command => 'describe-load-balancers' ); foreach my $load_balancer (@{$load_balancers->{LoadBalancers}}) { next if (!defined($load_balancer->{LoadBalancerArn}) || $load_balancer->{Type} ne 'application'); my %elb; $elb{type} = "application"; $elb{name} = $1 if ($load_balancer->{LoadBalancerArn} =~ /arn:aws:elasticloadbalancing:.*:loadbalancer\/(.*)/); $elb{dns_name} = $load_balancer->{DNSName}; $elb{availability_zones} = $load_balancer->{AvailabilityZones}; $elb{vpc_id} = $load_balancer->{VpcId}; $elb{security_groups} = $load_balancer->{SecurityGroups}; $elb{state} = $load_balancer->{State}->{Code}; push @disco_data, \%elb; } $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; $disco_stats->{discovered_items} = @disco_data; $disco_stats->{results} = \@disco_data; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE Application ELB discovery. =over 8 =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/aws/elb/application/mode/httpcodes.pm000066400000000000000000000227021417000230700254630ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::elb::application::mode::httpcodes; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my %metrics_mapping = ( 'HTTPCode_Target_2XX_Count' => { # Minimum, Maximum, and Average all return 1. 'output' => 'Target HTTP 2XXs', 'label' => 'httpcode-target-2xx', 'nlabel' => 'elb.httpcode.target.2xx.count', }, 'HTTPCode_Target_3XX_Count' => { # Minimum, Maximum, and Average all return 1. 'output' => 'Target HTTP 3XXs', 'label' => 'httpcode-target-3xx', 'nlabel' => 'elb.httpcode.target.3xx.count', }, 'HTTPCode_Target_4XX_Count' => { # Minimum, Maximum, and Average all return 1. 'output' => 'Target HTTP 4XXs', 'label' => 'httpcode-target-4xx', 'nlabel' => 'elb.httpcode.target.4xx.count', }, 'HTTPCode_Target_5XX_Count' => { # Minimum, Maximum, and Average all return 1. 'output' => 'Target HTTP 5XXs', 'label' => 'httpcode-target-5xx', 'nlabel' => 'elb.httpcode.target.5xx.count', }, 'HTTPCode_ELB_3XX_Count' => { # Minimum, Maximum, and Average all return 1. 'output' => 'ELB HTTP 3XXs', 'label' => 'httpcode-elb-3xx', 'nlabel' => 'elb.httpcode.elb.3xx.count', }, 'HTTPCode_ELB_4XX_Count' => { # Minimum, Maximum, and Average all return 1. 'output' => 'ELB HTTP 4XXs', 'label' => 'httpcode-elb-4xx', 'nlabel' => 'elb.httpcode.elb.4xx.count', }, 'HTTP_Redirect_Count' => { # Minimum, Maximum, and Average all return 1. 'output' => 'HTTP Redirect', 'label' => 'http-redirect', 'nlabel' => 'elb.http.redirect.count', }, ); sub prefix_metric_output { my ($self, %options) = @_; my $availability_zone = ""; if (defined($options{instance_value}->{availability_zone}) && $options{instance_value}->{availability_zone} ne '') { $availability_zone = "[$options{instance_value}->{availability_zone}] "; } return "ELB '" . $options{instance_value}->{display} . "' " . $availability_zone; } sub prefix_statistics_output { my ($self, %options) = @_; return "Statistic '" . $options{instance_value}->{display} . "' Metrics "; } sub long_output { my ($self, %options) = @_; my $availability_zone = ""; if (defined($options{instance_value}->{availability_zone}) && $options{instance_value}->{availability_zone} ne '') { $availability_zone = "[$options{instance_value}->{availability_zone}] "; } return "Checking '" . $options{instance_value}->{display} . "' " . $availability_zone; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metrics', type => 3, cb_prefix_output => 'prefix_metric_output', cb_long_output => 'long_output', message_multiple => 'All elb metrics are ok', indent_long_output => ' ', group => [ { name => 'statistics', display_long => 1, cb_prefix_output => 'prefix_statistics_output', message_multiple => 'All metrics are ok', type => 1, skipped_code => { -10 => 1 } }, ] } ]; foreach my $metric (keys %metrics_mapping) { my $entry = { label => $metrics_mapping{$metric}->{label}, nlabel => $metrics_mapping{$metric}->{nlabel}, set => { key_values => [ { name => $metric }, { name => 'display' } ], output_template => $metrics_mapping{$metric}->{output} . ': %.2f', perfdatas => [ { value => $metric , template => '%.2f', label_extra_instance => 1 } ], } }; push @{$self->{maps_counters}->{statistics}}, $entry; } } 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 => { "name:s@" => { name => 'name' }, "availability-zone:s" => { name => 'availability_zone' }, "filter-metric:s" => { name => 'filter_metric' }, "target-group:s" => { name => 'target_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; if (defined($self->{option_results}->{target_group}) && $self->{option_results}->{target_group} ne '') { push @{$self->{aws_dimensions}}, { Name => 'TargetGroup', Value => $self->{option_results}->{target_group} }; } $self->{aws_statistics} = ['Sum']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %metrics_mapping) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { push @{$self->{aws_dimensions}}, { Name => 'LoadBalancer', Value => $instance }; if (defined($self->{option_results}->{availability_zone}) && $self->{option_results}->{availability_zone} ne '') { push @{$self->{aws_dimensions}}, { Name => 'AvailabilityZone', Value => $self->{option_results}->{availability_zone} }; } $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/ApplicationELB', dimensions => $self->{aws_dimensions}, metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period}, ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{$instance}->{display} = $instance; $self->{metrics}->{$instance}->{availability_zone} = $self->{option_results}->{availability_zone}; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{display} = $statistic; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{$metric} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check Application ELB HTTP codes metrics. Example: perl centreon_plugins.pl --plugin=cloud::aws::elb::application::plugin --custommode=paws --mode=http-codes --region='eu-west-1' --name='app/AppProd/7c8ecfbd1093c5bd' --critical-httpcode-target-4xx='10' --verbose See 'https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-cloudwatch-metrics.html' for more informations. Default statistic: 'sum' / Most usefull statistics: 'sum'. =over 8 =item B<--name> Set the instance name (Required) (Can be multiple). =item B<--availability-zone> Add Availability Zone dimension. =item B<--filter-metric> Filter metrics (Can be: 'HTTPCode_Target_2XX_Count', 'HTTPCode_Target_3XX_Count', 'HTTPCode_Target_4XX_Count', 'HTTPCode_Target_5XX_Count', 'HTTPCode_ELB_3XX_Count', 'HTTPCode_ELB_4XX_Count', 'HTTP_Redirect_Count') (Can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds warning (Can be: 'httpcode-target-2xx', 'httpcode-target-3xx', 'httpcode-target-4xx', 'httpcode-target-5xx', 'httpcode-elb-3xx', 'httpcode-elb-4xx', 'http-redirect') =back =cut centreon-plugins-20220113/cloud/aws/elb/application/mode/targetshealth.pm000066400000000000000000000201561417000230700263260ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::elb::application::mode::targetshealth; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my %metrics_mapping = ( 'HealthyHostCount' => { 'output' => 'Healthy Hosts', 'label' => 'healthyhostcount', 'nlabel' => 'elb.healthyhostcount.count', }, 'UnHealthyHostCount' => { 'output' => 'Unhealthy Hosts', 'label' => 'unhealthyhostcount', 'nlabel' => 'elb.unhealthyhostcount.count', }, ); sub prefix_metric_output { my ($self, %options) = @_; my $availability_zone = ""; if (defined($options{instance_value}->{availability_zone}) && $options{instance_value}->{availability_zone} ne '') { $availability_zone = "[$options{instance_value}->{availability_zone}] "; } return "ELB '" . $options{instance_value}->{display} . "' " . $availability_zone; } sub prefix_statistics_output { my ($self, %options) = @_; return "Statistic '" . $options{instance_value}->{display} . "' Metrics "; } sub long_output { my ($self, %options) = @_; my $availability_zone = ""; if (defined($options{instance_value}->{availability_zone}) && $options{instance_value}->{availability_zone} ne '') { $availability_zone = "[$options{instance_value}->{availability_zone}] "; } return "Checking '" . $options{instance_value}->{display} . "' " . $availability_zone; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metrics', type => 3, cb_prefix_output => 'prefix_metric_output', cb_long_output => 'long_output', message_multiple => 'All elb metrics are ok', indent_long_output => ' ', group => [ { name => 'statistics', display_long => 1, cb_prefix_output => 'prefix_statistics_output', message_multiple => 'All metrics are ok', type => 1, skipped_code => { -10 => 1 } }, ] } ]; foreach my $metric (keys %metrics_mapping) { my $entry = { label => $metrics_mapping{$metric}->{label}, nlabel => $metrics_mapping{$metric}->{nlabel}, set => { key_values => [ { name => $metric }, { name => 'display' } ], output_template => $metrics_mapping{$metric}->{output} . ': %.2f', perfdatas => [ { value => $metric , template => '%.2f', label_extra_instance => 1 } ], } }; push @{$self->{maps_counters}->{statistics}}, $entry; } } 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 => { "name:s@" => { name => 'name' }, "availability-zone:s" => { name => 'availability_zone' }, "filter-metric:s" => { name => 'filter_metric' }, "statistic:s@" => { name => 'statistic' }, "target-group:s" => { name => 'target_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; if (defined($self->{option_results}->{target_group}) && $self->{option_results}->{target_group} ne '') { push @{$self->{aws_dimensions}}, { Name => 'TargetGroup', Value => $self->{option_results}->{target_group} }; } $self->{aws_statistics} = ['Average']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %metrics_mapping) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { push @{$self->{aws_dimensions}}, { Name => 'LoadBalancer', Value => $instance }; if (defined($self->{option_results}->{availability_zone}) && $self->{option_results}->{availability_zone} ne '') { push @{$self->{aws_dimensions}}, { Name => 'AvailabilityZone', Value => $self->{option_results}->{availability_zone} }; } $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/ApplicationELB', dimensions => $self->{aws_dimensions}, metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period} ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{$instance}->{display} = $instance; $self->{metrics}->{$instance}->{availability_zone} = $self->{option_results}->{availability_zone}; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{display} = $statistic; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{$metric} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check Application ELB targets health. Example: perl centreon_plugins.pl --plugin=cloud::aws::elb::application::plugin --custommode=paws --mode=targets-health --region='eu-west-1' --name='app/AppProd/7c8ecfbd1093c5bd' --critical-unhealthyhostcount='10' --verbose See 'https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-cloudwatch-metrics.html' for more informations. Default statistic: 'average' / Most usefull statistics: 'average', 'minimum', 'maximum'. =over 8 =item B<--name> Set the instance name (Required) (Can be multiple). =item B<--availability-zone> Add Availability Zone dimension. =item B<--filter-metric> Filter metrics (Can be: 'HealthyHostCount', 'UnHealthyHostCount') (Can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds warning (Can be: 'healthyhostcount', 'unhealthyhostcount'). =back =cut centreon-plugins-20220113/cloud/aws/elb/application/plugin.pm000066400000000000000000000032431417000230700240370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::elb::application::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} } = ( 'connections' => 'cloud::aws::elb::application::mode::connections', 'discovery' => 'cloud::aws::elb::application::mode::discovery', 'http-codes' => 'cloud::aws::elb::application::mode::httpcodes', 'targets-health' => 'cloud::aws::elb::application::mode::targetshealth', ); $self->{custom_modes}{paws} = 'cloud::aws::custom::paws'; $self->{custom_modes}{awscli} = 'cloud::aws::custom::awscli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Amazon Application Elastic Load Balancing (Amazon Application ELB). =cut centreon-plugins-20220113/cloud/aws/elb/classic/000077500000000000000000000000001417000230700213175ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/elb/classic/mode/000077500000000000000000000000001417000230700222435ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/elb/classic/mode/discovery.pm000066400000000000000000000057641417000230700246240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::elb::classic::mode::discovery; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "prettify" => { name => 'prettify' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my @disco_data; my $disco_stats; $disco_stats->{start_time} = time(); my $load_balancers = $options{custom}->discovery( service => 'elb', command => 'describe-load-balancers' ); foreach my $load_balancer (@{$load_balancers->{LoadBalancerDescriptions}}) { next if (!defined($load_balancer->{LoadBalancerName})); my %elb; $elb{type} = "classic"; $elb{name} = $load_balancer->{LoadBalancerName}; $elb{dns_name} = $load_balancer->{DNSName}; $elb{availability_zones} = $load_balancer->{AvailabilityZones}; $elb{vpc_id} = $load_balancer->{VPCId}; $elb{instances} = $load_balancer->{Instances}; $elb{security_groups} = $load_balancer->{SecurityGroups}; $elb{subnets} = $load_balancer->{Subnets}; push @disco_data, \%elb; } $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; $disco_stats->{discovered_items} = @disco_data; $disco_stats->{results} = \@disco_data; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE Classic ELB discovery. =over 8 =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/aws/elb/classic/mode/httpcodes.pm000066400000000000000000000244311417000230700246020ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::elb::classic::mode::httpcodes; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my %metrics_mapping = ( 'HTTPCode_Backend_2XX' => { # Minimum, Maximum, and Average all return 1. 'output' => 'HTTP 2XXs', 'label' => 'httpcode-backend-2xx', 'nlabel' => 'elb.httpcode.backend.2xx.count', }, 'HTTPCode_Backend_3XX' => { # Minimum, Maximum, and Average all return 1. 'output' => 'HTTP 3XXs', 'label' => 'httpcode-backend-3xx', 'nlabel' => 'elb.httpcode.backend.3xx.count', }, 'HTTPCode_Backend_4XX' => { # Minimum, Maximum, and Average all return 1. 'output' => 'HTTP 4XXs', 'label' => 'httpcode-backend-4xx', 'nlabel' => 'elb.httpcode.backend.4xx.count', }, 'HTTPCode_Backend_5XX' => { # Minimum, Maximum, and Average all return 1. 'output' => 'HTTP 5XXs', 'label' => 'httpcode-backend-5xx', 'nlabel' => 'elb.httpcode.backend.5xx.count', }, 'HTTPCode_ELB_4XX' => { # Minimum, Maximum, and Average all return 1. 'output' => 'ELB HTTP 4XXs', 'label' => 'httpcode-elb-4xx', 'nlabel' => 'elb.httpcode.elb.4xx.count', }, 'HTTPCode_ELB_5XX' => { # Minimum, Maximum, and Average all return 1. 'output' => 'ELB HTTP 5XXs', 'label' => 'httpcode-elb-5xx', 'nlabel' => 'elb.httpcode.elb.5xx.count', }, 'BackendConnectionErrors' => { 'output' => 'Backend Connection Errors', 'label' => 'backendconnectionerrors', 'nlabel' => 'elb.backendconnectionerrors.count', }, ); my %map_type = ( "loadbalancer" => "LoadBalancerName", "availabilityzone" => "AvailabilityZone", ); sub prefix_metric_output { my ($self, %options) = @_; my $availability_zone = ""; if (defined($options{instance_value}->{availability_zone}) && $options{instance_value}->{availability_zone} ne '') { $availability_zone = "[$options{instance_value}->{availability_zone}] "; } return ucfirst($self->{option_results}->{type}) . " '" . $options{instance_value}->{display} . "' " . $availability_zone; } sub prefix_statistics_output { my ($self, %options) = @_; return "Statistic '" . $options{instance_value}->{display} . "' Metrics "; } sub long_output { my ($self, %options) = @_; my $availability_zone = ""; if (defined($options{instance_value}->{availability_zone}) && $options{instance_value}->{availability_zone} ne '') { $availability_zone = "[$options{instance_value}->{availability_zone}] "; } return "Checking " . ucfirst($self->{option_results}->{type}) . " '" . $options{instance_value}->{display} . "' " . $availability_zone; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metrics', type => 3, cb_prefix_output => 'prefix_metric_output', cb_long_output => 'long_output', message_multiple => 'All elb metrics are ok', indent_long_output => ' ', group => [ { name => 'statistics', display_long => 1, cb_prefix_output => 'prefix_statistics_output', message_multiple => 'All metrics are ok', type => 1, skipped_code => { -10 => 1 } }, ] } ]; foreach my $metric (keys %metrics_mapping) { my $entry = { label => $metrics_mapping{$metric}->{label}, nlabel => $metrics_mapping{$metric}->{nlabel}, set => { key_values => [ { name => $metric }, { name => 'display' } ], output_template => $metrics_mapping{$metric}->{output} . ': %.2f', perfdatas => [ { value => $metric , template => '%.2f', label_extra_instance => 1 } ], } }; push @{$self->{maps_counters}->{statistics}}, $entry; } } 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 => { "type:s" => { name => 'type' }, "name:s@" => { name => 'name' }, "availability-zone:s" => { name => 'availability_zone' }, "filter-metric:s" => { name => 'filter_metric' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{type}) || $self->{option_results}->{type} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --type option."); $self->{output}->option_exit(); } if ($self->{option_results}->{type} ne 'loadbalancer' && $self->{option_results}->{type} ne 'availabilityzone') { $self->{output}->add_option_msg(short_msg => "Instance type '" . $self->{option_results}->{type} . "' is not handled for this mode"); $self->{output}->option_exit(); } if ($self->{option_results}->{type} eq 'availabilityzone' && defined($self->{option_results}->{availability_zone})) { $self->{output}->add_option_msg(short_msg => "Can't specify --availability-zone option with availabilityzone instance's type"); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Sum']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %metrics_mapping) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { push @{$self->{aws_dimensions}}, { Name => $map_type{$self->{option_results}->{type}}, Value => $instance }; if (defined($self->{option_results}->{availability_zone}) && $self->{option_results}->{availability_zone} ne '') { push @{$self->{aws_dimensions}}, { Name => 'AvailabilityZone', Value => $self->{option_results}->{availability_zone} }; } $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/ELB', dimensions => $self->{aws_dimensions}, metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period}, ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{$instance}->{display} = $instance; $self->{metrics}->{$instance}->{availability_zone} = $self->{option_results}->{availability_zone}; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{display} = $statistic; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{$metric} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check Classic ELB HTTP codes metrics. Example: perl centreon_plugins.pl --plugin=cloud::aws::elb::classic::plugin --custommode=paws --mode=http-codes --region='eu-west-1' --type='loadbalancer' --name='elb-www-fr' --critical-httpcode-backend-4xx='10' --verbose See 'https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-cloudwatch-metrics.html' for more informations. Default statistic: 'sum' / Most usefull statistics: 'sum'. =over 8 =item B<--type> Set the instance type (Required) (Can be: 'loadbalancer', 'availabilityzone'). =item B<--name> Set the instance name (Required) (Can be multiple). =item B<--availability-zone> Add Availability Zone dimension (only with --type='loadbalancer'). =item B<--filter-metric> Filter metrics (Can be: 'HTTPCode_Backend_2XX', 'HTTPCode_Backend_3XX', 'HTTPCode_Backend_4XX', 'HTTPCode_Backend_5XX', 'HTTPCode_ELB_4XX', 'HTTPCode_ELB_5XX', 'BackendConnectionErrors') (Can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds warning (Can be: 'httpcode-backend-2xx', 'httpcode-backend-3xx', 'httpcode-backend-4xx', 'httpcode-backend-5xx', 'httpcode-elb-4xx', 'httpcode-elb-5xx', 'backendconnectionerrors') =back =cut centreon-plugins-20220113/cloud/aws/elb/classic/mode/performances.pm000066400000000000000000000220261417000230700252670ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::elb::classic::mode::performances; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my %metrics_mapping = ( 'RequestCount' => { # Minimum, Maximum, and Average all return 1. 'output' => 'Requests', 'label' => 'requestcount', 'nlabel' => 'elb.requestcount.count', }, 'Latency' => { # Minimum is typically not useful 'output' => 'Latency', 'label' => 'latency', 'nlabel' => 'elb.latency.seconds', }, ); my %map_type = ( "loadbalancer" => "LoadBalancerName", "availabilityzone" => "AvailabilityZone", ); sub prefix_metric_output { my ($self, %options) = @_; my $availability_zone = ""; if (defined($options{instance_value}->{availability_zone}) && $options{instance_value}->{availability_zone} ne '') { $availability_zone = "[$options{instance_value}->{availability_zone}] "; } return ucfirst($self->{option_results}->{type}) . " '" . $options{instance_value}->{display} . "' " . $availability_zone; } sub prefix_statistics_output { my ($self, %options) = @_; return "Statistic '" . $options{instance_value}->{display} . "' Metrics "; } sub long_output { my ($self, %options) = @_; my $availability_zone = ""; if (defined($options{instance_value}->{availability_zone}) && $options{instance_value}->{availability_zone} ne '') { $availability_zone = "[$options{instance_value}->{availability_zone}] "; } return "Checking " . ucfirst($self->{option_results}->{type}) . " '" . $options{instance_value}->{display} . "' " . $availability_zone; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metrics', type => 3, cb_prefix_output => 'prefix_metric_output', cb_long_output => 'long_output', message_multiple => 'All elb metrics are ok', indent_long_output => ' ', group => [ { name => 'statistics', display_long => 1, cb_prefix_output => 'prefix_statistics_output', message_multiple => 'All metrics are ok', type => 1, skipped_code => { -10 => 1 } }, ] } ]; foreach my $metric (keys %metrics_mapping) { my $entry = { label => $metrics_mapping{$metric}->{label}, nlabel => $metrics_mapping{$metric}->{nlabel}, set => { key_values => [ { name => $metric }, { name => 'display' } ], output_template => $metrics_mapping{$metric}->{output} . ': %.2f', perfdatas => [ { value => $metric , template => '%.2f', label_extra_instance => 1 } ], } }; push @{$self->{maps_counters}->{statistics}}, $entry; } } 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 => { "type:s" => { name => 'type' }, "name:s@" => { name => 'name' }, "availability-zone:s" => { name => 'availability_zone' }, "filter-metric:s" => { name => 'filter_metric' }, "statistic:s@" => { name => 'statistic' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{type}) || $self->{option_results}->{type} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --type option."); $self->{output}->option_exit(); } if ($self->{option_results}->{type} ne 'loadbalancer' && $self->{option_results}->{type} ne 'availabilityzone') { $self->{output}->add_option_msg(short_msg => "Instance type '" . $self->{option_results}->{type} . "' is not handled for this mode"); $self->{output}->option_exit(); } if ($self->{option_results}->{type} eq 'availabilityzone' && defined($self->{option_results}->{availability_zone})) { $self->{output}->add_option_msg(short_msg => "Can't specify --availability-zone option with availabilityzone instance's type"); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Sum', 'Average']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %metrics_mapping) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { push @{$self->{aws_dimensions}}, { Name => $map_type{$self->{option_results}->{type}}, Value => $instance }; if (defined($self->{option_results}->{availability_zone}) && $self->{option_results}->{availability_zone} ne '') { push @{$self->{aws_dimensions}}, { Name => 'AvailabilityZone', Value => $self->{option_results}->{availability_zone} }; } $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/ELB', dimensions => $self->{aws_dimensions}, metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period}, ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{$instance}->{display} = $instance; $self->{metrics}->{$instance}->{availability_zone} = $self->{option_results}->{availability_zone}; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{display} = $statistic; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{$metric} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check Classic ELB performances. Example: perl centreon_plugins.pl --plugin=cloud::aws::elb::classic::plugin --custommode=paws --mode=performances --region='eu-west-1' --type='loadbalancer' --name='elb-www-fr' --critical-requestcount='10' --verbose See 'https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-cloudwatch-metrics.html' for more informations. Default statistic: 'sum', 'average' / Most usefull statistics: RequestCount: 'sum', Latency: 'average'. =over 8 =item B<--type> Set the instance type (Required) (Can be: 'loadbalancer', 'availabilityzone'). =item B<--name> Set the instance name (Required) (Can be multiple). =item B<--availability-zone> Add Availability Zone dimension (only with --type='loadbalancer'). =item B<--filter-metric> Filter metrics (Can be: 'RequestCount', 'Latency') (Can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds warning (Can be: 'requestcount', 'latency'). =back =cut centreon-plugins-20220113/cloud/aws/elb/classic/mode/queues.pm000066400000000000000000000222111417000230700241060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::elb::classic::mode::queues; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my %metrics_mapping = ( 'SpilloverCount' => { # Average, Minimum, and Maximum are reported per load balancer node and are not typically useful. 'output' => 'Spillover Count', 'label' => 'spillovercount', 'nlabel' => 'elb.spillovercount.count', }, 'SurgeQueueLength' => { # Sum is not useful. 'output' => 'Surge Queue Length', 'label' => 'surgequeuelength', 'nlabel' => 'elb.surgequeuelength.count', }, ); my %map_type = ( "loadbalancer" => "LoadBalancerName", "availabilityzone" => "AvailabilityZone", ); sub prefix_metric_output { my ($self, %options) = @_; my $availability_zone = ""; if (defined($options{instance_value}->{availability_zone}) && $options{instance_value}->{availability_zone} ne '') { $availability_zone = "[$options{instance_value}->{availability_zone}] "; } return ucfirst($self->{option_results}->{type}) . " '" . $options{instance_value}->{display} . "' " . $availability_zone; } sub prefix_statistics_output { my ($self, %options) = @_; return "Statistic '" . $options{instance_value}->{display} . "' Metrics "; } sub long_output { my ($self, %options) = @_; my $availability_zone = ""; if (defined($options{instance_value}->{availability_zone}) && $options{instance_value}->{availability_zone} ne '') { $availability_zone = "[$options{instance_value}->{availability_zone}] "; } return "Checking " . ucfirst($self->{option_results}->{type}) . " '" . $options{instance_value}->{display} . "' " . $availability_zone; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metrics', type => 3, cb_prefix_output => 'prefix_metric_output', cb_long_output => 'long_output', message_multiple => 'All elb metrics are ok', indent_long_output => ' ', group => [ { name => 'statistics', display_long => 1, cb_prefix_output => 'prefix_statistics_output', message_multiple => 'All metrics are ok', type => 1, skipped_code => { -10 => 1 } }, ] } ]; foreach my $metric (keys %metrics_mapping) { my $entry = { label => $metrics_mapping{$metric}->{label}, nlabel => $metrics_mapping{$metric}->{nlabel}, set => { key_values => [ { name => $metric }, { name => 'display' } ], output_template => $metrics_mapping{$metric}->{output} . ': %.2f', perfdatas => [ { value => $metric , template => '%.2f', label_extra_instance => 1 } ], } }; push @{$self->{maps_counters}->{statistics}}, $entry; } } 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 => { "type:s" => { name => 'type' }, "name:s@" => { name => 'name' }, "availability-zone:s" => { name => 'availability_zone' }, "filter-metric:s" => { name => 'filter_metric' }, "statistic:s@" => { name => 'statistic' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{type}) || $self->{option_results}->{type} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --type option."); $self->{output}->option_exit(); } if ($self->{option_results}->{type} ne 'loadbalancer' && $self->{option_results}->{type} ne 'availabilityzone') { $self->{output}->add_option_msg(short_msg => "Instance type '" . $self->{option_results}->{type} . "' is not handled for this mode"); $self->{output}->option_exit(); } if ($self->{option_results}->{type} eq 'availabilityzone' && defined($self->{option_results}->{availability_zone})) { $self->{output}->add_option_msg(short_msg => "Can't specify --availability-zone option with availabilityzone instance's type"); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Sum', 'Maximum']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %metrics_mapping) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { push @{$self->{aws_dimensions}}, { Name => $map_type{$self->{option_results}->{type}}, Value => $instance }; if (defined($self->{option_results}->{availability_zone}) && $self->{option_results}->{availability_zone} ne '') { push @{$self->{aws_dimensions}}, { Name => 'AvailabilityZone', Value => $self->{option_results}->{availability_zone} }; } $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/ELB', dimensions => $self->{aws_dimensions}, metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period}, ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{$instance}->{display} = $instance; $self->{metrics}->{$instance}->{availability_zone} = $self->{option_results}->{availability_zone}; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{display} = $statistic; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{$metric} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check Classic ELB surge queue. Example: perl centreon_plugins.pl --plugin=cloud::aws::elb::classic::plugin --custommode=paws --mode=queues --region='eu-west-1' --type='loadbalancer' --name='elb-www-fr' --critical-spillovercount-sum='10' --verbose See 'https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-cloudwatch-metrics.html' for more informations. Default statistic: 'sum', 'maximum' / Most usefull statistics: SpilloverCount: 'sum', SurgeQueueLength: 'maximum'. =over 8 =item B<--type> Set the instance type (Required) (Can be: 'loadbalancer', 'availabilityzone'). =item B<--name> Set the instance name (Required) (Can be multiple). =item B<--availability-zone> Add Availability Zone dimension (only with --type='loadbalancer'). =item B<--filter-metric> Filter metrics (Can be: 'SpilloverCount', 'SurgeQueueLength') (Can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds warning (Can be: 'spillovercount', 'surgequeuelength'). =back =cut centreon-plugins-20220113/cloud/aws/elb/classic/mode/targetshealth.pm000066400000000000000000000220221417000230700254360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::elb::classic::mode::targetshealth; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my %metrics_mapping = ( 'HealthyHostCount' => { 'output' => 'Healthy Hosts', 'label' => 'healthyhostcount', 'nlabel' => 'elb.healthyhostcount.count', }, 'UnHealthyHostCount' => { 'output' => 'Unhealthy Hosts', 'label' => 'unhealthyhostcount', 'nlabel' => 'elb.unhealthyhostcount.count', }, ); my %map_type = ( "loadbalancer" => "LoadBalancerName", "availabilityzone" => "AvailabilityZone", ); sub prefix_metric_output { my ($self, %options) = @_; my $availability_zone = ""; if (defined($options{instance_value}->{availability_zone}) && $options{instance_value}->{availability_zone} ne '') { $availability_zone = "[$options{instance_value}->{availability_zone}] "; } return ucfirst($self->{option_results}->{type}) . " '" . $options{instance_value}->{display} . "' " . $availability_zone; } sub prefix_statistics_output { my ($self, %options) = @_; return "Statistic '" . $options{instance_value}->{display} . "' Metrics "; } sub long_output { my ($self, %options) = @_; my $availability_zone = ""; if (defined($options{instance_value}->{availability_zone}) && $options{instance_value}->{availability_zone} ne '') { $availability_zone = "[$options{instance_value}->{availability_zone}] "; } return "Checking " . ucfirst($self->{option_results}->{type}) . " '" . $options{instance_value}->{display} . "' " . $availability_zone; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metrics', type => 3, cb_prefix_output => 'prefix_metric_output', cb_long_output => 'long_output', message_multiple => 'All elb metrics are ok', indent_long_output => ' ', group => [ { name => 'statistics', display_long => 1, cb_prefix_output => 'prefix_statistics_output', message_multiple => 'All metrics are ok', type => 1, skipped_code => { -10 => 1 } }, ] } ]; foreach my $metric (keys %metrics_mapping) { my $entry = { label => $metrics_mapping{$metric}->{label}, nlabel => $metrics_mapping{$metric}->{nlabel}, set => { key_values => [ { name => $metric }, { name => 'display' } ], output_template => $metrics_mapping{$metric}->{output} . ': %.2f', perfdatas => [ { value => $metric , template => '%.2f', label_extra_instance => 1 } ], } }; push @{$self->{maps_counters}->{statistics}}, $entry; } } 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 => { "type:s" => { name => 'type' }, "name:s@" => { name => 'name' }, "availability-zone:s" => { name => 'availability_zone' }, "filter-metric:s" => { name => 'filter_metric' }, "statistic:s@" => { name => 'statistic' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{type}) || $self->{option_results}->{type} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --type option."); $self->{output}->option_exit(); } if ($self->{option_results}->{type} ne 'loadbalancer' && $self->{option_results}->{type} ne 'availabilityzone') { $self->{output}->add_option_msg(short_msg => "Instance type '" . $self->{option_results}->{type} . "' is not handled for this mode"); $self->{output}->option_exit(); } if ($self->{option_results}->{type} eq 'availabilityzone' && defined($self->{option_results}->{availability_zone})) { $self->{output}->add_option_msg(short_msg => "Can't specify --availability-zone option with availabilityzone instance's type"); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Average']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %metrics_mapping) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { push @{$self->{aws_dimensions}}, { Name => $map_type{$self->{option_results}->{type}}, Value => $instance }; if (defined($self->{option_results}->{availability_zone}) && $self->{option_results}->{availability_zone} ne '') { push @{$self->{aws_dimensions}}, { Name => 'AvailabilityZone', Value => $self->{option_results}->{availability_zone} }; } $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/ELB', dimensions => $self->{aws_dimensions}, metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period}, ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{$instance}->{display} = $instance; $self->{metrics}->{$instance}->{availability_zone} = $self->{option_results}->{availability_zone}; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{display} = $statistic; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{$metric} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check Classic ELB instances health. Example: perl centreon_plugins.pl --plugin=cloud::aws::elb::classic::plugin --custommode=paws --mode=instancehealth --region='eu-west-1' --type='loadbalancer' --name='elb-www-fr' --critical-healthyhostcount='10' --verbose See 'https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-cloudwatch-metrics.html' for more informations. Default statistic: 'average' / Most usefull statistics: 'average', 'minimum', 'maximum'. =over 8 =item B<--type> Set the instance type (Required) (Can be: 'loadbalancer', 'availabilityzone'). =item B<--name> Set the instance name (Required) (Can be multiple). =item B<--availability-zone> Add Availability Zone dimension (only with --type='loadbalancer'). =item B<--filter-metric> Filter metrics (Can be: 'HealthyHostCount', 'UnHealthyHostCount') (Can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds warning (Can be: 'healthyhostcount', 'unhealthyhostcount'). =back =cut centreon-plugins-20220113/cloud/aws/elb/classic/plugin.pm000066400000000000000000000033251417000230700231560ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::elb::classic::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} } = ( 'discovery' => 'cloud::aws::elb::classic::mode::discovery', 'http-codes' => 'cloud::aws::elb::classic::mode::httpcodes', 'performances' => 'cloud::aws::elb::classic::mode::performances', 'queues' => 'cloud::aws::elb::classic::mode::queues', 'targets-health' => 'cloud::aws::elb::classic::mode::targetshealth', ); $self->{custom_modes}{paws} = 'cloud::aws::custom::paws'; $self->{custom_modes}{awscli} = 'cloud::aws::custom::awscli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Amazon Classic Elastic Load Balancing (Amazon Classic ELB). =cut centreon-plugins-20220113/cloud/aws/elb/network/000077500000000000000000000000001417000230700213675ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/elb/network/mode/000077500000000000000000000000001417000230700223135ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/elb/network/mode/discovery.pm000066400000000000000000000060351417000230700246640ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::elb::network::mode::discovery; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "prettify" => { name => 'prettify' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my @disco_data; my $disco_stats; $disco_stats->{start_time} = time(); my $load_balancers = $options{custom}->discovery( service => 'elbv2', command => 'describe-load-balancers' ); foreach my $load_balancer (@{$load_balancers->{LoadBalancers}}) { next if (!defined($load_balancer->{LoadBalancerArn}) || $load_balancer->{Type} ne 'network'); my %elb; $elb{type} = "network"; $elb{name} = $1 if ($load_balancer->{LoadBalancerArn} =~ /arn:aws:elasticloadbalancing:.*:loadbalancer\/(.*)/); $elb{dns_name} = $load_balancer->{DNSName}; $elb{availability_zones} = $load_balancer->{AvailabilityZones}; $elb{vpc_id} = $load_balancer->{VpcId}; $elb{security_groups} = $load_balancer->{SecurityGroups}; $elb{state} = $load_balancer->{State}->{Code}; push @disco_data, \%elb; } $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; $disco_stats->{discovered_items} = @disco_data; $disco_stats->{results} = \@disco_data; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE Network ELB discovery. =over 8 =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/aws/elb/network/mode/targetshealth.pm000066400000000000000000000174671417000230700255270ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::elb::network::mode::targetshealth; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my %metrics_mapping = ( 'HealthyHostCount' => { 'output' => 'Healthy Hosts', 'label' => 'healthyhostcount', 'nlabel' => 'elb.healthyhostcount.count', }, 'UnHealthyHostCount' => { 'output' => 'Unhealthy Hosts', 'label' => 'unhealthyhostcount', 'nlabel' => 'elb.unhealthyhostcount.count', }, ); sub prefix_metric_output { my ($self, %options) = @_; my $availability_zone = ""; if (defined($options{instance_value}->{availability_zone}) && $options{instance_value}->{availability_zone} ne '') { $availability_zone = "[$options{instance_value}->{availability_zone}] "; } return "ELB '" . $options{instance_value}->{display} . "' " . $availability_zone; } sub prefix_statistics_output { my ($self, %options) = @_; return "Statistic '" . $options{instance_value}->{display} . "' Metrics "; } sub long_output { my ($self, %options) = @_; my $availability_zone = ""; if (defined($options{instance_value}->{availability_zone}) && $options{instance_value}->{availability_zone} ne '') { $availability_zone = "[$options{instance_value}->{availability_zone}] "; } return "Checking '" . $options{instance_value}->{display} . "' " . $availability_zone; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metrics', type => 3, cb_prefix_output => 'prefix_metric_output', cb_long_output => 'long_output', message_multiple => 'All elb metrics are ok', indent_long_output => ' ', group => [ { name => 'statistics', display_long => 1, cb_prefix_output => 'prefix_statistics_output', message_multiple => 'All metrics are ok', type => 1, skipped_code => { -10 => 1 } }, ] } ]; foreach my $metric (keys %metrics_mapping) { my $entry = { label => $metrics_mapping{$metric}->{label}, nlabel => $metrics_mapping{$metric}->{nlabel}, set => { key_values => [ { name => $metric }, { name => 'display' } ], output_template => $metrics_mapping{$metric}->{output} . ': %.2f', perfdatas => [ { value => $metric , template => '%.2f', label_extra_instance => 1 } ], } }; push @{$self->{maps_counters}->{statistics}}, $entry; } } 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 => { "name:s@" => { name => 'name' }, "availability-zone:s" => { name => 'availability_zone' }, "filter-metric:s" => { name => 'filter_metric' }, "statistic:s@" => { name => 'statistic' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Average']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %metrics_mapping) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { push @{$self->{aws_dimensions}}, { Name => 'LoadBalancer', Value => $instance }; if (defined($self->{option_results}->{availability_zone}) && $self->{option_results}->{availability_zone} ne '') { push @{$self->{aws_dimensions}}, { Name => 'AvailabilityZone', Value => $self->{option_results}->{availability_zone} }; } $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/ApplicationELB', dimensions => $self->{aws_dimensions}, metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period}, ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{$instance}->{display} = $instance; $self->{metrics}->{$instance}->{availability_zone} = $self->{option_results}->{availability_zone}; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{display} = $statistic; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{$metric} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check Network ELB targets health. Example: perl centreon_plugins.pl --plugin=cloud::aws::elb::network::plugin --custommode=paws --mode=targets-health --region='eu-west-1' --name='net/NetProd/7c8ecfbd1093c5bd' --critical-unhealthyhostcount='10' --verbose See 'https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-cloudwatch-metrics.html' for more informations. Default statistic: 'average' / Most usefull statistics: 'average', 'minimum', 'maximum'. =over 8 =item B<--name> Set the instance name (Required) (Can be multiple). =item B<--availability-zone> Add Availability Zone dimension. =item B<--filter-metric> Filter metrics (Can be: 'HealthyHostCount', 'UnHealthyHostCount') (Can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds warning (Can be: 'healthyhostcount', 'unhealthyhostcount'). =back =cut centreon-plugins-20220113/cloud/aws/elb/network/plugin.pm000066400000000000000000000027451417000230700232330ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::elb::network::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} } = ( 'discovery' => 'cloud::aws::elb::network::mode::discovery', 'targets-health' => 'cloud::aws::elb::network::mode::targetshealth', ); $self->{custom_modes}{paws} = 'cloud::aws::custom::paws'; $self->{custom_modes}{awscli} = 'cloud::aws::custom::awscli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Amazon Network Elastic Load Balancing (Amazon Network ELB). =cut centreon-plugins-20220113/cloud/aws/fsx/000077500000000000000000000000001417000230700177345ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/fsx/mode/000077500000000000000000000000001417000230700206605ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/fsx/mode/datausage.pm000066400000000000000000000144771417000230700231710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::fsx::mode::datausage; use base qw(cloud::aws::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { extra_params => { message_multiple => 'All FSx metrics are ok' }, metrics => { DataReadBytes => { output => 'Data Read Bytes', label => 'data-read-bytes', nlabel => { absolute => 'fsx.data.read.bytes', per_second => 'fsx.data.read.bytespersecond' }, unit => 'B' }, DataWriteBytes => { output => 'Data Write Bytes', label => 'data-write-ops', nlabel => { absolute => 'fsx.data.write.bytes', per_second => 'fsx.data.write.bytespersecond' }, unit => 'B' }, DataReadOperations => { output => 'Data Read Ops', label => 'data-read-ops', nlabel => { absolute => 'fsx.data.io.read.count', per_second => 'fsx.data.io.read.persecond' }, unit => 'count' }, DataWriteOperations => { output => 'Data Write Ops', label => 'data-write-ops', nlabel => { absolute => 'fsx.data.io.write.count', per_second => 'fsx.data.io.write.persecond' }, unit => 'count' }, MetadataOperations => { output => 'MetaData Operations Bytes', label => 'metadata-ops-bytes', nlabel => { absolute => 'fsx.metadata.ops.bytes', per_second => 'fsx.metadata.ops.bytespersecond' }, unit => 'B' } } }; return $metrics_mapping; } sub long_output { my ($self, %options) = @_; return "FSx FileSystemId '" . $options{instance_value}->{display} . "' "; } 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 => { 'name:s@' => { name => 'name' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/FSx', dimensions => [ { Name => "FileSystemId", Value => $instance } ], metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period} ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{$instance}->{display} = $instance; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{display} = $statistic; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{timeframe} = $self->{aws_timeframe}; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{$metric} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check FSx FileSystem Data consumption metrics. Example: perl centreon_plugins.pl --plugin=cloud::aws::fsx::plugin --custommode=awscli --mode=datausage --region='eu-west-1' --name='fs-1234abcd' --filter-metric='DataReadIOBytes' --statistic='sum' --warning-data-read-bytes='5' --verbose See 'https://docs.aws.amazon.com/efs/latest/ug/efs-metrics.html' for more information. =over 8 =item B<--name> Set the instance name (Required) (Can be multiple). =item B<--filter-metric> Filter on a specific metric Can be: DataReadBytes, DataWriteBytes, DataReadOperations, DataWriteOperations, MetaDataOperations =item B<--statistic> Set the metric calculation method (Only Sum is relevant). =item B<--warning-$metric$> Thresholds warning ($metric$ can be: 'data-write-ops', 'data-write-ops', 'data-read-ops', 'data-read-bytes', 'metadata-ops-bytes'). =item B<--critical-$metric$> Thresholds critical ($metric$ can be: 'data-write-ops', 'data-write-ops', 'data-read-ops', 'data-read-bytes', 'metadata-ops-bytes'). =back =cut centreon-plugins-20220113/cloud/aws/fsx/mode/discovery.pm000066400000000000000000000057061417000230700232350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::fsx::mode::discovery; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'prettify' => { name => 'prettify' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my @disco_data; my $disco_stats; $disco_stats->{start_time} = time(); my $fsx_instances = $options{custom}->discovery( service => 'fsx', command => 'describe-file-systems' ); foreach my $fsx_instance (@{$fsx_instances->{FileSystems}}) { next if (!defined($fsx_instance->{FileSystemId})); my %fsx; $fsx{type} = "fsx"; $fsx{id} = $fsx_instance->{FileSystemId}; $fsx{dns_name} = $fsx_instance->{DNSName}; $fsx{creation_time} = $fsx_instance->{CreationTime}; $fsx{lifecycle} = $fsx_instance->{Lifecycle}; $fsx{fsx_type} = $fsx_instance->{FileSystemType}; foreach my $tag (@{$instance->{Tags}}) { push @{$fsx{tags}}, { key => $tag->{Key}, value => $tag->{Value} }; } push @disco_data, \%fsx; } $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; $disco_stats->{discovered_items} = @disco_data; $disco_stats->{results} = \@disco_data; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE FSX discovery. =over 8 =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/aws/fsx/mode/freespace.pm000066400000000000000000000107331417000230700231570ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::fsx::mode::freespace; use base qw(cloud::aws::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { metrics => { FreeStorageCapacity => { output => 'Free Storage Bytes', label => 'storage-free-bytes', nlabel => { absolute => 'fsx.storage.free.bytes', }, unit => 'B' } } }; return $metrics_mapping; } sub long_output { my ($self, %options) = @_; return "FSx FileSystemId '" . $options{instance_value}->{display} . "' "; } 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 => { 'name:s@' => { name => 'name' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/FSx', dimensions => [ { Name => "FileSystemId", Value => $instance } ], metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period} ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{$instance}->{display} = $instance; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{display} = $statistic; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{timeframe} = $self->{aws_timeframe}; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{$metric} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check FSx FileSystem Free Storage available in Bytes. Example: perl centreon_plugins.pl --plugin=cloud::aws::fsx::plugin --custommode=awscli --mode=freespace --region='eu-west-1' --name='fs-1234abcd' --warning-data-read-bytes='5' --verbose See 'https://docs.aws.amazon.com/efs/latest/ug/efs-metrics.html' for more information. =over 8 =item B<--name> Set the instance name (Required) (Can be multiple). =item B<--statistic> Set the metric calculation method (Default: Average) Can be 'minimum', 'average' =item B<--warning-storage-free-bytes> Thresholds warning on remaining available bytes. =item B<--critical-storage-free-bytes> Thresholds warning on remaining available bytes. =back =cut centreon-plugins-20220113/cloud/aws/fsx/plugin.pm000066400000000000000000000027251417000230700215760ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::fsx::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} = '1.0'; %{ $self->{modes} } = ( 'datausage' => 'cloud::aws::fsx::mode::datausage', 'discovery' => 'cloud::aws::fsx::mode::discovery', 'freespace' => 'cloud::aws::fsx::mode::freespace' ); $self->{custom_modes}{paws} = 'cloud::aws::custom::paws'; $self->{custom_modes}{awscli} = 'cloud::aws::custom::awscli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Amazon shared File Systems (Amazon FSx). =cut centreon-plugins-20220113/cloud/aws/health/000077500000000000000000000000001417000230700204015ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/health/mode/000077500000000000000000000000001417000230700213255ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/health/mode/events.pm000066400000000000000000000143571417000230700232010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::health::mode::events; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_global_output { my ($self, %options) = @_; return 'Events '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', cb_prefix_output => 'prefix_global_output', type => 0 } ]; $self->{maps_counters}->{global} = [ { label => 'total', nlabel => 'events.total.count', set => { key_values => [ { name => 'total' } ], output_template => 'total: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'open', nlabel => 'events.open.count', set => { key_values => [ { name => 'open' } ], output_template => 'open: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'closed', nlabel => 'events.closed.count', set => { key_values => [ { name => 'closed' } ], output_template => 'closed: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'upcoming', nlabel => 'events.upcoming.count', set => { key_values => [ { name => 'upcoming' } ], output_template => 'upcoming: %s', perfdatas => [ { template => '%s', min => 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-service:s@' => { name => 'filter_service' }, 'filter-region:s@' => { name => 'filter_region' }, 'filter-entity-value:s@' => { name => 'filter_entity_value' }, 'filter-event-status:s@' => { name => 'filter_event_status' }, 'filter-event-category:s@' => { name => 'filter_event_category' }, 'display-affected-entities' => { name => 'display_affected_entities' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{filter_options} = {}; foreach (('service', 'region', 'entity_value', 'event_status', 'event_category')) { $self->{filter_options}->{'filter_' . $_} = undef; if (defined($self->{option_results}->{'filter_' . $_})) { foreach my $option (@{$self->{option_results}->{'filter_' . $_}}) { next if ($option eq ''); $self->{filter_options}->{'filter_' . $_} = [] if (!defined($self->{filter_options}->{'filter_' . $_})); push @{$self->{filter_options}->{'filter_' . $_}}, split(/,/, $option); } } } } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->health_describe_events( %{$self->{filter_options}} ); $self->{global} = { total => 0, open => 0, closed => 0, upcoming => 0 }; my $events = {}; foreach my $entry (@$results) { $self->{global}->{ lc($entry->{statusCode}) }++; $self->{global}->{total}++; $events->{ $entry->{arn} } = $entry; } my $affected_entities; my @event_arns = sort { $events->{$b}->{startTime} cmp $events->{$a}->{startTime} } keys %$events; if (scalar(@event_arns) > 0 && defined($self->{option_results}->{display_affected_entities})) { $affected_entities = $options{custom}->health_describe_affected_entities(filter_event_arns => [@event_arns]); } foreach (@event_arns) { my $entity = ''; if (defined($affected_entities)) { $entity = '[affected entity: -]'; foreach my $affected (@$affected_entities) { if ($events->{$_}->{arn} eq $affected->{eventArn}) { $entity = '[affected entity: ' . $affected->{entityValue} . ']'; last; } } } $self->{output}->output_add(long_msg => sprintf( '[service: %s][region: %s][status: %s][type: %s][start: %s]%s', $events->{$_}->{service}, $events->{$_}->{region}, $events->{$_}->{statusCode}, $events->{$_}->{eventTypeCode}, scalar(localtime($events->{$_}->{startTime})), $entity ) ); } } 1; __END__ =head1 MODE Check health events. =over 8 =item B<--filter-service> Filter result by service (multiple option). Example: --filter-service=EC2 --filter-service=RDS =item B<--filter-region> Filter result by region (multiple option). Example: --filter-region=ap-southeast-1 --filter-region=eu-west-1 =item B<--filter-entity-value> Filter result by entity value (multiple option). Example: --filter-entity-value=i-34ab692e --filter-entity-value=vol-426ab23e =item B<--filter-event-status> Filter result by event status (multiple option). Example: --filter-event-status=open --filter-event-status=closed =item B<--filter-event-category> Filter result by event category (multiple option). Example: --filter-event-category=issue =item B<--display-affected-entities> Display affected entities by the event. =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'total', 'open', 'closed', 'upcoming'. =back =cut centreon-plugins-20220113/cloud/aws/health/plugin.pm000066400000000000000000000027131417000230700222400ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::health::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} = { 'events' => 'cloud::aws::health::mode::events' }; $self->{customdefault} = { paws => { region => 'us-east-1' }, awscli => { region => 'us-east-1' } }; $self->{custom_modes}->{paws} = 'cloud::aws::custom::paws'; $self->{custom_modes}->{awscli} = 'cloud::aws::custom::awscli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Amazon Health service. =cut centreon-plugins-20220113/cloud/aws/kinesis/000077500000000000000000000000001417000230700206015ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/kinesis/mode/000077500000000000000000000000001417000230700215255ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/kinesis/mode/discovery.pm000066400000000000000000000050551417000230700240770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::kinesis::mode::discovery; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "prettify" => { name => 'prettify' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my @disco_data; my $disco_stats; $disco_stats->{start_time} = time(); my $streams = $options{custom}->discovery( service => 'kinesis', command => 'list-streams' ); foreach my $stream (@{$streams->{StreamNames}}) { my %stream; $stream{type} = "kinesis_stream"; $stream{name} = $stream; push @disco_data, \%stream; } $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; $disco_stats->{discovered_items} = @disco_data; $disco_stats->{results} = \@disco_data; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE Kinesis Stream discovery. =over 8 =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/aws/kinesis/mode/recordsstats.pm000066400000000000000000000203571417000230700246120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::kinesis::mode::recordsstats; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my %metrics_mapping = ( 'GetRecords.IteratorAgeMilliseconds' => { 'output' => 'Get Records Iterator Age', 'label' => 'records-get-iteratorage', 'nlabel' => 'kinesis.stream.records.get.iteratorage.milliseconds', 'perf_unit' => 'ms', 'change_bytes' => '0', 'stats' => { 'sum' => 'false' } }, 'GetRecords.Bytes' => { 'output' => 'Get Records Bytes', 'label' => 'records-get-volume', 'nlabel' => 'kinesis.stream.records.get.volume.bytes', 'perf_unit' => 'B', 'change_bytes' => '2', }, 'GetRecords.Latency' => { 'output' => 'Get Records Latency', 'label' => 'records-get-latency', 'nlabel' => 'kinesis.stream.records.get.latency.milliseconds', 'perf_unit' => 'ms', 'change_bytes' => '0', 'stats' => { 'sum' => 'false' } }, 'GetRecords.Success' => { 'output' => 'Get Records Success', 'label' => 'records-get-success', 'nlabel' => 'kinesis.stream.records.get.success.count', 'perf_unit' => '', 'change_bytes' => '0', 'stats' => { 'average' => 'false' } }, 'PutRecord.Latency' => { 'output' => 'Put Records Latency', 'label' => 'records-put-latency', 'nlabel' => 'kinesis.stream.records.put.latency.milliseconds', 'perf_unit' => 'ms', 'change_bytes' => '0', 'stats' => { 'sum' => 'false' } }, 'PutRecord.Bytes' => { 'output' => 'Put Records Bytes', 'label' => 'records-put-volume', 'nlabel' => 'kinesis.stream.records.put.volume.bytes', 'perf_unit' => 'B', 'change_bytes' => '2' }, 'PutRecord.Success' => { 'output' => 'Put Records Success', 'label' => 'records-put-success', 'nlabel' => 'kinesis.stream.records.put.success.count', 'perf_unit' => '', 'change_bytes' => '0', 'stats' => { 'average' => 'false' } }, ); sub prefix_metric_output { my ($self, %options) = @_; return " '" . $options{instance_value}->{display} . "' "; } sub prefix_statistics_output { my ($self, %options) = @_; return "Statistic '" . $options{instance_value}->{display} . "' Metrics "; } sub long_output { my ($self, %options) = @_; return "Checking'" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metrics', type => 3, cb_prefix_output => 'prefix_metric_output', cb_long_output => 'long_output', message_multiple => 'All records to streams metrics are ok', indent_long_output => ' ', group => [ { name => 'statistics', display_long => 1, cb_prefix_output => 'prefix_statistics_output', message_multiple => 'All records to streams metrics are ok', type => 1, skipped_code => { -10 => 1 } }, ] } ]; foreach my $metric (keys %metrics_mapping) { my $entry = { label => $metrics_mapping{$metric}->{label}, nlabel => $metrics_mapping{$metric}->{nlabel}, set => { key_values => [ { name => $metric }, { name => 'display' } ], output_template => ($metrics_mapping{$metric}->{change_bytes} != 0) ? $metrics_mapping{$metric}->{output} . ': %.2f %s' : $metrics_mapping{$metric}->{output} . ': %.2f', change_bytes => $metrics_mapping{$metric}->{output_change_bytes}, perfdatas => [ { value => $metric , template => '%.2f', label_extra_instance => 1, unit => $metrics_mapping{$metric}->{perf_unit} } ], } }; push @{$self->{maps_counters}->{statistics}}, $entry; } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, force_new_perfdata => 1, %options); bless $self, $class; $options{options}->add_options(arguments => { 'stream-name:s@' => { name => 'stream_name' }, 'filter-metric:s' => { name => 'filter_metric' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); foreach my $instance (@{$self->{option_results}->{stream_name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Average','Sum']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %metrics_mapping) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/Kinesis', dimensions => [ { Name => 'StreamName', Value => $instance } ], metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period}, ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed}) || defined($metrics_mapping{$metric}->{stats}->{lc($statistic)}) && $metrics_mapping{$metric}->{stats}->{lc($statistic)} eq "false"); $self->{metrics}->{$instance}->{display} = $instance; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{display} = $statistic; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{$metric} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check metrics about records statistics in Kinesis streams. =over 8 =item B<--name> Set the stream name (Required) (Can be multiple). =item B<--filter-metric> Filter metrics (Can be: 'GetRecords.IteratorAgeMilliseconds', 'GetRecords.Bytes', ) =item B<--warning-*> B<--critical-*> Thresholds warning can be: 'records-get-iteratorage', 'records-get-volume', 'records-get-latency', 'records-get-success', 'records-put-volume', 'records-put-latency', 'records-get-success', =back =cut centreon-plugins-20220113/cloud/aws/kinesis/mode/streams.pm000066400000000000000000000164271417000230700235530ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::kinesis::mode::streams; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my %metrics_mapping = ( 'IncomingBytes' => { 'output' => 'Incoming Bytes', 'label' => 'incoming-volume', 'nlabel' => 'kinesis.stream.incoming.volume.bytes', 'perf_unit' => 'B', 'change_bytes' => '2' }, 'IncomingRecords' => { 'output' => 'Incoming Records', 'label' => 'incoming-records', 'nlabel' => 'kinesis.stream.incoming.records.count', 'perf_unit' => '', 'change_bytes' => '0', 'stats' => { 'average' => 'false' } }, 'OutgoingBytes' => { 'output' => 'Outgoing Bytes', 'label' => 'outgoing-volume', 'nlabel' => 'kinesis.stream.outgoing.volume.bytes', 'perf_unit' => 'B', 'change_bytes' => '2' }, 'OutgoingRecords' => { 'output' => 'Outgoing Records', 'label' => 'outgoing-records', 'nlabel' => 'kinesis.stream.outgoing.records.count', 'perf_unit' => '', 'change_bytes' => '0', 'stats' => { 'average' => 'false' } }, ); sub prefix_metric_output { my ($self, %options) = @_; return " '" . $options{instance_value}->{display} . "' "; } sub prefix_statistics_output { my ($self, %options) = @_; return "Statistic '" . $options{instance_value}->{display} . "' Metrics "; } sub long_output { my ($self, %options) = @_; return "Checking'" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metrics', type => 3, cb_prefix_output => 'prefix_metric_output', cb_long_output => 'long_output', message_multiple => 'All stream metrics are ok', indent_long_output => ' ', group => [ { name => 'statistics', display_long => 1, cb_prefix_output => 'prefix_statistics_output', message_multiple => 'All stream metrics are ok', type => 1, skipped_code => { -10 => 1 } }, ] } ]; foreach my $metric (keys %metrics_mapping) { my $entry = { label => $metrics_mapping{$metric}->{label}, nlabel => $metrics_mapping{$metric}->{nlabel}, set => { key_values => [ { name => $metric }, { name => 'display' } ], output_template => ($metrics_mapping{$metric}->{change_bytes} != 0) ? $metrics_mapping{$metric}->{output} . ': %.2f %s' : $metrics_mapping{$metric}->{output} . ': %.2f', change_bytes => $metrics_mapping{$metric}->{output_change_bytes}, perfdatas => [ { value => $metric , template => '%.2f', label_extra_instance => 1, unit => $metrics_mapping{$metric}->{perf_unit} } ], } }; push @{$self->{maps_counters}->{statistics}}, $entry; } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, force_new_perfdata => 1, %options); bless $self, $class; $options{options}->add_options(arguments => { 'stream-name:s@' => { name => 'stream_name' }, 'filter-metric:s' => { name => 'filter_metric' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); foreach my $instance (@{$self->{option_results}->{stream_name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Average','Sum']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %metrics_mapping) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/Kinesis', dimensions => [ { Name => 'StreamName', Value => $instance } ], metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period}, ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed}) || defined($metrics_mapping{$metric}->{stats}->{lc($statistic)}) && $metrics_mapping{$metric}->{stats}->{lc($statistic)} eq "false"); $self->{metrics}->{$instance}->{display} = $instance; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{display} = $statistic; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{$metric} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check metrics for Kinesis streams. note: Outgoing* metrics are only available when enhanced stats are enabled (paid metrics) =over 8 =item B<--stream-name> Set the stream name (Required) (Can be multiple). =item B<--filter-metric> Filter metrics (Can be: 'IncomingBytes', 'IncomingRecords', 'OutgoingBytes', 'OutgoingRecords') =item B<--warning-*> B<--critical-*> Thresholds warning can be: 'incoming-bytes', 'incoming-records', 'outgoing-volume', 'outgoing-volume'. =back =cut centreon-plugins-20220113/cloud/aws/kinesis/plugin.pm000066400000000000000000000030061417000230700224340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::kinesis::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} } = ( 'discovery' => 'cloud::aws::kinesis::mode::discovery', 'streams' => 'cloud::aws::kinesis::mode::streams', 'records-stats' => 'cloud::aws::kinesis::mode::recordsstats' ); $self->{custom_modes}{paws} = 'cloud::aws::custom::paws'; $self->{custom_modes}{awscli} = 'cloud::aws::custom::awscli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Amazon Kinesis Stream related metrics (AWS/Kinesis Service). =cut centreon-plugins-20220113/cloud/aws/lambda/000077500000000000000000000000001417000230700203545ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/lambda/mode/000077500000000000000000000000001417000230700213005ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/lambda/mode/invocations.pm000066400000000000000000000170071417000230700241770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::lambda::mode::invocations; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my %metrics_mapping = ( 'Duration' => { 'output' => 'Duration', 'label' => 'duration', 'nlabel' => 'lambda.function.duration.milliseconds', }, 'Invocations' => { 'output' => 'Invocations', 'label' => 'invocations', 'nlabel' => 'lambda.function.invocations.count', }, 'Errors' => { 'output' => 'Errors', 'label' => 'errors', 'nlabel' => 'lambda.function.errors.count', }, 'DeadLetterErrors' => { 'output' => 'Dead Letter Errors', 'label' => 'deadlettererrors', 'nlabel' => 'lambda.function.deadlettererrors.count', }, 'Throttles' => { 'output' => 'Throttles', 'label' => 'throttles', 'nlabel' => 'lambda.function.throttles.count', }, 'IteratorAge' => { 'output' => 'Iterator Age', 'label' => 'iteratorage', 'nlabel' => 'lambda.function.iteratorage.milliseconds', } ); sub prefix_metric_output { my ($self, %options) = @_; return "Function '" . $options{instance_value}->{display} . "' "; } sub prefix_statistics_output { my ($self, %options) = @_; return "Statistic '" . $options{instance_value}->{display} . "' Metrics "; } sub long_output { my ($self, %options) = @_; return "Checking Function '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metrics', type => 3, cb_prefix_output => 'prefix_metric_output', cb_long_output => 'long_output', message_multiple => 'All functions metrics are ok', indent_long_output => ' ', group => [ { name => 'statistics', display_long => 1, cb_prefix_output => 'prefix_statistics_output', message_multiple => 'All metrics are ok', type => 1, skipped_code => { -10 => 1 } }, ] } ]; foreach my $metric (keys %metrics_mapping) { my $entry = { label => $metrics_mapping{$metric}->{label}, nlabel => $metrics_mapping{$metric}->{nlabel}, set => { key_values => [ { name => $metric }, { name => 'display' } ], output_template => $metrics_mapping{$metric}->{output} . ': %.2f', perfdatas => [ { value => $metric , template => '%.2f', label_extra_instance => 1 } ], } }; push @{$self->{maps_counters}->{statistics}}, $entry; } } 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 => { "name:s@" => { name => 'name' }, "filter-metric:s" => { name => 'filter_metric' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Sum', 'Average']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %metrics_mapping) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/Lambda', dimensions => [ { Name => 'FunctionName', Value => $instance } ], metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period} ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{$instance}->{display} = $instance; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{display} = $statistic; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{timeframe} = $self->{aws_timeframe}; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{$metric} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check Lambda invocations metrics. Example: perl centreon_plugins.pl --plugin=cloud::aws::lambda::plugin --custommode=paws --mode=invocations --region='eu-west-1' --name='myFunction' --filter-metric='Duration' --statistic='average' --critical-duration='10' --verbose See 'https://docs.aws.amazon.com/lambda/latest/dg/monitoring-functions-metrics.html' for more informations. Default statistic: 'sum', 'average'. =over 8 =item B<--name> Set the function name (Required) (Can be multiple). =item B<--filter-metric> Filter metrics (Can be: 'Duration', 'Invocations', 'Errors', 'DeadLetterErrors', 'Throttles', 'IteratorAge') (Can be a regexp). =item B<--warning-*> Thresholds warning (Can be: 'invocations', 'errors', 'throttles', 'duration', 'deadlettererrors', 'iteratorage'). =item B<--critical-*> Thresholds critical (Can be: 'invocations', 'errors', 'throttles', 'duration', 'deadlettererrors', 'iteratorage'). =back =cut centreon-plugins-20220113/cloud/aws/lambda/plugin.pm000066400000000000000000000025361417000230700222160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::lambda::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} } = ( 'invocations' => 'cloud::aws::lambda::mode::invocations', ); $self->{custom_modes}{paws} = 'cloud::aws::custom::paws'; $self->{custom_modes}{awscli} = 'cloud::aws::custom::awscli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Amazon Lambda. =cut centreon-plugins-20220113/cloud/aws/rds/000077500000000000000000000000001417000230700177245ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/rds/mode/000077500000000000000000000000001417000230700206505ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/rds/mode/connections.pm000066400000000000000000000166161417000230700235420ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::rds::mode::connections; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my %map_type = ( "instance" => "DBInstanceIdentifier", "cluster" => "DBClusterIdentifier", ); sub prefix_metric_output { my ($self, %options) = @_; return ucfirst($options{instance_value}->{type}) . " '" . $options{instance_value}->{display} . "' " . $options{instance_value}->{stat} . " "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All database metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $statistic ('minimum', 'maximum', 'average', 'sum') { foreach my $metric ('DatabaseConnections') { my $entry = { label => lc($metric) . '-' . lc($statistic), set => { key_values => [ { name => $metric . '_' . $statistic }, { name => 'display' }, { name => 'type' }, { name => 'stat' } ], output_template => $metric . ': %d', perfdatas => [ { label => lc($metric) . '_' . lc($statistic), value => $metric . '_' . $statistic , template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "type:s" => { name => 'type' }, "name:s@" => { name => 'name' }, "filter-metric:s" => { name => 'filter_metric' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{type}) || $self->{option_results}->{type} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --type option."); $self->{output}->option_exit(); } if ($self->{option_results}->{type} ne 'cluster' && $self->{option_results}->{type} ne 'instance') { $self->{output}->add_option_msg(short_msg => "Instance type '" . $self->{option_results}->{type} . "' is not handled for this mode"); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Average']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } foreach my $metric ('DatabaseConnections') { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/RDS', dimensions => [ { Name => $map_type{$self->{option_results}->{type}}, Value => $instance } ], metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period} ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$instance . "_" . lc($statistic)}->{display} = $instance; $self->{metric}->{$instance . "_" . lc($statistic)}->{stat} = lc($statistic); $self->{metric}->{$instance . "_" . lc($statistic)}->{type} = $self->{option_results}->{type}; $self->{metric}->{$instance . "_" . lc($statistic)}->{$metric . "_" . lc($statistic)} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check RDS instances database connections. Example: perl centreon_plugins.pl --plugin=cloud::aws::rds::plugin --custommode=paws --mode=connections --region='eu-west-1' --type='cluster' --name='centreon-db-ppd-cluster' --filter-metric='DatabaseConnections' --statistic='sum' --critical-databaseconnections-sum='10' --verbose Works for the following database engines : aurora, mysql, mariadb. See 'https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/rds-metricscollected.html' for more informations. Default statistic: 'average' / All satistics are valid. =over 8 =item B<--type> Set the instance type (Required) (Can be: 'cluster', 'instance'). =item B<--name> Set the instance name (Required) (Can be multiple). =item B<--filter-metric> Filter metrics (Can be: 'DatabaseConnections') (Can be a regexp). =item B<--warning-$metric$-$statistic$> Thresholds warning ($metric$ can be: 'databaseconnections' $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =item B<--critical-$metric$-$statistic$> Thresholds warning ($metric$ can be: 'databaseconnections' $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =back =cut centreon-plugins-20220113/cloud/aws/rds/mode/cpu.pm000066400000000000000000000205061417000230700220000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::rds::mode::cpu; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my %map_type = ( "instance" => "DBInstanceIdentifier", "cluster" => "DBClusterIdentifier", ); sub prefix_metric_output { my ($self, %options) = @_; return ucfirst($options{instance_value}->{type}) . " '" . $options{instance_value}->{display} . "' " . $options{instance_value}->{stat} . " "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All CPU metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $statistic ('minimum', 'maximum', 'average', 'sum') { foreach my $metric ('CPUCreditBalance', 'CPUCreditUsage') { my $entry = { label => lc($metric) . '-' . lc($statistic), set => { key_values => [ { name => $metric . '_' . $statistic }, { name => 'display' }, { name => 'type' }, { name => 'stat' } ], output_template => $metric . ': %.2f', perfdatas => [ { label => lc($metric) . '_' . lc($statistic), value => $metric . '_' . $statistic , template => '%.2f', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } foreach my $metric ('CPUUtilization') { my $entry = { label => lc($metric) . '-' . lc($statistic), set => { key_values => [ { name => $metric . '_' . $statistic }, { name => 'display' }, { name => 'type' }, { name => 'stat' } ], output_template => $metric . ': %.2f %%', perfdatas => [ { label => lc($metric) . '_' . lc($statistic), value => $metric . '_' . $statistic , template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1, instance_use => 'display' }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "type:s" => { name => 'type' }, "name:s@" => { name => 'name' }, "filter-metric:s" => { name => 'filter_metric' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{type}) || $self->{option_results}->{type} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --type option."); $self->{output}->option_exit(); } if ($self->{option_results}->{type} ne 'cluster' && $self->{option_results}->{type} ne 'instance') { $self->{output}->add_option_msg(short_msg => "Instance type '" . $self->{option_results}->{type} . "' is not handled for this mode"); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_statistics} = ['Average']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } foreach my $metric ('CPUCreditBalance', 'CPUCreditUsage', 'CPUUtilization') { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/RDS', dimensions => [ { Name => $map_type{$self->{option_results}->{type}}, Value => $instance } ], metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period} ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$instance . "_" . lc($statistic)}->{display} = $instance; $self->{metric}->{$instance . "_" . lc($statistic)}->{stat} = lc($statistic); $self->{metric}->{$instance . "_" . lc($statistic)}->{type} = $self->{option_results}->{type}; $self->{metric}->{$instance . "_" . lc($statistic)}->{$metric . "_" . lc($statistic)} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check RDS instances CPU metrics. Example: perl centreon_plugins.pl --plugin=cloud::aws::rds::plugin --custommode=paws --mode=cpu --region='eu-west-1' --type='cluster' --name='centreon-db-ppd-cluster' --filter-metric='Credit' --statistic='average' --critical-cpucreditusage-average='10' --verbose Works for the following database engines : aurora, mysql, mariadb. See 'https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/rds-metricscollected.html' for more informations. Default statistic: 'average' / All satistics are valid. =over 8 =item B<--type> Set the instance type (Required) (Can be: 'cluster', 'instance'). =item B<--name> Set the instance name (Required) (Can be multiple). =item B<--filter-metric> Filter metrics (Can be: 'CPUCreditBalance', 'CPUCreditUsage', CPUUtilization') (Can be a regexp). =item B<--warning-$metric$-$statistic$> Thresholds warning ($metric$ can be: 'cpucreditusage', 'cpucreditbalance', 'cpuutilization', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =item B<--critical-$metric$-$statistic$> Thresholds critical ($metric$ can be: 'cpucreditusage', 'cpucreditbalance', 'cpuutilization', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =back =cut centreon-plugins-20220113/cloud/aws/rds/mode/discovery.pm000066400000000000000000000065121417000230700232210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::rds::mode::discovery; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "prettify" => { name => 'prettify' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my @disco_data; my $disco_stats; $disco_stats->{start_time} = time(); my $db_instances = $options{custom}->discovery( service => 'rds', command => 'describe-db-instances' ); foreach my $db_instance (@{$db_instances->{DBInstances}}) { next if (!defined($db_instance->{DbiResourceId})); my %rds; $rds{type} = "rds"; $rds{id} = $db_instance->{DbiResourceId}; $rds{name} = $db_instance->{DBInstanceIdentifier}; $rds{status} = $db_instance->{DBInstanceStatus}; $rds{storage_type} = $db_instance->{StorageType}; $rds{instance_class} = $db_instance->{DBInstanceClass}; $rds{availability_zone} = $db_instance->{AvailabilityZone}; $rds{vpc_id} = $db_instance->{DBSubnetGroup}->{VpcId}; $rds{engine} = $db_instance->{Engine}; $rds{engine_version} = $db_instance->{EngineVersion}; $rds{db_name} = $db_instance->{DBName}; $rds{endpoint_host_zone_id} = $db_instance->{Endpoint}->{HostedZoneId}; $rds{endpoint_port} = $db_instance->{Endpoint}->{Port}; $rds{endpoint_address} = $db_instance->{Endpoint}->{Address}; push @disco_data, \%rds; } $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; $disco_stats->{discovered_items} = @disco_data; $disco_stats->{results} = \@disco_data; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE RDS discovery. =over 8 =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/aws/rds/mode/diskio.pm000066400000000000000000000243241417000230700224750ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::rds::mode::diskio; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my %map_type = ( "instance" => "DBInstanceIdentifier", "cluster" => "DBClusterIdentifier", ); sub prefix_metric_output { my ($self, %options) = @_; return ucfirst($options{instance_value}->{type}) . " '" . $options{instance_value}->{display} . "' " . $options{instance_value}->{stat} . " "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All disk metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $statistic ('minimum', 'maximum', 'average', 'sum') { foreach my $metric ('ReadThroughput', 'WriteThroughput') { my $entry = { label => lc($metric) . '-' . lc($statistic), set => { key_values => [ { name => $metric . '_' . $statistic }, { name => 'display' }, { name => 'type' }, { name => 'stat' } ], output_template => $metric . ': %.2f %s/s', output_change_bytes => 1, perfdatas => [ { label => lc($metric) . '_' . lc($statistic), value => $metric . '_' . $statistic , template => '%.2f', unit => 'B/s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } foreach my $metric ('ReadIOPS', 'WriteIOPS') { my $entry = { label => lc($metric) . '-' . lc($statistic), set => { key_values => [ { name => $metric . '_' . $statistic }, { name => 'display' }, { name => 'type' }, { name => 'stat' } ], output_template => $metric . ': %.2f iops', perfdatas => [ { label => lc($metric) . '_' . lc($statistic), value => $metric . '_' . $statistic , template => '%.2f', unit => 'iops', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } foreach my $metric ('ReadLatency', 'WriteLatency') { my $entry = { label => lc($metric) . '-' . lc($statistic), set => { key_values => [ { name => $metric . '_' . $statistic }, { name => 'display' }, { name => 'type' }, { name => 'stat' } ], output_template => $metric . ': %.2f s', perfdatas => [ { label => lc($metric) . '_' . lc($statistic), value => $metric . '_' . $statistic , template => '%.2f', unit => 's', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } foreach my $metric ('DiskQueueDepth') { my $entry = { label => lc($metric) . '-' . lc($statistic), set => { key_values => [ { name => $metric . '_' . $statistic }, { name => 'display' }, { name => 'type' }, { name => 'stat' } ], output_template => $metric . ': %d', perfdatas => [ { label => lc($metric) . '_' . lc($statistic), value => $metric . '_' . $statistic , template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "type:s" => { name => 'type' }, "name:s@" => { name => 'name' }, "filter-metric:s" => { name => 'filter_metric' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{type}) || $self->{option_results}->{type} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --type option."); $self->{output}->option_exit(); } if ($self->{option_results}->{type} ne 'cluster' && $self->{option_results}->{type} ne 'instance') { $self->{output}->add_option_msg(short_msg => "Instance type '" . $self->{option_results}->{type} . "' is not handled for this mode"); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Average']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } foreach my $metric ('ReadThroughput', 'WriteThroughput', 'ReadIOPS', 'WriteIOPS', 'ReadLatency', 'WriteLatency', 'DiskQueueDepth') { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/RDS', dimensions => [ { Name => $map_type{$self->{option_results}->{type}}, Value => $instance } ], metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period}, ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$instance . "_" . lc($statistic)}->{display} = $instance; $self->{metric}->{$instance . "_" . lc($statistic)}->{stat} = lc($statistic); $self->{metric}->{$instance . "_" . lc($statistic)}->{type} = $self->{option_results}->{type}; $self->{metric}->{$instance . "_" . lc($statistic)}->{$metric . "_" . lc($statistic)} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check RDS instances disk IO metrics. Example: perl centreon_plugins.pl --plugin=cloud::aws::rds::plugin --custommode=paws --mode=diskio --region='eu-west-1' --type='cluster' --name='centreon-db-ppd-cluster' --filter-metric='Read' --statistic='sum' --critical-readiops-sum='10' --verbose Works for the following database engines : mysql, mariadb. See 'https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/rds-metricscollected.html' for more informations. Default statistic: 'average' / All satistics are valid. =over 8 =item B<--type> Set the instance type (Required) (Can be: 'cluster', 'instance'). =item B<--name> Set the instance name (Required) (Can be multiple). =item B<--filter-metric> Filter metrics (Can be: 'ReadThroughput', 'WriteThroughput', 'ReadIOPS', 'WriteIOPS', 'ReadLatency', 'WriteLatency', 'DiskQueueDepth') (Can be a regexp). =item B<--warning-$metric$-$statistic$> Thresholds warning ($metric$ can be: 'readthroughput', 'writethroughput', 'readiops', 'writeiops', 'readlatency', 'writelatency', 'diskqueuedepth', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =item B<--critical-$metric$-$statistic$> Thresholds critical ($metric$ can be: 'readthroughput', 'writethroughput', 'readiops', 'writeiops', 'readlatency', 'writelatency', 'diskqueuedepth', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =back =cut centreon-plugins-20220113/cloud/aws/rds/mode/instancestatus.pm000066400000000000000000000161331417000230700242620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::rds::mode::instancestatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf('state : %s', $self->{result_values}->{health}, $self->{result_values}->{replication_health}); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{state} = $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 => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }, { name => 'aws_instances', type => 1, cb_prefix_output => 'prefix_awsinstance_output', message_multiple => 'All instances are ok' }, ]; $self->{maps_counters}->{global} = [ { label => 'total-available', set => { key_values => [ { name => 'available' } ], output_template => "available : %s", perfdatas => [ { label => 'total_available', value => 'available', template => '%d', min => 0 }, ], } }, { label => 'total-failed', set => { key_values => [ { name => 'failed' } ], output_template => "failed : %s", perfdatas => [ { label => 'total_failed', value => 'failed', template => '%d', min => 0 }, ], } }, { label => 'total-backing-up', set => { key_values => [ { name => 'backing-up' } ], output_template => "backing-up : %s", perfdatas => [ { label => 'total_backing_up', value => 'backing-up', template => '%d', min => 0 }, ], } }, { label => 'total-maintenance', set => { key_values => [ { name => 'maintenance' } ], output_template => "maintenance : %s", perfdatas => [ { label => 'total_maintenance', value => 'maintenance', template => '%d', min => 0 }, ], } }, { label => 'total-stopped', set => { key_values => [ { name => 'stopped' } ], output_template => "stopped : %s", perfdatas => [ { label => 'total_stopped', value => 'stopped', template => '%d', min => 0 }, ], } }, { label => 'total-storage-full', set => { key_values => [ { name => 'storage-full' } ], output_template => "storage-full : %s", perfdatas => [ { label => 'total_storage_full', value => 'storage-full', template => '%d', min => 0 }, ], } }, ]; $self->{maps_counters}->{aws_instances} = [ { 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 => \&catalog_status_threshold, } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-instanceid:s" => { name => 'filter_instanceid' }, "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); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub prefix_global_output { my ($self, %options) = @_; return "Total instances "; } sub prefix_awsinstance_output { my ($self, %options) = @_; return "Instance '" . $options{instance_value}->{display} . "' "; } sub manage_selection { my ($self, %options) = @_; $self->{global} = { available => 0, 'backing-up' => 0, failed => 0, maintenance => 0, stopped => 0, 'storage-full' => 0, }; $self->{aws_instances} = {}; my $result = $options{custom}->rds_get_instances_status(); foreach my $instance_id (keys %{$result}) { if (defined($self->{option_results}->{filter_instanceid}) && $self->{option_results}->{filter_instanceid} ne '' && $instance_id !~ /$self->{option_results}->{filter_instanceid}/) { $self->{output}->output_add(long_msg => "skipping '" . $instance_id . "': no matching filter.", debug => 1); next; } $self->{aws_instances}->{$instance_id} = { display => $instance_id, state => $result->{$instance_id}->{state}, }; $self->{global}->{$result->{$instance_id}->{state}}++ if (defined($self->{global}->{$result->{$instance_id}->{state}})); } if (scalar(keys %{$self->{aws_instances}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No aws rds instance found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check RDS instances status. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^total-available$' =item B<--filter-instanceid> Filter by instance id (can be a regexp). =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{state}, %{display} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{state}, %{display} =item B<--warning-*> Threshold warning. Can be: 'total-available', 'total-backing-up', 'total-failed', 'total-maintenance', 'total-stopped', 'total-storage-full'. =item B<--critical-*> Threshold critical. Can be: 'total-available', 'total-backing-up', 'total-failed', 'total-maintenance', 'total-stopped', 'total-storage-full'. =back =cut centreon-plugins-20220113/cloud/aws/rds/mode/listclusters.pm000066400000000000000000000046731417000230700237600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::rds::mode::listclusters; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{instances} = $options{custom}->rds_list_clusters(); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach (@{$self->{instances}}) { $self->{output}->output_add(long_msg => sprintf("[Name = %s][DatabaseName = %s][Engine = %s][Status = %s]", $_->{Name}, $_->{DatabaseName}, $_->{Engine}, $_->{Status})); } $self->{output}->output_add(severity => 'OK', short_msg => 'List cluster:'); $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', 'databasename', 'engine', 'status']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach (@{$self->{instances}}) { $self->{output}->add_disco_entry( name => $_->{Name}, databasename => $_->{DatabaseName}, engine => $_->{Engine}, status => $_->{Status}, ); } } 1; __END__ =head1 MODE List RDS clusters. =over 8 =back =cut centreon-plugins-20220113/cloud/aws/rds/mode/listinstances.pm000066400000000000000000000051221417000230700240710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::rds::mode::listinstances; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{instances} = $options{custom}->rds_list_instances(); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach (@{$self->{instances}}) { $self->{output}->output_add(long_msg => sprintf("[Name = %s][AvailabilityZone = %s][Engine = %s][StorageType = %s][DBInstanceStatus = %s]", $_->{Name}, $_->{AvailabilityZone}, $_->{Engine}, $_->{StorageType}, $_->{DBInstanceStatus})); } $self->{output}->output_add(severity => 'OK', short_msg => 'List instances:'); $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', 'availabilityzone', 'engine', 'storagetype', 'state']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach (@{$self->{instances}}) { $self->{output}->add_disco_entry( name => $_->{Name}, availabilityzone => $_->{AvailabilityZone}, engine => $_->{Engine}, storagetype => $_->{StorageType}, state => $_->{DBInstanceStatus}, ); } } 1; __END__ =head1 MODE List RDS instances. =over 8 =back =cut centreon-plugins-20220113/cloud/aws/rds/mode/network.pm000066400000000000000000000167341417000230700227120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::rds::mode::network; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my %map_type = ( "instance" => "DBInstanceIdentifier", "cluster" => "DBClusterIdentifier", ); sub prefix_metric_output { my ($self, %options) = @_; return ucfirst($options{instance_value}->{type}) . " '" . $options{instance_value}->{display} . "' " . $options{instance_value}->{stat} . " "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All network metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $statistic ('minimum', 'maximum', 'average', 'sum') { foreach my $metric ('NetworkReceiveThroughput', 'NetworkTransmitThroughput') { my $entry = { label => lc($metric) . '-' . lc($statistic), set => { key_values => [ { name => $metric . '_' . $statistic }, { name => 'display' }, { name => 'type' }, { name => 'stat' } ], output_template => $metric . ': %.2f %s/s', output_change_bytes => 1, perfdatas => [ { label => lc($metric) . '_' . lc($statistic), value => $metric . '_' . $statistic , template => '%.2f', unit => 'B/s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'type:s' => { name => 'type' }, 'name:s@' => { name => 'name' }, 'filter-metric:s' => { name => 'filter_metric' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{type}) || $self->{option_results}->{type} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --type option."); $self->{output}->option_exit(); } if ($self->{option_results}->{type} ne 'cluster' && $self->{option_results}->{type} ne 'instance') { $self->{output}->add_option_msg(short_msg => "Instance type '" . $self->{option_results}->{type} . "' is not handled for this mode"); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Average']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } foreach my $metric ('NetworkReceiveThroughput', 'NetworkTransmitThroughput') { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/RDS', dimensions => [ { Name => $map_type{$self->{option_results}->{type}}, Value => $instance } ], metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period}, ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$instance . "_" . lc($statistic)}->{display} = $instance; $self->{metric}->{$instance . "_" . lc($statistic)}->{stat} = lc($statistic); $self->{metric}->{$instance . "_" . lc($statistic)}->{type} = $self->{option_results}->{type}; $self->{metric}->{$instance . "_" . lc($statistic)}->{$metric . "_" . lc($statistic)} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check RDS instances network metrics. Example: perl centreon_plugins.pl --plugin=cloud::aws::rds::plugin --custommode=paws --mode=network --region='eu-west-1' --type='cluster' --name='centreon-db-ppd-cluster' --filter-metric='Transmit' --statistic='sum' --critical-networktransmitthroughput-sum='10' --verbose Works for the following database engines : aurora, mysql, mariadb. See 'https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/MonitoringOverview.html' for more informations. Default statistic: 'average' / All statistics are valid. =over 8 =item B<--type> Set the instance type (Required) (Can be: 'cluster', 'instance'). =item B<--name> Set the instance name (Required) (Can be multiple). =item B<--filter-metric> Filter metrics (Can be: 'NetworkReceiveThroughput', 'NetworkTransmitThroughput') (Can be a regexp). =item B<--warning-$metric$-$statistic$> Thresholds warning ($metric$ can be: 'networkreceivethroughput', 'networktransmitthroughput', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =item B<--critical-$metric$-$statistic$> Thresholds warning ($metric$ can be: 'networkreceivethroughput', 'networktransmitthroughput', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =back =cut centreon-plugins-20220113/cloud/aws/rds/mode/queries.pm000066400000000000000000000222161417000230700226660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::rds::mode::queries; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my %map_type = ( "instance" => "DBInstanceIdentifier", "cluster" => "DBClusterIdentifier", ); sub prefix_metric_output { my ($self, %options) = @_; return ucfirst($options{instance_value}->{type}) . " '" . $options{instance_value}->{display} . "' " . $options{instance_value}->{stat} . " "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All queries metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $statistic ('minimum', 'maximum', 'average', 'sum') { foreach my $metric ('Queries', 'InsertThroughput', 'DeleteThroughput', 'SelectThroughput', 'UpdateThroughput', 'DMLThroughput', 'DDLThroughput') { my $entry = { label => lc($metric) . '-' . lc($statistic), set => { key_values => [ { name => $metric . '_' . $statistic }, { name => 'display' }, { name => 'type' }, { name => 'stat' } ], output_template => $metric . ': %d queries/s', perfdatas => [ { label => lc($metric) . '_' . lc($statistic), value => $metric . '_' . $statistic , template => '%d', unit => 'queries/s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } foreach my $metric ('InsertLatency', 'DeleteLatency', 'SelectLatency', 'UpdateLatency', 'DMLLatency', 'DDLLatency') { my $entry = { label => lc($metric) . '-' . lc($statistic), set => { key_values => [ { name => $metric . '_' . $statistic }, { name => 'display' }, { name => 'type' }, { name => 'stat' } ], output_template => $metric . ': %.2f ms', perfdatas => [ { label => lc($metric) . '_' . lc($statistic), value => $metric . '_' . $statistic , template => '%.2f', unit => 'ms', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "type:s" => { name => 'type' }, "name:s@" => { name => 'name' }, "filter-metric:s" => { name => 'filter_metric' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{type}) || $self->{option_results}->{type} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --type option."); $self->{output}->option_exit(); } if ($self->{option_results}->{type} ne 'cluster' && $self->{option_results}->{type} ne 'instance') { $self->{output}->add_option_msg(short_msg => "Instance type '" . $self->{option_results}->{type} . "' is not handled for this mode"); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Average']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } foreach my $metric ('Queries', 'InsertThroughput', 'DeleteThroughput', 'SelectThroughput', 'UpdateThroughput', 'DMLThroughput', 'DDLThroughput', 'InsertLatency', 'DeleteLatency', 'SelectLatency', 'UpdateLatency', 'DMLLatency', 'DDLLatency') { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/RDS', dimensions => [ { Name => $map_type{$self->{option_results}->{type}}, Value => $instance } ], metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period}, ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$instance . "_" . lc($statistic)}->{display} = $instance; $self->{metric}->{$instance . "_" . lc($statistic)}->{stat} = lc($statistic); $self->{metric}->{$instance . "_" . lc($statistic)}->{type} = $self->{option_results}->{type}; $self->{metric}->{$instance . "_" . lc($statistic)}->{$metric . "_" . lc($statistic)} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check RDS instances queries per second. Example: perl centreon_plugins.pl --plugin=cloud::aws::rds::plugin --custommode=paws --mode=queries --region='eu-west-1' --type='instance' --name='centreon-db-ppd' --filter-metric='' --statistic='average' --critical-queries-average='10' --verbose Works for the following database engines : aurora. See 'https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/rds-metricscollected.html' for more informations. Default statistic: 'average' / All satistics are valid. =over 8 =item B<--type> Set the instance type (Required) (Can be: 'cluster', 'instance'). =item B<--name> Set the instance name (Required) (Can be multiple). =item B<--filter-metric> Filter metrics (Can be: 'Queries', 'InsertThroughput', 'DeleteThroughput', 'SelectThroughput', 'UpdateThroughput', 'DMLThroughput', 'DDLThroughput', 'InsertLatency', 'DeleteLatency', 'SelectLatency', 'UpdateLatency', 'DMLLatency', 'DDLLatency') (Can be a regexp). =item B<--warning-$metric$-$statistic$> Thresholds warning ($metric$ can be: 'queries', 'insertthroughput', 'deletethroughput', 'selectthroughput', 'updatethroughput', 'dmlthroughput', 'ddlthroughput', 'insertlatency', 'deletelatency', 'selectlatency', 'updatelatency', 'dmllatency', 'ddllatency', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =item B<--critical-$metric$-$statistic$> Thresholds critical ($metric$ can be: 'queries', 'insertthroughput', 'deletethroughput', 'selectthroughput', 'updatethroughput', 'dmlthroughput', 'ddlthroughput', 'insertlatency', 'deletelatency', 'selectlatency', 'updatelatency', 'dmllatency', 'ddllatency', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =back =cut centreon-plugins-20220113/cloud/aws/rds/mode/storage.pm000066400000000000000000000324331417000230700226570ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::rds::mode::storage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my $metrics_mapping = { FreeStorageSpace => { output => 'storage space free', label => 'storage-space-free', nlabel => { absolute => 'storage.space.free.bytes' }, unit => 'B' }, FreeStorageSpacePrct => { output => 'storage space usage', label => 'storage-space-usage-prct', nlabel => { absolute => 'storage.space.usage.percentage' }, unit => '%', cw_metric => 0 }, FreeableMemory => { output => 'memory free', label => 'memory-free', nlabel => { absolute => 'memory.free.bytes' }, unit => 'B' } }; my $map_type = { instance => 'DBInstanceIdentifier', cluster => 'DBClusterIdentifier' }; sub custom_metric_calc { my ($self, %options) = @_; $self->{result_values}->{timeframe} = $options{new_datas}->{$self->{instance} . '_timeframe'}; $self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{metric}}; $self->{result_values}->{metric} = $options{extra_options}->{metric}; return 0; } sub custom_metric_threshold { my ($self, %options) = @_; return $self->{perfdata}->threshold_check( value => $self->{result_values}->{value}, threshold => [ { label => 'critical-' . $metrics_mapping->{ $self->{result_values}->{metric} }->{label} , exit_litteral => 'critical' }, { label => 'warning-' . $metrics_mapping->{ $self->{result_values}->{metric} }->{label}, exit_litteral => 'warning' } ] ); } sub custom_metric_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( instances => $self->{instance}, nlabel => $metrics_mapping->{ $self->{result_values}->{metric} }->{nlabel}->{absolute}, unit => $metrics_mapping->{ $self->{result_values}->{metric} }->{unit}, value => sprintf('%.2f', $self->{result_values}->{value}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $metrics_mapping->{ $self->{result_values}->{metric} }->{label}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $metrics_mapping->{ $self->{result_values}->{metric} }->{label}) ); } sub custom_metric_output { my ($self, %options) = @_; my ($value, $unit) = ($metrics_mapping->{ $self->{result_values}->{metric} }->{unit} eq 'B') ? $self->{perfdata}->change_bytes(value => $self->{result_values}->{value}) : ($self->{result_values}->{value}, $metrics_mapping->{ $self->{result_values}->{metric} }->{unit}); return sprintf("%s: %.2f %s", $metrics_mapping->{ $self->{result_values}->{metric} }->{output}, $value, $unit); } sub prefix_metric_output { my ($self, %options) = @_; return "'" . $options{instance_value}->{display} . "' "; } sub prefix_statistics_output { my ($self, %options) = @_; return "statistic '" . $options{instance_value}->{display} . "' metrics "; } sub long_output { my ($self, %options) = @_; return "AWS RDS '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metrics', type => 3, cb_prefix_output => 'prefix_metric_output', cb_long_output => 'long_output', message_multiple => 'All storage metrics are ok', indent_long_output => ' ', group => [ { name => 'statistics', display_long => 1, cb_prefix_output => 'prefix_statistics_output', message_multiple => 'All metrics are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; foreach my $metric (keys %$metrics_mapping) { my $entry = { label => $metrics_mapping->{$metric}->{label}, set => { key_values => [ { name => $metric }, { name => 'timeframe' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_metric_calc'), closure_custom_calc_extra_options => { metric => $metric }, 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') } }; push @{$self->{maps_counters}->{statistics}}, $entry; } } 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 => { 'type:s' => { name => 'type' }, 'name:s@' => { name => 'name' }, 'filter-metric:s' => { name => 'filter_metric' }, 'add-space-usage-percent' => { name => 'add_space_usage_percent' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{type}) || $self->{option_results}->{type} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --type option."); $self->{output}->option_exit(); } if (!defined($map_type->{ $self->{option_results}->{type} })) { $self->{output}->add_option_msg(short_msg => "Instance type '" . $self->{option_results}->{type} . "' is not handled for this mode"); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Average']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } }; foreach my $metric (keys %$metrics_mapping) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); next if (defined($metrics_mapping->{$metric}->{cw_metric}) && $metrics_mapping->{$metric}->{cw_metric} == 0); push @{$self->{aws_metrics}}, $metric; # For Aurora instance if ($metric eq 'FreeStorageSpace') { push @{$self->{aws_metrics}}, 'FreeLocalStorage'; } }; } sub add_metric { my ($self, %options) = @_; return if ( !defined($options{metric_value}) && !defined($self->{option_results}->{zeroed}) ); if (!defined($self->{metrics}->{ $options{instance} })) { $self->{metrics}->{ $options{instance} } = { display => $options{instance}, statistics => {} }; } $self->{metrics}->{ $options{instance} }->{statistics}->{ $options{statistic} }->{display} = $options{statistic}; $self->{metrics}->{ $options{instance} }->{statistics}->{ $options{statistic} }->{timeframe} = $self->{aws_timeframe}; $self->{metrics}->{ $options{instance} }->{statistics}->{ $options{statistic} }->{ $options{metric} } = defined($options{metric_value}) ? $options{metric_value} : 0; if (defined($metrics_mapping->{ $options{metric} }->{calc})) { $self->{metrics}->{ $options{instance} }->{statistics}->{ $options{statistic} }->{ $options{metric} } = eval $self->{metrics}->{ $options{instance} }->{statistics}->{ $options{statistic} }->{ $options{metric} } . $metrics_mapping->{ $options{metric} }->{calc}; } } sub add_metric_space_usage_percent { my ($self, %options) = @_; my $total_space; foreach (@{$options{list_rds_instances}}) { if ($_->{Name} eq $options{instance}) { $total_space = $_->{AllocatedStorage} * 1024 * 1024 * 1024; last; } } return if (!defined($total_space) || $total_space <= 0); my $space_usage = 100 - ($options{free_storage} * 100 / $total_space); $self->add_metric( metric_value => $space_usage, instance => $options{instance}, metric => 'FreeStorageSpacePrct', statistic => $options{statistic} ); } sub manage_selection { my ($self, %options) = @_; my $list_rds_instances; if (defined($self->{option_results}->{add_space_usage_percent})) { if ($self->{option_results}->{type} eq 'instance') { $list_rds_instances = $options{custom}->rds_list_instances(); } else { $list_rds_instances = $options{custom}->rds_list_clusters(); } } foreach my $instance (@{$self->{aws_instance}}) { my $metric_results = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/RDS', dimensions => [ { Name => $map_type->{ $self->{option_results}->{type} }, Value => $instance } ], metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period} ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { if ($metric eq 'FreeStorageSpace' && !defined($metric_results->{$metric}->{lc($statistic)})) { $self->add_metric( metric_value => $metric_results->{FreeLocalStorage}->{lc($statistic)}, instance => $instance, metric => 'FreeStorageSpace', statistic => lc($statistic) ); } else { $self->add_metric( metric_value => $metric_results->{$metric}->{lc($statistic)}, instance => $instance, metric => $metric, statistic => lc($statistic) ); } if (defined($self->{option_results}->{add_space_usage_percent}) && $metric eq 'FreeStorageSpace' && defined($self->{metrics}->{$instance}->{statistics}->{lc($statistic)})) { $self->add_metric_space_usage_percent( list_rds_instances => $list_rds_instances, free_storage => $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{$metric}, instance => $instance, metric => $metric, statistic => lc($statistic) ); } } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check RDS instances storage metrics. Example: perl centreon_plugins.pl --plugin=cloud::aws::rds::plugin --custommode=paws --mode=storage --region='eu-west-1' --type='cluster' --name='centreon-db-ppd-cluster' --filter-metric='FreeStorageSpace' --statistic='average' --critical-freestoragespace-average='10G:' --verbose Works for the following database engines : aurora, mysql, mariadb. See 'https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/MonitoringOverview.html' for more informations. Default statistic: 'average' / All statistics are valid. =over 8 =item B<--type> Set the instance type (Required) (Can be: 'cluster', 'instance'). =item B<--name> Set the instance name (Required) (Can be multiple). =item B<--filter-metric> Filter on a specific metric. Can be: FreeStorageSpace, FreeableMemory. =item B<--add-space-usage-percent> Check storage usage space percentage (need privileges to describe rds). =item B<--warning-$metric$> B<--critical-$metric$> Thresholds ($metric$ can be: 'storage-space-free', 'storage-space-usage-prct', 'memory-free'). =back =cut centreon-plugins-20220113/cloud/aws/rds/mode/transactions.pm000066400000000000000000000207311417000230700237210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::rds::mode::transactions; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my %map_type = ( "instance" => "DBInstanceIdentifier", "cluster" => "DBClusterIdentifier", ); sub prefix_metric_output { my ($self, %options) = @_; return ucfirst($options{instance_value}->{type}) . " '" . $options{instance_value}->{display} . "' " . $options{instance_value}->{stat} . " "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All transactions metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $statistic ('minimum', 'maximum', 'average', 'sum') { foreach my $metric ('ActiveTransactions', 'BlockedTransactions', 'CommitThroughput') { my $entry = { label => lc($metric) . '-' . lc($statistic), set => { key_values => [ { name => $metric . '_' . $statistic }, { name => 'display' }, { name => 'type' }, { name => 'stat' } ], output_template => $metric . ': %d ops', perfdatas => [ { label => lc($metric) . '_' . lc($statistic), value => $metric . '_' . $statistic , template => '%d', unit => 'ops', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } foreach my $metric ('CommitLatency') { my $entry = { label => lc($metric) . '-' . lc($statistic), set => { key_values => [ { name => $metric . '_' . $statistic }, { name => 'display' }, { name => 'type' }, { name => 'stat' } ], output_template => $metric . ': %.2f ms', perfdatas => [ { label => lc($metric) . '_' . lc($statistic), value => $metric . '_' . $statistic , template => '%.2f', unit => 'ms', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "type:s" => { name => 'type' }, "name:s@" => { name => 'name' }, "filter-metric:s" => { name => 'filter_metric' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{type}) || $self->{option_results}->{type} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --type option."); $self->{output}->option_exit(); } if ($self->{option_results}->{type} ne 'cluster' && $self->{option_results}->{type} ne 'instance') { $self->{output}->add_option_msg(short_msg => "Instance type '" . $self->{option_results}->{type} . "' is not handled for this mode"); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Average']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } foreach my $metric ('ActiveTransactions', 'BlockedTransactions', 'CommitThroughput', 'CommitLatency') { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/RDS', dimensions => [ { Name => $map_type{$self->{option_results}->{type}}, Value => $instance } ], metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period} ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$instance . "_" . lc($statistic)}->{display} = $instance; $self->{metric}->{$instance . "_" . lc($statistic)}->{stat} = lc($statistic); $self->{metric}->{$instance . "_" . lc($statistic)}->{type} = $self->{option_results}->{type}; $self->{metric}->{$instance . "_" . lc($statistic)}->{$metric . "_" . lc($statistic)} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check RDS instances transactions per second. Example: perl centreon_plugins.pl --plugin=cloud::aws::rds::plugin --custommode=paws --mode=transactions --region='eu-west-1' --type='instance' --name='centreon-db-ppd' --filter-metric='' --statistic='average' --critical-blockedtransactions-average='1' --verbose Works for the following database engines : aurora. See 'https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/rds-metricscollected.html' for more informations. Default statistic: 'average' / All satistics are valid. =over 8 =item B<--type> Set the instance type (Required) (Can be: 'cluster', 'instance'). =item B<--name> Set the instance name (Required) (Can be multiple). =item B<--filter-metric> Filter metrics (Can be: 'ActiveTransactions', 'BlockedTransactions', 'CommitThroughput', 'CommitLatency') (Can be a regexp). =item B<--warning-$metric$-$statistic$> Thresholds warning ($metric$ can be: 'activetransactions', 'blockedtransactions', 'committhroughput', 'commitlatency', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =item B<--critical-$metric$-$statistic$> Thresholds critical ($metric$ can be: 'activetransactions', 'blockedtransactions', 'committhroughput', 'commitlatency', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =back =cut centreon-plugins-20220113/cloud/aws/rds/mode/volume.pm000066400000000000000000000264331417000230700225250ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::rds::mode::volume; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my %map_type = ( "cluster" => "DbClusterIdentifier", ); sub prefix_metric_output { my ($self, %options) = @_; return ucfirst($options{instance_value}->{type}) . " '" . $options{instance_value}->{display} . "' " . $options{instance_value}->{stat} . " "; } sub custom_metric_calc { my ($self, %options) = @_; $self->{result_values}->{timeframe} = $options{new_datas}->{$self->{instance} . '_timeframe'}; $self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{metric} . '_' . $options{extra_options}->{stat}}; $self->{result_values}->{value_per_sec} = $self->{result_values}->{value} / $self->{result_values}->{timeframe}; $self->{result_values}->{stat} = $options{extra_options}->{stat}; $self->{result_values}->{metric} = $options{extra_options}->{metric}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub custom_metric_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check(value => defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}, threshold => [ { label => 'critical-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat}), exit_litteral => 'critical' }, { label => 'warning-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat}), exit_litteral => 'warning' } ]); return $exit; } sub custom_ops_perfdata { my ($self, %options) = @_; my $extra_label = ''; $extra_label = '_' . lc($self->{result_values}->{display}) if (!defined($options{extra_instance}) || $options{extra_instance} != 0); $self->{output}->perfdata_add(label => lc($self->{result_values}->{metric}) . "_" . lc($self->{result_values}->{stat}) . $extra_label, unit => defined($self->{instance_mode}->{option_results}->{per_sec}) ? 'ops/s' : 'ops', value => sprintf("%.2f", defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat})), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . lc($self->{result_values}->{metric}) . "-" . lc($self->{result_values}->{stat})), ); } sub custom_ops_output { my ($self, %options) = @_; my $msg =""; if (defined($self->{instance_mode}->{option_results}->{per_sec})) { $msg = sprintf("%s: %.2f ops/s", $self->{result_values}->{metric}, $self->{result_values}->{value_per_sec}); } else { $msg = sprintf("%s: %.2f ops", $self->{result_values}->{metric}, $self->{result_values}->{value}); } return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All volume metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $statistic ('minimum', 'maximum', 'average', 'sum') { foreach my $metric ('VolumeBytesUsed') { my $entry = { label => lc($metric) . '-' . lc($statistic), set => { key_values => [ { name => $metric . '_' . $statistic }, { name => 'display' }, { name => 'type' }, { name => 'stat' }, { name => 'timeframe' } ], output_template => $metric . ': %.2f %s', output_change_bytes => 1, perfdatas => [ { label => lc($metric) . '_' . lc($statistic), value => $metric . '_' . $statistic , template => '%.2f', unit => 'B', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } foreach my $metric ('VolumeReadIOPs', 'VolumeWriteIOPs') { my $entry = { label => lc($metric) . '-' . lc($statistic), set => { key_values => [ { name => $metric . '_' . $statistic }, { name => 'display' }, { name => 'stat' }, { name => 'timeframe' } ], closure_custom_calc => $self->can('custom_metric_calc'), closure_custom_calc_extra_options => { metric => $metric, stat => $statistic }, closure_custom_output => $self->can('custom_ops_output'), closure_custom_perfdata => $self->can('custom_ops_perfdata'), closure_custom_threshold_check => $self->can('custom_metric_threshold'), } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "type:s" => { name => 'type', default => 'cluster' }, "name:s@" => { name => 'name' }, "filter-metric:s" => { name => 'filter_metric' }, "per-sec" => { name => 'per_sec' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{type}) || $self->{option_results}->{type} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --type option."); $self->{output}->option_exit(); } if ($self->{option_results}->{type} ne 'cluster') { $self->{output}->add_option_msg(short_msg => "Instance type '" . $self->{option_results}->{type} . "' is not handled for this mode"); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Average']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } foreach my $metric ('VolumeBytesUsed', 'VolumeReadIOPs', 'VolumeWriteIOPs') { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/RDS', dimensions => [ { Name => $map_type{$self->{option_results}->{type}}, Value => $instance } , { Name => 'EngineName', Value => 'aurora' } ], metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period} ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$instance . "_" . lc($statistic)}->{display} = $instance; $self->{metric}->{$instance . "_" . lc($statistic)}->{stat} = lc($statistic); $self->{metric}->{$instance . "_" . lc($statistic)}->{type} = $self->{option_results}->{type}; $self->{metric}->{$instance . "_" . lc($statistic)}->{timeframe} = $self->{aws_timeframe}; $self->{metric}->{$instance . "_" . lc($statistic)}->{$metric . "_" . lc($statistic)} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check RDS instances volume metrics. Example: perl centreon_plugins.pl --plugin=cloud::aws::rds::plugin --custommode=paws --mode=volume --region='eu-west-1' --type='cluster' --name='centreon-db-ppd-cluster' --filter-metric='' --statistic='average' --critical-volumebytesused-average='10' --verbose Works for the following database engines : aurora. See 'https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/rds-metricscollected.html' for more informations. Default statistic: 'average' / All satistics are valid. =over 8 =item B<--type> Set the instance type (Required) (Can be: 'cluster'). =item B<--name> Set the instance name (Required) (Can be multiple). =item B<--filter-metric> Filter metrics (Can be: 'VolumeBytesUsed', 'VolumeReadIOPs', 'VolumeWriteIOPs') (Can be a regexp). =item B<--warning-$metric$-$statistic$> Thresholds warning ($metric$ can be: 'volumebytesused', 'volumereadiops', 'volumewriteiops', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =item B<--critical-$metric$-$statistic$> Thresholds critical ($metric$ can be: 'volumebytesused', 'volumereadiops', 'volumewriteiops', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =back =cut centreon-plugins-20220113/cloud/aws/rds/plugin.pm000066400000000000000000000040651417000230700215650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::rds::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} = { 'connections' => 'cloud::aws::rds::mode::connections', 'cpu' => 'cloud::aws::rds::mode::cpu', 'discovery' => 'cloud::aws::rds::mode::discovery', 'diskio' => 'cloud::aws::rds::mode::diskio', 'instance-status' => 'cloud::aws::rds::mode::instancestatus', 'list-clusters' => 'cloud::aws::rds::mode::listclusters', 'list-instances' => 'cloud::aws::rds::mode::listinstances', 'network' => 'cloud::aws::rds::mode::network', 'queries' => 'cloud::aws::rds::mode::queries', 'storage' => 'cloud::aws::rds::mode::storage', 'transactions' => 'cloud::aws::rds::mode::transactions', 'volume' => 'cloud::aws::rds::mode::volume', }; $self->{custom_modes}->{paws} = 'cloud::aws::custom::paws'; $self->{custom_modes}->{awscli} = 'cloud::aws::custom::awscli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Amazon Relational Database Service (Amazon RDS). =cut centreon-plugins-20220113/cloud/aws/s3/000077500000000000000000000000001417000230700174615ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/s3/mode/000077500000000000000000000000001417000230700204055ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/s3/mode/bucketsize.pm000066400000000000000000000174021417000230700231170ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::s3::mode::bucketsize; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; return "Bucket '" . $options{instance_value}->{display} . "' [" . ucfirst($options{instance_value}->{storage_type}) . "] " . $options{instance_value}->{stat} . " "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All size metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $statistic ('minimum', 'maximum', 'average', 'sum') { foreach my $metric ('BucketSizeBytes') { foreach my $storage_type ('StandardStorage', 'StandardIAStorage', 'ReducedRedundancyStorage') { my $entry = { label => lc($metric) . '-' . lc($storage_type) . '-' . lc($statistic), set => { key_values => [ { name => $metric . '_' . $storage_type . '_' . $statistic }, { name => 'display' }, { name => 'storage_type' }, { name => 'stat' } ], output_template => $metric . ': %d %s', output_change_bytes => 1, perfdatas => [ { label => lc($metric) . '_' . lc($storage_type) . '_' . lc($statistic), value => $metric . '_' . $storage_type . '_' . $statistic , template => '%d', unit => 'B', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "name:s@" => { name => 'name' }, "storage-type:s@" => { name => 'storage_type' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 172800; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 86400; $self->{aws_statistics} = ['Average']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } foreach my $metric ('BucketSizeBytes') { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } $self->{aws_storage_type} = ['StandardStorage']; if (defined($self->{option_results}->{storage_type})) { $self->{aws_storage_type} = []; foreach my $storage_type (@{$self->{option_results}->{storage_type}}) { if ($storage_type ne '') { push @{$self->{aws_storage_type}}, $storage_type; } } } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { foreach my $storage_type (@{$self->{aws_storage_type}}) { $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/S3', dimensions => [ {Name => 'StorageType', Value => $storage_type }, { Name => 'BucketName', Value => $instance } ], metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period} ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$instance . "_" . $storage_type . "_" . lc($statistic)}->{display} = $instance; $self->{metric}->{$instance . "_" . $storage_type . "_" . lc($statistic)}->{storage_type} = $storage_type; $self->{metric}->{$instance . "_" . $storage_type . "_" . lc($statistic)}->{stat} = lc($statistic); $self->{metric}->{$instance . "_" . $storage_type . "_" . lc($statistic)}->{$metric . "_" . $storage_type . "_" . lc($statistic)} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check S3 buckets size. Example: perl centreon_plugins.pl --plugin=cloud::aws::s3::plugin --custommode=paws --mode=bucket-size --region='eu-west-1' --name='centreon-iso' --critical-bucketsizebytes-standardiastorage-average='1000' --storage-type='StandardIAStorage' --verbose See 'https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/s3-metricscollected.html' for more informations. Default statistic: 'average' / All satistics are valid. =over 8 =item B<--name> Set the instance name (Required) (Can be multiple). =item B<--storage-type> Set the storage type of the bucket (Default: 'StandardStorage') (Can be multiple: 'StandardStorage', 'StandardIAStorage', 'ReducedRedundancyStorage'). =item B<--warning-$metric$-$storagetype$-$statistic$> Thresholds warning ($metric$ can be: 'bucketsizebytes', $storagetype$ can be: 'standardstorage', 'standardiastorage', 'reducedredundancystorage', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =item B<--critical-$metric$-$storagetype$-$statistic$> Thresholds critical ($metric$ can be: 'bucketsizebytes', $storagetype$ can be: 'standardstorage', 'standardiastorage', 'reducedredundancystorage', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =back =cut centreon-plugins-20220113/cloud/aws/s3/mode/discovery.pm000066400000000000000000000051331417000230700227540ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::s3::mode::discovery; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "prettify" => { name => 'prettify' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my @disco_data; my $disco_stats; $disco_stats->{start_time} = time(); my $buckets = $options{custom}->discovery( service => 's3api', command => 'list-buckets' ); foreach my $bucket (@{$buckets->{Buckets}}) { my %bucket; $bucket{type} = "s3_bucket"; $bucket{name} = $bucket->{Name}; $bucket{creation_date} = $bucket->{CreationDate}; push @disco_data, \%bucket; } $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; $disco_stats->{discovered_items} = @disco_data; $disco_stats->{results} = \@disco_data; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE S3 Buckets discovery. =over 8 =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/aws/s3/mode/objects.pm000066400000000000000000000144111417000230700223750ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::s3::mode::objects; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; return "Bucket '" . $options{instance_value}->{display} . "' " . $options{instance_value}->{stat} . " "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All objects metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $statistic ('minimum', 'maximum', 'average', 'sum') { foreach my $metric ('NumberOfObjects') { my $entry = { label => lc($metric) . '-' . lc($statistic), set => { key_values => [ { name => $metric . '_' . $statistic }, { name => 'display' }, { name => 'stat' } ], output_template => $metric . ': %d objects', perfdatas => [ { label => lc($metric) . '_' . lc($statistic), value => $metric . '_' . $statistic , template => '%d', unit => 'objects', label_extra_instance => 1, instance_use => 'display' }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "name:s@" => { name => 'name' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 172800; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 86400; $self->{aws_statistics} = ['Average']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } } foreach my $metric ('NumberOfObjects') { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/S3', dimensions => [ {Name => 'StorageType', Value => 'AllStorageTypes' }, { Name => 'BucketName', Value => $instance } ], metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period} ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$instance . "_" . lc($statistic)}->{display} = $instance; $self->{metric}->{$instance . "_" . lc($statistic)}->{stat} = lc($statistic); $self->{metric}->{$instance . "_" . lc($statistic)}->{type} = $self->{option_results}->{type}; $self->{metric}->{$instance . "_" . lc($statistic)}->{$metric . "_" . lc($statistic)} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check S3 buckets number of objects. Example: perl centreon_plugins.pl --plugin=cloud::aws::s3::plugin --custommode=paws --mode=objects --region='eu-west-1' --name='centreon-iso' --critical-numberofobjects-average='10' --verbose See 'https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/s3-metricscollected.html' for more informations. Default statistic: 'average' / All satistics are valid. =over 8 =item B<--name> Set the instance name (Required) (Can be multiple). =item B<--warning-$metric$-$statistic$> Thresholds warning ($metric$ can be: 'numberofobjects', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =item B<--critical-$metric$-$statistic$> Thresholds critical ($metric$ can be: 'numberofobjects', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =back =cut centreon-plugins-20220113/cloud/aws/s3/mode/requests.pm000066400000000000000000000144751417000230700226310ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::s3::mode::requests; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; return "Bucket '" . $options{instance_value}->{display} . "' " . $options{instance_value}->{stat} . " "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All requests metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $statistic ('minimum', 'maximum', 'average', 'sum') { foreach my $metric ('AllRequests', 'GetRequests', 'PutRequests', 'DeleteRequests', 'HeadRequests', 'PostRequests', 'ListRequests') { my $entry = { label => lc($metric) . '-' . lc($statistic), set => { key_values => [ { name => $metric . '_' . $statistic }, { name => 'display' }, { name => 'stat' } ], output_template => $metric . ': %d requests', perfdatas => [ { label => lc($metric) . '_' . lc($statistic), value => $metric . '_' . $statistic , template => '%d', unit => 'requests', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'name:s@' => { name => 'name' }, 'filter-metric:s' => { name => 'filter_metric' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{name}) || $self->{option_results}->{name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --name option."); $self->{output}->option_exit(); } foreach my $instance (@{$self->{option_results}->{name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; } } $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Sum']; foreach my $metric ('AllRequests', 'GetRequests', 'PutRequests', 'DeleteRequests', 'HeadRequests', 'PostRequests', 'ListRequests') { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/S3', dimensions => [ { Name => 'BucketName', Value => $instance } ], metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period} ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$instance . "_" . lc($statistic)}->{display} = $instance; $self->{metric}->{$instance . "_" . lc($statistic)}->{stat} = lc($statistic); $self->{metric}->{$instance . "_" . lc($statistic)}->{$metric . "_" . lc($statistic)} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check S3 buckets requests. Example: perl centreon_plugins.pl --plugin=cloud::aws::s3::plugin --custommode=paws --mode=requests --region='eu-west-1' --name='centreon-iso' --critical-allrequests-sum='5000000' --verbose See 'https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/s3-metricscollected.html' for more informations. Default statistic: 'sum' / Valid statistics: 'sum'. =over 8 =item B<--name> Set the instance name (Required) (Can be multiple). =item B<--filter-metric> Filter metrics (Can be: 'AllRequests', 'GetRequests', 'PutRequests', 'DeleteRequests', 'HeadRequests', 'PostRequests', 'ListRequests') (Can be a regexp). =item B<--warning-$metric$-$statistic$> Thresholds warning ($metric$ can be: 'allrequests', 'getrequests', 'putrequests', 'deleterequests', 'headrequests', 'postrequests', 'listrequests', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =item B<--critical-$metric$-$statistic$> Thresholds critical ($metric$ can be: 'allrequests', 'getrequests', 'putrequests', 'deleterequests', 'headrequests', 'postrequests', 'listrequests', $statistic$ can be: 'minimum', 'maximum', 'average', 'sum'). =back =cut centreon-plugins-20220113/cloud/aws/s3/plugin.pm000066400000000000000000000030341417000230700213150ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::s3::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} } = ( 'bucket-size' => 'cloud::aws::s3::mode::bucketsize', 'discovery' => 'cloud::aws::s3::mode::discovery', 'objects' => 'cloud::aws::s3::mode::objects', 'requests' => 'cloud::aws::s3::mode::requests', ); $self->{custom_modes}{paws} = 'cloud::aws::custom::paws'; $self->{custom_modes}{awscli} = 'cloud::aws::custom::awscli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Amazon Simple Storage Service (Amazon S3). =cut centreon-plugins-20220113/cloud/aws/ses/000077500000000000000000000000001417000230700177265ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/ses/mode/000077500000000000000000000000001417000230700206525ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/ses/mode/emails.pm000066400000000000000000000214241417000230700224650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::ses::mode::emails; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my %metrics_mapping = ( 'Send' => { 'output' => 'number of sent emails', 'label' => 'emails-sent', 'nlabel' => 'ses.emails.sent.count', }, 'Delivery' => { 'output' => 'number of emails successfully delivered', 'label' => 'emails-delivered', 'nlabel' => 'ses.emails.delivered.count', }, 'Reputation.BounceRate' => { 'output' => 'rate of rejected sent emails', 'label' => 'emails-rejected', 'nlabel' => 'ses.emails.rejected.rate', }, 'Reputation.ComplaintRate' => { 'output' => 'rate of sent emails marked as spam', 'label' => 'emails-spam', 'nlabel' => 'ses.emails.spam.rate', } ); sub custom_metric_calc { my ($self, %options) = @_; $self->{result_values}->{timeframe} = $options{new_datas}->{$self->{instance} . '_timeframe'}; $self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{metric}}; $self->{result_values}->{metric} = $options{extra_options}->{metric}; return 0; } sub custom_metric_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check( value => $self->{result_values}->{value}, threshold => [ { label => 'critical-' . $metrics_mapping{$self->{result_values}->{metric}}->{label}, exit_litteral => 'critical' }, { label => 'warning-' . $metrics_mapping{$self->{result_values}->{metric}}->{label}, exit_litteral => 'warning' } ]); return $exit; } sub custom_metric_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( instances => $self->{instance}, label => $metrics_mapping{$self->{result_values}->{metric}}->{label}, nlabel => $metrics_mapping{$self->{result_values}->{metric}}->{nlabel}, value => $self->{result_values}->{value}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $metrics_mapping{$self->{result_values}->{metric}}->{label}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $metrics_mapping{$self->{result_values}->{metric}}->{label}) ); } sub custom_metric_output { my ($self, %options) = @_; my $msg = ""; my $value = $self->{result_values}->{value}; return $msg = sprintf("%s: %.2f", $metrics_mapping{$self->{result_values}->{metric}}->{output}, $value); } sub prefix_metric_output { my ($self, %options) = @_; return "'" . $options{instance_value}->{display} . "' "; } sub prefix_statistics_output { my ($self, %options) = @_; return "Statistic '" . $options{instance_value}->{display} . "' Metrics "; } sub long_output { my ($self, %options) = @_; return "SES '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metrics', type => 3, cb_prefix_output => 'prefix_metric_output', cb_long_output => 'long_output', message_multiple => 'All emails metrics are ok', indent_long_output => ' ', group => [ { name => 'statistics', display_long => 1, cb_prefix_output => 'prefix_statistics_output', message_multiple => 'All metrics are ok', type => 1, skipped_code => { -10 => 1 } }, ] } ]; foreach my $metric (keys %metrics_mapping) { my $entry = { label => $metrics_mapping{$metric}->{label}, set => { key_values => [ { name => $metric }, { name => 'timeframe' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_metric_calc'), closure_custom_calc_extra_options => { metric => $metric }, 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'), } }; push @{$self->{maps_counters}->{statistics}}, $entry; } } 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 => { 'dimension:s%' => { name => 'dimension' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 172800; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 86400; $self->{aws_statistics} = ['Average']; foreach my $metric (keys %metrics_mapping) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; } $self->{dimension_name} = ''; my $append = ''; $self->{aws_dimensions} = []; if (defined($self->{option_results}->{dimension})) { foreach (keys %{$self->{option_results}->{dimension}}) { push @{$self->{aws_dimensions}}, { Name => $_, Value => $self->{option_results}->{dimension}->{$_} }; $self->{dimension_name} .= $append . $_ . '.' . $self->{option_results}->{dimension}->{$_}; $append = '-'; push @{$self->{aws_instance}}, $self->{option_results}->{dimension}->{$_}; } } else { $self->{aws_instance} = ["SES"]; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/SES', dimensions => $self->{aws_dimensions}, metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period} ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{$instance}->{display} = $instance; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{display} = $statistic; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{timeframe} = $self->{aws_timeframe}; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{$metric} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check Amazon SES sending activity. Example: perl centreon_plugins.pl --plugin=cloud::aws::ses::plugin --custommode=awscli --mode=emails --region='eu-west-1' --dimension='DimensionName1=ses-1234abcd' --dimension='DimensionName2=ses-5678efgh' See 'https://docs.aws.amazon.com/ses/latest/DeveloperGuide/monitor-sending-activity.html' for more information. =over 8 =item B<--dimension> Set SES dimensions (Can be multiple). Syntax: --dimension='DimensionName1=Value1' --dimension='DimensionName2=Value2'. =item B<--warning-emails-*> Set warning threshold where '*' can be 'sent', 'delivered', 'spam' or 'rejected'. =item B<--critical-emails-*> Set critical threshold where '*' can be 'sent', 'delivered', 'spam' or 'rejected'. =back =cut centreon-plugins-20220113/cloud/aws/ses/plugin.pm000066400000000000000000000025261417000230700215670ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::ses::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} = '1.0'; $self->{modes} = { 'emails' => 'cloud::aws::ses::mode::emails', }; $self->{custom_modes}{paws} = 'cloud::aws::custom::paws'; $self->{custom_modes}{awscli} = 'cloud::aws::custom::awscli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Amazon Simple Email Service (Amazon SES). =cut centreon-plugins-20220113/cloud/aws/sns/000077500000000000000000000000001417000230700177375ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/sns/mode/000077500000000000000000000000001417000230700206635ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/sns/mode/listtopics.pm000066400000000000000000000042501417000230700234170ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::sns::mode::listtopics; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{topics} = $options{custom}->sns_list_topics(); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $topic (@{$self->{topics}}) { $topic->{name} =~ s/(.*)\://g; $self->{output}->output_add(long_msg => sprintf( "[Name = %s]", $topic->{name} )); } $self->{output}->output_add( severity => 'OK', short_msg => 'Amazon SNS queues:' ); $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->manage_selection(%options); foreach my $topic (@{$self->{topics}}) { $topic->{name} =~ s/(.*)\://g; $self->{output}->add_disco_entry( name => $topic->{name} ); }; } 1; __END__ =head1 MODE List SNS queues. =over 8 =back =cut centreon-plugins-20220113/cloud/aws/sns/mode/notifications.pm000066400000000000000000000170101417000230700240710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::sns::mode::notifications; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my %metrics_mapping = ( 'NumberOfMessagesPublished' => { 'output' => 'number of notifications published', 'label' => 'notifications-published', 'nlabel' => 'sns.notifications.published.count', }, 'NumberOfNotificationsDelivered' => { 'output' => 'number of notifications delivered', 'label' => 'notifications-delivered', 'nlabel' => 'sns.notifications.delivered.count', }, 'NumberOfNotificationsFailed' => { 'output' => 'number of notifications failed', 'label' => 'notifications-failed', 'nlabel' => 'sns.notifications.failed.count', }, 'NumberOfNotificationsFilteredOut' => { 'output' => 'number of notifications filtered', 'label' => 'notifications-filtered', 'nlabel' => 'sns.notifications.filtered.count', } ); sub prefix_metric_output { my ($self, %options) = @_; return "'" . $options{instance_value}->{display} . "' "; } sub prefix_statistics_output { my ($self, %options) = @_; return "Statistic '" . $options{instance_value}->{display} . "' "; } sub long_output { my ($self, %options) = @_; return "Notifications for topic '" . $options{instance_value}->{display} . "' :"; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metrics', type => 3, cb_prefix_output => 'prefix_metric_output', cb_long_output => 'long_output', message_multiple => 'All SNS metrics are ok', indent_long_output => ' ', group => [ { name => 'statistics', display_long => 1, cb_prefix_output => 'prefix_statistics_output', message_multiple => 'All metrics are ok', type => 1, skipped_code => { -10 => 1 } }, ] } ]; foreach my $metric (keys %metrics_mapping) { my $entry = { label => $metrics_mapping{$metric}->{label}, nlabel => $metrics_mapping{$metric}->{nlabel}, set => { key_values => [ { name => $metric }, { name => 'display' } ], output_template => $metrics_mapping{$metric}->{output} . ': %d', perfdatas => [ { value => $metric, template => '%d', label_extra_instance => 1 } ], } }; push @{$self->{maps_counters}->{statistics}}, $entry; } } 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 => { "topic-name:s" => { name => 'topic_name' }, "filter-metric:s" => { name => 'filter_metric' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Sum']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } }; foreach my $metric (keys %metrics_mapping) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; }; } sub manage_selection { my ($self, %options) = @_; $self->{topics} = $options{custom}->sns_list_topics(); foreach my $topic (@{$self->{topics}}) { next if (defined($self->{option_results}->{topic_name}) && $self->{option_results}->{topic_name} ne '' && $topic->{name} !~ /$self->{option_results}->{topic_name}/ ); $topic->{name} =~ s/(.*)\://g; push @{$self->{aws_instance}}, $topic->{name}; }; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/SNS', dimensions => [ { Name => 'TopicName', Value => $instance } ], metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period}, ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{$instance}->{display} = $instance; $self->{metrics}->{$instance}->{type} = $self->{option_results}->{type}; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{display} = $statistic; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{$metric} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check Amazon SNS notifications statistics. Example: perl centreon_plugins.pl --plugin=cloud::aws::sns::plugin --custommode=paws --mode=notifications --region='eu-west-1' --topic-name='my_sns_topic_1' --filter-metric='NumberOfNotificationsFailed' --statistic='sum' --critical-messages-sent='200' --verbose See 'https://docs.aws.amazon.com/sns/latest/dg/sns-monitoring-using-cloudwatch.html' for more information. Default statistic: 'sum' / Valid statistics are: sum, average. =over 8 =item B<--topic-name> Filter on a specific SNS topic (Can be multiple, one instance per --topic-name option). Example: --topic-name="my_sns_topic_1" --topic-name="my_sns_topic_2". =item B<--filter-metric> Filter metrics (Can be: 'NumberOfMessagesPublished', 'NumberOfNotificationsDelivered', 'NumberOfNotificationsFailed', 'NumberOfNotificationsFilteredOut'). (Can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds warning (Can be 'notifications-published', 'notifications-delivered', 'notifications-failed', 'notifications-filtered). =back =cut centreon-plugins-20220113/cloud/aws/sns/plugin.pm000066400000000000000000000026571417000230700216050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::sns::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} = '1.0'; %{ $self->{modes} } = ( 'notifications' => 'cloud::aws::sns::mode::notifications', 'list-topics' => 'cloud::aws::sns::mode::listtopics' ); $self->{custom_modes}{paws} = 'cloud::aws::custom::paws'; $self->{custom_modes}{awscli} = 'cloud::aws::custom::awscli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Amazon Simple Notification Service (Amazon SNS). =cut centreon-plugins-20220113/cloud/aws/sqs/000077500000000000000000000000001417000230700177425ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/sqs/mode/000077500000000000000000000000001417000230700206665ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/sqs/mode/listqueues.pm000066400000000000000000000042101417000230700234240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::sqs::mode::listqueues; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{queues} = $options{custom}->sqs_list_queues(); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $queue (@{$self->{queues}}) { $queue =~ s/(.*)\///g; $self->{output}->output_add(long_msg => sprintf( "[Name = %s]", $queue )); } $self->{output}->output_add( severity => 'OK', short_msg => 'Amazon SQS queues:' ); $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->manage_selection(%options); foreach my $queue (@{$self->{queues}}) { $queue =~ s/(.*)\///g; $self->{output}->add_disco_entry( name => $queue ); }; } 1; __END__ =head1 MODE List SQS queues. =over 8 =back =cut centreon-plugins-20220113/cloud/aws/sqs/mode/queues.pm000066400000000000000000000167171417000230700225470ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::sqs::mode::queues; use base qw(cloud::aws::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { extra_params => { message_multiple => 'All queues metrics are ok' }, metrics => { 'ApproximateAgeOfOldestMessage' => { output => 'age of oldest message', label => 'messages-oldest-age', nlabel => { absolute => 'sqs.queue.messages.oldest.seconds' }, unit => '' }, 'ApproximateNumberOfMessagesDelayed' => { output => 'delayed messages', label => 'messages-delayed', nlabel => { absolute => 'sqs.queue.messages.delayed.count' }, unit => '' }, 'ApproximateNumberOfMessagesNotVisible' => { output => 'approximate number of messages not visible', label => 'messages-notvisible', nlabel => { absolute => 'sqs.queue.messages.notvisible.count' }, unit => '' }, 'ApproximateNumberOfMessagesVisible' => { output => 'approximate number of messages visible', label => 'messages-visible', nlabel => { absolute => 'sqs.queue.messages.visible.count' }, unit => '' }, 'NumberOfEmptyReceives' => { output => 'number of empty receives', label => 'messages-empty-receives', nlabel => { absolute => 'sqs.queue.messages.empty.count' }, unit => '' }, 'NumberOfMessagesDeleted' => { output => 'number of messages deleted', label => 'messages-deleted', nlabel => { absolute => 'sqs.queue.messages.deleted.count' }, unit => '' }, 'NumberOfMessagesReceived' => { output => 'number of messages received', label => 'messages-received', nlabel => { absolute => 'sqs.queue.messages.received.count' }, unit => '' }, 'NumberOfMessagesSent' => { output => 'number of messages sent', label => 'messages-sent', nlabel => { absolute => 'sqs.queue.messages.sent.count' }, unit => '' } } }; return $metrics_mapping; } sub prefix_metric_output { my ($self, %options) = @_; return "'" . $options{instance_value}->{display} . "' "; } sub long_output { my ($self, %options) = @_; return "SQS Queue'" . $options{instance_value}->{display} . "' "; } 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 => { "queue-name:s@" => { name => 'queue_name' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{queue_name}) || $self->{option_results}->{queue_name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --queue-name option."); $self->{output}->option_exit(); }; foreach my $instance (@{$self->{option_results}->{queue_name}}) { if ($instance ne '') { push @{$self->{aws_instance}}, $instance; }; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $instance (@{$self->{aws_instance}}) { $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/SQS', dimensions => [ { Name => 'QueueName', Value => $instance } ], metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period}, ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{$instance}->{display} = $instance; $self->{metrics}->{$instance}->{type} = $self->{option_results}->{type}; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{display} = $statistic; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{timeframe} = $self->{aws_timeframe}; $self->{metrics}->{$instance}->{statistics}->{lc($statistic)}->{$metric} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check Amazon SQS queues metrics. Example: perl centreon_plugins.pl --plugin=cloud::aws::sqs::plugin --custommode=paws --mode=queues --region='eu-west-1' --queue-name='my_aws_queue_1' --filter-metric='NumberOfMessagesSent' --statistic='average' --critical-messages-sent='200' --verbose See 'https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-monitoring-using-cloudwatch.html' for more information. Default statistic: 'average' / All satistics are valid. =over 8 =item B<--queue-name> Set the SQS queue name (Required) (Can be multiple, one instance per --queue-name option). Example: --queue-name="myqueue1" --queue-name="myqueue2". =item B<--filter-metric> Filter metrics (Can be: 'ApproximateAgeOfOldestMessage', 'ApproximateNumberOfMessagesDelayed', 'ApproximateNumberOfMessagesNotVisible', 'ApproximateNumberOfMessagesVisible', 'NumberOfEmptyReceives', 'NumberOfMessagesDeleted', 'NumberOfMessagesReceived', 'NumberOfMessagesSent'). (Can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds warning (Can be 'messages-oldest-age', 'messages-delayed', 'messages-notvisible', 'messages-visible', 'messages-empty-receives', 'messages-deleted', 'messages-received', 'messages-sent'). =back =cut centreon-plugins-20220113/cloud/aws/sqs/plugin.pm000066400000000000000000000026351417000230700216040ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::sqs::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} = '1.0'; %{ $self->{modes} } = ( 'queues' => 'cloud::aws::sqs::mode::queues', 'list-queues' => 'cloud::aws::sqs::mode::listqueues' ); $self->{custom_modes}{paws} = 'cloud::aws::custom::paws'; $self->{custom_modes}{awscli} = 'cloud::aws::custom::awscli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Amazon Simple Queue Service (Amazon SQS). =cut centreon-plugins-20220113/cloud/aws/transitgateway/000077500000000000000000000000001417000230700222025ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/transitgateway/mode/000077500000000000000000000000001417000230700231265ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/transitgateway/mode/listgateways.pm000066400000000000000000000042431417000230700262070ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::transitgateway::mode::listgateways; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{volume} = $options{custom}->tgw_list_gateways(); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach (@{$self->{volume}}) { $self->{output}->output_add(long_msg => sprintf("[id = %s][name = %s]", $_->{id}, $_->{name})); } $self->{output}->output_add( severity => 'OK', short_msg => 'Transit Gateways list:' ); $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 => ['id', 'name']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach (@{$self->{volume}}) { $self->{output}->add_disco_entry( id => $_->{id}, name => $_->{name} ); }; } 1; __END__ =head1 MODE List AWS TransitGateways. =over 8 =back =cut centreon-plugins-20220113/cloud/aws/transitgateway/mode/traffic.pm000066400000000000000000000151711417000230700251070ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::transitgateway::mode::traffic; use base qw(cloud::aws::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { extra_params => { message_multiple => 'All TransitGateways metrics are ok' }, metrics => { BytesIn => { output => 'Bytes In', label => 'bytes-in', nlabel => { absolute => 'gateway.traffic.in.bytes', per_second => 'gateway.traffic.in.bytespersecond' }, unit => 'B' }, BytesOut => { output => 'Bytes Out', label => 'bytes-out', nlabel => { absolute => 'gateway.traffic.out.bytes', per_second => 'gateway.traffic.out.bytespersecond' }, unit => 'B' }, PacketsIn => { output => 'Packets Received (In)', label => 'packets-in', nlabel => { absolute => 'gateway.packets.in.count', per_second => 'gateway.packets.in.countpersecond' }, unit => '' }, PacketsOut => { output => 'Packets Sent (Out)', label => 'packets-out', nlabel => { absolute => 'gateway.packets.out.count', per_second => 'gateway.packets.out.countpersecond' }, unit => '' }, PacketDropCountBlackhole => { output => 'Packets Drop Blackhole', label => 'packets-drop-blackhole', nlabel => { absolute => 'gateway.packets.blackholedropped.count', per_second => 'gateway.packets.blackholedropped.countpersecond' }, unit => '' }, PacketDropCountNoRoute => { output => 'Packets Drop No Route', label => 'packets-drop-noroute', nlabel => { absolute => 'gateway.packets.noroutedropped.count', per_second => 'gateway.packets.noroutedropped.countpersecond' }, unit => '' } } }; return $metrics_mapping; } sub long_output { my ($self, %options) = @_; return "AWS TransitGateway '" . $options{instance_value}->{display} . "' "; } 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-gateway:s' => { name => 'filter_gateway' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{gateways} = $options{custom}->tgw_list_gateways(); my %metric_results; foreach my $instance (@{$self->{gateways}}) { next if (defined($self->{option_results}->{filter_gateway}) && $self->{option_results}->{filter_gateway} ne '' && $instance->{id} !~ /$self->{option_results}->{filter_gateway}/); $instance->{name} =~ s/ /_/g; $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/TransitGateway', dimensions => [ { Name => 'TransitGateway', Value => $instance->{id} } ], metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period} ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{ $instance->{id} }->{display} = $instance->{id}; $self->{metrics}->{ $instance->{id} }->{statistics}->{lc($statistic)}->{display} = $statistic; $self->{metrics}->{ $instance->{id} }->{statistics}->{lc($statistic)}->{timeframe} = $self->{aws_timeframe}; $self->{metrics}->{ $instance->{id} }->{statistics}->{lc($statistic)}->{$metric} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check AWS TransitGateways statistics. Example: perl centreon_plugins.pl --plugin=cloud::aws::transitgateway::plugin --custommode=awscli --mode=traffic --region='eu-west-1' --filter-gateway='MyTGW_1' --warning-packets-drop-blackole='500' --critical-packets-drop-blackole='1000' --verbose See 'https://docs.aws.amazon.com/vpc/latest/tgw/transit-gateway-cloudwatch-metrics.html' for more information. =over 8 =item B<--filter-gateway> Filter on a specific TransitGateway ID. This filter is based on the "TransitGatewayId" attribute of the gateway. =item B<--filter-metric> Filter on a specific metric. Can be: BytesIn, BytesOut, PacketsIn, PacketsOut, PacketDropCountBlackhole, PacketDropCountNoRoute =item B<--warning-$metric$> Warning thresholds ($metric$ can be: 'bytes-in', 'bytes-out', 'packets-in', 'packets-out', 'packets-drop-blackhole', 'packets-drop-noroute'). =item B<--critical-$metric$> Critical thresholds ($metric$ can be: 'bytes-in', 'bytes-out', 'packets-in', 'packets-out', 'packets-drop-blackhole', 'packets-drop-noroute'). =back =cut centreon-plugins-20220113/cloud/aws/transitgateway/plugin.pm000066400000000000000000000030561417000230700240420ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::transitgateway::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} = { 'list-gateways' => 'cloud::aws::transitgateway::mode::listgateways', 'traffic' => 'cloud::aws::transitgateway::mode::traffic' }; $self->{customdefault} = { paws => { region => 'eu-west-1' }, awscli => { region => 'eu-west-1' } }; $self->{custom_modes}->{paws} = 'cloud::aws::custom::paws'; $self->{custom_modes}->{awscli} = 'cloud::aws::custom::awscli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check AWS Transit Gateways. =cut centreon-plugins-20220113/cloud/aws/vpn/000077500000000000000000000000001417000230700177375ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/vpn/mode/000077500000000000000000000000001417000230700206635ustar00rootroot00000000000000centreon-plugins-20220113/cloud/aws/vpn/mode/listvpn.pm000066400000000000000000000043701417000230700227240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::vpn::mode::listvpn; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{connection} = $options{custom}->vpn_list_connections(); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach (@{$self->{connection}}) { $self->{output}->output_add( long_msg => sprintf("[id = %s][name = %s][state = %s]", $_->{id}, $_->{name}, $_->{state} )); } $self->{output}->output_add( severity => 'OK', short_msg => 'List VPN connections:' ); $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 => ['id', 'name', 'state']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach (@{$self->{connection}}) { $self->{output}->add_disco_entry( id => $_->{id}, name => $_->{name}, state => $_->{state}, ); }; } 1; __END__ =head1 MODE List VPN instances. =over 8 =back =cut centreon-plugins-20220113/cloud/aws/vpn/mode/traffic.pm000066400000000000000000000260331417000230700226430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::vpn::mode::traffic; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my %metrics_mapping = ( 'TunnelState' => { 'output' => 'Tunnel State', 'label' => 'tunnel-state', 'nlabel' => { 'absolute' => 'vpn.tunnel.tunnelstate' }, 'unit' => '' }, 'TunnelDataIn' => { 'output' => 'Tunnel Data In', 'label' => 'tunnel-datain', 'nlabel' => { 'absolute' => 'vpn.tunnel.datain.bytes', 'per_second' => 'vpn.tunnel.datain.bytespersecond' }, 'unit' => 'B' }, 'TunnelDataOut' => { 'output' => 'Tunnel Data Out', 'label' => 'tunnel-dataout', 'nlabel' => { 'absolute' => 'vpn.tunnel.dataout.bytes', 'per_second' => 'vpn.tunnel.dataout.bytespersecond' }, 'unit' => 'B' } ); sub custom_metric_calc { my ($self, %options) = @_; $self->{result_values}->{timeframe} = $options{new_datas}->{$self->{instance} . '_timeframe'}; $self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{metric}}; $self->{result_values}->{value_per_sec} = $self->{result_values}->{value} / $self->{result_values}->{timeframe}; $self->{result_values}->{metric} = $options{extra_options}->{metric}; return 0; } sub custom_metric_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check( value => defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}, threshold => [ { label => 'critical-' . $metrics_mapping{$self->{result_values}->{metric}}->{label} , exit_litteral => 'critical' }, { label => 'warning-' . $metrics_mapping{$self->{result_values}->{metric}}->{label}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_metric_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( instances => $self->{instance}, nlabel => defined($self->{instance_mode}->{option_results}->{per_sec}) ? $metrics_mapping{$self->{result_values}->{metric}}->{nlabel}->{per_second} : $metrics_mapping{$self->{result_values}->{metric}}->{nlabel}->{absolute}, unit => defined($self->{instance_mode}->{option_results}->{per_sec}) && defined($metrics_mapping{$self->{result_values}->{metric}}->{nlabel}->{per_second}) ? $metrics_mapping{$self->{result_values}->{metric}}->{unit} . '/s' : $metrics_mapping{$self->{result_values}->{metric}}->{unit}, value => sprintf("%.2f", defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $metrics_mapping{$self->{result_values}->{metric}}->{label}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $metrics_mapping{$self->{result_values}->{metric}}->{label}), ); } sub custom_metric_output { my ($self, %options) = @_; my $msg = ""; if (defined($self->{instance_mode}->{option_results}->{per_sec}) && defined($metrics_mapping{$self->{result_values}->{metric}}->{nlabel}->{per_second})) { my ($value, $unit) = ($metrics_mapping{$self->{result_values}->{metric}}->{unit} eq 'B') ? $self->{perfdata}->change_bytes(value => $self->{result_values}->{value_per_sec}) : ($self->{result_values}->{value_per_sec}, $metrics_mapping{$self->{result_values}->{metric}}->{unit}); $msg = sprintf("%s: %.2f %s", $metrics_mapping{$self->{result_values}->{metric}}->{output}, $value, $unit . '/s'); } else { my ($value, $unit) = ($metrics_mapping{$self->{result_values}->{metric}}->{unit} eq 'B') ? $self->{perfdata}->change_bytes(value => $self->{result_values}->{value}) : ($self->{result_values}->{value}, $metrics_mapping{$self->{result_values}->{metric}}->{unit}); $msg = sprintf("%s: %.2f %s", $metrics_mapping{$self->{result_values}->{metric}}->{output}, $value, $unit); } return $msg; } sub prefix_metric_output { my ($self, %options) = @_; return "'" . $options{instance_value}->{display} . "' "; } sub prefix_statistics_output { my ($self, %options) = @_; return "Statistic '" . $options{instance_value}->{display} . "' Metrics "; } sub long_output { my ($self, %options) = @_; return "AWS VPN Tunnel '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metrics', type => 3, cb_prefix_output => 'prefix_metric_output', cb_long_output => 'long_output', message_multiple => 'All VPN metrics are ok', indent_long_output => ' ', group => [ { name => 'statistics', display_long => 1, cb_prefix_output => 'prefix_statistics_output', message_multiple => 'All metrics are ok', type => 1, skipped_code => { -10 => 1 } }, ] } ]; foreach my $metric (keys %metrics_mapping) { my $entry = { label => $metrics_mapping{$metric}->{label}, set => { key_values => [ { name => $metric }, { name => 'timeframe' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_metric_calc'), closure_custom_calc_extra_options => { metric => $metric }, 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'), } }; push @{$self->{maps_counters}->{statistics}}, $entry; } } 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 => { 'name' => { name => 'name' }, 'filter-vpn:s' => { name => 'filter_vpn' }, 'per-sec' => { name => 'per_sec' }, 'filter-metric:s' => { name => 'filter_metric' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{aws_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{aws_period} = defined($self->{option_results}->{period}) ? $self->{option_results}->{period} : 60; $self->{aws_statistics} = ['Average']; if (defined($self->{option_results}->{statistic})) { $self->{aws_statistics} = []; foreach my $stat (@{$self->{option_results}->{statistic}}) { if ($stat ne '') { push @{$self->{aws_statistics}}, ucfirst(lc($stat)); } } }; foreach my $metric (keys %metrics_mapping) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{aws_metrics}}, $metric; }; } sub manage_selection { my ($self, %options) = @_; my %metric_results; $self->{connections} = $options{custom}->vpn_list_connections(); foreach my $instance (@{$self->{connections}}) { my $display_key = defined($self->{option_results}->{name}) ? $instance->{name} : $instance->{id}; next if (defined($self->{option_results}->{filter_vpn}) && $self->{option_results}->{filter_vpn} ne '' && $display_key !~ /$self->{option_results}->{filter_vpn}/); $metric_results{$instance} = $options{custom}->cloudwatch_get_metrics( namespace => 'AWS/VPN', dimensions => [ { Name => 'VpnId', Value => $instance->{id} } ], metrics => $self->{aws_metrics}, statistics => $self->{aws_statistics}, timeframe => $self->{aws_timeframe}, period => $self->{aws_period} ); foreach my $metric (@{$self->{aws_metrics}}) { foreach my $statistic (@{$self->{aws_statistics}}) { next if (!defined($metric_results{$instance}->{$metric}->{lc($statistic)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{ $display_key }->{display} = $display_key; $self->{metrics}->{ $display_key }->{statistics}->{lc($statistic)}->{display} = $statistic; $self->{metrics}->{ $display_key }->{statistics}->{lc($statistic)}->{timeframe} = $self->{aws_timeframe}; $self->{metrics}->{ $display_key }->{statistics}->{lc($statistic)}->{$metric} = defined($metric_results{$instance}->{$metric}->{lc($statistic)}) ? $metric_results{$instance}->{$metric}->{lc($statistic)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check AWS VPN Connection. Example: perl centreon_plugins.pl --plugin=cloud::aws::vpn::plugin --custommode=awscli --mode=traffic --region='eu-west-1' --filter-vpn='vpn-1234567890abcdefg' --warning-tunnel-state='1:' --critical-tunnel-state='0.5:' --warning --verbose See 'https://docs.aws.amazon.com/vpn/latest/s2svpn/monitoring-cloudwatch-vpn.html' for more information. =over 8 =item B<--filter-vpn> Filter on a specific VPN connection. This can be done on the VPN ID (default) or on the VPN name if the option '--name' is specified. =item B<--name> Rather use VPN names in display than IDs. =item B<--filter-metric> Filter on a specific metric. Can be: TunnelState, TunnelDataIn, TunnelDataOut =item B<--warning-$metric$> Warning thresholds ($metric$ can be: 'tunnel-state', 'tunnel-datain', 'tunnel-dataout'). =item B<--critical-$metric$> Critical thresholds ($metric$ can be: 'tunnel-state', 'tunnel-datain', 'tunnel-dataout'). =back =cut centreon-plugins-20220113/cloud/aws/vpn/plugin.pm000066400000000000000000000026271417000230700216020ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::aws::vpn::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} = '1.0'; %{ $self->{modes} } = ( 'traffic' => 'cloud::aws::vpn::mode::traffic', 'list-vpn' => 'cloud::aws::vpn::mode::listvpn' ); $self->{custom_modes}{paws} = 'cloud::aws::custom::paws'; $self->{custom_modes}{awscli} = 'cloud::aws::custom::awscli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Amazon Site-To-Site VPN (Amazon VPN). =cut centreon-plugins-20220113/cloud/azure/000077500000000000000000000000001417000230700174705ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/analytics/000077500000000000000000000000001417000230700214575ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/analytics/eventhubs/000077500000000000000000000000001417000230700234625ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/analytics/eventhubs/mode/000077500000000000000000000000001417000230700244065ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/analytics/eventhubs/mode/backlog.pm000066400000000000000000000125311417000230700263500ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::analytics::eventhubs::mode::backlog; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'CaptureBacklog' => { 'output' => 'Capture Backlog', 'label' => 'backlog-capture', 'nlabel' => 'eventhubs.backlog.capture.count', 'unit' => '', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' }, 'resource-type:s' => { name => 'resource_type' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group & --resource-type options or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; if ($resource !~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.EventHub\/(.*)\/(.*)$/ && (!defined($self->{option_results}->{resource_group}) || $self->{option_results}->{resource_group} eq '' || !defined($self->{option_results}->{resource_type}) || $self->{option_results}->{resource_type} eq '')) { $self->{output}->add_option_msg(short_msg => 'Invalid or missing --resource-group or --resource-type option'); $self->{output}->option_exit(); } my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; my $resource_type = defined($self->{option_results}->{resource_type}) ? $self->{option_results}->{resource_type} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.EventHub\/(.*)\/(.*)$/) { $resource_group = $1; $resource_type = $2; $resource = $3; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = $resource_type; $self->{az_resource_namespace} = 'Microsoft.EventHub'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Event Hubs backlog statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::analytics::eventhubs::plugin --mode=backlog --custommode=api --resource= --resource-group= --resource-type= --aggregation='total' --warning-backlog-capture='1000' --critical-backlog-capture='2000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::analytics::eventhubs::plugin --mode=backlog --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.EventHub//' --aggregation='total' --warning-backlog-capture='1000' --critical-backlog-capture='2000' Default aggregation: 'total' / 'average', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--resource-type> Set resource group (Required if resource's name is used). Can be: 'namespaces', 'clusters'. =item B<--warning-backlog-capture> Warning threshold. =item B<--critical-backlog-capture> Critical threshold. =back =cut centreon-plugins-20220113/cloud/azure/analytics/eventhubs/mode/connections.pm000066400000000000000000000140261417000230700272710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::analytics::eventhubs::mode::connections; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'activeconnections' => { 'output' => 'Active Connections', 'label' => 'active-connections', 'nlabel' => 'eventhubs.connections.active.count', 'unit' => '', 'min' => '0' }, 'connectionsclosed' => { 'output' => 'Connections Closed', 'label' => 'closed-connections', 'nlabel' => 'eventhubs.connections.closed.count', 'unit' => '', 'min' => '0' }, 'connectionsopened' => { 'output' => 'Connections Opened', 'label' => 'opened-connections', 'nlabel' => 'eventhubs.connections.opened.count', 'unit' => '', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' }, 'resource-type:s' => { name => 'resource_type' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group & --resource-type options or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; if ($resource !~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.EventHub\/(.*)\/(.*)$/ && (!defined($self->{option_results}->{resource_group}) || $self->{option_results}->{resource_group} eq '' || !defined($self->{option_results}->{resource_type}) || $self->{option_results}->{resource_type} eq '')) { $self->{output}->add_option_msg(short_msg => 'Invalid or missing --resource-group or --resource-type option'); $self->{output}->option_exit(); } my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; my $resource_type = defined($self->{option_results}->{resource_type}) ? $self->{option_results}->{resource_type} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.EventHub\/(.*)\/(.*)$/) { $resource_group = $1; $resource_type = $2; $resource = $3; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = $resource_type; $self->{az_resource_namespace} = 'Microsoft.EventHub'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Event Hubs connections statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::analytics::eventhubs::plugin --mode=connections --custommode=api --resource= --resource-group= --resource-type= --aggregation='average' --warning-active-connections='1000' --critical-active-connections='2000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::analytics::eventhubs::plugin --mode=connections --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.EventHub//' --aggregation='average' --warning-active-connections='1000' --critical-active-connections='2000' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--resource-type> Set resource group (Required if resource's name is used). Can be: 'namespaces', 'clusters'. =item B<--warning-*> Warning threshold where '*' can be: 'active-connections', 'opened-connections', 'closed-connections'. =item B<--critical-*> Critical threshold where '*' can be: 'active-connections', 'opened-connections', 'closed-connections'. =back =cut centreon-plugins-20220113/cloud/azure/analytics/eventhubs/mode/discovery.pm000066400000000000000000000105371417000230700267610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::analytics::eventhubs::mode::discovery; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-type:s' => { name => 'filter_type' }, 'resource-group:s' => { name => 'resource_group' }, 'location:s' => { name => 'location' }, 'prettify' => { name => 'prettify' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); $self->{namespace} = 'Microsoft.EventHub'; $self->{filter_type} = $self->{option_results}->{filter_type}; $self->{location} = $self->{option_results}->{location}; $self->{resource_group} = $self->{option_results}->{resource_group}; } sub run { my ($self, %options) = @_; my @disco_data; my $disco_stats; $disco_stats->{start_time} = time(); my ($resources, $custom_resources); foreach my $resource_type ('namespaces', 'clusters') { next if (defined($self->{filter_type}) && $self->{filter_type} ne '' && $resource_type !~ /$self->{filter_type}/); $custom_resources->{$resource_type} = $options{custom}->azure_list_resources( namespace => $self->{namespace}, resource_type => $resource_type, location => $self->{location}, resource_group => $self->{resource_group} ); }; $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; foreach (keys %{$custom_resources}) { foreach my $resource (@{$custom_resources->{$_}}) { $resource->{type} =~ s/Microsoft\.EventHub\///; my $resource_group = ''; $resource_group = $resource->{resourceGroup} if (defined($resource->{resourceGroup})); $resource_group = $1 if ($resource_group eq '' && defined($resource->{id}) && $resource->{id} =~ /resourceGroups\/(.*)\/providers/); $resource->{resourceGroup} = $resource_group; foreach my $entry (keys %{$resource}) { next if (ref($resource->{$entry}) ne "HASH"); my @array; foreach my $key (keys %{$resource->{$entry}}) { push @array, { key => $key, value => $resource->{$entry}->{$key} }; } $resource->{$entry} = \@array; } push @disco_data, $resource; } } $disco_stats->{discovered_items} = @disco_data; $disco_stats->{results} = \@disco_data; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE Azure Event Hubs Resources discovery. =over 8 =item B<--namespace> Specify resources namespace. =item B<--filter-type> Only discover resources of a specific type. Can be 'clusters', 'namespaces'. =item B<--resource-group> Specify resources resource group. =item B<--location> Specify resources location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/analytics/eventhubs/mode/errors.pm000066400000000000000000000136711417000230700262700ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::analytics::eventhubs::mode::errors; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'quotaexceedederrors' => { 'output' => 'Quota Exceeded Errors', 'label' => 'quota-exceeded-errors', 'nlabel' => 'eventhubs.errors.quotaexceeded.count', 'unit' => '', 'min' => '0' }, 'servererrors' => { 'output' => 'Server Errors', 'label' => 'server-errors', 'nlabel' => 'eventhubs.errors.server.count', 'unit' => '', 'min' => '0' }, 'usererrors' => { 'output' => 'User Errors', 'label' => 'user-errors', 'nlabel' => 'eventhubs.errors.user.count', 'unit' => '', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' }, 'resource-type:s' => { name => 'resource_type' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group & --resource-type options or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; if ($resource !~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.EventHub\/(.*)\/(.*)$/ && (!defined($self->{option_results}->{resource_group}) || $self->{option_results}->{resource_group} eq '' || !defined($self->{option_results}->{resource_type}) || $self->{option_results}->{resource_type} eq '')) { $self->{output}->add_option_msg(short_msg => 'Invalid or missing --resource-group or --resource-type option'); $self->{output}->option_exit(); } my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; my $resource_type = defined($self->{option_results}->{resource_type}) ? $self->{option_results}->{resource_type} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.EventHub\/(.*)\/(.*)$/) { $resource_group = $1; $resource_type = $2; $resource = $3; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = $resource_type; $self->{az_resource_namespace} = 'Microsoft.EventHub'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Event Hub errors statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::analytics::eventhubs::plugin --mode=errors --custommode=api --resource= --resource-group= --resource-type= --aggregation='average' --warning-active-errors='1000' --critical-active-errors='2000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::analytics::eventhubs::plugin --mode=errors --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.EventHub//' --aggregation='average' --warning-active-errors='1000' --critical-active-errors='2000' Default aggregation: 'total' / 'average', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--resource-type> Set resource group (Required if resource's name is used). Can be: 'namespaces', 'clusters'. =item B<--warning-*> Warning threshold where '*' can be: 'server-errors', 'user-errors', 'quota-exceeded-errors'. =item B<--critical-*> Critical threshold where '*' can be: 'server-errors', 'user-errors', 'quota-exceeded-errors'. =back =cut centreon-plugins-20220113/cloud/azure/analytics/eventhubs/mode/health.pm000066400000000000000000000035501417000230700262140ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::analytics::eventhubs::mode::health; use base qw(cloud::azure::management::monitor::mode::health); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{az_resource_namespace} = 'Microsoft.EventHub'; } 1; __END__ =head1 MODE Check Event Hubs namespace/cluster status. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{summary} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /^Unavailable$/'). Can used special variables like: %{status}, %{summary} =item B<--unknown-status> Set unknown threshold for status (Default: '%{status} =~ /^Unknown$/'). Can used special variables like: %{status}, %{summary} =item B<--ok-status> Set ok threshold for status (Default: '%{status} =~ /^Available$/'). Can used special variables like: %{status}, %{summary} =back =cut centreon-plugins-20220113/cloud/azure/analytics/eventhubs/mode/messages.pm000066400000000000000000000140011417000230700265470ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::analytics::eventhubs::mode::messages; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'capturedmessages' => { 'output' => 'Captured messages', 'label' => 'captured-messages', 'nlabel' => 'eventhubs.messages.captured.count', 'unit' => '', 'min' => '0' }, 'incomingmessages' => { 'output' => 'Incoming Messages', 'label' => 'incoming-messages', 'nlabel' => 'eventhubs.messages.incoming.count', 'unit' => '', 'min' => '0' }, 'outgoingmessages' => { 'output' => 'Outgoing Messages', 'label' => 'outgoing-messages', 'nlabel' => 'eventhubs.messages.outgoing.count', 'unit' => '', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' }, 'resource-type:s' => { name => 'resource_type' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group & --resource-type options or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; if ($resource !~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.EventHub\/(.*)\/(.*)$/ && (!defined($self->{option_results}->{resource_group}) || $self->{option_results}->{resource_group} eq '' || !defined($self->{option_results}->{resource_type}) || $self->{option_results}->{resource_type} eq '')) { $self->{output}->add_option_msg(short_msg => 'Invalid or missing --resource-group or --resource-type option'); $self->{output}->option_exit(); } my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; my $resource_type = defined($self->{option_results}->{resource_type}) ? $self->{option_results}->{resource_type} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.EventHub\/(.*)\/(.*)$/) { $resource_group = $1; $resource_type = $2; $resource = $3; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = $resource_type; $self->{az_resource_namespace} = 'Microsoft.EventHub'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Event Hubs messages statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::analytics::eventhubs::plugin --mode=messages --custommode=api --resource= --resource-group= --resource-type= --aggregation='total' --warning-eventhub-active-messages='1000' --critical-eventhub-active-messages='2000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::analytics::eventhubs::plugin --mode=messages --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.EventHub//' --aggregation='total' --warning-eventhub-active-messages='1000' --critical-eventhub-active-messages='2000' Default aggregation: 'total' / 'average', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--resource-type> Set resource group (Required if resource's name is used). Can be: 'namespaces', 'clusters'. =item B<--warning-*> Warning threshold where '*' can be: 'captured-messages', 'outgoing-messages', 'incoming-messages'. =item B<--critical-*> Critical threshold where '*' can be: 'captured-messages', 'outgoing-messages', 'incoming-messages'. =back =cut centreon-plugins-20220113/cloud/azure/analytics/eventhubs/mode/requests.pm000066400000000000000000000137661417000230700266340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::analytics::eventhubs::mode::requests; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'incomingrequests' => { 'output' => 'Incoming Requests', 'label' => 'incoming-requests', 'nlabel' => 'eventhubs.requests.incoming.count', 'unit' => '', 'min' => '0' }, 'successfulrequests' => { 'output' => 'Successful Requests', 'label' => 'successful-requests', 'nlabel' => 'eventhubs.requests.successful.count', 'unit' => '', 'min' => '0' }, 'throttledrequests' => { 'output' => 'Throttled Requests', 'label' => 'throttled-requests', 'nlabel' => 'eventhubs.requests.throttled.count', 'unit' => '', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' }, 'resource-type:s' => { name => 'resource_type' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group & --resource-type options or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; if ($resource !~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.EventHub\/(.*)\/(.*)$/ && (!defined($self->{option_results}->{resource_group}) || $self->{option_results}->{resource_group} eq '' || !defined($self->{option_results}->{resource_type}) || $self->{option_results}->{resource_type} eq '')) { $self->{output}->add_option_msg(short_msg => 'Invalid or missing --resource-group or --resource-type option'); $self->{output}->option_exit(); } my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; my $resource_type = defined($self->{option_results}->{resource_type}) ? $self->{option_results}->{resource_type} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.EventHub\/(.*)\/(.*)$/) { $resource_group = $1; $resource_type = $2; $resource = $3; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = $resource_type; $self->{az_resource_namespace} = 'Microsoft.EventHub'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Event Hub requests statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::analytics::eventhubs::plugin --mode=requests --custommode=api --resource= --resource-group= --resource-type= --aggregation='total' --warning-throttled-requests='800' --critical-throttled-requests='900' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::analytics::eventhubs::plugin --mode=requests --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.EventHub//' --aggregation='total' --warning-throttled-requests='800' --critical-throttled-requests='900' Default aggregation: 'total' / 'average', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--resource-type> Set resource group (Required if resource's name is used). Can be: 'namespaces', 'clusters'. =item B<--warning-*> Warning threshold where '*' can be: 'incoming-requests', 'throttled-requests', 'successful-requests'. =item B<--critical-*> Critical threshold where '*' can be: 'incoming-requests', 'throttled-requests', 'successful-requests'. =back =cut centreon-plugins-20220113/cloud/azure/analytics/eventhubs/mode/throughput.pm000066400000000000000000000137201417000230700271600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::analytics::eventhubs::mode::throughput; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'capturedbytes' => { 'output' => 'Captured Bytes', 'label' => 'captured-bytes', 'nlabel' => 'eventhubs.throughput.captured.bytes', 'unit' => 'B', 'min' => '0' }, 'IncomingBytes' => { 'output' => 'Incoming Bytes', 'label' => 'incoming-bytes', 'nlabel' => 'eventhubs.throughput.incoming.bytes', 'unit' => 'B', 'min' => '0' }, 'OutgoingBytes' => { 'output' => 'Outgoing Bytes', 'label' => 'outgoing-bytes', 'nlabel' => 'eventhubs.throughput.outgoing.bytes', 'unit' => 'B', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' }, 'resource-type:s' => { name => 'resource_type' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group & --resource-type options or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; if ($resource !~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.EventHub\/(.*)\/(.*)$/ && (!defined($self->{option_results}->{resource_group}) || $self->{option_results}->{resource_group} eq '' || !defined($self->{option_results}->{resource_type}) || $self->{option_results}->{resource_type} eq '')) { $self->{output}->add_option_msg(short_msg => 'Invalid or missing --resource-group or --resource-type option'); $self->{output}->option_exit(); } my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; my $resource_type = defined($self->{option_results}->{resource_type}) ? $self->{option_results}->{resource_type} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.EventHub\/(.*)\/(.*)$/) { $resource_group = $1; $resource_type = $2; $resource = $3; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = $resource_type; $self->{az_resource_namespace} = 'Microsoft.EventHub'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Event Hub throughput statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::analytics::eventhubs::plugin --mode=throughput --custommode=api --resource= --resource-group= --resource-type= --aggregation='total' --warning-incoming-bytes='800000000' --critical-incoming-bytes='900000000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::analytics::eventhubs::plugin --mode=throughput --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.EventHub//' --aggregation='total' --warning-incoming-bytes='800000000' --critical-incoming-bytes='900000000' Default aggregation: 'total' / 'average', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--resource-type> Set resource group (Required if resource's name is used). Can be: 'namespaces', 'clusters'. =item B<--warning-*> Warning threshold where '*' can be: 'outgoing-bytes', 'captured-bytes', 'incoming-bytes'. =item B<--critical-*> Critical threshold where '*' can be: 'outgoing-bytes', 'captured-bytes', 'incoming-bytes'. =back =cut centreon-plugins-20220113/cloud/azure/analytics/eventhubs/plugin.pm000066400000000000000000000042201417000230700253140ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::analytics::eventhubs::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} = { 'backlog' => 'cloud::azure::analytics::eventhubs::mode::backlog', 'connections' => 'cloud::azure::analytics::eventhubs::mode::connections', 'discovery' => 'cloud::azure::analytics::eventhubs::mode::discovery', 'errors' => 'cloud::azure::analytics::eventhubs::mode::errors', 'health' => 'cloud::azure::analytics::eventhubs::mode::health', 'messages' => 'cloud::azure::analytics::eventhubs::mode::messages', 'requests' => 'cloud::azure::analytics::eventhubs::mode::requests', 'throughput' => 'cloud::azure::analytics::eventhubs::mode::throughput' }; $self->{custom_modes}->{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}->{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' }, }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure Event Hubs namespaces & clusters. =cut centreon-plugins-20220113/cloud/azure/common/000077500000000000000000000000001417000230700207605ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/common/appservice/000077500000000000000000000000001417000230700231215ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/common/appservice/mode/000077500000000000000000000000001417000230700240455ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/common/appservice/mode/appusage.pm000066400000000000000000000136011417000230700262110ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::common::appservice::mode::appusage; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'appconnections' => { 'output' => 'Connections', 'label' => 'connections', 'nlabel' => 'appservice.connections.count', 'unit' => '', 'min' => '0', 'max' => '' }, 'currentassemblies' => { 'output' => 'Current Assemblies', 'label' => 'assemblies', 'nlabel' => 'appservice.assemblies.current.count', 'unit' => '', 'min' => '0', 'max' => '' }, 'handles' => { 'output' => 'Handle Count', 'label' => 'handle', 'nlabel' => 'appservice.handle.count', 'unit' => '', 'min' => '0', 'max' => '' }, 'threads' => { 'output' => 'Thread Count', 'label' => 'thread', 'nlabel' => 'appservice.thread.count', 'unit' => '', 'min' => '0', 'max' => '' }, 'totalappdomains' => { 'output' => 'Total App Domains', 'label' => 'app-domains', 'nlabel' => 'appservice.appdomains.count', 'unit' => '', 'min' => '0', 'max' => '' }, 'totalappdomainsunloaded' => { 'output' => 'Total App Domains Unloaded', 'label' => 'app-domain-unloaded', 'nlabel' => 'appservice.appdomains.unloaded.count', 'unit' => '', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Web\/sites\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'sites'; $self->{az_resource_namespace} = 'Microsoft.Web'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure App Service app usage. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::common::appservice::plugin --mode=app-usage --custommode=api --resource= --resource-group= --aggregation='total' --warning-thread='80' --critical-thread='90' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::common::appservice::plugin --mode=app-usage --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Web/sites/' --aggregation='average' --warning-thread='80' --critical-thread='90' Default aggregation: 'average' / 'minimum', 'maximum' and 'total' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'connections', 'assemblies', 'handle', 'thread', 'app-domains', 'app-domain-unloaded'. =item B<--critical-*> Critical threshold where '*' can be:. 'connections', 'assemblies', 'handle', 'thread', 'app-domains', 'app-domain-unloaded'. =back =cut centreon-plugins-20220113/cloud/azure/common/appservice/mode/cputime.pm000066400000000000000000000106741417000230700260610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::common::appservice::mode::cputime; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'cputime' => { 'output' => 'CPU Time', 'label' => 'cpu-time', 'nlabel' => 'appservice.cpu.consumed.seconds', 'unit' => 's', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Web\/sites\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'sites'; $self->{az_resource_namespace} = 'Microsoft.Web'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure App Service CPU time consumed by the app. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::common::appservice::plugin --mode=cpu-time --custommode=api --resource= --resource-group= --aggregation='total' --warning-cpu-time='80' --critical-cpu-time='90' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::common::appservice::plugin --mode=cpu-time --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Web/sites/' --aggregation='total' --warning-cpu-time='80' --critical-cpu-time='90' Default aggregation: 'total' / 'minimum', 'maximum' and 'average' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-cpu-time> Consumed CPU time warning threshold. =item B<--critical-cpu-time> Consumed CPU time critical threshold. =back =cut centreon-plugins-20220113/cloud/azure/common/appservice/mode/data.pm000066400000000000000000000113301417000230700253120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::common::appservice::mode::data; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'bytesreceived' => { 'output' => 'Data In', 'label' => 'data-in', 'nlabel' => 'appservice.data.in.bytes', 'unit' => 'B', 'min' => '0', 'max' => '' }, 'bytessent' => { 'output' => 'Data Out', 'label' => 'data-out', 'nlabel' => 'appservice.data.out.bytes', 'unit' => 'B', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Web\/sites\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'sites'; $self->{az_resource_namespace} = 'Microsoft.Web'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure App Service bandwith consumed by the app. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::common::appservice::plugin --mode=data --custommode=api --resource= --resource-group= --aggregation='total' --warning-data-in='80000' --critical-data-in='90000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::common::appservice::plugin --mode=data --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Web/sites/' --aggregation='total' --warning-data-in='80000' --critical-data-in='90000' Default aggregation: 'total' / 'minimum', 'maximum' and 'average' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'data-in', 'data-out'. =item B<--critical-*> Critical threshold where '*' can be:. 'data-in', 'data-out'. =back =cut centreon-plugins-20220113/cloud/azure/common/appservice/mode/discovery.pm000066400000000000000000000024171417000230700264160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::common::appservice::mode::discovery; use base qw(cloud::azure::management::monitor::mode::discovery); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{namespace} = 'Microsoft.Web'; $self->{type} = 'sites'; } 1; __END__ =head1 MODE Azure App Service discovery. =over 8 =item B<--resource-group> Specify resource group. =item B<--location> Specify location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/common/appservice/mode/filesystem.pm000066400000000000000000000107241417000230700265730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::common::appservice::mode::filesystem; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'filesystemusage' => { 'output' => 'File System Usage', 'label' => 'usage', 'nlabel' => 'appservice.filesystem.usage.bytes', 'unit' => 'B', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Web\/sites\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'sites'; $self->{az_resource_namespace} = 'Microsoft.Web'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT6H'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure App Service file system usage. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::common::appservice::plugin --mode=filesystem-usage --custommode=api --resource= --resource-group= --aggregation='average' --warning-usage='80000' --critical-usage='90000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::common::appservice::plugin --mode=filesystem-usage --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Web/sites/' --aggregation='average' --warning-usage='80000' --critical-usage='90000' Default aggregation: 'average' / 'minimum', 'maximum' and 'total' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-usage> File system usage warning threshold. =item B<--critical-usage> File system usage critical threshold. =back =cut centreon-plugins-20220113/cloud/azure/common/appservice/mode/gcusage.pm000066400000000000000000000120051417000230700260170ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::common::appservice::mode::gcusage; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'gen0collections' => { 'output' => 'Gen 0 Garbage Collections', 'label' => 'gc-gen0', 'nlabel' => 'appservice.gc.gen0.count', 'unit' => '', 'min' => '0', 'max' => '' }, 'gen1collections' => { 'output' => 'Gen 1 Garbage Collections', 'label' => 'gc-gen2', 'nlabel' => 'appservice.gc.gen1.count', 'unit' => '', 'min' => '0', 'max' => '' }, 'Gen2collections' => { 'output' => 'Gen 2 Garbage Collections', 'label' => 'gc-gen2', 'nlabel' => 'appservice.gc.gen2.count', 'unit' => '', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Web\/sites\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'sites'; $self->{az_resource_namespace} = 'Microsoft.Web'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure App Service garbage collector. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::common::appservice::plugin --mode=gc-usage --custommode=api --resource= --resource-group= --aggregation='total' --warning-gc-gen0='80' --critical-gc-gen0='90' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::common::appservice::plugin --mode=gc-usage --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Web/sites/' --aggregation='total' --warning-gc-gen0='80' --critical-gc-gen0='90' Default aggregation: 'total' / 'minimum', 'maximum' and 'average' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'gc-gen0', 'gc-gen1', 'gc-gen2'. =item B<--critical-*> Critical threshold where '*' can be:. 'gc-gen0', 'gc-gen1', 'gc-gen2'. =back =cut centreon-plugins-20220113/cloud/azure/common/appservice/mode/health.pm000066400000000000000000000036251417000230700256560ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::common::appservice::mode::health; use base qw(cloud::azure::management::monitor::mode::health); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{az_resource_namespace} = 'Microsoft.Web'; $self->{az_resource_type} = 'sites'; } 1; __END__ =head1 MODE Check Azure App Service health status. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-status> Set warning threshold for status (Default: ''). Special variables that can be used: %{status}, %{summary}. =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /^Unavailable$/'). Special variables that can be used: %{status}, %{summary}. =item B<--unknown-status> Set unknown threshold for status (Default: '%{status} =~ /^Unknown$/'). Special variables that can be used: %{status}, %{summary}. =item B<--ok-status> Set ok threshold for status (Default: '%{status} =~ /^Available$/'). Special variables that can be used: %{status}, %{summary}. =back =cut centreon-plugins-20220113/cloud/azure/common/appservice/mode/httprequests.pm000066400000000000000000000163041417000230700271620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::common::appservice::mode::httprequests; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'requests' => { 'output' => 'Requests', 'label' => 'requests', 'nlabel' => 'appservice.http.request.count', 'unit' => '', 'min' => '0', 'max' => '' }, 'requestsinapplicationqueue' => { 'output' => 'Requests In Application Queue', 'label' => 'requests-queue', 'nlabel' => 'appservice.http.request.queue.count', 'unit' => '', 'min' => '0', 'max' => '' }, 'http101' => { 'output' => 'Http 101', 'label' => 'http-101', 'nlabel' => 'appservice.htpp.request.101.count', 'unit' => '', 'min' => '0', 'max' => '' }, 'http2xx' => { 'output' => 'Http 2xx', 'label' => 'http-2xx', 'nlabel' => 'appservice.htpp.request.2xx.count', 'unit' => '', 'min' => '0', 'max' => '' }, 'http3xx' => { 'output' => 'Http 3xx', 'label' => 'http-3xx', 'nlabel' => 'appservice.htpp.request.3xx.count', 'unit' => '', 'min' => '0', 'max' => '' }, 'http4xx' => { 'output' => 'Http 4xx', 'label' => 'http-4xx', 'nlabel' => 'appservice.htpp.request.4xx.count', 'unit' => '', 'min' => '0', 'max' => '' }, 'http401' => { 'output' => 'Http 401', 'label' => 'http-401', 'nlabel' => 'appservice.htpp.request.401.count', 'unit' => '', 'min' => '0', 'max' => '' }, 'http403' => { 'output' => 'Http 403', 'label' => 'http-403', 'nlabel' => 'appservice.htpp.request.403.count', 'unit' => '', 'min' => '0', 'max' => '' }, 'http404' => { 'output' => 'Http 404', 'label' => 'http-404', 'nlabel' => 'appservice.htpp.request.404.count', 'unit' => '', 'min' => '0', 'max' => '' }, 'http406' => { 'output' => 'Http 406', 'label' => 'http-406', 'nlabel' => 'appservice.htpp.request.406.count', 'unit' => '', 'min' => '0', 'max' => '' }, 'http5xx' => { 'output' => 'Http 5xx', 'label' => 'http-5xx', 'nlabel' => 'appservice.htpp.request.5xx.count', 'unit' => '', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Web\/sites\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'sites'; $self->{az_resource_namespace} = 'Microsoft.Web'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure App Service HTTP requests count. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::common::appservice::plugin --mode=http-requests --custommode=api --resource= --resource-group= --aggregation='total' --warning-requests='80' --critical-requests='90' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::common::appservice::plugin --mode=http-requests --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Web/sites/' --aggregation='total' --warning-requests='80' --critical-requests='90' Default aggregation: 'total' / 'minimum', 'maximum' and 'average' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'requests', 'requests-queue', 'http-101', 'http-2xx', 'http-3xx', 'http-4xx', 'http-401','http-403', 'http-404', 'http-406', 'http-5xx'. =item B<--critical-*> Critical threshold where '*' can be:. 'requests', 'requests-queue', 'http-101', 'http-2xx', 'http-3xx', 'http-4xx', 'http-401','http-403', 'http-404', 'http-406', 'http-5xx'. =back =cut centreon-plugins-20220113/cloud/azure/common/appservice/mode/iooperations.pm000066400000000000000000000142641417000230700271250ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::common::appservice::mode::iooperations; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'iootherbytespersecond' => { 'output' => 'IO Other Bytes Per Second', 'label' => 'other-bytes', 'nlabel' => 'appservice.bytes.other.bytespersecond', 'unit' => 'B/s', 'min' => '0', 'max' => '' }, 'iootheroperationspersecond' => { 'output' => 'IO Other Operations Per Second', 'label' => 'other-operations', 'nlabel' => 'appservice.operations.other.bytespersecond', 'unit' => 'B/s', 'min' => '0', 'max' => '' }, 'ioreadbytespersecond' => { 'output' => 'IO Read Bytes Per Second', 'label' => 'read-bytes', 'nlabel' => 'appservice.bytes.read.bytespersecond', 'unit' => 'B/s', 'min' => '0', 'max' => '' }, 'ioreadoperationspersecond' => { 'output' => 'IO Read Operations Per Second', 'label' => 'read-operations', 'nlabel' => 'appservice.operations.read.bytespersecond', 'unit' => 'B/s', 'min' => '0', 'max' => '' }, 'iowritebytespersecond' => { 'output' => 'IO Write Bytes Per Second', 'label' => 'write-bytes', 'nlabel' => 'appservice.bytes.write.bytespersecond', 'unit' => 'B/s', 'min' => '0', 'max' => '' }, 'iowriteoperationspersecond' => { 'output' => 'IO Write Operations Per Second', 'label' => 'write-operations', 'nlabel' => 'appservice.operations.write.bytespersecond', 'unit' => 'B/s', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Web\/sites\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'sites'; $self->{az_resource_namespace} = 'Microsoft.Web'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure App Service I/O operations by the app. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::common::appservice::plugin --mode=io-operations --custommode=api --resource= --resource-group= --aggregation='total' --warning-write-bytes='80000' --critical-write-bytes='90000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::common::appservice::plugin --mode=io-operations --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Web/sites/' --aggregation='total' --warning-write-bytes='80000' --critical-write-bytes='90000' Default aggregation: 'total' / 'minimum', 'maximum' and 'average' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'other-bytes', 'other-operations', 'read-bytes', 'read-operations', 'write-bytes', 'write-operations'. =item B<--critical-*> Critical threshold where '*' can be:. 'other-bytes', 'other-operations', 'read-bytes', 'read-operations', 'write-bytes', 'write-operations'. =back =cut centreon-plugins-20220113/cloud/azure/common/appservice/mode/memory.pm000066400000000000000000000122111417000230700257100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::common::appservice::mode::memory; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'averagememoryworkingset' => { 'output' => 'Average memory working set', 'label' => 'app-average-memory', 'nlabel' => 'appservice.memory.average.usage.bytes', 'unit' => 'B', 'min' => '0', 'max' => '', }, 'memoryworkingset' => { 'output' => 'Memory working set', 'label' => 'app-memory', 'nlabel' => 'appservice.memory.usage.bytes', 'unit' => 'B', 'min' => '0', 'max' => '', }, 'privatebytes' => { 'output' => 'Private Bytes', 'label' => 'app-private-bytes', 'nlabel' => 'appservice.memory.privatebytes.usage.bytes', 'unit' => 'B', 'min' => '0', 'max' => '', } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Web\/sites\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'sites'; $self->{az_resource_namespace} = 'Microsoft.Web'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure App Service app memory usage. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::common::appservice::plugin --mode=memory --custommode=api --resource= --resource-group= --aggregation='average' --warning-app-memory='80' --critical-app-memory='90' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::common::appservice::plugin --mode=memory --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Web/sites/' --aggregation='average' --warning-app-memory='80' --critical-app-memory='90' Default aggregation: 'average' / 'minimum', 'maximum' and 'total' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'app-average-memory', 'app-memory', 'app-private-bytes'. =item B<--critical-*> Critical threshold where '*' can be:. 'app-average-memory', 'app-memory', 'app-private-bytes'. =back =cut centreon-plugins-20220113/cloud/azure/common/appservice/mode/responsetime.pm000066400000000000000000000107641417000230700271300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::common::appservice::mode::responsetime; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'httpresponsetime' => { 'output' => 'Response Time', 'label' => 'response-time', 'nlabel' => 'appservice.http.response.time.seconds', 'unit' => 's', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Web\/sites\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'sites'; $self->{az_resource_namespace} = 'Microsoft.Web'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure App Service HTTP response time. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::common::appservice::plugin --mode=response-time --custommode=api --resource= --resource-group= --aggregation='average' --warning-response-time='80' --critical-response-time='90' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::common::appservice::plugin --mode=response-time --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Web/sites/' --aggregation='total' --warning-response-time='80' --critical-response-time='90' Default aggregation: 'average' / 'minimum', 'maximum' and 'total' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-response-time> Response time warning threshold. =item B<--critical-response-time> Response time critical threshold. =back =cut centreon-plugins-20220113/cloud/azure/common/appservice/mode/status.pm000066400000000000000000000106721417000230700257340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::common::appservice::mode::status; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'healthcheckstatus' => { 'output' => 'Health check status', 'label' => 'status', 'nlabel' => 'appservice.status.count', 'unit' => '', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Web\/sites\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'sites'; $self->{az_resource_namespace} = 'Microsoft.Web'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure App Service app health status. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::common::appservice::plugin --mode=status --custommode=api --resource= --resource-group= --aggregation='average' --warning-status='80000'' --critical-status='90000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::common::appservice::plugin --mode=filesystem-status --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Web/sites/' --aggregation='average' --warning-status='80000' --critical-status='90000' Default aggregation: 'average' / 'minimum', 'maximum' and 'total' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-status> App status warning threshold. =item B<--critical-status> App status critical threshold. =back =cut centreon-plugins-20220113/cloud/azure/compute/000077500000000000000000000000001417000230700211445ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/compute/aks/000077500000000000000000000000001417000230700217225ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/compute/aks/mode/000077500000000000000000000000001417000230700226465ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/compute/aks/mode/allocatableresources.pm000066400000000000000000000123751417000230700274120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::compute::aks::mode::allocatableresources; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'kube_node_status_allocatable_cpu_cores' => { 'output' => 'Allocatable CPU Cores', 'label' => 'allocatable-cpu-cores', 'nlabel' => 'aks.node.allocatable.cpu.cores', 'unit' => '', 'min' => '0', }, 'kube_node_status_allocatable_memory_bytes' => { 'output' => 'Allocatable Memory Bytes', 'label' => 'allocatable-memory-bytes', 'nlabel' => 'aks.node.allocatable.memory.bytes', 'unit' => 'B', 'min' => '0', } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; my $resource_type = $self->{option_results}->{resource_type}; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.ContainerService\/managedClusters\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'managedClusters'; $self->{az_resource_namespace} = 'Microsoft.ContainerService'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check remaining Azure Kubernetes Cluster Allocatable CPU Cores and Memory in Bytes. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::compute::aks::plugin --mode=allocatable-resources --custommode=api --resource= --resource-group= --warning-allocatable-memory-bytes=16GB: --critical-allocatable-memory-bytes=8GB: Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::compute::aks::plugin --mode=allocatable-resources --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.ContainerService/managedClusters/' --warning-allocatable-memory-bytes=16GB: --critical-allocatable-memory-bytes=8GB: =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-allocatable-memory-bytes> Set warning threshold for remaining allocatable memory in bytes. It is a range, set 16GB: to get WARNING if there are less than 16GB allocatable left. =item B<--critical-allocatable-memory-bytes> Set critical threshold for remaining allocatable memory in bytes. It is a range, set 8GB: to get CRITICAL if there are less than 8GB allocatable left. =item B<--warning-allocatable-cpu-cores> Set warning threshold for number of remaining allocatable CPU Cores. It is a range, set 10: to get WARNING if there are less than 10 CPU cores allocatable remaining. =item B<--critical-allocatable-cpu-cores> Set critical threshold for number of remaining allocatable CPU Cores. It is a range, set 5: to get CRITICAL if there are less than 5 CPU cores allocatable remaining. =back =cut centreon-plugins-20220113/cloud/azure/compute/aks/mode/cpu.pm000066400000000000000000000103201417000230700237670ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::compute::aks::mode::cpu; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'node_cpu_usage_percentage' => { 'output' => 'CPU percent', 'label' => 'cpu-usage', 'nlabel' => 'aks.node.cpu.utilization.percentage', 'unit' => '%', 'min' => '0', 'max' => '100' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; my $resource_type = $self->{option_results}->{resource_type}; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.ContainerService\/managedClusters\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'managedClusters'; $self->{az_resource_namespace} = 'Microsoft.ContainerService'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Kubernetes Cluster CPU usage in percentage. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::compute::aks::plugin --mode=cpu --custommode=api --resource= --resource-group= --warning-cpu-usage='80' --critical-cpu-usage='90' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::compute::aks::plugin --mode=cpu --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.ContainerService/managedClusters/' --warning-cpu-usage='80' --critical-cpu-usage='90' =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-cpu-usage> Set warning threshold for CPU utilization percentage. =item B<--critical-cpu-usage> Set critical threshold for CPU utilization percentage. =back =cut centreon-plugins-20220113/cloud/azure/compute/aks/mode/discovery.pm000066400000000000000000000023641417000230700252200ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::compute::aks::mode::discovery; use base qw(cloud::azure::management::monitor::mode::discovery); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{namespace} = 'Microsoft.ContainerService'; $self->{type} = 'managedClusters'; } 1; __END__ =head1 MODE Managed Cluster Discovery. =over 8 =item B<--location> Specify resources location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/compute/aks/mode/health.pm000066400000000000000000000037041417000230700244550ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::compute::aks::mode::health; use base qw(cloud::azure::management::monitor::mode::health); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{az_resource_namespace} = 'Microsoft.ContainerService'; $self->{az_resource_type} = 'managedClusters'; } 1; __END__ =head1 MODE Check Azure Kubernetes Cluster health status. (Usefull to determine host status) =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{summary} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /^Unavailable$/'). Can used special variables like: %{status}, %{summary} =item B<--unknown-status> Set unknown threshold for status (Default: '%{status} =~ /^Unknown$/'). Can used special variables like: %{status}, %{summary} =item B<--ok-status> Set ok threshold for status (Default: '%{status} =~ /^Available$/'). Can used special variables like: %{status}, %{summary} =back =cut centreon-plugins-20220113/cloud/azure/compute/aks/mode/storage.pm000066400000000000000000000110351417000230700246500ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::compute::aks::mode::storage; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'node_disk_usage_bytes' => { 'output' => 'Storage Used', 'label' => 'storage-used', 'nlabel' => 'aks.node.disk.usage.bytes', 'unit' => 'B', 'min' => '0' }, 'node_disk_usage_percentage' => { 'output' => 'Storage Percent', 'label' => 'storage-percent', 'nlabel' => 'aks.node.disk.usage.percentage', 'unit' => '%', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; my $resource_type = $self->{option_results}->{resource_type}; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.ContainerService\/managedClusters\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'managedClusters'; $self->{az_resource_namespace} = 'Microsoft.ContainerService'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Storage usage on Azure Kubernetes Cluster. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::compute::aks::plugin --mode=storage --custommode=api --resource= --resource-group= --warning-storage-percent='90' --critical-storage-percent='95' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::compute::aks::plugin --mode=storage --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.ContainerService/managedClusters/' --warning-storage-percent='90' --critical-storage-percent='95' =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-storage-used> Warning threshold in Bytes. =item B<--critical-storage-used> Critical threshold in Bytes. =item B<--warning-storage-percent> Warning threshold in percent. =item B<--critical-storage-percent> Critical threshold in percent. =back =cut centreon-plugins-20220113/cloud/azure/compute/aks/mode/traffic.pm000066400000000000000000000106661417000230700246330ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::compute::aks::mode::traffic; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'node_network_out_bytes' => { 'output' => 'Network Out', 'label' => 'traffic-out', 'nlabel' => 'aks.node.traffic.out.bytes', 'unit' => 'B', 'min' => '0', }, 'node_network_in_bytes' => { 'output' => 'Network In', 'label' => 'traffic-in', 'nlabel' => 'aks.node.traffic.in.bytes', 'unit' => 'B', 'min' => '0', } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; my $resource_type = $self->{option_results}->{resource_type}; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.ContainerService\/managedClusters\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'managedClusters'; $self->{az_resource_namespace} = 'Microsoft.ContainerService'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Kubernetes Cluster network traffic usage in Bytes. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::compute::aks::plugin --mode=traffic --custommode=api --resource= --resource-group= --warning-traffic-out=10000 --critical-traffic-in=15000 Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::compute::aks::plugin --mode=traffic --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.ContainerService/managedClusters/' --warning-traffic-out=10000 --critical-traffic-in=15000 =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'traffic-out', 'traffic-in'. =item B<--critical-*> Critical threshold where '*' can be: 'traffic-out', 'traffic-in'. =back =cut centreon-plugins-20220113/cloud/azure/compute/aks/mode/unneedednodes.pm000066400000000000000000000104351417000230700260270ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::compute::aks::mode::unneedednodes; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'cluster_autoscaler_unneeded_nodes_count' => { 'output' => 'Cluster Autoscaler Unneeded Nodes', 'label' => 'unneeded-nodes', 'nlabel' => 'aks.cluster.autoscaler.unneeded.nodes', 'unit' => '', 'min' => '0', } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; my $resource_type = $self->{option_results}->{resource_type}; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.ContainerService\/managedClusters\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'managedClusters'; $self->{az_resource_namespace} = 'Microsoft.ContainerService'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Kubernetes Cluster Autoscaler unneeded nodes. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::compute::aks::plugin --mode=unneedednodes --custommode=api --resource= --resource-group= --zeroed --warning-unneeded-nodes=5 --critical-unneeded-nodes=10 Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::compute::aks::plugin --mode=unneedednodes --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.ContainerService/managedClusters/' --zeroed --warning-unneeded-nodes=5 --critical-unneeded-nodes=10 =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-unneeded-nodes> Set warning threshold for number of unneeded nodes. =item B<--critical-unneeded-nodes> Set critical threshold for number of unneeded nodes. =back =cut centreon-plugins-20220113/cloud/azure/compute/aks/plugin.pm000066400000000000000000000040621417000230700235600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::compute::aks::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} = { 'allocatable-resources' => 'cloud::azure::compute::aks::mode::allocatableresources', 'cpu' => 'cloud::azure::compute::aks::mode::cpu', 'discovery' => 'cloud::azure::compute::aks::mode::discovery', 'health' => 'cloud::azure::compute::aks::mode::health', 'storage' => 'cloud::azure::compute::aks::mode::storage', 'traffic' => 'cloud::azure::compute::aks::mode::traffic', 'unneeded-nodes' => 'cloud::azure::compute::aks::mode::unneedednodes' }; $self->{custom_modes}->{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}->{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' }, }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure Kubernetes Service. =cut centreon-plugins-20220113/cloud/azure/compute/disk/000077500000000000000000000000001417000230700220765ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/compute/disk/mode/000077500000000000000000000000001417000230700230225ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/compute/disk/mode/discovery.pm000066400000000000000000000024251417000230700253720ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::compute::disk::mode::discovery; use base qw(cloud::azure::management::monitor::mode::discovery); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{namespace} = 'Microsoft.Compute'; $self->{type} = 'disks'; } 1; __END__ =head1 MODE Disk discovery. =over 8 =item B<--resource-group> Specify resources resource group. =item B<--location> Specify resources location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/compute/disk/mode/diskio.pm000066400000000000000000000127051417000230700246470ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::compute::disk::mode::diskio; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'Composite Disk Read Bytes/sec' => { 'output' => 'Disk Read Bytes', 'label' => 'disk-read-bytes', 'nlabel' => 'disk.read.bytes.count', 'unit' => 'B', 'min' => '0', 'max' => '' }, 'Composite Disk Write Bytes/sec' => { 'output' => 'Disk Write Bytes', 'label' => 'disk-write-bytes', 'nlabel' => 'disk.write.bytes.count', 'unit' => 'B', 'min' => '0', 'max' => '' }, 'Composite Disk Read Operations/sec' => { 'output' => 'Disk Read Operations/sec', 'label' => 'disk-read-ops-persec', 'nlabel' => 'disk.write.ops.persec', 'unit' => '', 'min' => '0', 'max' => '' }, 'Composite Disk Write Operations/sec' => { 'output' => 'Disk Write Operations/sec', 'label' => 'disk-write-ops-persec', 'nlabel' => 'disk.write.ops.persec', 'unit' => '', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.compute\/disks\/(.*)\/provider\/microsoft.insights$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'disks'; $self->{az_resource_namespace} = 'microsoft.compute'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 3600; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT1H'; $self->{az_aggregations} = ['average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Disk I/O volume and ops. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::compute::disks::plugin --mode=diskio --custommode=api --resource= --resource-group= --warning-disk-read-ops-persec=10 --critical-disk-read-ops-persec=10 Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::compute::disks::plugin --mode=diskio --custommode=api --resource='/subscriptions//resourceGroups//providers/microsoft.computeengine/disks/' --warning-disk-read-ops-persec=10 --critical-disk-read-ops-persec=10 Default aggregation: 'average'. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'disk-read-bytes', 'disk-write-bytes', 'disk-read-ops-persec', 'disk-write-ops-persec' =item B<--critical-*> Critical threshold where '*' can be: 'disk-read-bytes', 'disk-write-bytes', 'disk-read-ops-persec', 'disk-write-ops-persec' =back =cutcentreon-plugins-20220113/cloud/azure/compute/disk/plugin.pm000066400000000000000000000032421417000230700237330ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::compute::disk::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} } = ( 'discovery' => 'cloud::azure::compute::disk::mode::discovery', 'diskio' => 'cloud::azure::compute::disk::mode::diskio' ); $self->{custom_modes}{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' }, }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure Disks attached to Virtual Machines =cut centreon-plugins-20220113/cloud/azure/compute/functions/000077500000000000000000000000001417000230700231545ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/compute/functions/mode/000077500000000000000000000000001417000230700241005ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/compute/functions/mode/executions.pm000066400000000000000000000114711417000230700266300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::compute::functions::mode::executions; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'functionexecutioncount' => { 'output' => 'Function Execution Count', 'label' => 'execution-count', 'nlabel' => 'functions.executions.count', 'unit' => '', 'min' => '0', 'max' => '' }, 'functionexecutionunits' => { 'output' => 'Function Execution Units', 'label' => 'execution-unit', 'nlabel' => 'functions.executions.units.count', 'unit' => '', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Web\/sites\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'sites'; $self->{az_resource_namespace} = 'Microsoft.Web'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Functions App. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::web::appservice::plugin --mode=executions --custommode=api --resource= --resource-group= --aggregation='total' --warning-execution-count='80' --critical-execution-count='90' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::web::appservice::plugin --mode=executions --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Web/sites/' --aggregation='total' --warning-execution-count='80' --critical-execution-count='90' Default aggregation: 'total' / 'minimum', 'maximum' and 'average' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'execution-count', 'execution-unit'. =item B<--critical-*> Critical threshold where '*' can be:. 'execution-count', 'execution-unit'. =back =cut centreon-plugins-20220113/cloud/azure/compute/functions/plugin.pm000066400000000000000000000051011417000230700250050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::compute::functions::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} = { 'data' => 'cloud::azure::common::appservice::mode::data', 'health' => 'cloud::azure::common::appservice::mode::health', 'memory' => 'cloud::azure::common::appservice::mode::memory', 'status' => 'cloud::azure::common::appservice::mode::status', 'cpu-time' => 'cloud::azure::common::appservice::mode::cputime', 'gc-usage' => 'cloud::azure::common::appservice::mode::gcusage', 'app-usage' => 'cloud::azure::common::appservice::mode::appusage', 'discovery' => 'cloud::azure::common::appservice::mode::discovery', 'executions' => 'cloud::azure::compute::functions::mode::executions', 'io-operations' => 'cloud::azure::common::appservice::mode::iooperations', 'http-requests' => 'cloud::azure::common::appservice::mode::httprequests', 'response-time' => 'cloud::azure::common::appservice::mode::responsetime', 'filesystem-usage' => 'cloud::azure::common::appservice::mode::filesystem' }; $self->{custom_modes}->{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}->{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' } }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure Functions Service. =cut centreon-plugins-20220113/cloud/azure/compute/virtualmachine/000077500000000000000000000000001417000230700241575ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/compute/virtualmachine/mode/000077500000000000000000000000001417000230700251035ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/compute/virtualmachine/mode/cpu.pm000066400000000000000000000214671417000230700262420ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::compute::virtualmachine::mode::cpu; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; return "Resource '" . $options{instance_value}->{display} . "' " . $options{instance_value}->{stat} . " "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All CPU metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $aggregation ('minimum', 'maximum', 'average', 'total') { foreach my $metric ('CPU Credits Remaining', 'CPU Credits Consumed') { my $metric_perf = lc($metric); my $metric_label = lc($metric); $metric_perf =~ s/ /_/g; $metric_label =~ s/ /-/g; my $entry = { label => $metric_label . '-' . $aggregation, set => { key_values => [ { name => $metric_perf . '_' . $aggregation }, { name => 'display' }, { name => 'stat' } ], output_template => $metric . ': %.2f', perfdatas => [ { label => $metric_perf . '_' . $aggregation, value => $metric_perf . '_' . $aggregation , template => '%.2f', unit => 'credits', label_extra_instance => 1, instance_use => 'display', min => 0 }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } foreach my $metric ('Percentage CPU') { my $metric_perf = lc($metric); my $metric_label = lc($metric); $metric_perf =~ s/ /_/g; $metric_label =~ s/ /-/g; my $entry = { label => $metric_label . '-' . $aggregation, set => { key_values => [ { name => $metric_perf . '_' . $aggregation }, { name => 'display' }, { name => 'stat' } ], output_template => $metric . ': %.2f %%', perfdatas => [ { label => $metric_perf . '_' . $aggregation, value => $metric_perf . '_' . $aggregation , template => '%.2f', unit => '%', label_extra_instance => 1, instance_use => 'display', min => 0, max => 100 }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'resource:s@' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' }, 'filter-metric:s' => { name => 'filter_metric' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource})) { $self->{output}->add_option_msg(short_msg => "Need to specify either --resource with --resource-group option or --resource ."); $self->{output}->option_exit(); } $self->{az_resource} = $self->{option_results}->{resource}; $self->{az_resource_group} = $self->{option_results}->{resource_group} if (defined($self->{option_results}->{resource_group})); $self->{az_resource_type} = 'virtualMachines'; $self->{az_resource_namespace} = 'Microsoft.Compute'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : "PT5M"; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric ('CPU Credits Remaining', 'CPU Credits Consumed', 'Percentage CPU') { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $resource (@{$self->{az_resource}}) { my $resource_group = $self->{az_resource_group}; my $resource_name = $resource; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Compute\/virtualMachines\/(.*)$/) { $resource_group = $1; $resource_name = $2; } ($metric_results{$resource_name}, undef, undef) = $options{custom}->azure_get_metrics( resource => $resource_name, resource_group => $resource_group, resource_type => $self->{az_resource_type}, resource_namespace => $self->{az_resource_namespace}, metrics => $self->{az_metrics}, aggregations => $self->{az_aggregations}, timeframe => $self->{az_timeframe}, interval => $self->{az_interval}, ); foreach my $metric (@{$self->{az_metrics}}) { my $metric_name = lc($metric); $metric_name =~ s/ /_/g; foreach my $aggregation (@{$self->{az_aggregations}}) { next if (!defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{display} = $resource_name; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{stat} = lc($aggregation); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{$metric_name . "_" . lc($aggregation)} = defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) ? $metric_results{$resource_name}->{$metric_name}->{lc($aggregation)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check virtual machine resources CPU metrics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::compute::virtualmachine::plugin --custommode=azcli --mode=cpu --resource=MYSQLINSTANCE --resource-group=MYHOSTGROUP --filter-metric='Credits' --aggregation='average' --critical-cpu-credits-remaining-average='10' --verbose Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::compute::virtualmachine::plugin --custommode=azcli --mode=cpu --resource='/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Compute/virtualMachines/xxx' --filter-metric='Credits' --aggregation='average' --critical-cpu-credits-remaining-average='10' --verbose Default aggregation: 'average' / All aggregations are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--filter-metric> Filter metrics (Can be: 'CPU Credits Remaining', 'CPU Credits Consumed', 'Percentage CPU') (Can be a regexp). =item B<--warning-$metric$-$aggregation$> Thresholds warning ($metric$ can be: 'cpu-credits-remaining', 'cpu-credits-consumed', 'percentage-cpu', $aggregation$ can be: 'minimum', 'maximum', 'average', 'total'). =item B<--critical-$metric$-$aggregation$> Thresholds critical ($metric$ can be: 'cpu-credits-remaining', 'cpu-credits-consumed', 'percentage-cpu', $aggregation$ can be: 'minimum', 'maximum', 'average', 'total'). =back =cut centreon-plugins-20220113/cloud/azure/compute/virtualmachine/mode/discovery.pm000066400000000000000000000024641417000230700274560ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::compute::virtualmachine::mode::discovery; use base qw(cloud::azure::management::monitor::mode::discovery); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{namespace} = 'Microsoft.Compute'; $self->{type} = 'virtualMachines'; } 1; __END__ =head1 MODE Virtual Machine discovery. =over 8 =item B<--resource-group> Specify resources resource group. =item B<--location> Specify resources location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/compute/virtualmachine/mode/diskio.pm000066400000000000000000000335541417000230700267350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::compute::virtualmachine::mode::diskio; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; return "Resource '" . $options{instance_value}->{display} . "' " . $options{instance_value}->{stat} . " "; } sub custom_metric_calc { my ($self, %options) = @_; $self->{result_values}->{stat} = $options{new_datas}->{$self->{instance} . '_stat'}; $self->{result_values}->{metric_perf} = lc($options{extra_options}->{metric_perf}); $self->{result_values}->{metric_label} = lc($options{extra_options}->{metric_label}); $self->{result_values}->{metric_name} = $options{extra_options}->{metric_name}; $self->{result_values}->{timeframe} = $options{new_datas}->{$self->{instance} . '_timeframe'}; $self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_' . $self->{result_values}->{metric_perf} . '_' . $self->{result_values}->{stat}}; $self->{result_values}->{value_per_sec} = $self->{result_values}->{value} / $self->{result_values}->{timeframe}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub custom_metric_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check(value => defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}, threshold => [ { label => 'critical-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}, exit_litteral => 'warning' } ]); return $exit; } sub custom_usage_perfdata { my ($self, %options) = @_; my $extra_label = ''; $extra_label = '_' . lc($self->{result_values}->{display}) if (!defined($options{extra_instance}) || $options{extra_instance} != 0); $self->{output}->perfdata_add(label => $self->{result_values}->{metric_perf} . "_" . $self->{result_values}->{stat} . $extra_label, unit => defined($self->{instance_mode}->{option_results}->{per_sec}) ? 'B/s' : 'B', value => sprintf("%.2f", defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}), min => 0 ); } sub custom_usage_output { my ($self, %options) = @_; my $msg = ""; if (defined($self->{instance_mode}->{option_results}->{per_sec})) { my ($value, $unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{value_per_sec}); $msg = $self->{result_values}->{metric_name} . ": " . $value . $unit . "/s"; } else { my ($value, $unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{value}); $msg = $self->{result_values}->{metric_name} . ": " . $value . $unit; } return $msg; } sub custom_ops_perfdata { my ($self, %options) = @_; my $extra_label = ''; $extra_label = '_' . lc($self->{result_values}->{display}) if (!defined($options{extra_instance}) || $options{extra_instance} != 0); $self->{output}->perfdata_add(label => $self->{result_values}->{metric_perf} . "_" . $self->{result_values}->{stat} . $extra_label, unit => 'ops/s', value => sprintf("%.2f", $self->{result_values}->{value}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}), min => 0 ); } sub custom_ops_output { my ($self, %options) = @_; my $msg = sprintf("%s: %.2f ops/s", $self->{result_values}->{metric_name}, $self->{result_values}->{value}); return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All disk metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $aggregation ('minimum', 'maximum', 'average', 'total') { foreach my $metric ('Disk Read Bytes', 'Disk Write Bytes') { my $metric_perf = lc($metric); my $metric_label = lc($metric); $metric_perf =~ s/ /_/g; $metric_label =~ s/ /-/g; my $entry = { label => $metric_label . '-' . $aggregation, set => { key_values => [ { name => $metric_perf . '_' . $aggregation }, { name => 'display' }, { name => 'stat' }, { name => 'timeframe' } ], closure_custom_calc => $self->can('custom_metric_calc'), closure_custom_calc_extra_options => { metric_perf => $metric_perf, metric_label => $metric_label, metric_name => $metric }, closure_custom_output => $self->can('custom_usage_output'), closure_custom_perfdata => $self->can('custom_usage_perfdata'), closure_custom_threshold_check => $self->can('custom_metric_threshold'), } }; push @{$self->{maps_counters}->{metric}}, $entry; } foreach my $metric ('Disk Read Operations/Sec', 'Disk Write Operations/Sec') { my $metric_perf = lc($metric); my $metric_label = lc($metric); $metric_perf =~ s/ /_/g; $metric_label =~ s/( |\/)/-/g; my $entry = { label => $metric_label . '-' . $aggregation, set => { key_values => [ { name => $metric_perf . '_' . $aggregation }, { name => 'display' }, { name => 'stat' }, { name => 'timeframe' } ], closure_custom_calc => $self->can('custom_metric_calc'), closure_custom_calc_extra_options => { metric_perf => $metric_perf, metric_label => $metric_label, metric_name => $metric }, closure_custom_output => $self->can('custom_ops_output'), closure_custom_perfdata => $self->can('custom_ops_perfdata'), closure_custom_threshold_check => $self->can('custom_metric_threshold'), } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource:s@" => { name => 'resource' }, "resource-group:s" => { name => 'resource_group' }, "filter-metric:s" => { name => 'filter_metric' }, "per-sec" => { name => 'per_sec' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource})) { $self->{output}->add_option_msg(short_msg => "Need to specify either --resource with --resource-group option or --resource ."); $self->{output}->option_exit(); } $self->{az_resource} = $self->{option_results}->{resource}; $self->{az_resource_group} = $self->{option_results}->{resource_group} if (defined($self->{option_results}->{resource_group})); $self->{az_resource_type} = 'virtualMachines'; $self->{az_resource_namespace} = 'Microsoft.Compute'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : "PT5M"; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric ('Disk Read Bytes', 'Disk Write Bytes', 'Disk Read Operations/Sec', 'Disk Write Operations/Sec') { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $resource (@{$self->{az_resource}}) { my $resource_group = $self->{az_resource_group}; my $resource_name = $resource; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Compute\/virtualMachines\/(.*)$/) { $resource_group = $1; $resource_name = $2; } ($metric_results{$resource_name}, undef, undef) = $options{custom}->azure_get_metrics( resource => $resource_name, resource_group => $resource_group, resource_type => $self->{az_resource_type}, resource_namespace => $self->{az_resource_namespace}, metrics => $self->{az_metrics}, aggregations => $self->{az_aggregations}, timeframe => $self->{az_timeframe}, interval => $self->{az_interval}, ); foreach my $metric (@{$self->{az_metrics}}) { my $metric_name = lc($metric); $metric_name =~ s/ /_/g; foreach my $aggregation (@{$self->{az_aggregations}}) { next if (!defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{display} = $resource_name; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{timeframe} = $self->{az_timeframe}; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{stat} = lc($aggregation); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{$metric_name . "_" . lc($aggregation)} = defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) ? $metric_results{$resource_name}->{$metric_name}->{lc($aggregation)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check virtual machine resources disk IO metrics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::compute::virtualmachine::plugin --custommode=azcli --mode=diskio --resource=MYSQLINSTANCE --resource-group=MYHOSTGROUP --aggregation='total' --aggregation='average' --critical-disk-write-bytes-total='10' --verbose Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::compute::virtualmachine::plugin --custommode=azcli --mode=diskio --resource='/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Compute/virtualMachines/xxx' --aggregation='total' --aggregation='average' --critical-disk-write-bytes-total='10' --verbose Default aggregation: 'total', 'average' / All aggregations are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--filter-metric> Filter metrics (Can be: 'Disk Read Bytes', 'Disk Write Bytes', 'Disk Read Operations/Sec', 'Disk Write Operations/Sec') (Can be a regexp). =item B<--warning-$metric$-$aggregation$> Thresholds warning ($metric$ can be: 'disk-read-bytes', 'disk-write-bytes', 'disk-read-operations-sec', 'disk-write-operations-sec', $aggregation$ can be: 'minimum', 'maximum', 'average', 'total'). =item B<--critical-$metric$-$aggregation$> Thresholds critical ($metric$ can be: 'disk-read-bytes', 'disk-write-bytes', 'disk-read-operations-sec', 'disk-write-operations-sec', $aggregation$ can be: 'minimum', 'maximum', 'average', 'total'). =item B<--per-sec> Change the data to be unit/sec. =back =cut centreon-plugins-20220113/cloud/azure/compute/virtualmachine/mode/health.pm000066400000000000000000000036721417000230700267160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::compute::virtualmachine::mode::health; use base qw(cloud::azure::management::monitor::mode::health); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{az_resource_namespace} = 'Microsoft.Compute'; $self->{az_resource_type} = 'virtualMachines'; } 1; __END__ =head1 MODE Check Virtual Machine health status. (Usefull to determine host status) =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{summary} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /^Unavailable$/'). Can used special variables like: %{status}, %{summary} =item B<--unknown-status> Set unknown threshold for status (Default: '%{status} =~ /^Unknown$/'). Can used special variables like: %{status}, %{summary} =item B<--ok-status> Set ok threshold for status (Default: '%{status} =~ /^Available$/'). Can used special variables like: %{status}, %{summary} =back =cut centreon-plugins-20220113/cloud/azure/compute/virtualmachine/mode/listresources.pm000066400000000000000000000130561417000230700303540ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::compute::virtualmachine::mode::listresources; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource-group:s" => { name => 'resource_group' }, "filter-name:s" => { name => 'filter_name' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{vms} = $options{custom}->azure_list_vms( resource_group => $self->{option_results}->{resource_group}, show_details => 1 ); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $vm (@{$self->{vms}}) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $vm->{name} !~ /$self->{option_results}->{filter_name}/); my $computer_name = '-'; $computer_name = $vm->{properties}->{osProfile}->{computerName} if (defined($vm->{properties}->{osProfile}->{computerName})); $computer_name = $vm->{osProfile}->{computerName} if (defined($vm->{osProfile}->{computerName})); my $resource_group = '-'; $resource_group = $vm->{resourceGroup} if (defined($vm->{resourceGroup})); $resource_group = $1 if (defined($vm->{id}) && $vm->{id} =~ /resourceGroups\/(.*)\/providers/); my @tags; foreach my $tag (keys %{$vm->{tags}}) { push @tags, $tag . ':' . $vm->{tags}->{$tag}; } $self->{output}->output_add(long_msg => sprintf("[name = %s][computername = %s][resourcegroup = %s]" . "[location = %s][vmid = %s][vmsize = %s][os = %s][state = %s][tags = %s]", $vm->{name}, $computer_name, $resource_group, $vm->{location}, (defined($vm->{properties}->{vmId})) ? $vm->{properties}->{vmId} : $vm->{vmId}, (defined($vm->{properties}->{hardwareProfile}->{vmSize})) ? $vm->{properties}->{hardwareProfile}->{vmSize} : $vm->{hardwareProfile}->{vmSize}, (defined($vm->{properties}->{storageProfile}->{osDisk}->{osType})) ? $vm->{properties}->{storageProfile}->{osDisk}->{osType} : $vm->{storageProfile}->{osDisk}->{osType}, (defined($vm->{powerState})) ? $vm->{powerState} : "-", join(',', @tags), )); } $self->{output}->output_add(severity => 'OK', short_msg => 'List vitual 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', 'computername', 'resourcegroup', 'location', 'vmid', 'vmsize', 'os', 'state', 'tags']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $vm (@{$self->{vms}}) { my $computer_name = '-'; $computer_name = $vm->{properties}->{osProfile}->{computerName} if (defined($vm->{properties}->{osProfile}->{computerName})); $computer_name = $vm->{osProfile}->{computerName} if (defined($vm->{osProfile}->{computerName})); my $resource_group = '-'; $resource_group = $vm->{resourceGroup} if (defined($vm->{resourceGroup})); $resource_group = $1 if (defined($vm->{id}) && $vm->{id} =~ /resourceGroups\/(.*)\/providers/); my @tags; foreach my $tag (keys %{$vm->{tags}}) { push @tags, $tag . ':' . $vm->{tags}->{$tag}; } $self->{output}->add_disco_entry( name => $vm->{name}, computername => $computer_name, resourcegroup => $resource_group, location => $vm->{location}, vmid => (defined($vm->{properties}->{vmId})) ? $vm->{properties}->{vmId} : $vm->{vmId}, vmsize => (defined($vm->{properties}->{hardwareProfile}->{vmSize})) ? $vm->{properties}->{hardwareProfile}->{vmSize} : $vm->{hardwareProfile}->{vmSize}, os => (defined($vm->{properties}->{storageProfile}->{osDisk}->{osType})) ? $vm->{properties}->{storageProfile}->{osDisk}->{osType} : $vm->{storageProfile}->{osDisk}->{osType}, state => (defined($vm->{powerState})) ? $vm->{powerState} : "-", tags => join(',', @tags), ); } } 1; __END__ =head1 MODE List vitual machines. =over 8 =item B<--resource-group> Set resource group (Optional). =item B<--filter-name> Filter resource name (Can be a regexp). =back =cut centreon-plugins-20220113/cloud/azure/compute/virtualmachine/mode/memory.pm000066400000000000000000000102621417000230700267520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::compute::virtualmachine::mode::memory; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'Available Memory Bytes' => { 'output' => 'Available Memory Bytes', 'label' => 'memory-available', 'nlabel' => 'memory.available.bytes', 'unit' => 'B' } }; return $metrics_mapping; } 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 => { 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Compute\/virtualMachines\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'virtualMachines'; $self->{az_resource_namespace} = 'Microsoft.Compute'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure MS Compute Virtual Machine available memory. perl centreon_plugins.pl --plugin=cloud::azure::compute::virtualmachine::plugin --mode=memory \ --custommode='api' --resource='***' --resource-group='***' \ --subscription='***' --tenant='***' --client-id='***' --client-secret='**' --timeframe='900' \ --interval='PT1M' --aggregation='average' --warning-memory-available=1024: --verbose Note that using a specific threshold syntax is required to trigger an alert when the value drops below available memory ":" =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-memory-available> Warning threshold. =item B<--critical-memory-available> Critical threshold. =back =cut centreon-plugins-20220113/cloud/azure/compute/virtualmachine/mode/network.pm000066400000000000000000000263031417000230700271360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::compute::virtualmachine::mode::network; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; return "Resource '" . $options{instance_value}->{display} . "' " . $options{instance_value}->{stat} . " "; } sub custom_metric_calc { my ($self, %options) = @_; $self->{result_values}->{stat} = $options{new_datas}->{$self->{instance} . '_stat'}; $self->{result_values}->{metric_perf} = lc($options{extra_options}->{metric_perf}); $self->{result_values}->{metric_label} = lc($options{extra_options}->{metric_label}); $self->{result_values}->{metric_name} = $options{extra_options}->{metric_name}; $self->{result_values}->{timeframe} = $options{new_datas}->{$self->{instance} . '_timeframe'}; $self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_' . $self->{result_values}->{metric_perf} . '_' . $self->{result_values}->{stat}}; $self->{result_values}->{value_per_sec} = $self->{result_values}->{value} / $self->{result_values}->{timeframe}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub custom_metric_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check(value => defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}, threshold => [ { label => 'critical-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}, exit_litteral => 'warning' } ]); return $exit; } sub custom_traffic_perfdata { my ($self, %options) = @_; my $extra_label = ''; $extra_label = '_' . lc($self->{result_values}->{display}) if (!defined($options{extra_instance}) || $options{extra_instance} != 0); $self->{output}->perfdata_add(label => $self->{result_values}->{metric_perf} . "_" . $self->{result_values}->{stat} . $extra_label, unit => defined($self->{instance_mode}->{option_results}->{per_sec}) ? 'B/s' : 'B', value => sprintf("%.2f", defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}), min => 0 ); } sub custom_traffic_output { my ($self, %options) = @_; my $msg = ""; if (defined($self->{instance_mode}->{option_results}->{per_sec})) { my ($value, $unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{value_per_sec}); $msg = $self->{result_values}->{metric_name} . ": " . $value . $unit . "/s"; } else { my ($value, $unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{value}); $msg = $self->{result_values}->{metric_name} . ": " . $value . $unit; } return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All network metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $aggregation ('minimum', 'maximum', 'average', 'total') { foreach my $metric ('Network In', 'Network Out') { my $metric_perf = lc($metric); my $metric_label = lc($metric); $metric_perf =~ s/ /_/g; $metric_label =~ s/ /-/g; my $entry = { label => $metric_label . '-' . $aggregation, set => { key_values => [ { name => $metric_perf . '_' . $aggregation }, { name => 'display' }, { name => 'stat' }, { name => 'timeframe' } ], closure_custom_calc => $self->can('custom_metric_calc'), closure_custom_calc_extra_options => { metric_perf => $metric_perf, metric_label => $metric_label, metric_name => $metric }, closure_custom_output => $self->can('custom_traffic_output'), closure_custom_perfdata => $self->can('custom_traffic_perfdata'), closure_custom_threshold_check => $self->can('custom_metric_threshold'), } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource:s@" => { name => 'resource' }, "resource-group:s" => { name => 'resource_group' }, "filter-metric:s" => { name => 'filter_metric' }, "per-sec" => { name => 'per_sec' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource})) { $self->{output}->add_option_msg(short_msg => "Need to specify either --resource with --resource-group option or --resource ."); $self->{output}->option_exit(); } $self->{az_resource} = $self->{option_results}->{resource}; $self->{az_resource_group} = $self->{option_results}->{resource_group} if (defined($self->{option_results}->{resource_group})); $self->{az_resource_type} = 'virtualMachines'; $self->{az_resource_namespace} = 'Microsoft.Compute'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : "PT5M"; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric ('Network In', 'Network Out') { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $resource (@{$self->{az_resource}}) { my $resource_group = $self->{az_resource_group}; my $resource_name = $resource; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Compute\/virtualMachines\/(.*)$/) { $resource_group = $1; $resource_name = $2; } ($metric_results{$resource_name}, undef, undef) = $options{custom}->azure_get_metrics( resource => $resource_name, resource_group => $resource_group, resource_type => $self->{az_resource_type}, resource_namespace => $self->{az_resource_namespace}, metrics => $self->{az_metrics}, aggregations => $self->{az_aggregations}, timeframe => $self->{az_timeframe}, interval => $self->{az_interval}, ); foreach my $metric (@{$self->{az_metrics}}) { my $metric_name = lc($metric); $metric_name =~ s/ /_/g; foreach my $aggregation (@{$self->{az_aggregations}}) { next if (!defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{display} = $resource_name; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{timeframe} = $self->{az_timeframe}; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{stat} = lc($aggregation); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{$metric_name . "_" . lc($aggregation)} = defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) ? $metric_results{$resource_name}->{$metric_name}->{lc($aggregation)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check virtual machine resources network metrics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::compute::virtualmachine::plugin --custommode=azcli --mode=network --resource=MYSQLINSTANCE --resource-group=MYHOSTGROUP --aggregation='total' --critical-network-out-total='10' --verbose Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::compute::virtualmachine::plugin --custommode=azcli --mode=network --resource='/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Compute/virtualMachines/xxx' --aggregation='total' --critical-network-out-total='10' --verbose Default aggregation: 'total' / All aggregations are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--filter-metric> Filter metrics (Can be: 'Network In', 'Network Out') (Can be a regexp). =item B<--warning-$metric$-$aggregation$> Thresholds warning ($metric$ can be: 'network-in', 'network-out', $aggregation$ can be: 'minimum', 'maximum', 'average', 'total'). =item B<--critical-$metric$-$aggregation$> Thresholds critical ($metric$ can be: 'network-in', 'network-out', $aggregation$ can be: 'minimum', 'maximum', 'average', 'total'). =item B<--per-sec> Change the data to be unit/sec. =back =cut centreon-plugins-20220113/cloud/azure/compute/virtualmachine/mode/vmsizes.pm000066400000000000000000000334231417000230700271460ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::compute::virtualmachine::mode::vmsizes; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my %vm_types = ( 'general' => ['Standard_B1s', 'Standard_B1ms', 'Standard_B2s', 'Standard_B2ms', 'Standard_B4ms', 'Standard_B8ms', 'Standard_D2s_v3', 'Standard_D4s_v3', 'Standard_D8s_v3', 'Standard_D16s_v3', 'Standard_D32s_v3', 'Standard_D64s_v3', 'Standard_D2_v3', 'Standard_D4_v3', 'Standard_D8_v3', 'Standard_D16_v3', 'Standard_D32_v3', 'Standard_D64_v3', 'Standard_DS1_v2', 'Standard_DS2_v2', 'Standard_DS3_v2', 'Standard_DS4_v2', 'Standard_DS5_v2', 'Standard_D1_v2', 'Standard_D2_v2', 'Standard_D3_v2', 'Standard_D4_v2', 'Standard_D5_v2', 'Standard_A1_v2', 'Standard_A2_v2', 'Standard_A4_v2', 'Standard_A8_v2', 'Standard_A2m_v2', 'Standard_A4m_v2', 'Standard_A8m_v2'], 'compute' => ['Standard_F2s_v2', 'Standard_F4s_v2', 'Standard_F8s_v2', 'Standard_F16s_v2', 'Standard_F32s_v2', 'Standard_F64s_v2', 'Standard_F72s_v2', 'Standard_F1s', 'Standard_F2s', 'Standard_F4s', 'Standard_F8s', 'Standard_F16s', 'Standard_F1', 'Standard_F2', 'Standard_F4', 'Standard_F8', 'Standard_F16'], 'memory' => ['Standard_E2s_v3', 'Standard_E4s_v3', 'Standard_E8s_v3', 'Standard_E16s_v3', 'Standard_E32s_v3', 'Standard_E64s_v3', 'Standard_E64is_v3', 'Standard_E2_v3', 'Standard_E4_v3', 'Standard_E8_v3', 'Standard_E16_v3', 'Standard_E32_v3', 'Standard_E64_v3', 'Standard_E64i_v3', 'Standard_M8ms3', 'Standard_M16ms', 'Standard_M32ts', 'Standard_M32ls', 'Standard_M32ms', 'Standard_M64s', 'Standard_M64ls', 'Standard_M64ms', 'Standard_M128s', 'Standard_M128ms', 'Standard_M64', 'Standard_M64m', 'Standard_M128', 'Standard_M128m', 'Standard_GS1', 'Standard_GS2', 'Standard_GS3', 'Standard_GS4', 'Standard_GS5', 'Standard_G1', 'Standard_G2', 'Standard_G3', 'Standard_G4', 'Standard_G5', 'Standard_DS11_v2', 'Standard_DS12_v2', 'Standard_DS13_v2', 'Standard_DS14_v2', 'Standard_DS15_v2', 'Standard_D11_v2', 'Standard_D12_v2', 'Standard_D13_v2', 'Standard_D14_v2', 'Standard_D15_v2'], 'storage' => ['Standard_L4s', 'Standard_L8s', 'Standard_L16s', 'Standard_L32s'], 'gpu' => ['Standard_NC6', 'Standard_NC12', 'Standard_NC24', 'Standard_NC24r', 'Standard_NC6s_v2', 'Standard_NC12s_v2', 'Standard_NC24s_v2', 'Standard_NC24rs_v2', 'Standard_NC6s_v3', 'Standard_NC12s_v3', 'Standard_NC24s_v3', 'Standard_NC24rs_v3', 'Standard_ND6s', 'Standard_ND12s', 'Standard_ND24s', 'Standard_ND24rs', 'Standard_NV6', 'Standard_NV12', 'Standard_NV24'], 'high_performance' => ['Standard_H8', 'Standard_H16', 'Standard_H8m', 'Standard_H16m', 'Standard_H16r', 'Standard_H16mr'], ); sub prefix_general_output { my ($self, %options) = @_; return "Virtual machine type 'General purpose' resource sizes count "; } sub prefix_compute_output { my ($self, %options) = @_; return "Virtual machine type 'Compute optimized' resource sizes count "; } sub prefix_memory_output { my ($self, %options) = @_; return "Virtual machine type 'Memory optimized' resource sizes count "; } sub prefix_storage_output { my ($self, %options) = @_; return "Virtual machine type 'Storage optimized' resource sizes count "; } sub prefix_gpu_output { my ($self, %options) = @_; return "Virtual machine type 'GPU' resource sizes count "; } sub prefix_high_performance_output { my ($self, %options) = @_; return "Virtual machine type 'High performance compute' resource sizes count "; } sub set_counters { my ($self, %options) = @_; foreach my $type (keys %vm_types) { my $counter = { name => $type, type => 0, cb_prefix_output => 'prefix_' . $type . '_output', skipped_code => { -10 => 1 } }; push @{$self->{maps_counters_type}}, $counter; $self->{maps_counters}->{$type} = []; foreach my $size (@{$vm_types{$type}}) { my $perf = lc($size); my $label = lc($size); $label =~ s/_/-/g; my $entry = { label => $label, set => { key_values => [ { name => $size } ], output_template => $size . ": %s", perfdatas => [ { label => $perf, value => $size , template => '%d', min => 0 }, ], } }; push @{$self->{maps_counters}->{$type}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource-group:s" => { name => 'resource_group' }, "filter-type:s" => { name => 'filter_type' }, "filter-size:s" => { name => 'filter_size' }, "running" => { name => 'running' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; foreach my $type (keys %vm_types) { if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' && $type !~ /$self->{option_results}->{filter_type}/) { $self->{output}->output_add(long_msg => sprintf("skipping type '%s'", $type), debug => 1); $self->{maps_counters}->{$type} = undef; } else { foreach my $size (@{$vm_types{$type}}) { if (defined($self->{option_results}->{filter_size}) && $self->{option_results}->{filter_size} ne '' && $size !~ /$self->{option_results}->{filter_size}/) { next; } $self->{$type}->{$size} = 0; } } } my $vms = $options{custom}->azure_list_vms(resource_group => $self->{option_results}->{resource_group}, show_details => 1); foreach my $vm (@{$vms}) { next if (defined($self->{option_results}->{running}) && defined($vm->{powerState}) && $vm->{powerState} !~ /running/); if (defined($self->{option_results}->{filter_size}) && $self->{option_results}->{filter_size} ne '' && (defined($vm->{hardwareProfile}->{vmSize}) && $vm->{hardwareProfile}->{vmSize} !~ /$self->{option_results}->{filter_size}/ || defined($vm->{properties}->{hardwareProfile}->{vmSize}) && $vm->{properties}->{hardwareProfile}->{vmSize} !~ /$self->{option_results}->{filter_size}/)) { $self->{output}->output_add(long_msg => sprintf("skipping size '%s'", $vm->{hardwareProfile}->{vmSize}), debug => 1) if (defined($vm->{hardwareProfile}->{vmSize})); $self->{output}->output_add(long_msg => sprintf("skipping size '%s'", $vm->{properties}->{hardwareProfile}->{vmSize}), debug => 1) if (defined($vm->{properties}->{hardwareProfile}->{vmSize})); next; } foreach my $type (keys %vm_types) { next if (!defined($self->{maps_counters}->{$type})); $self->{$type}->{$vm->{hardwareProfile}->{vmSize}}++ if (defined($vm->{hardwareProfile}->{vmSize}) && map(/$vm->{hardwareProfile}->{vmSize}/, @{$vm_types{$type}})); $self->{$type}->{$vm->{properties}->{hardwareProfile}->{vmSize}}++ if (defined($vm->{properties}->{hardwareProfile}->{vmSize}) && map(/$vm->{properties}->{hardwareProfile}->{vmSize}/, @{$vm_types{$type}})); } } if (scalar(keys %{$self->{general}}) <= 0 && scalar(keys %{$self->{compute}}) <= 0 && scalar(keys %{$self->{memory}}) <= 0 && scalar(keys %{$self->{storage}}) <= 0 && scalar(keys %{$self->{gpu}}) <= 0 && scalar(keys %{$self->{high_performance}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No result matched with applied filters."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE List virtual machine resources sizes. =over 8 =item B<--resource-group> Set resource group (Optional). =item B<--filter-type> Filter by virtual machine type (regexp) (Can be: 'general', 'compute', 'memory', 'storage', 'gpu', 'high_performance') =item B<--filter-size> Filter by virtual machine size (regexp) =item B<--warning-*> Threshold warning. Can be: 'standard-b1s', 'standard-b1ms', 'standard-b2s', 'standard-b2ms', 'standard-b4ms', 'standard-b8ms', 'standard-d2s-v3', 'standard-d4s-v3', 'standard-d8s-v3', 'standard-d16s-v3', 'standard-d32s-v3', 'standard-d64s-v3', 'standard-d2-v3', 'standard-d4-v3', 'standard-d8-v3', 'standard-d16-v3', 'standard-d32-v3', 'standard-d64-v3', 'standard-ds1-v2', 'standard-ds2-v2', 'standard-ds3-v2', 'standard-ds4-v2', 'standard-ds5-v2', 'standard-d1-v2', 'standard-d2-v2', 'standard-d3-v2', 'standard-d4-v2', 'standard-d5-v2', 'standard-a1-v2', 'standard-a2-v2', 'standard-a4-v2', 'standard-a8-v2', 'standard-a2m-v2', 'standard-a4m-v2', 'standard-a8m-v2', 'standard-f2s-v2', 'standard-f4s-v2', 'standard-f8s-v2', 'standard-f16s-v2', 'standard-f32s-v2', 'standard-f64s-v2', 'standard-f72s-v2', 'standard-f1s', 'standard-f2s', 'standard-f4s', 'standard-f8s', 'standard-f16s', 'standard-f1', 'standard-f2', 'standard-f4', 'standard-f8', 'standard-f16', 'standard-e2s-v3', 'standard-e4s-v3', 'standard-e8s-v3', 'standard-e16s-v3', 'standard-e32s-v3', 'standard-e64s-v3', 'standard-e64is-v3', 'standard-e2-v3', 'standard-e4-v3', 'standard-e8-v3', 'standard-e16-v3', 'standard-e32-v3', 'standard-e64-v3', 'standard-e64i-v3', 'standard-m8ms3', 'standard-m16ms', 'standard-m32ts', 'standard-m32ls', 'standard-m32ms', 'standard-m64s', 'standard-m64ls', 'standard-m64ms', 'standard-m128s', 'standard-m128ms', 'standard-m64', 'standard-m64m', 'standard-m128', 'standard-m128m', 'standard-gs1', 'standard-gs2', 'standard-gs3', 'standard-gs4', 'standard-gs5', 'standard-g1', 'standard-g2', 'standard-g3', 'standard-g4', 'standard-g5', 'standard-ds11-v2', 'standard-ds12-v2', 'standard-ds13-v2', 'standard-ds14-v2', 'standard-ds15-v2', 'standard-d11-v2', 'standard-d12-v2', 'standard-d13-v2', 'standard-d14-v2', 'standard-d15-v2', 'standard-l4s', 'standard-l8s', 'standard-l16s', 'standard-l32s', 'standard-nc6', 'standard-nc12', 'standard-nc24', 'standard-nc24r', 'standard-nc6s-v2', 'standard-nc12s-v2', 'standard-nc24s-v2', 'standard-nc24rs-v2', 'standard-nc6s-v3', 'standard-nc12s-v3', 'standard-nc24s-v3', 'standard-nc24rs-v3', 'standard-nd6s', 'standard-nd12s', 'standard-nd24s', 'standard-nd24rs', 'standard-nv6', 'standard-nv12', 'standard-nv24','standard-h8', 'standard-h16', 'standard-h8m', 'standard-h16m', 'standard-h16r', 'standard-h16mr'. =item B<--critical-*> Threshold critical. Can be: 'standard-b1s', 'standard-b1ms', 'standard-b2s', 'standard-b2ms', 'standard-b4ms', 'standard-b8ms', 'standard-d2s-v3', 'standard-d4s-v3', 'standard-d8s-v3', 'standard-d16s-v3', 'standard-d32s-v3', 'standard-d64s-v3', 'standard-d2-v3', 'standard-d4-v3', 'standard-d8-v3', 'standard-d16-v3', 'standard-d32-v3', 'standard-d64-v3', 'standard-ds1-v2', 'standard-ds2-v2', 'standard-ds3-v2', 'standard-ds4-v2', 'standard-ds5-v2', 'standard-d1-v2', 'standard-d2-v2', 'standard-d3-v2', 'standard-d4-v2', 'standard-d5-v2', 'standard-a1-v2', 'standard-a2-v2', 'standard-a4-v2', 'standard-a8-v2', 'standard-a2m-v2', 'standard-a4m-v2', 'standard-a8m-v2', 'standard-f2s-v2', 'standard-f4s-v2', 'standard-f8s-v2', 'standard-f16s-v2', 'standard-f32s-v2', 'standard-f64s-v2', 'standard-f72s-v2', 'standard-f1s', 'standard-f2s', 'standard-f4s', 'standard-f8s', 'standard-f16s', 'standard-f1', 'standard-f2', 'standard-f4', 'standard-f8', 'standard-f16', 'standard-e2s-v3', 'standard-e4s-v3', 'standard-e8s-v3', 'standard-e16s-v3', 'standard-e32s-v3', 'standard-e64s-v3', 'standard-e64is-v3', 'standard-e2-v3', 'standard-e4-v3', 'standard-e8-v3', 'standard-e16-v3', 'standard-e32-v3', 'standard-e64-v3', 'standard-e64i-v3', 'standard-m8ms3', 'standard-m16ms', 'standard-m32ts', 'standard-m32ls', 'standard-m32ms', 'standard-m64s', 'standard-m64ls', 'standard-m64ms', 'standard-m128s', 'standard-m128ms', 'standard-m64', 'standard-m64m', 'standard-m128', 'standard-m128m', 'standard-gs1', 'standard-gs2', 'standard-gs3', 'standard-gs4', 'standard-gs5', 'standard-g1', 'standard-g2', 'standard-g3', 'standard-g4', 'standard-g5', 'standard-ds11-v2', 'standard-ds12-v2', 'standard-ds13-v2', 'standard-ds14-v2', 'standard-ds15-v2', 'standard-d11-v2', 'standard-d12-v2', 'standard-d13-v2', 'standard-d14-v2', 'standard-d15-v2', 'standard-l4s', 'standard-l8s', 'standard-l16s', 'standard-l32s', 'standard-nc6', 'standard-nc12', 'standard-nc24', 'standard-nc24r', 'standard-nc6s-v2', 'standard-nc12s-v2', 'standard-nc24s-v2', 'standard-nc24rs-v2', 'standard-nc6s-v3', 'standard-nc12s-v3', 'standard-nc24s-v3', 'standard-nc24rs-v3', 'standard-nd6s', 'standard-nd12s', 'standard-nd24s', 'standard-nd24rs', 'standard-nv6', 'standard-nv12', 'standard-nv24','standard-h8', 'standard-h16', 'standard-h8m', 'standard-h16m', 'standard-h16r', 'standard-h16mr'. =item B<--running> Only check running virtual machines (only with az CLI). =back =cut centreon-plugins-20220113/cloud/azure/compute/virtualmachine/mode/vmsstate.pm000066400000000000000000000137441417000230700273200ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::compute::virtualmachine::mode::vmsstate; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf('state: %s', $self->{result_values}->{state}); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{state} = $options{new_datas}->{$self->{instance} . '_state'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub prefix_global_output { my ($self, %options) = @_; return "Total vitual machines "; } sub prefix_vm_output { my ($self, %options) = @_; return "Virtual machine '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }, { name => 'vms', type => 1, cb_prefix_output => 'prefix_vm_output', message_multiple => 'All virtual machines are ok' }, ]; $self->{maps_counters}->{global} = [ { label => 'total-running', set => { key_values => [ { name => 'running' } ], output_template => "running : %s", perfdatas => [ { label => 'total_running', value => 'running', template => '%d', min => 0 }, ], } }, { label => 'total-stopped', set => { key_values => [ { name => 'stopped' } ], output_template => "stopped : %s", perfdatas => [ { label => 'total_stopped', value => 'stopped', template => '%d', min => 0 }, ], } }, ]; $self->{maps_counters}->{vms} = [ { 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 => \&catalog_status_threshold, } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource-group:s" => { name => 'resource_group' }, "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); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; $self->{global} = { running => 0, stopped => 0, }; $self->{vms} = {}; my $vms = $options{custom}->azure_list_vms(resource_group => $self->{option_results}->{resource_group}, show_details => 1); foreach my $vm (@{$vms}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $vm->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $vm->{name} . "': no matching filter.", debug => 1); next; } $self->{vms}->{$vm->{id}} = { display => $vm->{name}, state => $vm->{powerState}, }; foreach my $state (keys %{$self->{global}}) { $self->{global}->{$state}++ if ($vm->{powerState} =~ /$state/); } } if (scalar(keys %{$self->{vms}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No virtual machines found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check virtual machines status (Only with az CLI). Example: perl centreon_plugins.pl --plugin=cloud::azure::compute::virtualmachine::plugin --custommode=azcli --mode=vms-state --filter-name='.*' --filter-counters='^total-running$' --critical-total-running='10' --verbose =over 8 =item B<--resource-group> Set resource group (Optional). =item B<--filter-name> Filter resource name (Can be a regexp). =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^total-running$' =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{state}, %{display} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{state}, %{display} =item B<--warning-*> Threshold warning. Can be: 'total-running', 'total-stopped'. =item B<--critical-*> Threshold critical. Can be: 'total-running', 'total-stopped'. =back =cut centreon-plugins-20220113/cloud/azure/compute/virtualmachine/plugin.pm000066400000000000000000000044351417000230700260210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::compute::virtualmachine::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} } = ( 'cpu' => 'cloud::azure::compute::virtualmachine::mode::cpu', 'discovery' => 'cloud::azure::compute::virtualmachine::mode::discovery', 'diskio' => 'cloud::azure::compute::virtualmachine::mode::diskio', 'health' => 'cloud::azure::compute::virtualmachine::mode::health', 'list-resources' => 'cloud::azure::compute::virtualmachine::mode::listresources', 'memory' => 'cloud::azure::compute::virtualmachine::mode::memory', 'network' => 'cloud::azure::compute::virtualmachine::mode::network', 'vm-sizes' => 'cloud::azure::compute::virtualmachine::mode::vmsizes', 'vms-state' => 'cloud::azure::compute::virtualmachine::mode::vmsstate' ); $self->{custom_modes}{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' }, }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure virtual machine. =cut centreon-plugins-20220113/cloud/azure/compute/vmscalesets/000077500000000000000000000000001417000230700234755ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/compute/vmscalesets/mode/000077500000000000000000000000001417000230700244215ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/compute/vmscalesets/mode/cpu.pm000066400000000000000000000117441417000230700255550ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::compute::vmscalesets::mode::cpu; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'CPU Credits Consumed' => { 'output' => 'CPU Credits Consumed', 'label' => 'cpu-credits-consumed', 'nlabel' => 'cpu.credits.consumed.count', 'unit' => '', 'min' => '0' }, 'CPU Credits Remaining' => { 'output' => 'CPU Credits Remaining', 'label' => 'cpu-credits-remaining', 'nlabel' => 'cpu.credits.remaining.count', 'unit' => '', 'min' => '0' }, 'Percentage CPU' => { 'output' => 'CPU percent', 'label' => 'cpu-usage', 'nlabel' => 'cpu.utilization.percentage', 'unit' => '%', 'min' => '0', 'max' => '100' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; my $resource_type = $self->{option_results}->{resource_type}; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Compute\/virtualMachineScaleSets\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'virtualMachineScaleSets'; $self->{az_resource_namespace} = 'Microsoft.Compute'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Virtual Machine Scale Sets CPU usage. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::compute::vmscalesets::plugin --mode=cpu --custommode=api --resource= --resource-group= --warning-cpu-usage='80' --critical-cpu-usage='90' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::vmscalesets::plugin --mode=cpu --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Compute/virtualMachineScaleSets/' --warning-cpu-usage='80' --critical-cpu-usage='90' =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-cpu-usage> Set warning threshold for CPU utilization percentage. =item B<--critical-cpu-usage> Set critical threshold for CPU utilization percentage. =item B<--warning-cpu-credits-remaining> Set warning threshold on number of CPU credits remaining. Only available for B-series burstable VMs. =item B<--critical-cpu-credits-remaining> Set critical threshold on number of CPU credits remaining. Only available for B-series burstable VMs. =back =cut centreon-plugins-20220113/cloud/azure/compute/vmscalesets/mode/discovery.pm000066400000000000000000000024061417000230700267700ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::compute::vmscalesets::mode::discovery; use base qw(cloud::azure::management::monitor::mode::discovery); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{namespace} = 'Microsoft.Compute'; $self->{type} = 'virtualMachineScaleSets'; } 1; __END__ =head1 MODE Virtual Machine Scale Sets Discovery. =over 8 =item B<--location> Specify resources location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/compute/vmscalesets/mode/diskio.pm000066400000000000000000000111451417000230700262430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::compute::vmscalesets::mode::diskio; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'Disk Read Operations/sec' => { 'output' => 'Disk Read Operations/sec', 'label' => 'disk-read-ops-persec', 'nlabel' => 'disk.write.ops.persec', 'unit' => '', 'min' => '0', 'max' => '' }, 'Disk Write Operations/sec' => { 'output' => 'Disk Write Operations/sec', 'label' => 'disk-write-ops-persec', 'nlabel' => 'disk.write.ops.persec', 'unit' => '', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; my $resource_type = $self->{option_results}->{resource_type}; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Compute\/virtualMachineScaleSets\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'virtualMachineScaleSets'; $self->{az_resource_namespace} = 'Microsoft.Compute'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Virtual Machine Scale Sets I/O operations per second. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::compute::vmscalesets::plugin --mode=diskio --custommode=api --resource= --resource-group= --warning-disk-read-ops-persec=10 --critical-disk-read-ops-persec=10 Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::compute::vmscalesets::plugin --mode=diskio --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Compute/virtualMachineScaleSets/' --warning-disk-read-ops-persec=10 --critical-disk-read-ops-persec=10 =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'disk-read-ops-persec', 'disk-write-ops-persec' =item B<--critical-*> Critical threshold where '*' can be: 'disk-read-ops-persec', 'disk-write-ops-persec' =back =cut centreon-plugins-20220113/cloud/azure/compute/vmscalesets/mode/health.pm000066400000000000000000000037141417000230700262310ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::compute::vmscalesets::mode::health; use base qw(cloud::azure::management::monitor::mode::health); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{az_resource_namespace} = 'Microsoft.Compute'; $self->{az_resource_type} = 'virtualMachineScaleSets'; } 1; __END__ =head1 MODE Check Azure Virtual Machine Scale Sets Health. (Usefull to determine host status) =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{summary} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /^Unavailable$/'). Can used special variables like: %{status}, %{summary} =item B<--unknown-status> Set unknown threshold for status (Default: '%{status} =~ /^Unknown$/'). Can used special variables like: %{status}, %{summary} =item B<--ok-status> Set ok threshold for status (Default: '%{status} =~ /^Available$/'). Can used special variables like: %{status}, %{summary} =back =cut centreon-plugins-20220113/cloud/azure/compute/vmscalesets/mode/memory.pm000066400000000000000000000105601417000230700262710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::compute::vmscalesets::mode::memory; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'Available Memory Bytes' => { 'output' => 'Available Memory Bytes', 'label' => 'memory-available', 'nlabel' => 'memory.available.bytes', 'unit' => 'B', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; my $resource_type = $self->{option_results}->{resource_type}; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Compute\/virtualMachineScaleSets\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'virtualMachineScaleSets'; $self->{az_resource_namespace} = 'Microsoft.Compute'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Virtual Machine Scale Sets Available Memory. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::compute::vmscalesets::plugin --mode=memory --custommode=api --resource= --resource-group= --critical-memory-available='8GB:' --warning-memory-available='16GB:' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::vmscalesets::plugin --mode=memory --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Compute/virtualMachineScaleSets/' --critical-memory-available='8GB:' --warning-memory-available='16GB:' =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-memory-available> Warning threshold. It is a range, set 16GB: for example to get WARNING if there are less than 16GB available left. =item B<--critical-memory-available> Critical threshold. It is a range, set 8GB: for example to get CRITICAL if there are less than 8GB available left. =back =cut centreon-plugins-20220113/cloud/azure/compute/vmscalesets/mode/traffic.pm000066400000000000000000000107321417000230700264000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::compute::vmscalesets::mode::traffic; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'Network In Total' => { 'output' => 'Network In Total', 'label' => 'traffic-in', 'nlabel' => 'traffic.in.bytes', 'unit' => 'B', 'min' => '0', }, 'Network Out Total' => { 'output' => 'Network Out Total', 'label' => 'traffic-out', 'nlabel' => 'traffic.out.bytes', 'unit' => 'B', 'min' => '0', } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; my $resource_type = $self->{option_results}->{resource_type}; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Compute\/virtualMachineScaleSets\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'virtualMachineScaleSets'; $self->{az_resource_namespace} = 'Microsoft.Compute'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Virtual Machine Scale Sets Traffic In and Out. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::compute::vmscalesets::plugin --mode=traffic --custommode=api --resource= --resource-group= --warning-traffic-out=10000 --critical-traffic-in=15000 Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::vmscalesets::plugin --mode=traffic --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Compute/virtualMachineScaleSets/' --warning-traffic-out=10000 --critical-traffic-in=15000 =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'traffic-out', 'traffic-in'. =item B<--critical-*> Critical threshold where '*' can be: 'traffic-out', 'traffic-in'. =item B<--per-sec> Change the data to be unit/sec. =back =cut centreon-plugins-20220113/cloud/azure/compute/vmscalesets/plugin.pm000066400000000000000000000037571417000230700253450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::compute::vmscalesets::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} = { 'cpu' => 'cloud::azure::compute::vmscalesets::mode::cpu', 'discovery' => 'cloud::azure::compute::vmscalesets::mode::discovery', 'diskio' => 'cloud::azure::compute::vmscalesets::mode::diskio', 'health' => 'cloud::azure::compute::vmscalesets::mode::health', 'memory' => 'cloud::azure::compute::vmscalesets::mode::memory', 'traffic' => 'cloud::azure::compute::vmscalesets::mode::traffic' }; $self->{custom_modes}->{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}->{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' }, }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Virtual Machine Scale Sets. =cutcentreon-plugins-20220113/cloud/azure/custom/000077500000000000000000000000001417000230700210025ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/custom/api.pm000066400000000000000000000727151417000230700221250ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::custom::api; use strict; use warnings; use DateTime; use centreon::plugins::http; use centreon::plugins::statefile; use JSON::XS; use URI::Encode; use Digest::MD5 qw(md5_hex); 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 => { 'subscription:s' => { name => 'subscription' }, 'tenant:s' => { name => 'tenant' }, 'client-id:s' => { name => 'client_id' }, 'client-secret:s' => { name => 'client_secret' }, 'login-endpoint:s' => { name => 'login_endpoint' }, 'management-endpoint:s' => { name => 'management_endpoint' }, 'timeframe:s' => { name => 'timeframe' }, 'interval:s' => { name => 'interval' }, 'aggregation:s@' => { name => 'aggregation' }, 'zeroed' => { name => 'zeroed' }, 'timeout:s' => { name => 'timeout' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); $self->{cache} = centreon::plugins::statefile->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; if (defined($self->{option_results}->{aggregation})) { foreach my $aggregation (@{$self->{option_results}->{aggregation}}) { if ($aggregation !~ /average|maximum|minimum|total|count/i) { $self->{output}->add_option_msg(short_msg => "Aggregation '" . $aggregation . "' is not handled"); $self->{output}->option_exit(); } } } $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{timeframe} = (defined($self->{option_results}->{timeframe})) ? $self->{option_results}->{timeframe} : undef; $self->{step} = (defined($self->{option_results}->{step})) ? $self->{option_results}->{step} : undef; $self->{subscription} = (defined($self->{option_results}->{subscription})) ? $self->{option_results}->{subscription} : undef; $self->{tenant} = (defined($self->{option_results}->{tenant})) ? $self->{option_results}->{tenant} : undef; $self->{client_id} = (defined($self->{option_results}->{client_id})) ? $self->{option_results}->{client_id} : undef; $self->{client_secret} = (defined($self->{option_results}->{client_secret})) ? $self->{option_results}->{client_secret} : undef; $self->{login_endpoint} = (defined($self->{option_results}->{login_endpoint})) ? $self->{option_results}->{login_endpoint} : 'https://login.microsoftonline.com'; $self->{management_endpoint} = (defined($self->{option_results}->{management_endpoint})) ? $self->{option_results}->{management_endpoint} : 'https://management.azure.com'; $self->{api_version} = (defined($self->{option_results}->{api_version})) ? $self->{option_results}->{api_version} : undef; if (!defined($self->{subscription}) || $self->{subscription} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --subscription option."); $self->{output}->option_exit(); } if (!defined($self->{tenant}) || $self->{tenant} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --tenant option."); $self->{output}->option_exit(); } if (!defined($self->{client_id}) || $self->{client_id} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --client-id option."); $self->{output}->option_exit(); } if (!defined($self->{client_secret}) || $self->{client_secret} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --client-secret option."); $self->{output}->option_exit(); } if (!defined($self->{api_version}) || $self->{api_version} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-version option."); $self->{output}->option_exit(); } $self->{cache}->check_options(option_results => $self->{option_results}); return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{warning_status} = ''; $self->{option_results}->{critical_status} = ''; $self->{option_results}->{unknown_status} = '%{http_code} < 200 or %{http_code} >= 500'; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); if (defined($self->{access_token})) { $self->{http}->add_header(key => 'Authorization', value => 'Bearer ' . $self->{access_token}); } $self->{http}->set_options(%{$self->{option_results}}); } sub get_access_token { my ($self, %options) = @_; my $has_cache_file = $options{statefile}->read( statefile => 'azure_api_' . md5_hex($self->{subscription}) . '_' . md5_hex($self->{tenant}) . '_' . md5_hex($self->{client_id}) . '_' . md5_hex($self->{management_endpoint}) ); my $expires_on = $options{statefile}->get(name => 'expires_on'); my $access_token = $options{statefile}->get(name => 'access_token'); if ($has_cache_file == 0 || !defined($access_token) || (($expires_on - time()) < 10)) { $self->settings(); my $content = $self->{http}->request( method => 'POST', full_url => $self->{login_endpoint} . '/' . $self->{tenant} . '/oauth2/token', hostname => '', post_param => [ 'grant_type=client_credentials', 'client_id=' . $self->{client_id}, 'client_secret=' . $self->{client_secret}, 'resource=' . $self->{management_endpoint} ] ); if (!defined($content) || $content eq '' || $self->{http}->get_header(name => 'content-length') == 0) { $self->{output}->add_option_msg(short_msg => "Login endpoint API returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->output_add(long_msg => $@, debug => 1); $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } if (defined($decoded->{error})) { $self->{output}->output_add(long_msg => "Error message : " . $decoded->{error_description}, debug => 1); $self->{output}->add_option_msg(short_msg => "Login endpoint API returns error code '" . $decoded->{error} . "' (add --debug option for detailed message)"); $self->{output}->option_exit(); } $access_token = $decoded->{access_token}; my $datas = { last_timestamp => time(), access_token => $decoded->{access_token}, expires_on => $decoded->{expires_on} }; $options{statefile}->write(data => $datas); } return $access_token; } sub request_api { my ($self, %options) = @_; if (!defined($self->{access_token})) { $self->{access_token} = $self->get_access_token(statefile => $self->{cache}); } $self->settings(); my $content = $self->{http}->request(%options); if (!defined($content) || $content eq '' || $self->{http}->get_header(name => 'content-length') == 0) { $self->{output}->add_option_msg(short_msg => "Management endpoint API returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->output_add(long_msg => $@, debug => 1); $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } if (defined($decoded->{error})) { $self->{output}->output_add(long_msg => "Error message : " . $decoded->{error}->{message}, debug => 1); $self->{output}->add_option_msg(short_msg => "Management endpoint API returns error code '" . $decoded->{error}->{code} . "' (add --debug option for detailed message)"); $self->{output}->option_exit(); } if (defined($decoded->{code})) { $self->{output}->output_add(long_msg => "Message : " . $decoded->{message}, debug => 1); $self->{output}->add_option_msg(short_msg => "Management endpoint API returns code '" . $decoded->{code} . "' (add --debug option for detailed message)"); $self->{output}->option_exit(); } return $decoded; } sub convert_duration { my ($self, %options) = @_; my $duration; if ($options{time_string} =~ /^P.*S$/) { centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'DateTime::Format::Duration::ISO8601', error_msg => "Cannot load module 'DateTime::Format::Duration::ISO8601'." ); my $format = DateTime::Format::Duration::ISO8601->new; my $d = $format->parse_duration($options{time_string}); $duration = $d->minutes * 60 + $d->seconds; } elsif ($options{time_string} =~ /^(\d+):(\d+):(\d+)\.\d+$/) { centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'DateTime::Duration', error_msg => "Cannot load module 'DateTime::Format::Duration'." ); my $d = DateTime::Duration->new(hours => $1, minutes => $2, seconds => $3); $duration = $d->minutes * 60 + $d->seconds; } return $duration; } sub json_decode { my ($self, %options) = @_; $options{content} =~ s/\r//mg; my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($options{content}); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } return $decoded; } sub azure_get_metrics_set_url { my ($self, %options) = @_; my $uri = URI::Encode->new({encode_reserved => 1}); my $encoded_metrics = $uri->encode(join(',', @{$options{metrics}})); my $encoded_aggregations = $uri->encode(join(',', @{$options{aggregations}})); my $encoded_timespan = $uri->encode($options{start_time} . '/' . $options{end_time}); my $url = $self->{management_endpoint} . "/subscriptions/" . $self->{subscription} . "/resourceGroups/" . $options{resource_group} . "/providers/" . $options{resource_namespace} . "/" . $options{resource_type} . "/" . $options{resource} . "/providers/microsoft.insights/metrics?api-version=" . $self->{api_version} . "&metricnames=" . $encoded_metrics . "&aggregation=" . $encoded_aggregations . "×pan=" . $encoded_timespan . "&interval=" . $options{interval}; $url .= "&\$filter=" . $options{dimension} if defined($options{dimension}); $url .= "&metricnamespace=" . $uri->encode($options{metric_namespace}) if defined($options{metric_namespace}); return $url; } sub azure_get_metrics { my ($self, %options) = @_; my $results = {}; my $start_time = DateTime->now->subtract(seconds => $options{timeframe})->iso8601.'Z'; my $end_time = DateTime->now->iso8601.'Z'; my $full_url = $self->azure_get_metrics_set_url(%options, start_time => $start_time, end_time => $end_time); my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => ''); foreach my $metric (@{$response->{value}}) { my $metric_name = lc($metric->{name}->{value}); $metric_name =~ s/ /_/g; $results->{$metric_name} = { points => 0, name => $metric->{name}->{localizedValue} }; foreach my $timeserie (@{$metric->{timeseries}}) { foreach my $point (@{$timeserie->{data}}) { if (defined($point->{average})) { $results->{$metric_name}->{average} = 0 if (!defined($results->{$metric_name}->{average})); $results->{$metric_name}->{average} += $point->{average}; $results->{$metric_name}->{points}++; } if (defined($point->{minimum})) { $results->{$metric_name}->{minimum} = $point->{minimum} if (!defined($results->{$metric_name}->{minimum}) || $point->{minimum} < $results->{$metric_name}->{minimum}); } if (defined($point->{maximum})) { $results->{$metric_name}->{maximum} = $point->{maximum} if (!defined($results->{$metric_name}->{maximum}) || $point->{maximum} > $results->{$metric_name}->{maximum}); } if (defined($point->{total})) { $results->{$metric_name}->{total} = 0 if (!defined($results->{$metric_name}->{total})); $results->{$metric_name}->{total} += $point->{total}; $results->{$metric_name}->{points}++; } if (defined($point->{count})) { $results->{$metric_name}->{count} = $point->{count}; } } } if (defined($results->{$metric_name}->{average})) { $results->{$metric_name}->{average} /= $results->{$metric_name}->{points}; } } return $results, $response; } sub azure_get_resource_health_set_url { my ($self, %options) = @_; my $url = $self->{management_endpoint} . "/subscriptions/" . $self->{subscription} . "/resourceGroups/" . $options{resource_group} . "/providers/" . $options{resource_namespace} . "/" . $options{resource_type} . "/" . $options{resource} . "/providers/Microsoft.ResourceHealth/availabilityStatuses/current?api-version=" . $options{api_version}; return $url; } sub azure_get_resource_health { my ($self, %options) = @_; my $full_url = $self->azure_get_resource_health_set_url(%options); my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => ''); return $response; } sub azure_get_resource_alert_set_url { my ($self, %options) = @_; my $url = $self->{management_endpoint} . "/subscriptions/" . $self->{subscription} . "/providers/Microsoft.AlertsManagement/alertsSummary" . "?api-version=" . $self->{api_version} . "&groupby=" . $options{group_by} . "&targetResourceGroup=" . $options{resource_group} . "&targetResourceName=" . $options{resource}. "&timeRange=" . $options{time_range}; return $url; } sub azure_get_resource_alert { my ($self, %options) = @_; my $full_url = $self->azure_get_resource_alert_set_url(%options); my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => ''); return $response; } sub azure_list_resources_set_url { my ($self, %options) = @_; my $filter = ''; my %filter; $filter{resource_type} = "resourceType eq '" . $options{namespace} . '/' . $options{resource_type} . "'" if (defined($options{namespace}) && $options{namespace} ne '' && defined($options{resource_type}) && $options{resource_type} ne ''); $filter{resource_group} = "resourceGroup eq '" . $options{resource_group} . "'" if (defined($options{resource_group}) && $options{resource_group} ne ''); $filter{location} = "location eq '" . $options{location} . "'" if (defined($options{location}) && $options{location} ne ''); my $append = ''; foreach (('resource_type', 'resource_group', 'location')) { next if (!defined($filter{$_})); $filter .= $append . $filter{$_}; $append = ' and '; } my $uri = URI::Encode->new({encode_reserved => 1}); my $encoded_filter = $uri->encode($filter); my $url = $self->{management_endpoint} . "/subscriptions/" . $self->{subscription} . "/resources?api-version=" . $self->{api_version}; $url .= "&\$filter=" . $encoded_filter if (defined($encoded_filter) && $encoded_filter ne ''); return $url; } sub azure_list_resources { my ($self, %options) = @_; my $full_response = []; my $full_url = $self->azure_list_resources_set_url(%options); while (1) { my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => ''); foreach (@{$response->{value}}) { push @$full_response, $_; } last if (!defined($response->{nextLink})); $full_url = $response->{nextLink}; } return $full_response; } sub azure_list_vms_set_url { my ($self, %options) = @_; my $url = $self->{management_endpoint} . "/subscriptions/" . $self->{subscription}; $url .= "/resourceGroups/" . $options{resource_group} if (defined($options{resource_group}) && $options{resource_group} ne ''); $url .= "/providers/Microsoft.Compute/virtualMachines?api-version=" . $self->{api_version}; return $url; } sub azure_list_vms { my ($self, %options) = @_; my $full_url = $self->azure_list_vms_set_url(%options); my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => ''); return $response->{value}; } sub azure_list_groups_set_url { my ($self, %options) = @_; my $url = $self->{management_endpoint} . "/subscriptions/" . $self->{subscription} . "/resourcegroups?api-version=" . $self->{api_version}; return $url; } sub azure_list_groups { my ($self, %options) = @_; my $full_url = $self->azure_list_groups_set_url(%options); my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => ''); return $response->{value}; } sub azure_list_deployments_set_url { my ($self, %options) = @_; my $url = $self->{management_endpoint} . "/subscriptions/" . $self->{subscription} . "/resourcegroups/" . $options{resource_group} . "/providers/Microsoft.Resources/deployments?api-version=" . $self->{api_version}; return $url; } sub azure_list_deployments { my ($self, %options) = @_; my $full_url = $self->azure_list_deployments_set_url(%options); my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => ''); return $response->{value}; } sub azure_list_vaults_set_url { my ($self, %options) = @_; my $url = $self->{management_endpoint} . "/subscriptions/" . $self->{subscription}; $url .= "/resourceGroups/" . $options{resource_group} if (defined($options{resource_group}) && $options{resource_group} ne ''); $url .= "/providers/Microsoft.RecoveryServices/vaults?api-version=" . $self->{api_version}; return $url; } sub azure_list_vaults { my ($self, %options) = @_; my $full_url = $self->azure_list_vaults_set_url(%options); my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => ''); return $response->{value}; } sub azure_list_backup_jobs_set_url { my ($self, %options) = @_; my $url = $self->{management_endpoint} . "/subscriptions/" . $self->{subscription} . "/resourcegroups/" . $options{resource_group} . "/providers/Microsoft.RecoveryServices/vaults/" . $options{vault_name} . "/backupJobs?api-version=" . $self->{api_version}; return $url; } sub azure_list_backup_jobs { my ($self, %options) = @_; my $full_url = $self->azure_list_backup_jobs_set_url(%options); my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => ''); return $response->{value}; } sub azure_list_backup_items_set_url { my ($self, %options) = @_; my $url = $self->{management_endpoint} . "/subscriptions/" . $self->{subscription} . "/resourcegroups/" . $options{resource_group} . "/providers/Microsoft.RecoveryServices/vaults/" . $options{vault_name} . "/backupProtectedItems?api-version=" . $self->{api_version}; return $url; } sub azure_list_backup_items { my ($self, %options) = @_; my $full_url = $self->azure_list_backup_items_set_url(%options); my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => ''); return $response->{value}; } sub azure_list_expressroute_circuits_set_url { my ($self, %options) = @_; my $url = $self->{management_endpoint} . "/subscriptions/" . $self->{subscription}; $url .= "/resourceGroups/" . $options{resource_group} if (defined($options{resource_group}) && $options{resource_group} ne ''); $url .= "/providers/Microsoft.Network/expressRouteCircuits?api-version=" . $self->{api_version}; return $url; } sub azure_list_expressroute_circuits { my ($self, %options) = @_; my $full_url = $self->azure_list_expressroute_circuits_set_url(%options); my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => ''); return $response->{value}; } sub azure_list_vpn_gateways_set_url { my ($self, %options) = @_; my $url = $self->{management_endpoint} . "/subscriptions/" . $self->{subscription} . "/resourcegroups/" . $options{resource_group} . "/providers/Microsoft.Network/virtualNetworkGateways?api-version=" . $self->{api_version}; return $url; } sub azure_list_vpn_gateways { my ($self, %options) = @_; my $full_url = $self->azure_list_vpn_gateways_set_url(%options); my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => ''); return $response->{value}; } sub azure_list_virtualnetworks_set_url { my ($self, %options) = @_; my $url = $self->{management_endpoint} . "/subscriptions/" . $self->{subscription} . "/resourcegroups/" . $options{resource_group} . "/providers/Microsoft.Network/virtualNetworks?api-version=" . $self->{api_version}; return $url; } sub azure_list_virtualnetworks { my ($self, %options) = @_; my $full_url = $self->azure_list_virtualnetworks_set_url(%options); my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => ''); return $response->{value}; } sub azure_list_vnet_peerings_set_url { my ($self, %options) = @_; my $url = $self->{management_endpoint} . "/subscriptions/" . $self->{subscription} . "/resourcegroups/" . $options{resource_group} . "/providers/Microsoft.Network/virtualNetworks/" . $options{resource} . "/virtualNetworkPeerings?api-version=" . $self->{api_version}; return $url; } sub azure_list_vnet_peerings { my ($self, %options) = @_; my $full_url = $self->azure_list_vnet_peerings_set_url(%options); my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => ''); return $response->{value}; } sub azure_list_sqlservers_set_url { my ($self, %options) = @_; my $url = $self->{management_endpoint} . "/subscriptions/" . $self->{subscription}; $url .= "/resourceGroups/" . $options{resource_group} if (defined($options{resource_group}) && $options{resource_group} ne ''); $url .= "/providers/Microsoft.Sql/servers?api-version=" . $self->{api_version}; return $url; } sub azure_list_sqlservers { my ($self, %options) = @_; my $full_url = $self->azure_list_sqlservers_set_url(%options); my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => ''); return $response->{value}; } sub azure_list_sqldatabases_set_url { my ($self, %options) = @_; my $url = $self->{management_endpoint} . "/subscriptions/" . $self->{subscription}; $url .= "/resourceGroups/" . $options{resource_group} if (defined($options{resource_group}) && $options{resource_group} ne ''); $url .= "/providers/Microsoft.Sql/servers/" . $options{server} if (defined($options{server}) && $options{server} ne ''); $url .= "/databases?api-version=" . $self->{api_version}; return $url; } sub azure_list_sqldatabases { my ($self, %options) = @_; my $full_url = $self->azure_list_sqldatabases_set_url(%options); my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => ''); return $response->{value}; } sub azure_get_log_analytics_set_url { my ($self, %options) = @_; my $uri = URI::Encode->new({encode_reserved => 1}); my $encoded_query = $uri->encode($options{query}); my $encoded_timespan = $uri->encode($options{timespan}); my $url = $self->{management_endpoint} . '/v1/workspaces/' . $options{workspace_id} . '/query?query=' . $encoded_query; $url .= '×pan=' . $encoded_timespan if (defined($encoded_timespan)); $url .= '&api-version=' . $self->{api_version}; return $url; } sub azure_get_log_analytics { my ($self, %options) = @_; my $full_url = $self->azure_get_log_analytics_set_url(%options); my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => ''); return $response; } sub azure_get_insights_analytics { my ($self, %options) = @_; my $raw_results = {}; my $analytics_results = $self->azure_get_log_analytics( workspace_id => $options{workspace_id}, query => $options{query}, timespan => $options{timespan} ); foreach (@{$analytics_results->{tables}}) { my ($i, $j) = (0, 0); foreach my $entry (@{$_->{columns}}) { $raw_results->{index}->{$entry->{name}} = $i; $i++; } foreach (@{$_->{rows}}) { $raw_results->{data}->{$j}->{tags} = @$_[$raw_results->{index}->{Tags}]; $raw_results->{data}->{$j}->{computer} = @$_[$raw_results->{index}->{Computer}]; $raw_results->{data}->{$j}->{resourceid} = @$_[$raw_results->{index}->{_ResourceId}]; if (!defined($options{disco})) { $raw_results->{data}->{$j}->{timegenerated} = @$_[$raw_results->{index}->{TimeGenerated}]; $raw_results->{data}->{$j}->{name} = @$_[$raw_results->{index}->{Name}]; $raw_results->{data}->{$j}->{value} = @$_[$raw_results->{index}->{Val}]; } $j++; } } return $raw_results; } sub azure_get_publicip_set_url { my ($self, %options) = @_; my $url = $self->{management_endpoint} . "/subscriptions/" . $self->{subscription}; $url .= "/resourceGroups/" . $options{resource_group} if (defined($options{resource_group}) && $options{resource_group} ne ''); $url .= "/providers/Microsoft.Network/publicIPAddresses/" . $options{resource} if (defined($options{resource}) && $options{resource} ne ''); $url .= "?api-version=" . $self->{api_version}; return $url; } sub azure_get_publicip { my ($self, %options) = @_; my $full_url = $self->azure_get_publicip_set_url(%options); my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => ''); return $response; } 1; __END__ =head1 NAME Microsoft Azure Rest API =head1 REST API OPTIONS Microsoft Azure Rest API To connect to the Azure Rest API, you must register an application. Follow the 'How-to guide' in https://docs.microsoft.com/en-us/azure/active-directory/develop/howto-create-service-principal-portal The application needs the 'Monitoring Reader' role (See https://docs.microsoft.com/en-us/azure/azure-monitor/platform/roles-permissions-security#monitoring-reader). This custom mode is using the 'OAuth 2.0 Client Credentials Grant Flow' For futher informations, visit https://docs.microsoft.com/en-us/azure/active-directory/develop/v1-oauth2-client-creds-grant-flow =over 8 =item B<--subscription> Set Azure subscription ID. =item B<--tenant> Set Azure tenant ID. =item B<--client-id> Set Azure client ID. =item B<--client-secret> Set Azure client secret. =item B<--login-endpoint> Set Azure login endpoint URL (Default: 'https://login.microsoftonline.com') =item B<--management-endpoint> Set Azure management endpoint URL (Default: 'https://management.azure.com') =item B<--timeframe> Set timeframe in seconds (i.e. 3600 to check last hour). =item B<--interval> Set interval of the metric query (Can be : PT1M, PT5M, PT15M, PT30M, PT1H, PT6H, PT12H, PT24H). =item B<--aggregation> Set monitor aggregation (Can be multiple, Can be: 'minimum', 'maximum', 'average', 'total', 'count'). =item B<--zeroed> Set metrics value to 0 if none. Usefull when Monitor does not return value when not defined. =item B<--timeout> Set timeout in seconds (Default: 10). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/cloud/azure/custom/azcli.pm000066400000000000000000000556761417000230700224650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::custom::azcli; use strict; use warnings; use DateTime; use JSON::XS; 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 => { 'subscription:s' => { name => 'subscription' }, 'tenant:s' => { name => 'tenant' }, 'client-id:s' => { name => 'client_id' }, 'client-secret:s' => { name => 'client_secret' }, 'timeframe:s' => { name => 'timeframe' }, 'interval:s' => { name => 'interval' }, 'aggregation:s@' => { name => 'aggregation' }, 'zeroed' => { name => 'zeroed' }, 'timeout:s' => { name => 'timeout', default => 50 }, 'sudo' => { name => 'sudo' }, 'command:s' => { name => 'command', default => 'az' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '' }, 'proxyurl:s' => { name => 'proxyurl' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'AZCLI OPTIONS', once => 1); $self->{output} = $options{output}; return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; if (defined($self->{option_results}->{proxyurl}) && $self->{option_results}->{proxyurl} ne '') { $ENV{HTTP_PROXY} = $self->{option_results}->{proxyurl}; $ENV{HTTPS_PROXY} = $self->{option_results}->{proxyurl}; } if (defined($self->{option_results}->{aggregation})) { foreach my $aggregation (@{$self->{option_results}->{aggregation}}) { if ($aggregation !~ /average|maximum|minimum|total|count/i) { $self->{output}->add_option_msg(short_msg => "Aggregation '" . $aggregation . "' is not handled"); $self->{output}->option_exit(); } } } $self->{subscription} = (defined($self->{option_results}->{subscription})) ? $self->{option_results}->{subscription} : undef; return 0; } sub execute { my ($self, %options) = @_; $self->{output}->output_add(long_msg => "Command line: '" . $self->{option_results}->{command} . " " . $options{cmd_options} . "'", debug => 1); my ($response) = 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 => $options{cmd_options}); my $raw_results; eval { $raw_results = JSON::XS->new->utf8->decode($response); }; if ($@) { $self->{output}->output_add(long_msg => $response, debug => 1); $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } return $raw_results; } sub convert_duration { my ($self, %options) = @_; my $duration; if ($options{time_string} =~ /^P.*S$/) { centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'DateTime::Format::Duration::ISO8601', error_msg => "Cannot load module 'DateTime::Format::Duration::ISO8601'." ); my $format = DateTime::Format::Duration::ISO8601->new; my $d = $format->parse_duration($options{time_string}); $duration = $d->minutes * 60 + $d->seconds; } elsif ($options{time_string} =~ /^(\d+):(\d+):(\d+)\.\d+$/) { centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'DateTime::Duration', error_msg => "Cannot load module 'DateTime::Format::Duration'." ); my $d = DateTime::Duration->new(hours => $1, minutes => $2, seconds => $3); $duration = $d->minutes * 60 + $d->seconds; } return $duration; } sub azure_get_metrics_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "monitor metrics list --metrics '" . join('\' \'', @{$options{metrics}}) . "' --start-time $options{start_time} --end-time $options{end_time} " . "--interval $options{interval} --aggregation '" . join('\' \'', @{$options{aggregations}}) . "' --only-show-errors --output json --resource '$options{resource}' " . "--resource-group '$options{resource_group}' --resource-type '$options{resource_type}' --resource-namespace '$options{resource_namespace}'"; $cmd_options .= " --subscription '$self->{subscription}'" if (defined($self->{subscription}) && $self->{subscription} ne ''); $cmd_options .= " --filter '$options{dimension}'" if defined($options{dimension}); $cmd_options .= " --namespace '$options{metric_namespace}'" if defined($options{metric_namespace}); return $cmd_options; } sub azure_get_metrics { my ($self, %options) = @_; my $results = {}; my $start_time = DateTime->now->subtract(seconds => $options{timeframe})->iso8601.'Z'; my $end_time = DateTime->now->iso8601.'Z'; my $cmd_options = $self->azure_get_metrics_set_cmd(%options, start_time => $start_time, end_time => $end_time); my $raw_results = $self->execute(cmd_options => $cmd_options); foreach my $metric (@{$raw_results->{value}}) { my $metric_name = lc($metric->{name}->{value}); $metric_name =~ s/ /_/g; $results->{$metric_name} = { points => 0, name => $metric->{name}->{localizedValue} }; foreach my $timeserie (@{$metric->{timeseries}}) { foreach my $point (@{$timeserie->{data}}) { if (defined($point->{average})) { $results->{$metric_name}->{average} = 0 if (!defined($results->{$metric_name}->{average})); $results->{$metric_name}->{average} += $point->{average}; $results->{$metric_name}->{points}++; } if (defined($point->{minimum})) { $results->{$metric_name}->{minimum} = $point->{minimum} if (!defined($results->{$metric_name}->{minimum}) || $point->{minimum} < $results->{$metric_name}->{minimum}); } if (defined($point->{maximum})) { $results->{$metric_name}->{maximum} = $point->{maximum} if (!defined($results->{$metric_name}->{maximum}) || $point->{maximum} > $results->{$metric_name}->{maximum}); } if (defined($point->{total})) { $results->{$metric_name}->{total} = 0 if (!defined($results->{$metric_name}->{total})); $results->{$metric_name}->{total} += $point->{total}; $results->{$metric_name}->{points}++; } if (defined($point->{count})) { $results->{$metric_name}->{count} = $point->{count}; } } } if (defined($results->{$metric_name}->{average})) { $results->{$metric_name}->{average} /= $results->{$metric_name}->{points}; } } return $results, $raw_results; } sub azure_get_resource_health_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "rest --only-show-errors --output json"; $cmd_options .= " --uri /subscriptions/" . $self->{subscription} . "/resourceGroups/" . $options{resource_group} . "/providers/" . $options{resource_namespace} . "/" . $options{resource_type} . "/" . $options{resource} . "/providers/Microsoft.ResourceHealth/availabilityStatuses/current?api-version=" . $options{api_version}; return $cmd_options; } sub azure_get_resource_health { my ($self, %options) = @_; my $cmd_options = $self->azure_get_resource_health_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); return $raw_results; } sub azure_list_resources_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "resource list --only-show-errors --output json"; $cmd_options .= " --namespace '$options{resource_namespace}'" if (defined($options{resource_namespace}) && $options{resource_namespace} ne ''); $cmd_options .= " --resource-type '$options{resource_type}'" if (defined($options{resource_type}) && $options{resource_type} ne ''); $cmd_options .= " --location '$options{location}'" if (defined($options{location}) && $options{location} ne ''); $cmd_options .= " --resource-group '$options{resource_group}'" if (defined($options{resource_group}) && $options{resource_group} ne ''); $cmd_options .= " --subscription '$self->{subscription}'" if (defined($self->{subscription}) && $self->{subscription} ne ''); return $cmd_options; } sub azure_list_resources { my ($self, %options) = @_; my $cmd_options = $self->azure_list_resources_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); return $raw_results; } sub azure_list_vm_sizes_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "vm list-sizes --location '$options{location}' --only-show-errors --output json"; $cmd_options .= " --subscription '$self->{subscription}'" if (defined($self->{subscription}) && $self->{subscription} ne ''); return $cmd_options; } sub azure_list_vm_sizes { my ($self, %options) = @_; my $cmd_options = $self->azure_list_vm_sizes_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); return $raw_results; } sub azure_list_vms_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "vm list --only-show-errors --output json"; $cmd_options .= " --resource-group '$options{resource_group}'" if (defined($options{resource_group}) && $options{resource_group} ne ''); $cmd_options .= " --show-details" if (defined($options{show_details})); $cmd_options .= " --subscription '$self->{subscription}'" if (defined($self->{subscription}) && $self->{subscription} ne ''); return $cmd_options; } sub azure_list_vms { my ($self, %options) = @_; my $cmd_options = $self->azure_list_vms_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); return $raw_results; } sub azure_list_groups_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "group list --only-show-errors --output json"; $cmd_options .= " --subscription '$self->{subscription}'" if (defined($self->{subscription}) && $self->{subscription} ne ''); return $cmd_options; } sub azure_list_groups { my ($self, %options) = @_; my $cmd_options = $self->azure_list_groups_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); return $raw_results; } sub azure_list_deployments_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "group deployment list --resource-group '$options{resource_group}' --only-show-errors --output json"; $cmd_options .= " --subscription '$self->{subscription}'" if (defined($self->{subscription}) && $self->{subscription} ne ''); return $cmd_options; } sub azure_list_deployments { my ($self, %options) = @_; my $cmd_options = $self->azure_list_deployments_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); return $raw_results; } sub azure_list_vaults_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "backup vault list --only-show-errors --output json"; $cmd_options .= " --resource-group '$options{resource_group}'" if (defined($options{resource_group}) && $options{resource_group} ne ''); $cmd_options .= " --subscription '$self->{subscription}'" if (defined($self->{subscription}) && $self->{subscription} ne ''); return $cmd_options; } sub azure_list_vaults { my ($self, %options) = @_; my $cmd_options = $self->azure_list_vaults_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); return $raw_results; } sub azure_list_backup_jobs_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "backup job list --resource-group '$options{resource_group}' --vault-name '$options{vault_name}' --only-show-errors --output json"; $cmd_options .= " --subscription '$self->{subscription}'" if (defined($self->{subscription}) && $self->{subscription} ne ''); return $cmd_options; } sub azure_list_backup_jobs { my ($self, %options) = @_; my $cmd_options = $self->azure_list_backup_jobs_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); return $raw_results; } sub azure_list_backup_items_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "backup item list --resource-group '$options{resource_group}' --vault-name '$options{vault_name}' --only-show-errors --output json"; $cmd_options .= " --subscription '$self->{subscription}'" if (defined($self->{subscription}) && $self->{subscription} ne ''); return $cmd_options; } sub azure_list_backup_items { my ($self, %options) = @_; my $cmd_options = $self->azure_list_backup_items_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); return $raw_results; } sub azure_list_expressroute_circuits_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "network express-route list --only-show-errors --output json"; $cmd_options .= " --resource-group '$options{resource_group}'" if (defined($options{resource_group}) && $options{resource_group} ne ''); $cmd_options .= " --subscription '$self->{subscription}'" if (defined($self->{subscription}) && $self->{subscription} ne ''); return $cmd_options; } sub azure_list_expressroute_circuits { my ($self, %options) = @_; my $cmd_options = $self->azure_list_expressroute_circuits_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); return $raw_results; } sub azure_list_vpn_gateways_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "network vnet-gateway list --resource-group '$options{resource_group}' --only-show-errors --output json"; $cmd_options .= " --subscription '$self->{subscription}'" if (defined($self->{subscription}) && $self->{subscription} ne ''); return $cmd_options; } sub azure_list_vpn_gateways { my ($self, %options) = @_; my $cmd_options = $self->azure_list_vpn_gateways_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); return $raw_results; } sub azure_list_virtualnetworks_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "network vnet list --resource-group '$options{resource_group}' --only-show-errors --output json "; $cmd_options .= " --subscription '$self->{subscription}'" if (defined($self->{subscription}) && $self->{subscription} ne ''); return $cmd_options; } sub azure_list_virtualnetworks { my ($self, %options) = @_; my $cmd_options = $self->azure_list_virtualnetworks_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); return $raw_results; } sub azure_list_vnet_peerings_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "network vnet peering list --resource-group '$options{resource_group}' --vnet-name '$options{resource}' --only-show-errors --output json"; $cmd_options .= " --subscription '$self->{subscription}'" if (defined($self->{subscription}) && $self->{subscription} ne ''); return $cmd_options; } sub azure_list_vnet_peerings { my ($self, %options) = @_; my $cmd_options = $self->azure_list_vnet_peerings_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); return $raw_results; } sub azure_list_sqlservers_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "sql server list --only-show-errors --output json"; $cmd_options .= " --resource-group '$options{resource_group}'" if (defined($options{resource_group}) && $options{resource_group} ne ''); $cmd_options .= " --subscription '$self->{subscription}'" if (defined($self->{subscription}) && $self->{subscription} ne ''); return $cmd_options; } sub azure_list_sqlservers { my ($self, %options) = @_; my $cmd_options = $self->azure_list_sqlservers_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); return $raw_results; } sub azure_list_sqldatabases_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "sql db list --resource-group '$options{resource_group}' --server '$options{server}' --only-show-errors --output json"; $cmd_options .= " --subscription '$self->{subscription}'" if (defined($self->{subscription}) && $self->{subscription} ne ''); return $cmd_options; } sub azure_list_sqldatabases { my ($self, %options) = @_; my $cmd_options = $self->azure_list_sqldatabases_set_cmd(%options); my $raw_results = $self->execute(cmd_options => $cmd_options); return $raw_results; } sub azure_get_log_analytics_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "monitor log-analytics query --workspace '$options{workspace_id}' --analytics-query \"$options{query}\" --only-show-errors"; $cmd_options .= " --timespan '$options{timespan}'" if (defined($options{timespan})); return $cmd_options; } sub azure_get_log_analytics { my ($self, %options) = @_; my $cmd_options = $self->azure_get_log_analytics_set_cmd(%options); return $self->execute(cmd_options => $cmd_options); } sub azure_get_publicip_set_cmd { my ($self, %options) = @_; return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); my $cmd_options = "network public-ip show --resource-group '$options{resource_group}' --name '$options{resource}'"; $cmd_options .= " --subscription '$self->{subscription}'" if (defined($self->{subscription}) && $self->{subscription} ne ''); return $cmd_options; } sub azure_get_publicip { my ($self, %options) = @_; my $cmd_options = $self->azure_get_log_analytics_set_cmd(%options); return $self->execute(cmd_options => $cmd_options); } 1; __END__ =head1 NAME Microsoft Azure CLI =head1 AZCLI OPTIONS Microsoft Azure CLI 2.0 To install the Azure CLI 2.0 in a CentOS/RedHat environment : (As root) # rpm --import https://packages.microsoft.com/keys/microsoft.asc # sh -c 'echo -e "[azure-cli]\nname=Azure CLI\nbaseurl=https://packages.microsoft.com/yumrepos/azure-cli\nenabled=1\ngpgcheck=1\ngpgkey=https://packages.microsoft.com/keys/microsoft.asc" > /etc/yum.repos.d/azure-cli.repo' # yum install azure-cli (As centreon-engine) # az login Go to https://aka.ms/devicelogin and enter the code given by the last command. For futher informations, visit https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest. =over 8 =item B<--subscription> Set Azure subscription (Required if logged to several subscriptions). =item B<--timeframe> Set timeframe in seconds (i.e. 3600 to check last hour). =item B<--interval> Set interval of the metric query (Can be : PT1M, PT5M, PT15M, PT30M, PT1H, PT6H, PT12H, PT24H). =item B<--aggregation> Set monitor aggregation (Can be multiple, Can be: 'minimum', 'maximum', 'average', 'total', 'count'). =item B<--zeroed> Set metrics value to 0 if none. Usefull when Monitor does not return value when not defined. =item B<--timeout> Set timeout in seconds (Default: 50). =item B<--sudo> Use 'sudo' to execute the command. =item B<--command> Command to get information (Default: 'az'). 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: none). =item B<--proxyurl> Proxy URL if any =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/cloud/azure/custom/mode.pm000066400000000000000000000225121417000230700222660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::custom::mode; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-dimension:s' => { name => 'filter_dimension' }, 'per-sec' => { name => 'per_second'} }); $options{options}->add_help(package => __PACKAGE__, sections => 'CUSTOM MODE OPTIONS', once => 1); return $self; } sub custom_metric_calc { my ($self, %options) = @_; $self->{result_values}->{timeframe} = $options{new_datas}->{$self->{instance} . '_timeframe'}; $self->{result_values}->{value}->{absolute} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{metric}}; $self->{result_values}->{value}->{per_second} = $self->{result_values}->{value}->{absolute} / $self->{result_values}->{timeframe}; $self->{result_values}->{metric} = $options{extra_options}->{metric}; return 0; } sub custom_metric_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check( value => defined($self->{instance_mode}->{option_results}->{per_second}) ? $self->{result_values}->{value}->{per_second} : $self->{result_values}->{value}->{absolute}, threshold => [ { label => 'critical-' . $self->{instance_mode}->{metrics_mapping}->{$self->{result_values}->{metric}}->{label} , exit_litteral => 'critical' }, { label => 'warning-' . $self->{instance_mode}->{metrics_mapping}->{$self->{result_values}->{metric}}->{label}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_metric_perfdata { my ($self, %options) = @_; my $options = $self->{instance_mode}->{metrics_mapping}->{$self->{result_values}->{metric}}; my $value = defined($self->{instance_mode}->{option_results}->{per_second}) ? $self->{result_values}->{value}->{per_second} : $self->{result_values}->{value}->{absolute}; my $format = defined($self->{instance_mode}->{metrics_mapping}->{$self->{result_values}->{metric}}->{template}) ? $self->{instance_mode}->{metrics_mapping}->{$self->{result_values}->{metric}}->{template} : '%.2f'; if (defined($self->{instance_mode}->{option_results}->{per_second})) { $self->{instance_mode}->{metrics_mapping}->{$self->{result_values}->{metric}}->{nlabel} .= '.persecond'; $self->{instance_mode}->{metrics_mapping}->{$self->{result_values}->{metric}}->{unit} .= '/s'; } $self->{output}->perfdata_add( instances => $self->{instance}, value => sprintf($format, $value), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{instance_mode}->{metrics_mapping}->{$self->{result_values}->{metric}}->{label}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{instance_mode}->{metrics_mapping}->{$self->{result_values}->{metric}}->{label}), %{$options} ); } sub custom_metric_output { my ($self, %options) = @_; my $network = defined($self->{instance_mode}->{metrics_mapping}->{$self->{result_values}->{metric}}->{network}) ? { network => '1' } : undef; my ($value, $unit) = $self->{instance_mode}->{metrics_mapping}->{$self->{result_values}->{metric}}->{unit} eq 'B' ? $self->{perfdata}->change_bytes(value => $self->{result_values}->{value}->{absolute}, %{$network}) : ($self->{result_values}->{value}->{absolute}, $self->{instance_mode}->{metrics_mapping}->{$self->{result_values}->{metric}}->{unit}); if (defined($self->{instance_mode}->{option_results}->{per_second})) { ($value, $unit) = $self->{instance_mode}->{metrics_mapping}->{$self->{result_values}->{metric}}->{unit} eq 'B' ? $self->{perfdata}->change_bytes(value => $self->{result_values}->{value}->{per_second}, %{$network}) : ($self->{result_values}->{value}->{per_second}, $unit); $unit .= '/s'; } my $format = defined($self->{instance_mode}->{metrics_mapping}->{$self->{result_values}->{metric}}->{template}) ? $self->{instance_mode}->{metrics_mapping}->{$self->{result_values}->{metric}}->{template} : '%.2f'; return sprintf('%s: ' . $format . '%s', $self->{instance_mode}->{metrics_mapping}->{$self->{result_values}->{metric}}->{output}, $value, $unit); } sub prefix_metric_output { my ($self, %options) = @_; return "Instance '" . $options{instance_value}->{display} . "' "; } sub prefix_statistics_output { my ($self, %options) = @_; return "Statistic '" . $options{instance_value}->{display} . "' Metrics "; } sub long_output { my ($self, %options) = @_; return "Checking '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{metrics_mapping} = $self->get_metrics_mapping; $self->{maps_counters_type} = [ { name => 'metrics', type => 3, cb_prefix_output => 'prefix_metric_output', cb_long_output => 'long_output', message_multiple => 'All metrics are ok', indent_long_output => ' ', group => [ { name => 'statistics', display_long => 1, cb_prefix_output => 'prefix_statistics_output', message_multiple => 'All metrics are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; foreach my $metric (keys %{$self->{metrics_mapping}}) { my $entry = { label => $self->{metrics_mapping}->{$metric}->{label}, set => { key_values => [ { name => $metric }, { name => 'timeframe' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_metric_calc'), closure_custom_calc_extra_options => { metric => $metric }, 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') } }; push @{$self->{maps_counters}->{statistics}}, $entry; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; my $raw_results; if (defined($self->{option_results}->{filter_dimension}) && $self->{option_results}->{filter_dimension} ne '') { $self->{az_dimension} = $self->{option_results}->{filter_dimension}; } ($metric_results{$self->{az_resource}}, $raw_results) = $options{custom}->azure_get_metrics( aggregations => $self->{az_aggregations}, dimension => $self->{az_dimension}, interval => $self->{az_interval}, metrics => $self->{az_metrics}, resource => $self->{az_resource}, resource_group => $self->{az_resource_group}, resource_namespace => $self->{az_resource_namespace}, resource_type => $self->{az_resource_type}, timeframe => $self->{az_timeframe} ); foreach my $metric (@{$self->{az_metrics}}) { my $metric_name = lc($metric); $metric_name =~ s/ /_/g; foreach my $aggregation (@{$self->{az_aggregations}}) { next if (!defined($metric_results{$self->{az_resource}}->{$metric_name}->{lc($aggregation)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{$self->{az_resource}}->{display} = $self->{az_resource}; $self->{metrics}->{$self->{az_resource}}->{statistics}->{lc($aggregation)}->{display} = lc($aggregation); $self->{metrics}->{$self->{az_resource}}->{statistics}->{lc($aggregation)}->{timeframe} = $self->{az_timeframe}; $self->{metrics}->{$self->{az_resource}}->{statistics}->{lc($aggregation)}->{$metric} = defined($metric_results{$self->{az_resource}}->{$metric_name}->{lc($aggregation)}) ? $metric_results{$self->{az_resource}}->{$metric_name}->{lc($aggregation)} : 0; } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Azure custom class for monitor based modes. =head1 CUSTOM MODE OPTIONS =over 8 =item B<--filter-dimension> Specify the metric dimension (required for some specific metrics) Syntax example: --filter-dimension="$metricname eq '$metricvalue'" =item B<--per-sec> Display the statistics based on a per-second period. =back =cut centreon-plugins-20220113/cloud/azure/database/000077500000000000000000000000001417000230700212345ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/database/cosmosdb/000077500000000000000000000000001417000230700230455ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/database/cosmosdb/mode/000077500000000000000000000000001417000230700237715ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/database/cosmosdb/mode/availability.pm000066400000000000000000000113121417000230700267770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::cosmosdb::mode::availability; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'serviceavailability' => { 'output' => 'Service Availability', 'label' => 'service-availability-percentage', 'nlabel' => 'cosmosdb.account.service.availability.percentage', 'unit' => '%', 'min' => '0', 'max' => '100' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.DocumentDB\/databaseAccounts\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'databaseAccounts'; $self->{az_resource_namespace} = 'Microsoft.DocumentDB'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 3600; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT1H'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Cosmos DB Accounts availability statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::cosmosdb::plugin --mode=availability --custommode=api --resource= --resource-group= --aggregation='average' --warning-service-availability-percentage='90:' --critical-service-availability-percentage='80:' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::database::cosmosdb::plugin --mode=availability --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.DocumentDB/databaseAccounts/' --aggregation='average' --warning-service-availability-percentage='90:' --critical-service-availability-percentage='80:' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-service-availability-percentage> Warning threshold. =item B<--critical-service-availability-percentage> Critical threshold. =back =cut centreon-plugins-20220113/cloud/azure/database/cosmosdb/mode/cache.pm000066400000000000000000000132421417000230700253740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::cosmosdb::mode::cache; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'integratedcacheevictedentriessize' => { 'output' => 'Integrated Cache Evicted Entries Size', 'label' => 'cache-evicted-size', 'nlabel' => 'cosmosdb.account.integratedcache.evicted.size.bytes', 'unit' => 'B', 'min' => '0' }, 'integratedcachehitrate' => { 'output' => 'Integrated Cache Hit Rate', 'label' => 'cache-hitrate-percentage', 'nlabel' => 'cosmosdb.account.integratedcache.hitrate.percentage', 'unit' => '%', 'min' => '0', 'max' => '100' }, 'integratedcachesize' => { 'output' => 'Integrated Cache Size', 'label' => 'cache-size', 'nlabel' => 'cosmosdb.account.integratedcache.size.bytes', 'unit' => 'B', 'min' => '0' }, 'integratedcachettlexpirationcount' => { 'output' => 'Integrated Cache TTL Expiration Count', 'label' => 'cache-ttl-expiration', 'nlabel' => 'cosmosdb.account.integratedcache.ttlexpiration.count', 'unit' => '', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.DocumentDB\/databaseAccounts\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'databaseAccounts'; $self->{az_resource_namespace} = 'Microsoft.DocumentDB'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Cosmos DB Accounts integrated cache statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::cosmosdb::plugin --mode=cache --custommode=api --resource= --resource-group= --aggregation='average' --warning-cache-hitrate-percentage='90:' --critical-cache-hitrate-percentage='80:' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::database::cosmosdb::plugin --mode=cache --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.DocumentDB/databaseAccounts/' --aggregation='average' --warning-cache-hitrate-percentage='90:' --critical-cache-hitrate-percentage='80:' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'cache-hitrate-percentage', 'cache-size', 'cache-ttl-expiration', 'cache-evicted-size'. =item B<--critical-*> Critical threshold where '*' can be: 'cache-hitrate-percentage', 'cache-size', 'cache-ttl-expiration', 'cache-evicted-size'. =back =cut centreon-plugins-20220113/cloud/azure/database/cosmosdb/mode/discovery.pm000066400000000000000000000024611417000230700263410ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::cosmosdb::mode::discovery; use base qw(cloud::azure::management::monitor::mode::discovery); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{namespace} = 'Microsoft.DocumentDB'; $self->{type} = 'databaseAccounts'; } 1; __END__ =head1 MODE Discover Azure Cosmos DB Accounts resources. =over 8 =item B<--resource-group> Specify resource group. =item B<--location> Specify location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/database/cosmosdb/mode/document.pm000066400000000000000000000115151417000230700261500ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::cosmosdb::mode::document; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'documentcount' => { 'output' => 'Document Count', 'label' => 'document-count', 'nlabel' => 'cosmosdb.account.document.count', 'unit' => '', 'min' => '0' }, 'documentquota' => { 'output' => 'Document Quota', 'label' => 'document-quota', 'nlabel' => 'cosmosdb.account.document.quota.bytes', 'unit' => 'B', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.DocumentDB\/databaseAccounts\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'databaseAccounts'; $self->{az_resource_namespace} = 'Microsoft.DocumentDB'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Cosmos DB Accounts document statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::cosmosdb::plugin --mode=document --custommode=api --resource= --resource-group= --aggregation='total' --warning-document-count='80000' --critical-document-count='90000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::database::cosmosdb::plugin --mode=document --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.DocumentDB/databaseAccounts/' --aggregation='total' --warning-document-count='80000' --critical-document-count='90000' Default aggregation: 'total' / 'minimum', 'maximum' and 'average' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'document-count', 'document-quota'. =item B<--critical-*> Critical threshold where '*' can be: 'document-count', 'document-quota'. =back =cut centreon-plugins-20220113/cloud/azure/database/cosmosdb/mode/health.pm000066400000000000000000000036361417000230700256040ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::cosmosdb::mode::health; use base qw(cloud::azure::management::monitor::mode::health); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{az_resource_namespace} = 'Microsoft.DocumentDB'; $self->{az_resource_type} = 'databaseAccounts'; } 1; __END__ =head1 MODE Check Azure Cosmos DB Accounts health status. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{summary} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /^Unavailable$/'). Can used special variables like: %{status}, %{summary} =item B<--unknown-status> Set unknown threshold for status (Default: '%{status} =~ /^Unknown$/'). Can used special variables like: %{status}, %{summary} =item B<--ok-status> Set ok threshold for status (Default: '%{status} =~ /^Available$/'). Can used special variables like: %{status}, %{summary} =back =cut centreon-plugins-20220113/cloud/azure/database/cosmosdb/mode/latency.pm000066400000000000000000000116501417000230700257710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::cosmosdb::mode::latency; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'replicationlatency' => { 'output' => 'P99 Replication Latency', 'label' => 'replication-latency', 'nlabel' => 'cosmosdb.account.latency.replication.milliseconds', 'unit' => 'ms', 'min' => '0' }, 'serversidelatency' => { 'output' => 'Server Side Latency', 'label' => 'serverside-latency', 'nlabel' => 'cosmosdb.account.latency.serverside.milliseconds', 'unit' => 'ms', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.DocumentDB\/databaseAccounts\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'databaseAccounts'; $self->{az_resource_namespace} = 'Microsoft.DocumentDB'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT1M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Cosmos DB Accounts latency statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::cosmosdb::plugin --mode=latency --custommode=api --resource= --resource-group= --aggregation='average' --warning-serverside-latency='800' --critical-serverside-latency='900' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::database::cosmosdb::plugin --mode=latency --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.DocumentDB/databaseAccounts/' --aggregation='average' --warning-serverside-latency='800' --critical-serverside-latency='900' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'serverside-latency', 'replication-latency'. =item B<--critical-*> Critical threshold where '*' can be: 'serverside-latency', 'replication-latency'. =back =cut centreon-plugins-20220113/cloud/azure/database/cosmosdb/mode/throughput.pm000066400000000000000000000117341417000230700265460ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::cosmosdb::mode::throughput; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'autoscalemaxthroughput' => { 'output' => 'Autoscale Max Throughput', 'label' => 'autoscale-max-throughput', 'nlabel' => 'cosmosdb.account.troughput.autoscale.count', 'unit' => '', 'min' => '0' }, 'provisionedthroughput' => { 'output' => 'Provisioned Throughput', 'label' => 'provisioned-throughput', 'nlabel' => 'cosmosdb.account.troughput.provisioned.count', 'unit' => '', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.DocumentDB\/databaseAccounts\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'databaseAccounts'; $self->{az_resource_namespace} = 'Microsoft.DocumentDB'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Maximum']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Cosmos DB Accounts throughput statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::cosmosdb::plugin --mode=throughput --custommode=api --resource= --resource-group= --aggregation='maximum' --warning-provisioned-throughput='800' --critical-provisioned-throughput='900' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::database::cosmosdb::plugin --mode=throughput --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.DocumentDB/databaseAccounts/' --aggregation='maximum' --warning-provisioned-throughput='800' --critical-provisioned-throughput='900' Default aggregation: 'maximum' / 'total', 'minimum' and 'average' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'provisioned-throughput', 'autoscale-max-throughput'. =item B<--critical-*> Critical threshold where '*' can be: 'provisioned-throughput', 'autoscale-max-throughput'. =back =cut centreon-plugins-20220113/cloud/azure/database/cosmosdb/mode/units.pm000066400000000000000000000110651417000230700254740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::cosmosdb::mode::units; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'totalrequestunits' => { 'output' => 'Total Request Units', 'label' => 'total-request-units', 'nlabel' => 'cosmosdb.account.requestunits.total.count', 'unit' => '', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.DocumentDB\/databaseAccounts\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'databaseAccounts'; $self->{az_resource_namespace} = 'Microsoft.DocumentDB'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Cosmos DB Accounts request units statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::cosmosdb::plugin --mode=units --custommode=api --resource= --resource-group= --aggregation='total' --warning-total-request-units='8000' --critical-total-request-units='9000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::database::cosmosdb::plugin --mode=units --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.DocumentDB/databaseAccounts/' --aggregation='total' --warning-total-request-units='8000' --critical-total-request-units='9000' Default aggregation: 'total' / 'minimum', 'maximum' and 'average' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-total-request-units> Warning threshold. =item B<--critical-total-request-units> Critical threshold. =back =cut centreon-plugins-20220113/cloud/azure/database/cosmosdb/mode/usage.pm000066400000000000000000000114171417000230700254370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::cosmosdb::mode::usage; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'datausage' => { 'output' => 'Data Usage', 'label' => 'data-usage', 'nlabel' => 'cosmosdb.account.data.usage.bytes', 'unit' => 'B', 'min' => '0' }, 'indexusage' => { 'output' => 'Index Usage', 'label' => 'index-usage', 'nlabel' => 'cosmosdb.account.index.usage.bytes', 'unit' => 'B', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.DocumentDB\/databaseAccounts\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'databaseAccounts'; $self->{az_resource_namespace} = 'Microsoft.DocumentDB'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Cosmos DB Accounts usage statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::cosmosdb::plugin --mode=usage --custommode=api --resource= --resource-group= --aggregation='total' --warning-data-usage='80000' --critical-data-usage='90000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::database::cosmosdb::plugin --mode=usage --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.DocumentDB/databaseAccounts/' --aggregation='total' --warning-data-usage='80000' --critical-data-usage='90000' Default aggregation: 'total' / 'minimum', 'maximum' and 'average' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'data-usage', 'index-usage'. =item B<--critical-*> Critical threshold where '*' can be: 'data-usage', 'index-usage'. =back =cut centreon-plugins-20220113/cloud/azure/database/cosmosdb/plugin.pm000066400000000000000000000043051417000230700247030ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::cosmosdb::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} } = ( 'availability' => 'cloud::azure::database::cosmosdb::mode::availability', 'cache' => 'cloud::azure::database::cosmosdb::mode::cache', 'discovery' => 'cloud::azure::database::cosmosdb::mode::discovery', 'document' => 'cloud::azure::database::cosmosdb::mode::document', 'health' => 'cloud::azure::database::cosmosdb::mode::health', 'latency' => 'cloud::azure::database::cosmosdb::mode::latency', 'throughput' => 'cloud::azure::database::cosmosdb::mode::throughput', 'units' => 'cloud::azure::database::cosmosdb::mode::units', 'usage' => 'cloud::azure::database::cosmosdb::mode::usage' ); $self->{custom_modes}->{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}->{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' }, }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure Cosmos DB Accounts. =cut centreon-plugins-20220113/cloud/azure/database/elasticpool/000077500000000000000000000000001417000230700235525ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/database/elasticpool/mode/000077500000000000000000000000001417000230700244765ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/database/elasticpool/mode/cpu.pm000066400000000000000000000251351417000230700256310ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::elasticpool::mode::cpu; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my %metrics_mapping = ( 'cpu_limit' => { 'output' => 'CPU Limit', 'label' => 'cpu-limit', 'nlabel' => 'elasticpool.cpu.limit.count', 'unit' => '' }, 'cpu_percent' => { 'output' => 'CPU Percentage Usage', 'label' => 'cpu-percent', 'nlabel' => 'elasticpool.cpu.usage.percentage', 'unit' => '%' }, 'cpu_used' => { 'output' => 'CPU Used', 'label' => 'cpu-used', 'nlabel' => 'elasticpool.cpu.used.count', 'unit' => '' } ); sub custom_metric_calc { my ($self, %options) = @_; $self->{result_values}->{timeframe} = $options{new_datas}->{$self->{instance} . '_timeframe'}; $self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{metric}}; $self->{result_values}->{metric} = $options{extra_options}->{metric}; return 0; } sub custom_metric_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check( value => $self->{result_values}->{value}, threshold => [ { label => 'critical-' . $metrics_mapping{$self->{result_values}->{metric}}->{label} , exit_litteral => 'critical' }, { label => 'warning-' . $metrics_mapping{$self->{result_values}->{metric}}->{label}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_metric_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( instances => $self->{instance}, nlabel => $metrics_mapping{$self->{result_values}->{metric}}->{nlabel}, unit => $metrics_mapping{$self->{result_values}->{metric}}->{unit}, value => sprintf('%.2f', $self->{result_values}->{value}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $metrics_mapping{$self->{result_values}->{metric}}->{label}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $metrics_mapping{$self->{result_values}->{metric}}->{label}) ); } sub custom_metric_output { my ($self, %options) = @_; my ($value, $unit) = ($self->{result_values}->{value}, $metrics_mapping{$self->{result_values}->{metric}}->{unit}); return sprintf('%s: %.2f %s', $metrics_mapping{$self->{result_values}->{metric}}->{output}, $value, $unit); } sub prefix_metric_output { my ($self, %options) = @_; return "Elastic Pool '" . $options{instance_value}->{display} . "' "; } sub prefix_statistics_output { my ($self, %options) = @_; return "Statistic '" . $options{instance_value}->{display} . "' Metrics "; } sub long_output { my ($self, %options) = @_; return "Checking Pool'" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metrics', type => 3, cb_prefix_output => 'prefix_metric_output', cb_long_output => 'long_output', message_multiple => 'All CPU metrics are ok', indent_long_output => ' ', group => [ { name => 'statistics', display_long => 1, cb_prefix_output => 'prefix_statistics_output', message_multiple => 'All metrics are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; foreach my $metric (keys %metrics_mapping) { my $entry = { label => $metrics_mapping{$metric}->{label}, nlabel => $metrics_mapping{$metric}->{nlabel}, set => { key_values => [ { name => $metric }, { name => 'timeframe' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_metric_calc'), closure_custom_calc_extra_options => { metric => $metric }, 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') } }; push @{$self->{maps_counters}->{statistics}}, $entry; } } 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 => { 'resource:s@' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' }, 'filter-metric:s' => { name => 'filter_metric' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } $self->{az_resource} = $self->{option_results}->{resource}; $self->{az_resource_group} = $self->{option_results}->{resource_group} if (defined($self->{option_results}->{resource_group})); $self->{az_resource_type} = 'servers'; $self->{az_resource_namespace} = 'Microsoft.Sql'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %metrics_mapping) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; my $raw_results; foreach my $resource (@{$self->{az_resource}}) { my $resource_group = $self->{az_resource_group}; my ($resource_display, $resource_name); if ($resource =~ /^(.*)\/elasticpools\/(.*)/) { ($resource_display, $resource_name) = ($1 . '/' . $2, $resource); } else { $self->{output}->add_option_msg(short_msg => 'Incorrect resource format'); $self->{output}->option_exit(); }; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Sql\/servers\/(.*)\/elasticpools\/(.*)$/) { $resource_group = $1; $resource_display = $2 . '/' . $3; $resource_name = $2 . '/elasticpools/' . $3; } ($metric_results{$resource_display}, $raw_results) = $options{custom}->azure_get_metrics( resource => $resource_name, resource_group => $resource_group, resource_type => $self->{az_resource_type}, resource_namespace => $self->{az_resource_namespace}, metrics => $self->{az_metrics}, aggregations => $self->{az_aggregations}, timeframe => $self->{az_timeframe}, interval => $self->{az_interval} ); foreach my $metric (@{$self->{az_metrics}}) { foreach my $aggregation (@{$self->{az_aggregations}}) { next if (!defined($metric_results{$resource_display}->{$metric}->{lc($aggregation)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{$resource_display}->{display} = $resource_display; $self->{metrics}->{$resource_display}->{statistics}->{lc($aggregation)}->{display} = lc($aggregation); $self->{metrics}->{$resource_display}->{statistics}->{lc($aggregation)}->{timeframe} = $self->{az_timeframe}; $self->{metrics}->{$resource_display}->{statistics}->{lc($aggregation)}->{$metric} = defined($metric_results{$resource_display}->{$metric}->{lc($aggregation)}) ? $metric_results{$resource_display}->{$metric}->{lc($aggregation)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check Azure SQL Elastic Pool CPU metrics. (Only applies to vCore-based elastic pools) Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::elasticpool::plugin --custommode=azcli --mode=cpu --resource=/elasticpools/ --resource-group= --aggregation='average' --critical-cpu-percent='90' --verbose Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::compute::virtualmachine::plugin --custommode=azcli --mode=cpu --resource='/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Sql/servers/xxx/elasticpools/xxx' --aggregation='average' --critical-cpu-percent='90' --verbose Default aggregation: 'average' / 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--filter-metric> Filter on specific metrics. The Azure format must be used, for example: 'cpu_percent' (Can be a regexp). =item B<--warning-*> Warning threshold where * can be: 'cpu-limit', 'cpu-percent', 'cpu-used'. =item B<--critical-*> Critical threshold where * can be: 'cpu-limit', 'cpu-percent', 'cpu-used'. =back =cut centreon-plugins-20220113/cloud/azure/database/elasticpool/mode/discovery.pm000066400000000000000000000024411417000230700270440ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::elasticpool::mode::discovery; use base qw(cloud::azure::management::monitor::mode::discovery); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{namespace} = 'Microsoft.Sql'; $self->{type} = 'servers/elasticpools'; } 1; __END__ =head1 MODE Network Interface discovery. =over 8 =item B<--resource-group> Specify resource group. =item B<--location> Specify location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/database/elasticpool/mode/dtu.pm000066400000000000000000000253101417000230700256310ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::elasticpool::mode::dtu; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my %metrics_mapping = ( 'dtu_consumption_percent' => { 'output' => 'DTU consumption percentage', 'label' => 'dtu-consumption-percent', 'nlabel' => 'elasticpool.dtu.consumpution.percentage', 'unit' => '%' }, 'eDTU_limit' => { 'output' => 'eDTU Limit', 'label' => 'edtu-limit', 'nlabel' => 'elasticpool.edtu.limit.count', 'unit' => '' }, 'eDTU_used' => { 'output' => 'eDTU Used', 'label' => 'edtu-used', 'nlabel' => 'elasticpool.edtu.used.count', 'unit' => '' } ); sub custom_metric_calc { my ($self, %options) = @_; $self->{result_values}->{timeframe} = $options{new_datas}->{$self->{instance} . '_timeframe'}; $self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{metric}}; $self->{result_values}->{metric} = $options{extra_options}->{metric}; return 0; } sub custom_metric_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check( value => $self->{result_values}->{value}, threshold => [ { label => 'critical-' . $metrics_mapping{$self->{result_values}->{metric}}->{label} , exit_litteral => 'critical' }, { label => 'warning-' . $metrics_mapping{$self->{result_values}->{metric}}->{label}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_metric_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( instances => $self->{instance}, nlabel => $metrics_mapping{$self->{result_values}->{metric}}->{nlabel}, unit => $metrics_mapping{$self->{result_values}->{metric}}->{unit}, value => sprintf('%.2f', $self->{result_values}->{value}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $metrics_mapping{$self->{result_values}->{metric}}->{label}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $metrics_mapping{$self->{result_values}->{metric}}->{label}) ); } sub custom_metric_output { my ($self, %options) = @_; my ($value, $unit) = ($self->{result_values}->{value}, $metrics_mapping{$self->{result_values}->{metric}}->{unit}); return sprintf('%s: %.2f %s', $metrics_mapping{$self->{result_values}->{metric}}->{output}, $value, $unit); } sub prefix_metric_output { my ($self, %options) = @_; return "Elastic Pool '" . $options{instance_value}->{display} . "' "; } sub prefix_statistics_output { my ($self, %options) = @_; return "Statistic '" . $options{instance_value}->{display} . "' Metrics "; } sub long_output { my ($self, %options) = @_; return "Checking Pool'" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metrics', type => 3, cb_prefix_output => 'prefix_metric_output', cb_long_output => 'long_output', message_multiple => 'All CPU metrics are ok', indent_long_output => ' ', group => [ { name => 'statistics', display_long => 1, cb_prefix_output => 'prefix_statistics_output', message_multiple => 'All metrics are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; foreach my $metric (keys %metrics_mapping) { my $entry = { label => $metrics_mapping{$metric}->{label}, nlabel => $metrics_mapping{$metric}->{nlabel}, set => { key_values => [ { name => $metric }, { name => 'timeframe' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_metric_calc'), closure_custom_calc_extra_options => { metric => $metric }, 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') } }; push @{$self->{maps_counters}->{statistics}}, $entry; } } 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 => { 'resource:s@' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' }, 'filter-metric:s' => { name => 'filter_metric' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } $self->{az_resource} = $self->{option_results}->{resource}; $self->{az_resource_group} = $self->{option_results}->{resource_group} if (defined($self->{option_results}->{resource_group})); $self->{az_resource_type} = 'servers'; $self->{az_resource_namespace} = 'Microsoft.Sql'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %metrics_mapping) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; my $raw_results; foreach my $resource (@{$self->{az_resource}}) { my $resource_group = $self->{az_resource_group}; my ($resource_display, $resource_name); if ($resource =~ /^(.*)\/elasticpools\/(.*)/) { ($resource_display, $resource_name) = ($1 . '/' . $2, $resource); } else { $self->{output}->add_option_msg(short_msg => 'Incorrect resource format'); $self->{output}->option_exit(); }; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Sql\/servers\/(.*)\/elasticpools\/(.*)$/) { $resource_group = $1; $resource_display = $2 . '/' . $3; $resource_name = $2 . '/elasticpools/' . $3; } ($metric_results{$resource_display}, $raw_results) = $options{custom}->azure_get_metrics( resource => $resource_name, resource_group => $resource_group, resource_type => $self->{az_resource_type}, resource_namespace => $self->{az_resource_namespace}, metrics => $self->{az_metrics}, aggregations => $self->{az_aggregations}, timeframe => $self->{az_timeframe}, interval => $self->{az_interval} ); foreach my $metric (@{$self->{az_metrics}}) { foreach my $aggregation (@{$self->{az_aggregations}}) { next if (!defined($metric_results{$resource_display}->{$metric}->{lc($aggregation)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{$resource_display}->{display} = $resource_display; $self->{metrics}->{$resource_display}->{statistics}->{lc($aggregation)}->{display} = lc($aggregation); $self->{metrics}->{$resource_display}->{statistics}->{lc($aggregation)}->{timeframe} = $self->{az_timeframe}; $self->{metrics}->{$resource_display}->{statistics}->{lc($aggregation)}->{$metric} = defined($metric_results{$resource_display}->{$metric}->{lc($aggregation)}) ? $metric_results{$resource_display}->{$metric}->{lc($aggregation)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check Azure SQL Elastic Pool DTU metrics. (Only applies to DTU-based elastic pools) Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::elasticpool::plugin --custommode=azcli --mode=dtu --resource=/elasticpools/ --resource-group= --aggregation='average' --critical-dtu-consumption-percent='90' --verbose Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::compute::virtualmachine::plugin --custommode=azcli --mode=dtu --resource='/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Sql/servers/xxx/elasticpools/xxx' --aggregation='average' --critical-dtu-consumption-percent='90' --verbose Default aggregation: 'average' / 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--filter-metric> Filter on specific metrics. The Azure format must be used, for example: 'dtu_consumption_percent' (Can be a regexp). =item B<--warning-*> Warning threshold where * can be: 'dtu-consumption-percent', 'edtu-limit', 'edtu-used'. =item B<--critical-*> Critical threshold where * can be: 'dtu-consumption-percent', 'edtu-limit', 'edtu-used'. =back =cut centreon-plugins-20220113/cloud/azure/database/elasticpool/mode/log.pm000066400000000000000000000257671417000230700256360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::elasticpool::mode::log; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my %metrics_mapping = ( 'log_write_percent' => { 'output' => 'Log write IO percentage', 'label' => 'log-write-percent', 'nlabel' => 'elasticpool.log.write.percentage', 'unit' => '%' }, 'tempdb_log_size' => { 'output' => 'Tempdb Log file size', 'label' => 'tempdb-log-size', 'nlabel' => 'elasticpool.log.tempdb.size.kilobytes', 'unit' => 'KB' }, 'tempdb_log_used_percent' => { 'output' => 'Tempdb log usage percentage', 'label' => 'tempdb-log-used-percent', 'nlabel' => 'elasticpool.log.tempdb.usage.percentage', 'unit' => '%' } ); sub custom_metric_calc { my ($self, %options) = @_; $self->{result_values}->{timeframe} = $options{new_datas}->{$self->{instance} . '_timeframe'}; $self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{metric}}; $self->{result_values}->{metric} = $options{extra_options}->{metric}; return 0; } sub custom_metric_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check( value => $self->{result_values}->{value}, threshold => [ { label => 'critical-' . $metrics_mapping{$self->{result_values}->{metric}}->{label} , exit_litteral => 'critical' }, { label => 'warning-' . $metrics_mapping{$self->{result_values}->{metric}}->{label}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_metric_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( instances => $self->{instance}, nlabel => $metrics_mapping{$self->{result_values}->{metric}}->{nlabel}, unit => $metrics_mapping{$self->{result_values}->{metric}}->{unit}, value => sprintf('%.2f', $self->{result_values}->{value}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $metrics_mapping{$self->{result_values}->{metric}}->{label}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $metrics_mapping{$self->{result_values}->{metric}}->{label}) ); } sub custom_metric_output { my ($self, %options) = @_; my ($value, $unit) = ($metrics_mapping{$self->{result_values}->{metric}}->{unit} eq 'KB') ? $self->{perfdata}->change_bytes(value => $self->{result_values}->{value} * 1000) : ($self->{result_values}->{value}, $metrics_mapping{$self->{result_values}->{metric}}->{unit}); return sprintf('%s: %.2f %s', $metrics_mapping{$self->{result_values}->{metric}}->{output}, $value, $unit); } sub prefix_metric_output { my ($self, %options) = @_; return "Elastic Pool '" . $options{instance_value}->{display} . "' "; } sub prefix_statistics_output { my ($self, %options) = @_; return "Statistic '" . $options{instance_value}->{display} . "' Metrics "; } sub long_output { my ($self, %options) = @_; return "Checking Pool'" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metrics', type => 3, cb_prefix_output => 'prefix_metric_output', cb_long_output => 'long_output', message_multiple => 'All CPU metrics are ok', indent_long_output => ' ', group => [ { name => 'statistics', display_long => 1, cb_prefix_output => 'prefix_statistics_output', message_multiple => 'All metrics are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; foreach my $metric (keys %metrics_mapping) { my $entry = { label => $metrics_mapping{$metric}->{label}, nlabel => $metrics_mapping{$metric}->{nlabel}, set => { key_values => [ { name => $metric }, { name => 'timeframe' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_metric_calc'), closure_custom_calc_extra_options => { metric => $metric }, 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') } }; push @{$self->{maps_counters}->{statistics}}, $entry; } } 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 => { 'resource:s@' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' }, 'filter-metric:s' => { name => 'filter_metric' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } $self->{az_resource} = $self->{option_results}->{resource}; $self->{az_resource_group} = $self->{option_results}->{resource_group} if (defined($self->{option_results}->{resource_group})); $self->{az_resource_type} = 'servers'; $self->{az_resource_namespace} = 'Microsoft.Sql'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average', 'Maximum']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %metrics_mapping) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; my $raw_results; foreach my $resource (@{$self->{az_resource}}) { my $resource_group = $self->{az_resource_group}; my ($resource_display, $resource_name); if ($resource =~ /^(.*)\/elasticpools\/(.*)/) { ($resource_display, $resource_name) = ($1 . '/' . $2, $resource); } else { $self->{output}->add_option_msg(short_msg => 'Incorrect resource format'); $self->{output}->option_exit(); }; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Sql\/servers\/(.*)\/elasticpools\/(.*)$/) { $resource_group = $1; $resource_display = $2 . '/' . $3; $resource_name = $2 . '/elasticpools/' . $3; } ($metric_results{$resource_display}, $raw_results) = $options{custom}->azure_get_metrics( resource => $resource_name, resource_group => $resource_group, resource_type => $self->{az_resource_type}, resource_namespace => $self->{az_resource_namespace}, metrics => $self->{az_metrics}, aggregations => $self->{az_aggregations}, timeframe => $self->{az_timeframe}, interval => $self->{az_interval} ); foreach my $metric (@{$self->{az_metrics}}) { foreach my $aggregation (@{$self->{az_aggregations}}) { next if (!defined($metric_results{$resource_display}->{$metric}->{lc($aggregation)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{$resource_display}->{display} = $resource_display; $self->{metrics}->{$resource_display}->{statistics}->{lc($aggregation)}->{display} = lc($aggregation); $self->{metrics}->{$resource_display}->{statistics}->{lc($aggregation)}->{timeframe} = $self->{az_timeframe}; $self->{metrics}->{$resource_display}->{statistics}->{lc($aggregation)}->{$metric} = defined($metric_results{$resource_display}->{$metric}->{lc($aggregation)}) ? $metric_results{$resource_display}->{$metric}->{lc($aggregation)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check Azure SQL Elastic Pool Storage metrics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::elasticpool::plugin --custommode=azcli --mode=storage --resource=/elasticpools/ --resource-group= --aggregation='average' --allocated-data-storage-percent='90' --verbose Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::compute::virtualmachine::plugin --custommode=azcli --mode=sessions --resource='/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Sql/servers/xxx/elasticpools/xxx' --aggregation='average' --allocated-data-storage-percent='90' --verbose Default aggregation: 'average' / 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--filter-metric> Filter on specific metrics. The Azure format must be used, for example: 'allocated_data_storage_percent' (Can be a regexp). =item B<--warning-*> Warning threshold where * can be: 'allocated-data-storage', allocated-data-storage-percent', 'storage-percent', 'storage-used'. =item B<--critical-*> Critical threshold where * can be: 'allocated-data-storage', allocated-data-storage-percent', 'storage-percent', 'storage-used'. =back =cut centreon-plugins-20220113/cloud/azure/database/elasticpool/mode/sessions.pm000066400000000000000000000247451417000230700267160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::elasticpool::mode::sessions; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my %metrics_mapping = ( 'sessions_percent' => { 'output' => 'Sessions usage percentage', 'label' => 'sessions-percent', 'nlabel' => 'elasticpool.sessions.usage.percentage', 'unit' => '%' }, 'workers_percent' => { 'output' => 'Workers usage percentage', 'label' => 'workers-percent', 'nlabel' => 'elasticpool.workers.usage.percentage', 'unit' => '%' } ); sub custom_metric_calc { my ($self, %options) = @_; $self->{result_values}->{timeframe} = $options{new_datas}->{$self->{instance} . '_timeframe'}; $self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{metric}}; $self->{result_values}->{metric} = $options{extra_options}->{metric}; return 0; } sub custom_metric_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check( value => $self->{result_values}->{value}, threshold => [ { label => 'critical-' . $metrics_mapping{$self->{result_values}->{metric}}->{label} , exit_litteral => 'critical' }, { label => 'warning-' . $metrics_mapping{$self->{result_values}->{metric}}->{label}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_metric_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( instances => $self->{instance}, nlabel => $metrics_mapping{$self->{result_values}->{metric}}->{nlabel}, unit => $metrics_mapping{$self->{result_values}->{metric}}->{unit}, value => sprintf('%.2f', $self->{result_values}->{value}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $metrics_mapping{$self->{result_values}->{metric}}->{label}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $metrics_mapping{$self->{result_values}->{metric}}->{label}) ); } sub custom_metric_output { my ($self, %options) = @_; my ($value, $unit) = ($self->{result_values}->{value}, $metrics_mapping{$self->{result_values}->{metric}}->{unit}); return sprintf('%s: %.2f %s', $metrics_mapping{$self->{result_values}->{metric}}->{output}, $value, $unit); } sub prefix_metric_output { my ($self, %options) = @_; return "Elastic Pool '" . $options{instance_value}->{display} . "' "; } sub prefix_statistics_output { my ($self, %options) = @_; return "Statistic '" . $options{instance_value}->{display} . "' Metrics "; } sub long_output { my ($self, %options) = @_; return "Checking Pool'" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metrics', type => 3, cb_prefix_output => 'prefix_metric_output', cb_long_output => 'long_output', message_multiple => 'All CPU metrics are ok', indent_long_output => ' ', group => [ { name => 'statistics', display_long => 1, cb_prefix_output => 'prefix_statistics_output', message_multiple => 'All metrics are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; foreach my $metric (keys %metrics_mapping) { my $entry = { label => $metrics_mapping{$metric}->{label}, nlabel => $metrics_mapping{$metric}->{nlabel}, set => { key_values => [ { name => $metric }, { name => 'timeframe' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_metric_calc'), closure_custom_calc_extra_options => { metric => $metric }, 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') } }; push @{$self->{maps_counters}->{statistics}}, $entry; } } 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 => { 'resource:s@' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' }, 'filter-metric:s' => { name => 'filter_metric' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } $self->{az_resource} = $self->{option_results}->{resource}; $self->{az_resource_group} = $self->{option_results}->{resource_group} if (defined($self->{option_results}->{resource_group})); $self->{az_resource_type} = 'servers'; $self->{az_resource_namespace} = 'Microsoft.Sql'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %metrics_mapping) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; my $raw_results; foreach my $resource (@{$self->{az_resource}}) { my $resource_group = $self->{az_resource_group}; my ($resource_display, $resource_name); if ($resource =~ /^(.*)\/elasticpools\/(.*)/) { ($resource_display, $resource_name) = ($1 . '/' . $2, $resource); } else { $self->{output}->add_option_msg(short_msg => 'Incorrect resource format'); $self->{output}->option_exit(); }; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Sql\/servers\/(.*)\/elasticpools\/(.*)$/) { $resource_group = $1; $resource_display = $2 . '/' . $3; $resource_name = $2 . '/elasticpools/' . $3; } ($metric_results{$resource_display}, $raw_results) = $options{custom}->azure_get_metrics( resource => $resource_name, resource_group => $resource_group, resource_type => $self->{az_resource_type}, resource_namespace => $self->{az_resource_namespace}, metrics => $self->{az_metrics}, aggregations => $self->{az_aggregations}, timeframe => $self->{az_timeframe}, interval => $self->{az_interval} ); foreach my $metric (@{$self->{az_metrics}}) { foreach my $aggregation (@{$self->{az_aggregations}}) { next if (!defined($metric_results{$resource_display}->{$metric}->{lc($aggregation)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{$resource_display}->{display} = $resource_display; $self->{metrics}->{$resource_display}->{statistics}->{lc($aggregation)}->{display} = lc($aggregation); $self->{metrics}->{$resource_display}->{statistics}->{lc($aggregation)}->{timeframe} = $self->{az_timeframe}; $self->{metrics}->{$resource_display}->{statistics}->{lc($aggregation)}->{$metric} = defined($metric_results{$resource_display}->{$metric}->{lc($aggregation)}) ? $metric_results{$resource_display}->{$metric}->{lc($aggregation)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check Azure SQL Elastic Pool Sessions metrics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::elasticpool::plugin --custommode=azcli --mode=sessions --resource=/elasticpools/ --resource-group= --aggregation='average' --critical-sessions-percent='90' --verbose Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::compute::virtualmachine::plugin --custommode=azcli --mode=sessions --resource='/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Sql/servers/xxx/elasticpools/xxx' --aggregation='average' --critical-sessions-percent='90' --verbose Default aggregation: 'average' / 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--filter-metric> Filter on specific metrics. The Azure format must be used, for example: 'sessions_percent' (Can be a regexp). =item B<--warning-*> Warning threshold where * can be: 'workers-percent', sessions_percent'. =item B<--critical-*> Critical threshold where * can be: 'workers-percent', sessions_percent'. =back =cut centreon-plugins-20220113/cloud/azure/database/elasticpool/mode/storage.pm000066400000000000000000000263131417000230700265050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::elasticpool::mode::storage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; my %metrics_mapping = ( 'allocated_data_storage_percent' => { 'output' => 'Allocated data storage percentage', 'label' => 'allocated-data-storage-percent', 'nlabel' => 'elasticpool.storage.data.allocated.percentage', 'unit' => '%' }, 'allocated_data_storage' => { 'output' => 'Allocated data storage', 'label' => 'allocated-data-storage', 'nlabel' => 'elasticpool.storage.data.allocated.bytes', 'unit' => 'B' }, 'storage_percent' => { 'output' => 'Storage usage percentage', 'label' => 'storage-percent', 'nlabel' => 'elasticpool.storage.usage.percentage', 'unit' => '%' }, 'storage_used' => { 'output' => 'Storage usage', 'label' => 'storage-used', 'nlabel' => 'elasticpool.storage.used.bytes', 'unit' => 'B' } ); sub custom_metric_calc { my ($self, %options) = @_; $self->{result_values}->{timeframe} = $options{new_datas}->{$self->{instance} . '_timeframe'}; $self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{metric}}; $self->{result_values}->{metric} = $options{extra_options}->{metric}; return 0; } sub custom_metric_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check( value => $self->{result_values}->{value}, threshold => [ { label => 'critical-' . $metrics_mapping{$self->{result_values}->{metric}}->{label} , exit_litteral => 'critical' }, { label => 'warning-' . $metrics_mapping{$self->{result_values}->{metric}}->{label}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_metric_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( instances => $self->{instance}, nlabel => $metrics_mapping{$self->{result_values}->{metric}}->{nlabel}, unit => $metrics_mapping{$self->{result_values}->{metric}}->{unit}, value => sprintf('%.2f', $self->{result_values}->{value}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $metrics_mapping{$self->{result_values}->{metric}}->{label}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $metrics_mapping{$self->{result_values}->{metric}}->{label}) ); } sub custom_metric_output { my ($self, %options) = @_; my ($value, $unit) = ($metrics_mapping{$self->{result_values}->{metric}}->{unit} eq 'B') ? $self->{perfdata}->change_bytes(value => $self->{result_values}->{value}) : ($self->{result_values}->{value}, $metrics_mapping{$self->{result_values}->{metric}}->{unit}); return sprintf('%s: %.2f %s', $metrics_mapping{$self->{result_values}->{metric}}->{output}, $value, $unit); } sub prefix_metric_output { my ($self, %options) = @_; return "Elastic Pool '" . $options{instance_value}->{display} . "' "; } sub prefix_statistics_output { my ($self, %options) = @_; return "Statistic '" . $options{instance_value}->{display} . "' Metrics "; } sub long_output { my ($self, %options) = @_; return "Checking Pool'" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metrics', type => 3, cb_prefix_output => 'prefix_metric_output', cb_long_output => 'long_output', message_multiple => 'All CPU metrics are ok', indent_long_output => ' ', group => [ { name => 'statistics', display_long => 1, cb_prefix_output => 'prefix_statistics_output', message_multiple => 'All metrics are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; foreach my $metric (keys %metrics_mapping) { my $entry = { label => $metrics_mapping{$metric}->{label}, nlabel => $metrics_mapping{$metric}->{nlabel}, set => { key_values => [ { name => $metric }, { name => 'timeframe' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_metric_calc'), closure_custom_calc_extra_options => { metric => $metric }, 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') } }; push @{$self->{maps_counters}->{statistics}}, $entry; } } 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 => { 'resource:s@' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' }, 'filter-metric:s' => { name => 'filter_metric' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } $self->{az_resource} = $self->{option_results}->{resource}; $self->{az_resource_group} = $self->{option_results}->{resource_group} if (defined($self->{option_results}->{resource_group})); $self->{az_resource_type} = 'servers'; $self->{az_resource_namespace} = 'Microsoft.Sql'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %metrics_mapping) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; my $raw_results; foreach my $resource (@{$self->{az_resource}}) { my $resource_group = $self->{az_resource_group}; my ($resource_display, $resource_name); if ($resource =~ /^(.*)\/elasticpools\/(.*)/) { ($resource_display, $resource_name) = ($1 . '/' . $2, $resource); } else { $self->{output}->add_option_msg(short_msg => 'Incorrect resource format'); $self->{output}->option_exit(); }; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Sql\/servers\/(.*)\/elasticpools\/(.*)$/) { $resource_group = $1; $resource_display = $2 . '/' . $3; $resource_name = $2 . '/elasticpools/' . $3; } ($metric_results{$resource_display}, $raw_results) = $options{custom}->azure_get_metrics( resource => $resource_name, resource_group => $resource_group, resource_type => $self->{az_resource_type}, resource_namespace => $self->{az_resource_namespace}, metrics => $self->{az_metrics}, aggregations => $self->{az_aggregations}, timeframe => $self->{az_timeframe}, interval => $self->{az_interval} ); foreach my $metric (@{$self->{az_metrics}}) { foreach my $aggregation (@{$self->{az_aggregations}}) { next if (!defined($metric_results{$resource_display}->{$metric}->{lc($aggregation)}) && !defined($self->{option_results}->{zeroed})); $self->{metrics}->{$resource_display}->{display} = $resource_display; $self->{metrics}->{$resource_display}->{statistics}->{lc($aggregation)}->{display} = lc($aggregation); $self->{metrics}->{$resource_display}->{statistics}->{lc($aggregation)}->{timeframe} = $self->{az_timeframe}; $self->{metrics}->{$resource_display}->{statistics}->{lc($aggregation)}->{$metric} = defined($metric_results{$resource_display}->{$metric}->{lc($aggregation)}) ? $metric_results{$resource_display}->{$metric}->{lc($aggregation)} : 0; } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check Azure SQL Elastic Pool Storage metrics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::elasticpool::plugin --custommode=azcli --mode=storage --resource=/elasticpools/ --resource-group= --aggregation='average' --allocated-data-storage-percent='90' --verbose Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::compute::virtualmachine::plugin --custommode=azcli --mode=sessions --resource='/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Sql/servers/xxx/elasticpools/xxx' --aggregation='average' --allocated-data-storage-percent='90' --verbose Default aggregation: 'average' / 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--filter-metric> Filter on specific metrics. The Azure format must be used, for example: 'allocated_data_storage_percent' (Can be a regexp). =item B<--warning-*> Warning threshold where * can be: 'allocated-data-storage', allocated-data-storage-percent', 'storage-percent', 'storage-used'. =item B<--critical-*> Critical threshold where * can be: 'allocated-data-storage', allocated-data-storage-percent', 'storage-percent', 'storage-used'. =back =cut centreon-plugins-20220113/cloud/azure/database/elasticpool/plugin.pm000066400000000000000000000037231417000230700254130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::elasticpool::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} } = ( 'cpu' => 'cloud::azure::database::elasticpool::mode::cpu', 'discovery' => 'cloud::azure::database::elasticpool::mode::discovery', 'dtu' => 'cloud::azure::database::elasticpool::mode::dtu', 'log' => 'cloud::azure::database::elasticpool::mode::log', 'sessions' => 'cloud::azure::database::elasticpool::mode::sessions', 'storage' => 'cloud::azure::database::elasticpool::mode::storage' ); $self->{custom_modes}->{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}->{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' }, }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure SQL Elastic Pools. =cut centreon-plugins-20220113/cloud/azure/database/mysql/000077500000000000000000000000001417000230700224015ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/database/mysql/mode/000077500000000000000000000000001417000230700233255ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/database/mysql/mode/connections.pm000066400000000000000000000145131417000230700262110ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::mysql::mode::connections; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'active_connections' => { 'output' => 'Active Connections', 'label' => 'connections-active', 'nlabel' => 'azmysql.connections.active.count', 'unit' => '', 'min' => '0' }, 'connections_failed' => { 'output' => 'Failed Connections', 'label' => 'connections-failed', 'nlabel' => 'azmysql.connections.failed.count', 'unit' => '', 'min' => '0' }, 'aborted_connections' => { 'output' => 'Aborted Connections', 'label' => 'connections-aborted', 'nlabel' => 'azmysql.connections.aborted.count', 'unit' => '', 'min' => '0' }, 'total_connections' => { 'output' => 'Total Connections', 'label' => 'connections-total', 'nlabel' => 'azmysql.connections.total.count', 'unit' => '', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' }, 'resource-type:s' => { name => 'resource_type' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{resource_type}) || $self->{option_results}->{resource_type} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --resource-type option'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; my $resource_type = $self->{option_results}->{resource_type}; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.DBforMySQL\/(.*)\/(.*)$/) { $resource_group = $1; $resource_type = $2; $resource = $3; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = $resource_type; $self->{az_resource_namespace} = 'Microsoft.DBforMySQL'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } my $resource_mapping = { 'servers' => [ 'active_connections', 'connections_failed' ], 'flexibleServers' => [ 'active_connections', 'aborted_connections', 'total_connections' ] }; my $metrics_mapping_transformed; foreach my $metric_type (@{$resource_mapping->{$resource_type}}) { $metrics_mapping_transformed->{$metric_type} = $self->{metrics_mapping}->{$metric_type}; } foreach my $metric (keys %{$metrics_mapping_transformed}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Database for MySQL connections status. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::mysql::plugin --mode=connections --custommode=api --resource= --resource-group= --aggregation='total' --warning-connections-active='1000' --critical-connections-active='2000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::integration::servicebus::plugin --mode=connections --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.DBforMySQL/servers/' --aggregation='total' --warning-connections-active='1000' --critical-connections-active='2000' Default aggregation: 'total' / 'average', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--resource-type> Set resource type (Default: 'servers'). Can be 'servers', 'flexibleServers'. =item B<--warning-*> Warning threshold where '*' can be: 'connections-active', 'connections-failed', 'connections-aborted', 'connections-total'. =item B<--critical-*> Critical threshold where '*' can be: 'connections-active', 'connections-failed', 'connections-aborted', 'connections-total'. =back =cut centreon-plugins-20220113/cloud/azure/database/mysql/mode/cpu.pm000066400000000000000000000117671417000230700244660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::mysql::mode::cpu; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'cpu_percent' => { 'output' => 'CPU percent', 'label' => 'cpu-usage', 'nlabel' => 'azmysql.cpu.utilization.percentage', 'unit' => '%', 'min' => '0', 'max' => '100' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' }, 'resource-type:s' => { name => 'resource_type' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{resource_type}) || $self->{option_results}->{resource_type} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --resource-type option'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; my $resource_type = $self->{option_results}->{resource_type}; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.DBforMySQL\/(.*)\/(.*)$/) { $resource_group = $1; $resource_type = $2; $resource = $3; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = $resource_type; $self->{az_resource_namespace} = 'Microsoft.DBforMySQL'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Database for MySQL CPU usage. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::mysql::plugin --mode=cpu --custommode=api --resource= --resource-group= --aggregation='average' --warning-cpu-usage='80' --critical-cpu-usage='90' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::integration::servicebus::plugin --mode=cpu --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.DBforMySQL/servers/' --aggregation='average' --warning-cpu-usage='80' --critical-cpu-usage='90' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--resource-type> Set resource type (Default: 'servers'). Can be 'servers', 'flexibleServers'. =item B<--warning-cpu-usage> Set warning threshold for CPU utilization percentage. =item B<--critical-cpu-usage> Set critical threshold for CPU utilization percentage. =back =cut centreon-plugins-20220113/cloud/azure/database/mysql/mode/discovery.pm000066400000000000000000000077651417000230700257110ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::mysql::mode::discovery; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'namespace:s' => { name => 'namespace' }, 'type:s' => { name => 'type' }, 'resource-group:s' => { name => 'resource_group' }, 'location:s' => { name => 'location' }, 'prettify' => { name => 'prettify' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); $self->{namespace} = $self->{option_results}->{namespace}; $self->{type} = $self->{option_results}->{type}; $self->{location} = $self->{option_results}->{location}; $self->{resource_group} = $self->{option_results}->{resource_group}; } sub run { my ($self, %options) = @_; my @disco_data; my $disco_stats; $disco_stats->{start_time} = time(); my $resources = $options{custom}->azure_list_resources( namespace => $self->{namespace}, resource_type => $self->{type}, location => $self->{location}, resource_group => $self->{resource_group} ); $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; foreach my $resource (@{$resources}) { next if ($resource->{type} !~ /Microsoft\.DBforMySQL/); $resource->{type} =~ s/Microsoft\.DBforMySQL\///; my $resource_group = ''; $resource_group = $resource->{resourceGroup} if (defined($resource->{resourceGroup})); $resource_group = $1 if ($resource_group eq '' && defined($resource->{id}) && $resource->{id} =~ /resourceGroups\/(.*)\/providers/); $resource->{resourceGroup} = $resource_group; foreach my $entry (keys %{$resource}) { next if (ref($resource->{$entry}) ne "HASH"); my @array; foreach my $key (keys %{$resource->{$entry}}) { push @array, { key => $key, value => $resource->{$entry}->{$key} }; } $resource->{$entry} = \@array; } push @disco_data, $resource; } $disco_stats->{discovered_items} = @disco_data; $disco_stats->{results} = \@disco_data; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE Resources discovery. =over 8 =item B<--namespace> Specify resources namespace. =item B<--type> Specify resources type. =item B<--resource-group> Specify resources resource group. =item B<--location> Specify resources location. =item B<--prettify> Prettify JSON output. =back =cutcentreon-plugins-20220113/cloud/azure/database/mysql/mode/ioconsumption.pm000066400000000000000000000121511417000230700265710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::mysql::mode::ioconsumption; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'io_consumption_percent' => { 'output' => 'IO Percent', 'label' => 'ioconsumption-usage', 'nlabel' => 'azmysql.ioconsumption.usage.percentage', 'unit' => '%', 'min' => '0', 'max' => '100' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' }, 'resource-type:s' => { name => 'resource_type' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{resource_type}) || $self->{option_results}->{resource_type} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --resource-type option'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; my $resource_type = $self->{option_results}->{resource_type}; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.DBforMySQL\/(.*)\/(.*)$/) { $resource_group = $1; $resource_type = $2; $resource = $3; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = $resource_type; $self->{az_resource_namespace} = 'Microsoft.DBforMySQL'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Maximum']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Database for MySQL IO comsuption usage. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::mysql::plugin --mode=io-consumption --custommode=api --resource= --resource-group= --aggregation='maximum' --warning-ioconsumption-usage='80' --critical-ioconsumption-usage='90' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::integration::servicebus::plugin --mode=io-consumption --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.DBforMySQL/servers/' --aggregation='maximum' --warning-ioconsumption-usage='80' --critical-ioconsumption-usage='90' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--resource-type> Set resource type (Default: 'servers'). Can be 'servers', 'flexibleServers'. =item B<--warning-ioconsumption-usage> Set warning threshold for IO comsuption usage. =item B<--critical-ioconsumption-usage> Set critical threshold for IO comsuption usage. =back =cut centreon-plugins-20220113/cloud/azure/database/mysql/mode/memory.pm000066400000000000000000000120421417000230700251720ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::mysql::mode::memory; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'memory_percent' => { 'output' => 'Memory percent', 'label' => 'memory-usage', 'nlabel' => 'azmysql.memory.usage.percentage', 'unit' => '%', 'min' => '0', 'max' => '100' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' }, 'resource-type:s' => { name => 'resource_type' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{resource_type}) || $self->{option_results}->{resource_type} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --resource-type option'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; my $resource_type = $self->{option_results}->{resource_type}; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.DBforMySQL\/(.*)\/(.*)$/) { $resource_group = $1; $resource_type = $2; $resource = $3; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = $resource_type; $self->{az_resource_namespace} = 'Microsoft.DBforMySQL'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Database for MySQL memory usage. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::mysql::plugin --mode=memory --custommode=api --resource= --resource-group= --aggregation='average' --warning-memory-usage='80' --critical-memory-usage='90' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::integration::servicebus::plugin --mode=memory --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.DBforMySQL/servers/' --aggregation='average' --warning-memory-usage='80' --critical-memory-usage='90' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--resource-type> Set resource type (Default: 'servers'). Can be 'servers', 'flexibleServers'. =item B<--warning-memory-usage> Set warning threshold for memory utilization percentage. =item B<--critical-memory-usage> Set critical threshold for memory utilization percentage. =back =cut centreon-plugins-20220113/cloud/azure/database/mysql/mode/queries.pm000066400000000000000000000107641417000230700253500ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::mysql::mode::queries; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'queries' => { 'output' => 'Queries', 'label' => 'queries', 'nlabel' => 'azmysql.queries.count', 'unit' => '', 'min' => '0', } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; my $resource_type = $self->{option_results}->{resource_type}; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.DBforMySQL\/flexibleServers\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'flexibleServers'; $self->{az_resource_namespace} = 'Microsoft.DBforMySQL'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Database for MySQL network usage. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::mysql::plugin --mode=queries --custommode=api --resource= --resource-group= --aggregation='total' --warning-queries='80' --critical-queries='90' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::integration::servicebus::plugin --mode=queries --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.DBforMySQL/servers/' --aggregation='total' --warning-queries='80' --critical-queries='90' Default aggregation: 'total' / 'average', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-queries> Set warning threshold for queries count. =item B<--critical-queries> Set critical threshold for queries count. =back =cut centreon-plugins-20220113/cloud/azure/database/mysql/mode/replication.pm000066400000000000000000000132751417000230700262040ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::mysql::mode::replication; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'replication_lag' => { 'output' => 'Replication Lag In Seconds', 'label' => 'replication-lag', 'nlabel' => 'azmysql.replication.lag.seconds', 'unit' => 's', 'min' => '0' }, 'seconds_behind_master' => { 'output' => 'Replication lag in seconds', 'label' => 'replication-lag-count', 'nlabel' => 'azmysql.replication.lag.count', 'unit' => '', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' }, 'resource-type:s' => { name => 'resource_type' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{resource_type}) || $self->{option_results}->{resource_type} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --resource-type option'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; my $resource_type = $self->{option_results}->{resource_type}; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.DBforMySQL\/(.*)\/(.*)$/) { $resource_group = $1; $resource_type = $2; $resource = $3; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = $resource_type; $self->{az_resource_namespace} = 'Microsoft.DBforMySQL'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Maximum']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } my $resource_mapping = { 'servers' => [ 'seconds_behind_master' ], 'flexibleServers' => [ 'replication_lag' ] }; my $metrics_mapping_transformed; foreach my $metric_type (@{$resource_mapping->{$resource_type}}) { $metrics_mapping_transformed->{$metric_type} = $self->{metrics_mapping}->{$metric_type}; } foreach my $metric (keys %{$metrics_mapping_transformed}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Database for MySQL replication status. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::mysql::plugin --mode=connections --custommode=api --resource= --resource-group= --aggregation='maximum' --warning-replication-lag='1000' --critical-replication-lag='2000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::integration::servicebus::plugin --mode=connections --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.DBforMySQL/servers/' --aggregation='maximum' --warning-replication-lag='1000' --critical-replication-lag='2000' Default aggregation: 'maximum' / 'average', 'minimum' and 'total' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--resource-type> Set resource type (Default: 'servers'). Can be 'servers', 'flexibleServers'. =item B<--warning-*> Warning threshold where '*' can be: 'replication-lag', 'replication-lag-count'. =item B<--critical-*> Critical threshold where '*' can be: 'replication-lag', 'replication-lag-count'. =back =cut centreon-plugins-20220113/cloud/azure/database/mysql/mode/storage.pm000066400000000000000000000164171417000230700253400ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::mysql::mode::storage; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'backup_storage_used' => { 'output' => 'Backup Storage used', 'label' => 'storage-backup', 'nlabel' => 'azmysql.storage.backup.usage.bytes', 'unit' => 'B', 'min' => '0' }, 'serverlog_storage_limit' => { 'output' => 'Server Log storage limit', 'label' => 'serverlog-limit', 'nlabel' => 'azmysql.storage.serverlog.limit.bytes', 'unit' => 'B', 'min' => '0' }, 'serverlog_storage_percent' => { 'output' => 'Server Log storage percent', 'label' => 'serverlog-percent', 'nlabel' => 'azmysql.storage.serverlog.usage.percentage', 'unit' => '%', 'min' => '0' }, 'serverlog_storage_usage' => { 'output' => 'Server Log storage used', 'label' => 'servelog-usage', 'nlabel' => 'azmysql.storage.serverlog.usage.bytes', 'unit' => 'B', 'min' => '0' }, 'storage_limit' => { 'output' => 'Storage Limit', 'label' => 'storage-limit', 'nlabel' => 'azmysql.storage.limit.bytes', 'unit' => 'B', 'min' => '0' }, 'storage_percent' => { 'output' => 'Storage Percent', 'label' => 'storage-percent', 'nlabel' => 'azmysql.storage.usage.percentage', 'unit' => '%', 'min' => '0' }, 'storage_used' => { 'output' => 'Storage Used', 'label' => 'storage-used', 'nlabel' => 'azmysql.storage.usage.bytes', 'unit' => 'B', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' }, 'resource-type:s' => { name => 'resource_type' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{resource_type}) || $self->{option_results}->{resource_type} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --resource-type option'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; my $resource_type = $self->{option_results}->{resource_type}; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.DBforMySQL\/(.*)\/(.*)$/) { $resource_group = $1; $resource_type = $2; $resource = $3; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = $resource_type; $self->{az_resource_namespace} = 'Microsoft.DBforMySQL'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT15M'; $self->{az_aggregations} = ['Maximum']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } my $resource_mapping = { 'servers' => [ 'backup_storage_used', 'serverlog_storage_limit', 'serverlog_storage_percent', 'serverlog_storage_usage', 'storage_limit', 'storage_percent', 'storage_used' ], 'flexibleServers' => [ 'backup_storage_used', 'storage_limit', 'storage_percent', 'storage_used' ] }; my $metrics_mapping_transformed; foreach my $metric_type (@{$resource_mapping->{$resource_type}}) { $metrics_mapping_transformed->{$metric_type} = $self->{metrics_mapping}->{$metric_type}; } foreach my $metric (keys %{$metrics_mapping_transformed}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Database for MySQL storage usage. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::mysql::plugin --mode=storage --custommode=api --resource= --resource-group= --aggregation='maximum' --warning-storage_used='1000' --critical-storage_used='2000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::integration::servicebus::plugin --mode=storage --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.DBforMySQL/servers/' --aggregation='maximum' --warning-storage_used='1000' --critical-storage_used='2000' Default aggregation: 'maximum' / 'average', 'minimum' and 'total' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--resource-type> Set resource type (Default: 'servers'). Can be 'servers', 'flexibleServers'. =item B<--warning-*> Warning threshold where '*' can be: 'storage-backup', 'serverlog-limit', 'serverlog-percent', 'servelog-usage', 'storage-limit', 'storage-percent', 'storage-used'. =item B<--critical-*> Critical threshold where '*' can be: 'storage-backup', 'serverlog-limit', 'serverlog-percent', 'servelog-usage', 'storage-limit', 'storage-percent', 'storage-used'. =back =cut centreon-plugins-20220113/cloud/azure/database/mysql/mode/traffic.pm000066400000000000000000000123441417000230700253050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::mysql::mode::traffic; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'network_bytes_egress' => { 'output' => 'Network Out', 'label' => 'traffic-out', 'nlabel' => 'azmysql.traffic.out.bytes', 'unit' => 'B', 'min' => '0', }, 'network_bytes_ingress' => { 'output' => 'Network In', 'label' => 'traffic-in', 'nlabel' => 'azmysql.traffic.in.bytes', 'unit' => 'B', 'min' => '0', } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' }, 'resource-type:s' => { name => 'resource_type' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{resource_type}) || $self->{option_results}->{resource_type} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --resource-type option'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; my $resource_type = $self->{option_results}->{resource_type}; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.DBforMySQL\/(.*)\/(.*)$/) { $resource_group = $1; $resource_type = $2; $resource = $3; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = $resource_type; $self->{az_resource_namespace} = 'Microsoft.DBforMySQL'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Database for MySQL network usage. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::mysql::plugin --mode=traffic --custommode=api --resource= --resource-group= --aggregation='average' --warning-traffic-out='80' --critical-traffic-out='90' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::integration::servicebus::plugin --mode=traffic --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.DBforMySQL/servers/' --aggregation='average' --warning-traffic-out='80' --critical-traffic-out='90' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--resource-type> Set resource type (Default: 'servers'). Can be 'servers', 'flexibleServers'. =item B<--warning-*> Warning threshold where '*' can be: 'traffic-out', 'traffic-in'. =item B<--critical-*> Critical threshold where '*' can be: 'traffic-out', 'traffic-in'. =back =cut centreon-plugins-20220113/cloud/azure/database/mysql/plugin.pm000066400000000000000000000043051417000230700242370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::mysql::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} = { 'connections' => 'cloud::azure::database::mysql::mode::connections', 'cpu' => 'cloud::azure::database::mysql::mode::cpu', 'discovery' => 'cloud::azure::database::mysql::mode::discovery', 'io-consumption' => 'cloud::azure::database::mysql::mode::ioconsumption', 'memory' => 'cloud::azure::database::mysql::mode::memory', 'queries' => 'cloud::azure::database::mysql::mode::queries', 'replication' => 'cloud::azure::database::mysql::mode::replication', 'storage' => 'cloud::azure::database::mysql::mode::storage', 'traffic' => 'cloud::azure::database::mysql::mode::traffic' }; $self->{custom_modes}->{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}->{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' }, }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure Database for MySQL resources. =cut centreon-plugins-20220113/cloud/azure/database/redis/000077500000000000000000000000001417000230700223425ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/database/redis/mode/000077500000000000000000000000001417000230700232665ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/database/redis/mode/cachelatency.pm000066400000000000000000000106721417000230700262550ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::redis::mode::cachelatency; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'cachelatency' => { 'output' => 'Cache Latency', 'label' => 'cache-latency', 'nlabel' => 'redis.cache.latency.microseconds', 'unit' => 'μs', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Cache\/Redis\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'Redis'; $self->{az_resource_namespace} = 'Microsoft.Cache'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Redis cache latency statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::redis::plugin --mode=cache-latency --custommode=api --resource= --resource-group= --aggregation='average' --warning-cache-latency='8000' --critical-cache-latency='9000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::database::redis::plugin --mode=cache-latency --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Cache/Redis/' --aggregation='average' --warning-total-latency='50' --critical-total-latency='100' Default aggregation: 'average' / 'minimum', 'maximum' and 'total' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-cache-latency> Warning threshold. =item B<--critical-cache-latency> Critical threshold. =back =cut centreon-plugins-20220113/cloud/azure/database/redis/mode/cachethroughput.pm000066400000000000000000000115721417000230700270270ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::redis::mode::cachethroughput; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'cachewrite' => { 'output' => 'Cache Write Throughput', 'label' => 'cache-write-throughput', 'nlabel' => 'redis.cache.write.throughput.bytespersecond', 'unit' => 'B/s', 'min' => '0' }, 'cacheread' => { 'output' => 'Cache Read Throughput', 'label' => 'cache-read-throughput', 'nlabel' => 'redis.cache.read.throughput.bytespersecond', 'unit' => 'B/s', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Cache\/Redis\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'Redis'; $self->{az_resource_namespace} = 'Microsoft.Cache'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Maximum']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Redis cache throughput statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::redis::plugin --mode=cache-throughput --custommode=api --resource= --resource-group= --aggregation='maximum' --warning-cache-read-throughput='800000' --critical-cache-read-throughput='900000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::database::redis::plugin --mode=cache-throughput --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Cache/Redis/' --aggregation='maximum' --warning-cache-read-throughput='800000' --critical-cache-read-throughput='900000' Default aggregation: 'maximum' / 'minimum', 'total' and 'average' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'cache-read-throughput', 'cache-write-throughput'. =item B<--critical-*> Critical threshold where '*' can be: 'cache-read-throughput', 'cache-write-throughput'. =back =cut centreon-plugins-20220113/cloud/azure/database/redis/mode/cacheusage.pm000066400000000000000000000112721417000230700257170ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::redis::mode::cacheusage; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'cachehits' => { 'output' => 'Cache Hits', 'label' => 'cache-hits', 'nlabel' => 'redis.cache.hits.count', 'unit' => '', 'min' => '0' }, 'cachemisses' => { 'output' => 'Cache Misses', 'label' => 'cache-misses', 'nlabel' => 'redis.cache.misses.count', 'unit' => '', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Cache\/Redis\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'Redis'; $self->{az_resource_namespace} = 'Microsoft.Cache'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Redis cache usage statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::redis::plugin --mode=cache-usage --custommode=api --resource= --resource-group= --aggregation='total' --warning-cache-misses='800' --critical-cache-misses='900' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::database::redis::plugin --mode=cache-usage --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Cache/Redis/' --aggregation='total' --warning-cache-misses='800' --critical-cache-misses='900' Default aggregation: 'total' / 'minimum', 'maximum' and 'average' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'cache-misses', 'cache-hits'. =item B<--critical-*> Critical threshold where '*' can be: 'cache-misses', 'cache-hits'. =back =cut centreon-plugins-20220113/cloud/azure/database/redis/mode/clients.pm000066400000000000000000000107621417000230700252730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::redis::mode::clients; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'connectedclients' => { 'output' => 'Connected Clients', 'label' => 'connected-clients', 'nlabel' => 'redis.cache.clients.connected.count', 'unit' => '', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Cache\/Redis\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'Redis'; $self->{az_resource_namespace} = 'Microsoft.Cache'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Redis clients statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::redis::plugin --mode=clients --custommode=api --resource= --resource-group= --aggregation='average' --warning-connected-clients='800' --critical-connected-clients='900' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::database::redis::plugin --mode=clients --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Cache/Redis/' --aggregation='average' --warning-connected-clients='800' --critical-connected-clients='900' Default aggregation: 'average' / 'minimum', 'maximum' and 'total' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'connected-clients'. =item B<--critical-*> Critical threshold where '*' can be: 'connected-clients'. =back =cut centreon-plugins-20220113/cloud/azure/database/redis/mode/cpu.pm000066400000000000000000000107611417000230700244200ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::redis::mode::cpu; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'percentprocessortime' => { 'output' => 'CPU Usage Percentage', 'label' => 'cpu-usage-percentage', 'nlabel' => 'redis.cache.cpu.usage.percentage', 'unit' => '%', 'min' => '0', 'max' => '100' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Cache\/Redis\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'Redis'; $self->{az_resource_namespace} = 'Microsoft.Cache'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Maximum']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Redis CPU usage statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::redis::plugin --mode=cpu --custommode=api --resource= --resource-group= --aggregation='maximum' --warning-cpu-usage-percentage='80' --critical-cpu-usage-percentage='90' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::database::redis::plugin --mode=cpu --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Cache/Redis/' --aggregation='maximum' --warning-cpu-usage-percentage='80' --critical-cpu-usage-percentage='90' Default aggregation: 'maximum' / 'minimum', 'average' and 'total' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-cpu-usage-percentage> Warning threshold. =item B<--critical-cpu-usage-percentage> Critical threshold. =back =cut centreon-plugins-20220113/cloud/azure/database/redis/mode/discovery.pm000066400000000000000000000024161417000230700256360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::redis::mode::discovery; use base qw(cloud::azure::management::monitor::mode::discovery); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{namespace} = 'Microsoft.Cache'; $self->{type} = 'Redis'; } 1; __END__ =head1 MODE Azure Redis Cache discovery. =over 8 =item B<--resource-group> Specify resource group. =item B<--location> Specify location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/database/redis/mode/errors.pm000066400000000000000000000104731417000230700251450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::redis::mode::errors; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'errors' => { 'output' => 'Errors', 'label' => 'errors-count', 'nlabel' => 'redis.cache.errors.count', 'unit' => '', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Cache\/Redis\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'Redis'; $self->{az_resource_namespace} = 'Microsoft.Cache'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Redis errors statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::redis::plugin --mode=errors --custommode=api --resource= --resource-group= --aggregation='total' --critical-errors-count='1' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::database::redis::plugin --mode=errors --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Cache/Redis/' --aggregation='total' --critical-errors-count='1' Default aggregation: 'total' / 'minimum', 'maximum' and 'average' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-errors-count> Warning threshold. =item B<--critical-errors-count> Critical threshold. =back =cut centreon-plugins-20220113/cloud/azure/database/redis/mode/health.pm000066400000000000000000000036041417000230700250740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::redis::mode::health; use base qw(cloud::azure::management::monitor::mode::health); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{az_resource_namespace} = 'Microsoft.Cache'; $self->{az_resource_type} = 'Redis'; } 1; __END__ =head1 MODE Check Azure Redis cache health status. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{summary} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /^Unavailable$/'). Can used special variables like: %{status}, %{summary} =item B<--unknown-status> Set unknown threshold for status (Default: '%{status} =~ /^Unknown$/'). Can used special variables like: %{status}, %{summary} =item B<--ok-status> Set ok threshold for status (Default: '%{status} =~ /^Available$/'). Can used special variables like: %{status}, %{summary} =back =cut centreon-plugins-20220113/cloud/azure/database/redis/mode/load.pm000066400000000000000000000107661417000230700245550ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::redis::mode::load; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'serverload' => { 'output' => 'Server Load', 'label' => 'server-load-percentage', 'nlabel' => 'redis.cache.server.load.percentage', 'unit' => '%', 'min' => '0', 'max' => '100' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Cache\/Redis\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'Redis'; $self->{az_resource_namespace} = 'Microsoft.Cache'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Maximum']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Redis server load statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::redis::plugin --mode=load --custommode=api --resource= --resource-group= --aggregation='maximum' --warning-server-load-percentage='80' --critical-server-load-percentage='90' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::database::redis::plugin --mode=load --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Cache/Redis/' --aggregation='maximum' --warning-server-load-percentage='80' --critical-server-load-percentage='90' Default aggregation: 'maximum' / 'minimum', 'maximum' and 'average' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-server-load-percentage> Warning threshold. =item B<--critical-server-load-percentage> Critical threshold. =back =cut centreon-plugins-20220113/cloud/azure/database/redis/mode/memory.pm000066400000000000000000000110221417000230700251300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::redis::mode::memory; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'usedmemorypercentage' => { 'output' => 'Memory Usage Percentage', 'label' => 'memory-usage-percentage', 'nlabel' => 'redis.cache.memory.usage.percentage', 'unit' => '%', 'min' => '0', 'max' => '100' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Cache\/Redis\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'Redis'; $self->{az_resource_namespace} = 'Microsoft.Cache'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Maximum']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Redis memory statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::redis::plugin --mode=memory --custommode=api --resource= --resource-group= --aggregation='maximum' --warning-memory-usage-percentage='80' --critical-memory-usage-percentage='90' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::database::redis::plugin --mode=memory --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Cache/Redis/' --aggregation='maximum' --warning-memory-usage-percentage='80' --critical-memory-usage-percentage='90' Default aggregation: 'maximum' / 'minimum', 'average' and 'total' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-memory-usage-percentage> Warning threshold. =item B<--critical-memory-usage-percentage> Critical threshold. =back =cut centreon-plugins-20220113/cloud/azure/database/redis/mode/operations.pm000066400000000000000000000107631417000230700260160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::redis::mode::operations; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'operationspersecond' => { 'output' => 'Operations per seconds', 'label' => 'operations-per-second', 'nlabel' => 'redis.cache.operations.persecond', 'unit' => 'op/s', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Cache\/Redis\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'Redis'; $self->{az_resource_namespace} = 'Microsoft.Cache'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Maximum']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Redis operations statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::redis::plugin --mode=operations --custommode=api --resource= --resource-group= --aggregation='maximum' --warning-operations-per-second='80' --critical-operations-per-second='90' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::database::redis::plugin --mode=operations --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Cache/Redis/' --aggregation='maximum' --warning-operations-per-second='80' --critical-operations-per-second='90' Default aggregation: 'maximum' / 'minimum', 'average' and 'total' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-operations-per-second> Warning threshold. =item B<--critical-operations-per-second> Critical threshold. =back =cut centreon-plugins-20220113/cloud/azure/database/redis/plugin.pm000066400000000000000000000045521417000230700242040ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::redis::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} = { 'cache-latency' => 'cloud::azure::database::redis::mode::cachelatency', 'cache-throughput' => 'cloud::azure::database::redis::mode::cachethroughput', 'cache-usage' => 'cloud::azure::database::redis::mode::cacheusage', 'clients' => 'cloud::azure::database::redis::mode::clients', 'cpu' => 'cloud::azure::database::redis::mode::cpu', 'discovery' => 'cloud::azure::database::redis::mode::discovery', 'errors' => 'cloud::azure::database::redis::mode::errors', 'health' => 'cloud::azure::database::redis::mode::health', 'load' => 'cloud::azure::database::redis::mode::load', 'memory' => 'cloud::azure::database::redis::mode::memory', 'operations' => 'cloud::azure::database::redis::mode::operations', }; $self->{custom_modes}->{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}->{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' } }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure Redis Cache service. =cut centreon-plugins-20220113/cloud/azure/database/sqldatabase/000077500000000000000000000000001417000230700235205ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/database/sqldatabase/mode/000077500000000000000000000000001417000230700244445ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/database/sqldatabase/mode/appresources.pm000066400000000000000000000123551417000230700275230ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::sqldatabase::mode::appresources; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'app_cpu_percent' => { 'output' => 'App CPU percent ', 'label' => 'app-cpu', 'nlabel' => 'sqldatabase.serverless.app.cpu.percentage', 'unit' => '%', 'min' => '0', 'max' => '' }, 'app_memory_percent' => { 'output' => 'App Memory percent', 'label' => 'app-memory', 'nlabel' => 'sqldatabase.serverless.app.memory.percentage', 'unit' => '%', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' }, 'server:s' => { name => 'server' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group and --server option OR --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $server = $self->{option_results}->{server}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Sql\/servers\/(.*)\/databases\/(.*)$/) { $resource_group = $1; $resource = $2 . '/databases/' . $3; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'servers'; $self->{az_resource_namespace} = 'Microsoft.Sql'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure SQL Database app resource consumption (Serverless DB only). Metrics are only available for: - vCore based model - General purpose Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::sqldatabase::plugin --mode=app-resources --custommode=api --resource= --resource-group= --server= --aggregation='average' --critical-app-cpu='80'' --critical-app-memory='90' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::database::sqldatabase::plugin --mode=app-resources --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Sql/servers//databases/' --aggregation='average' --critical-app-cpu='80'' --critical-app-memory='90' Default aggregation: 'average', other are not identified as relevant nor available by Microsoft. =over 8 =item B<--resource> Set resource name or id (Required). It is the database name. =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--server> Set server name (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'app-cpu', 'app-memory'. =item B<--critical-*> Critical threshold where '*' can be: 'app-cpu', 'app-memory'. =back =cut centreon-plugins-20220113/cloud/azure/database/sqldatabase/mode/connections.pm000066400000000000000000000132321417000230700273250ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::sqldatabase::mode::connections; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'blocked_by_firewall' => { 'output' => 'Blocked by firewall ', 'label' => 'connection-blocked', 'nlabel' => 'sqldatabase.connection.blocked.count', 'unit' => '', 'min' => '0', 'max' => '' }, 'connection_failed' => { 'output' => 'Connection failed ', 'label' => 'connection-failed', 'nlabel' => 'sqldatabase.connection.failed.count', 'unit' => '', 'min' => '0', 'max' => '' }, 'connection_successful' => { 'output' => 'Connection successful ', 'label' => 'connection-successful', 'nlabel' => 'sqldatabase.connection.successful.count', 'unit' => '', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' }, 'server:s' => { name => 'server' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group and --server option OR --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $server = $self->{option_results}->{server}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Sql\/servers\/(.*)\/databases\/(.*)$/) { $resource_group = $1; $server = $2; $resource = $2 . '/databases/' . $3; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'servers'; $self->{az_resource_namespace} = 'Microsoft.Sql'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check connections to Azure SQL database. Metrics are available with: - Tier 'DTU based' - Basic, Standard, Premium - vCore based model - General purpose & Business critical - HyperScale Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::sqldatabase::plugin --mode=connections --custommode=api --resource= --resource-group= --server= --aggregation='total' --warning-connection-failed='10'' --critical-connection-failed='30' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::database::sqldatabase::plugin --mode=connections --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Sql/servers//databases/' --aggregation='total' --warning-connection-failed='10'' --critical-connection-failed='30' Default aggregation: 'maximum', other are not identified as relevant nor available by Microsoft. =over 8 =item B<--resource> Set resource name or id (Required). It is the database name. =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--server> Set server name (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'connection-failed', 'connection-successful'. =item B<--critical-*> Critical threshold where '*' can be: 'connection-failed', 'connection-successful'. =back =cutcentreon-plugins-20220113/cloud/azure/database/sqldatabase/mode/deadlocks.pm000066400000000000000000000115521417000230700267370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::sqldatabase::mode::deadlocks; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'deadlocks' => { 'output' => 'Deadlocks ', 'label' => 'deadlocks', 'nlabel' => 'sqldatabase.deadlocks.count', 'unit' => '', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' }, 'server:s' => { name => 'server' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group and --server option OR --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $server = $self->{option_results}->{server}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Sql\/servers\/(.*)\/databases\/(.*)$/) { $resource_group = $1; $server = $2; $resource = $2 . '/databases/' . $3; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'servers'; $self->{az_resource_namespace} = 'Microsoft.Sql'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check deadlocks happening on Azure SQL Databases. Metrics are available with: - Tier 'DTU based' - Basic, Standard, Premium - vCore based model - General purpose & Business critical - HyperScale Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::sqldatabase::plugin --mode=deadlocks --custommode=api --resource= --resource-group= --server= --aggregation='total' --critical-deadlock='0' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::database::sqldatabase::plugin --mode=deadlocks --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Sql/servers//databases/' --aggregation='total' --critical-deadlock='0' Default aggregation: 'total', other are not identified as relevant nor available by Microsoft. =over 8 =item B<--resource> Set resource name or id (Required). It is the database name. =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--server> Set server name (Required if resource's name is used). =item B<--warning-deadlocks> Warning threshold. =item B<--critical-deadlocks> Critical threshold. =back =cutcentreon-plugins-20220113/cloud/azure/database/sqldatabase/mode/discovery.pm000066400000000000000000000024321417000230700270120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::sqldatabase::mode::discovery; use base qw(cloud::azure::management::monitor::mode::discovery); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{namespace} = 'Microsoft.Sql'; $self->{type} = 'servers/databases'; } 1; __END__ =head1 MODE SQL Databases discovery. =over 8 =item B<--resource-group> Specify resource group. =item B<--location> Specify location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/database/sqldatabase/mode/health.pm000066400000000000000000000036361417000230700262570ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::sqldatabase::mode::health; use base qw(cloud::azure::management::monitor::mode::health); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{namespace} = 'Microsoft.Sql'; $self->{type} = 'servers/databases'; } 1; __END__ =head1 MODE Check SQL Database health status. (Useful to determine host status) =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{summary} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /^Unavailable$/'). Can used special variables like: %{status}, %{summary} =item B<--unknown-status> Set unknown threshold for status (Default: '%{status} =~ /^Unknown$/'). Can used special variables like: %{status}, %{summary} =item B<--ok-status> Set ok threshold for status (Default: '%{status} =~ /^Available$/'). Can used special variables like: %{status}, %{summary} =back =cut centreon-plugins-20220113/cloud/azure/database/sqldatabase/mode/listdatabases.pm000066400000000000000000000116331417000230700276310ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::sqldatabase::mode::listdatabases; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource-group:s" => { name => 'resource_group' }, "server:s" => { name => 'server' }, "filter-name:s" => { name => 'filter_name' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{resource_group}) || $self->{option_results}->{resource_group} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --resource-group option"); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{server}) || $self->{option_results}->{server} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --server option"); $self->{output}->option_exit(); } } sub manage_selection { my ($self, %options) = @_; $self->{databases} = $options{custom}->azure_list_sqldatabases( resource_group => $self->{option_results}->{resource_group}, server => $self->{option_results}->{server} ); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $database (@{$self->{databases}}) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $database->{name} !~ /$self->{option_results}->{filter_name}/); my $resource_group = '-'; $resource_group = $database->{resourceGroup} if (defined($database->{resourceGroup})); $resource_group = $1 if ($resource_group eq '-' && defined($database->{id}) && $database->{id} =~ /resourceGroups\/(.*)\/providers/); my @tags; foreach my $tag (keys %{$database->{tags}}) { push @tags, $tag . ':' . $database->{tags}->{$tag}; } $self->{output}->output_add(long_msg => sprintf("[name = %s][kind = %s][resourcegroup = %s][location = %s][id = %s][tags = %s]", $database->{name}, ($database->{kind}) ? $database->{kind} : $database->{properties}->{kind}, $resource_group, $database->{location}, $database->{id}, join(',', @tags), )); } $self->{output}->output_add(severity => 'OK', short_msg => 'List SQL databases:'); $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', 'kind', 'resourcegroup', 'location', 'id', 'tags']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $database (@{$self->{databases}}) { my $resource_group = '-'; $resource_group = $database->{resourceGroup} if (defined($database->{resourceGroup})); $resource_group = $1 if ($resource_group eq '-' && defined($database->{id}) && $database->{id} =~ /resourceGroups\/(.*)\/providers/); my @tags; foreach my $tag (keys %{$database->{tags}}) { push @tags, $tag . ':' . $database->{tags}->{$tag}; } $self->{output}->add_disco_entry( name => $database->{name}, kind => ($database->{kind}) ? $database->{kind} : $database->{properties}->{kind}, resourcegroup => $resource_group, location => $database->{location}, id => $database->{id}, tags => join(',', @tags), ); } } 1; __END__ =head1 MODE List SQL databases. =over 8 =item B<--resource-group> Set resource group (Required). =item B<--resource-group> Set SQL erver (Required). =item B<--filter-name> Filter resource name (Can be a regexp). =back =cut centreon-plugins-20220113/cloud/azure/database/sqldatabase/mode/sessions.pm000066400000000000000000000115531417000230700266550ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::sqldatabase::mode::sessions; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'sessions_percent' => { 'output' => 'Sessions ', 'label' => 'sessions', 'nlabel' => 'sqldatabase.sessions.count', 'unit' => '', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' }, 'server:s' => { name => 'server' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group and --server option OR --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $server = $self->{option_results}->{server}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Sql\/servers\/(.*)\/databases\/(.*)$/) { $resource_group = $1; $server = $2; $resource = $2 . '/databases/' . $3; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'servers'; $self->{az_resource_namespace} = 'Microsoft.Sql'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check opened session on Azure SQL Database. Metrics are available with: - Tier 'DTU based' - Basic, Standard, Premium - vCore based model - General purpose & Business critical - HyperScale Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::sqldatabase::plugin --mode=sessions --custommode=api --resource= --resource-group= --server= --aggregation='total' --critical-sessions='100' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::database::sqldatabase::plugin --mode=sessions --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Sql/servers//databases/' --aggregation='total' --critical-sessions='100' Default aggregation: 'average', other are not identified as relevant nor available by Microsoft. =over 8 =item B<--resource> Set resource name or id (Required). It is the database name. =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--server> Set server name (Required if resource's name is used). =item B<--warning-sessions> Warning threshold. =item B<--critical-sessions> Critical threshold. =back =cutcentreon-plugins-20220113/cloud/azure/database/sqldatabase/mode/storage.pm000066400000000000000000000124401417000230700264470ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::sqldatabase::mode::storage; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'storage' => { 'output' => 'Storage used ', 'label' => 'usage-bytes', 'nlabel' => 'sqldatabase.storage.space.usage.bytes', 'unit' => 'B', 'min' => '0', 'max' => '' }, 'storage_percent' => { 'output' => 'Storage used percent', 'label' => 'usage-percent', 'nlabel' => 'sqldatabase.storage.space.usage.percentage', 'unit' => '%', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' }, 'server:s' => { name => 'server' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group and --server option OR --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $server = $self->{option_results}->{server}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Sql\/servers\/(.*)\/databases\/(.*)$/) { $resource_group = $1; $server = $2; $resource = $2 . '/databases/' . $3; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'servers'; $self->{az_resource_namespace} = 'Microsoft.Sql'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Maximum']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure SQL Database storage. Metrics are available with: - Tier 'DTU based' - Basic, Standard, Premium - vCore based model - General purpose & Business critical - HyperScale Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::sqldatabase::plugin --mode=storage --custommode=api --resource= --resource-group= --server= --aggregation='maximum' --warning-usage-percent='80'' --critical-usage-percent='90' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::database::sqldatabase::plugin --mode=storage --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Sql/servers//databases/' --aggregation='maximum' --warning-usage-percent='80'' --critical-usage-percent='90' Default aggregation: 'maximum', other are not identified as relevant nor available by Microsoft. =over 8 =item B<--resource> Set resource name or id (Required). It is the database name. =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--server> Set server name (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'usage-bytes','usage-percent'. =item B<--critical-*> Critical threshold where '*' can be: 'usage-bytes','usage-percent'. =back =cutcentreon-plugins-20220113/cloud/azure/database/sqldatabase/mode/workers.pm000066400000000000000000000115371417000230700265050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::sqldatabase::mode::workers; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'sessions_percent' => { 'output' => 'Workers ', 'label' => 'workers', 'nlabel' => 'sqldatabase.workers.count', 'unit' => '', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' }, 'server:s' => { name => 'server' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group and --server option OR --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $server = $self->{option_results}->{server}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Sql\/servers\/(.*)\/databases\/(.*)$/) { $resource_group = $1; $server = $2; $resource = $2 . '/databases/' . $3; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'servers'; $self->{az_resource_namespace} = 'Microsoft.Sql'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check active workers on Azure SQL Database. Metrics are available with: - Tier 'DTU based' - Basic, Standard, Premium - vCore based model - General purpose & Business critical - HyperScale Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::sqldatabase::plugin --mode=workers --custommode=api --resource= --resource-group= --server= --aggregation='total' --critical-workers='10' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::database::sqldatabase::plugin --mode=workers --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Sql/servers//databases/' --aggregation='total' --critical-workers='10' Default aggregation: 'average', other are not identified as relevant nor available by Microsoft. =over 8 =item B<--resource> Set resource name or id (Required). It is the database name. =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--server> Set server name (Required if resource's name is used). =item B<--warning-workers> Warning threshold. =item B<--critical-workers> Critical threshold. =back =cutcentreon-plugins-20220113/cloud/azure/database/sqldatabase/plugin.pm000066400000000000000000000043031417000230700253540ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::sqldatabase::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} } = ( 'app-resources' => 'cloud::azure::database::sqldatabase::mode::appresources', 'connections' => 'cloud::azure::database::sqldatabase::mode::connections', 'discovery' => 'cloud::azure::database::sqldatabase::mode::discovery', 'deadlocks' => 'cloud::azure::database::sqldatabase::mode::deadlocks', 'health' => 'cloud::azure::database::sqldatabase::mode::health', 'sessions' => 'cloud::azure::database::sqldatabase::mode::sessions', 'storage' => 'cloud::azure::database::sqldatabase::mode::storage', 'workers' => 'cloud::azure::database::sqldatabase::mode::workers' ); $self->{custom_modes}->{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}->{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' }, }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure SQL Databases (Microsoft.Sql/Servers/Databases). =cut centreon-plugins-20220113/cloud/azure/database/sqlmanagedinstance/000077500000000000000000000000001417000230700250755ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/database/sqlmanagedinstance/mode/000077500000000000000000000000001417000230700260215ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/database/sqlmanagedinstance/mode/cpu.pm000066400000000000000000000115701417000230700271520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::sqlmanagedinstance::mode::cpu; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'avg_cpu_percent' => { 'output' => 'Average CPU percentage', 'label' => 'cpu-average', 'nlabel' => 'sqlmanagedinstance.cpu.utilization.percentage', 'unit' => '%', 'min' => '0', 'max' => '100' }, 'virtual_core_count' => { 'output' => 'Virtual core count', 'label' => 'core-count', 'nlabel' => 'sqlmanagedinstance.cpu.virtualcores.count', 'unit' => '', 'min' => '0', 'max' => '' }, }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Sql\/managedInstances\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'managedInstances'; $self->{az_resource_namespace} = 'Microsoft.Sql'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure SQL Managed Instance CPU. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::sqlmanagedinstance::plugin --mode=cpu --custommode=api --resource= --resource-group= --aggregation='average' --warning-cpu-average='80'' --critical-cpu-average='90' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::database::sqlmanagedinstance::plugin --mode=cpu --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Sql/managedInstances/' --aggregation='average' --warning-cpu-average='80'' --critical-cpu-average='90' Default aggregation: 'average' / 'minimum', 'maximum' and 'total' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'cpu-average', 'core-count'. =item B<--critical-*> Critical threshold where '*' can be:. 'cpu-average', 'core-count'. =back =cut centreon-plugins-20220113/cloud/azure/database/sqlmanagedinstance/mode/discovery.pm000066400000000000000000000024551417000230700303740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::sqlmanagedinstance::mode::discovery; use base qw(cloud::azure::management::monitor::mode::discovery); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{namespace} = 'Microsoft.Sql'; $self->{type} = 'managedInstances'; } 1; __END__ =head1 MODE Azure SQL Managed Instance discovery. =over 8 =item B<--resource-group> Specify resource group. =item B<--location> Specify location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/database/sqlmanagedinstance/mode/diskio.pm000066400000000000000000000122311417000230700276400ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::sqlmanagedinstance::mode::diskio; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'io_bytes_read' => { 'output' => 'IO bytes read', 'label' => 'bytes-read', 'nlabel' => 'sqlmanagedinstance.bytes.read.bytes', 'unit' => 'B', 'min' => '0', 'max' => '' }, 'io_bytes_written' => { 'output' => 'IO bytes written', 'label' => 'bytes-written', 'nlabel' => 'sqlmanagedinstance.bytes.written.bytes', 'unit' => 'B', 'min' => '0', 'max' => '' }, 'io_requests' => { 'output' => 'IO requests count', 'label' => 'requests', 'nlabel' => 'sqlmanagedinstance.io.requests.count', 'unit' => '', 'min' => '0', 'max' => '' }, }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Sql\/managedInstances\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'managedInstances'; $self->{az_resource_namespace} = 'Microsoft.Sql'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure SQL Managed Instance disk IO. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::sqlmanagedinstance::plugin --mode=diskio --custommode=api --resource= --resource-group= --aggregation='average' --warning-bytes-written='80'' --critical-bytes-written='90' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::database::sqlmanagedinstance::plugin --mode=diskio --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Sql/managedInstances/' --aggregation='average' --warning-bytes-written='80'' --critical-bytes-written='90' Default aggregation: 'average' / 'minimum', 'maximum' and 'total' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'bytes-written', 'bytes-read', 'requests'. =item B<--critical-*> Critical threshold where '*' can be:. 'bytes-written', 'bytes-read', 'requests'. =back =cut centreon-plugins-20220113/cloud/azure/database/sqlmanagedinstance/mode/health.pm000066400000000000000000000036631417000230700276340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::sqlmanagedinstance::mode::health; use base qw(cloud::azure::management::monitor::mode::health); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{az_resource_namespace} = 'Microsoft.Sql'; $self->{az_resource_type} = 'managedInstances'; } 1; __END__ =head1 MODE Check Azure SQL Managed Instance health status. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-status> Set warning threshold for status (Default: ''). Special variables that can be used: %{status}, %{summary}. =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /^Unavailable$/'). Special variables that can be used: %{status}, %{summary}. =item B<--unknown-status> Set unknown threshold for status (Default: '%{status} =~ /^Unknown$/'). Special variables that can be used: %{status}, %{summary}. =item B<--ok-status> Set ok threshold for status (Default: '%{status} =~ /^Available$/'). Special variables that can be used: %{status}, %{summary}. =back =cut centreon-plugins-20220113/cloud/azure/database/sqlmanagedinstance/mode/storage.pm000066400000000000000000000115301417000230700300230ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::sqlmanagedinstance::mode::storage; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'reserved_storage_mb' => { 'output' => 'Storage space reserved', 'label' => 'reserved', 'nlabel' => 'sqlmanagedinstance.storage.space.reserved.count', 'unit' => '', 'min' => '0', 'max' => '' }, 'storage_space_used_mb' => { 'output' => 'Storage space used', 'label' => 'used', 'nlabel' => 'sqlmanagedinstance.storage.space.used.count', 'unit' => '', 'min' => '0', 'max' => '' }, }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Sql\/managedInstances\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'managedInstances'; $self->{az_resource_namespace} = 'Microsoft.Sql'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure SQL Managed Instance storage. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::database::sqlmanagedinstance::plugin --mode=storage --custommode=api --resource= --resource-group= --aggregation='average' --warning-used='80'' --critical-used='90' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::database::sqlmanagedinstance::plugin --mode=storage --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Sql/managedInstances/' --aggregation='average' --warning-used='80'' --critical-used='90' Default aggregation: 'average' / 'minimum', 'maximum' and 'total' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'used', 'reserved'. =item B<--critical-*> Critical threshold where '*' can be:. 'used', 'reserved'. =back =cut centreon-plugins-20220113/cloud/azure/database/sqlmanagedinstance/plugin.pm000066400000000000000000000036621417000230700267400ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::sqlmanagedinstance::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} = { 'cpu' => 'cloud::azure::database::sqlmanagedinstance::mode::cpu', 'discovery' => 'cloud::azure::database::sqlmanagedinstance::mode::discovery', 'health' => 'cloud::azure::database::sqlmanagedinstance::mode::health', 'storage' => 'cloud::azure::database::sqlmanagedinstance::mode::storage', 'diskio' => 'cloud::azure::database::sqlmanagedinstance::mode::diskio' }; $self->{custom_modes}->{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}->{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' } }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure SQL Managed Instance. =cut centreon-plugins-20220113/cloud/azure/database/sqlserver/000077500000000000000000000000001417000230700232625ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/database/sqlserver/mode/000077500000000000000000000000001417000230700242065ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/database/sqlserver/mode/discovery.pm000066400000000000000000000024761417000230700265640ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::sqlserver::mode::discovery; use base qw(cloud::azure::management::monitor::mode::discovery); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{namespace} = 'Microsoft.Sql'; $self->{type} = 'servers'; } 1; __END__ =head1 MODE SQL Server discovery. Only works with --api-version=2020-08-01 option. =over 8 =item B<--resource-group> Specify resource group. =item B<--location> Specify location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/database/sqlserver/mode/listservers.pm000066400000000000000000000114531417000230700271350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::sqlserver::mode::listservers; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource-group:s" => { name => 'resource_group' }, "location:s" => { name => 'location' }, "filter-name:s" => { name => 'filter_name' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{servers} = $options{custom}->azure_list_sqlservers( resource_group => $self->{option_results}->{resource_group} ); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $server (@{$self->{servers}}) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $server->{name} !~ /$self->{option_results}->{filter_name}/); next if (defined($self->{option_results}->{location}) && $self->{option_results}->{location} ne '' && $server->{location} !~ /$self->{option_results}->{location}/); my $resource_group = '-'; $resource_group = $server->{resourceGroup} if (defined($server->{resourceGroup})); $resource_group = $1 if ($resource_group eq '-' && defined($server->{id}) && $server->{id} =~ /resourceGroups\/(.*)\/providers/); my @tags; foreach my $tag (keys %{$server->{tags}}) { push @tags, $tag . ':' . $server->{tags}->{$tag}; } $self->{output}->output_add(long_msg => sprintf("[name = %s][fqdn = %s][version = %s][resourcegroup = %s][location = %s][id = %s][tags = %s]", $server->{name}, ($server->{fullyQualifiedDomainName}) ? $server->{fullyQualifiedDomainName} : $server->{properties}->{fullyQualifiedDomainName}, ($server->{version}) ? $server->{version} : $server->{properties}->{version}, $resource_group, $server->{location}, $server->{id}, join(',', @tags), )); } $self->{output}->output_add(severity => 'OK', short_msg => 'List SQL 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', 'fqdn', 'version', 'resourcegroup', 'location', 'id', 'tags']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $server (@{$self->{servers}}) { my $resource_group = '-'; $resource_group = $server->{resourceGroup} if (defined($server->{resourceGroup})); $resource_group = $1 if ($resource_group eq '-' && defined($server->{id}) && $server->{id} =~ /resourceGroups\/(.*)\/providers/); my @tags; foreach my $tag (keys %{$server->{tags}}) { push @tags, $tag . ':' . $server->{tags}->{$tag}; } $self->{output}->add_disco_entry( name => $server->{name}, fqdn => ($server->{fullyQualifiedDomainName}) ? $server->{fullyQualifiedDomainName} : $server->{properties}->{fullyQualifiedDomainName}, version => ($server->{version}) ? $server->{version} : $server->{properties}->{version}, resourcegroup => $resource_group, location => $server->{location}, id => $server->{id}, tags => join(',', @tags), ); } } 1; __END__ =head1 MODE List SQL servers. =over 8 =item B<--resource-group> Set resource group. =item B<--location> Set resource location. =item B<--filter-name> Filter resource name (Can be a regexp). =back =cut centreon-plugins-20220113/cloud/azure/database/sqlserver/mode/serverstatus.pm000066400000000000000000000103571417000230700273240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::sqlserver::mode::serverstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("State '%s' [FQDN: %s]", $self->{result_values}->{state}, $self->{result_values}->{fqdn}); return $msg; } sub prefix_server_output { my ($self, %options) = @_; return "Server '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'servers', type => 1, cb_prefix_output => 'prefix_server_output', message_multiple => 'All servers are ok' }, ]; $self->{maps_counters}->{servers} = [ { label => 'status', type => 2, critical_default => '%{state} ne "Ready"', set => { key_values => [ { name => 'state' }, { name => 'fqdn' }, { name => 'display' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng, } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource-group:s" => { name => 'resource_group' }, "location:s" => { name => 'location' }, "filter-name:s" => { name => 'filter_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{servers} = {}; my $servers = $options{custom}->azure_list_sqlservers(resource_group => $self->{option_results}->{resource_group}); foreach my $server (@{$servers}) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $server->{name} !~ /$self->{option_results}->{filter_name}/); next if (defined($self->{option_results}->{location}) && $self->{option_results}->{location} ne '' && $server->{location} !~ /$self->{option_results}->{location}/); $self->{servers}->{$server->{id}} = { display => $server->{name}, state => ($server->{state}) ? $server->{state} : $server->{properties}->{state}, fqdn => ($server->{fullyQualifiedDomainName}) ? $server->{fullyQualifiedDomainName} : $server->{properties}->{fullyQualifiedDomainName}, }; } if (scalar(keys %{$self->{servers}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No SQL servers found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check SQL servers status. Example: perl centreon_plugins.pl --plugin=cloud::azure::database::sqlserver::plugin --custommode=azcli --mode=server-status --resource-group='MYRESOURCEGROUP' --verbose =over 8 =item B<--resource-group> Set resource group. =item B<--location> Set resource location. =item B<--filter-name> Filter server name (Can be a regexp). =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{state}, %{fqdn}, %{display} =item B<--critical-status> Set critical threshold for status (Default: '%{state} ne "Ready"'). Can used special variables like: %{state}, %{fqdn}, %{display} =back =cutcentreon-plugins-20220113/cloud/azure/database/sqlserver/plugin.pm000066400000000000000000000034071417000230700251220ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::database::sqlserver::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} } = ( 'discovery' => 'cloud::azure::database::sqlserver::mode::discovery', 'server-status' => 'cloud::azure::database::sqlserver::mode::serverstatus', 'list-servers' => 'cloud::azure::database::sqlserver::mode::listservers' ); $self->{custom_modes}->{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}->{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2020-08-01-preview' }, }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure SQL Server. =cut centreon-plugins-20220113/cloud/azure/devtools/000077500000000000000000000000001417000230700213275ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/devtools/appconfiguration/000077500000000000000000000000001417000230700246775ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/devtools/appconfiguration/mode/000077500000000000000000000000001417000230700256235ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/devtools/appconfiguration/mode/discovery.pm000066400000000000000000000024671417000230700302010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::devtools::appconfiguration::mode::discovery; use base qw(cloud::azure::management::monitor::mode::discovery); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{namespace} = 'Microsoft.AppConfiguration'; $self->{type} = 'configurationStores'; } 1; __END__ =head1 MODE Azure App Configuration discovery. =over 8 =item B<--resource-group> Specify resource group. =item B<--location> Specify location. =item B<--prettify> Prettify JSON output. =back =cutcentreon-plugins-20220113/cloud/azure/devtools/appconfiguration/mode/httprequests.pm000066400000000000000000000125221417000230700307360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::devtools::appconfiguration::mode::httprequests; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'httpincomingrequestcount' => { 'output' => 'Incoming HTTP requests', 'label' => 'http-requests', 'nlabel' => 'appconfiguration.http.incoming.requests.count', 'unit' => '', 'min' => '0' }, 'httpincomingrequestduration' => { 'output' => 'Incoming HTTP requests duration', 'label' => 'http-requests-duration', 'nlabel' => 'appconfiguration.http.incoming.requests.milliseconds', 'unit' => 'ms', 'min' => '0' }, 'throttledhttprequestcount' => { 'output' => 'Throttled Incoming HTTP requests', 'label' => 'http-throttled-requests', 'nlabel' => 'appconfiguration.http.throttled.incoming.requests.count', 'unit' => '', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.AppConfiguration\/configurationStores\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'configurationStores'; $self->{az_resource_namespace} = 'Microsoft.AppConfiguration'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Count']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure App Configuration HTTP requests. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::devtools::appconfiguration::plugin --mode=http-requests --custommode=api --resource= --resource-group= --aggregation='count' --warning-http-requests='1000' --critical-http-requests='2000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::devtools::appconfiguration::plugin --mode=http-requests --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.AppConfiguration/configurationStores/' --aggregation='count' --warning-http-requests='1000' --critical-http-requests='2000' Default aggregation: 'count' / 'total', 'average', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'http-requests', 'http-requests-duration', 'http-throttled-requests'. =item B<--critical-*> Critical threshold where '*' can be: 'http-requests', 'http-requests-duration', 'http-throttled-requests'. =back =cutcentreon-plugins-20220113/cloud/azure/devtools/appconfiguration/plugin.pm000066400000000000000000000033001417000230700265270ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::devtools::appconfiguration::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} = { 'discovery' => 'cloud::azure::devtools::appconfiguration::mode::discovery', 'http-requests' => 'cloud::azure::devtools::appconfiguration::mode::httprequests' }; $self->{custom_modes}->{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}->{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' }, }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure App Configuration. =cutcentreon-plugins-20220113/cloud/azure/integration/000077500000000000000000000000001417000230700220135ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/integration/eventgrid/000077500000000000000000000000001417000230700240025ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/integration/eventgrid/mode/000077500000000000000000000000001417000230700247265ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/integration/eventgrid/mode/discovery.pm000066400000000000000000000077731417000230700273110ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::integration::eventgrid::mode::discovery; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'namespace:s' => { name => 'namespace' }, 'type:s' => { name => 'type' }, 'resource-group:s' => { name => 'resource_group' }, 'location:s' => { name => 'location' }, 'prettify' => { name => 'prettify' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); $self->{namespace} = $self->{option_results}->{namespace}; $self->{type} = $self->{option_results}->{type}; $self->{location} = $self->{option_results}->{location}; $self->{resource_group} = $self->{option_results}->{resource_group}; } sub run { my ($self, %options) = @_; my @disco_data; my $disco_stats; $disco_stats->{start_time} = time(); my $resources = $options{custom}->azure_list_resources( namespace => $self->{namespace}, resource_type => $self->{type}, location => $self->{location}, resource_group => $self->{resource_group} ); $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; foreach my $resource (@{$resources}) { next if ($resource->{type} !~ /Microsoft\.EventGrid/); $resource->{type} =~ s/Microsoft\.EventGrid\///; my $resource_group = ''; $resource_group = $resource->{resourceGroup} if (defined($resource->{resourceGroup})); $resource_group = $1 if ($resource_group eq '' && defined($resource->{id}) && $resource->{id} =~ /resourceGroups\/(.*)\/providers/); $resource->{resourceGroup} = $resource_group; foreach my $entry (keys %{$resource}) { next if (ref($resource->{$entry}) ne "HASH"); my @array; foreach my $key (keys %{$resource->{$entry}}) { push @array, { key => $key, value => $resource->{$entry}->{$key} }; } $resource->{$entry} = \@array; } push @disco_data, $resource; } $disco_stats->{discovered_items} = @disco_data; $disco_stats->{results} = \@disco_data; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE Resources discovery. =over 8 =item B<--namespace> Specify resources namespace. =item B<--type> Specify resources type. =item B<--resource-group> Specify resources resource group. =item B<--location> Specify resources location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/integration/eventgrid/mode/events.pm000066400000000000000000000155631417000230700266020ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::integration::eventgrid::mode::events; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'deadletteredcount' => { 'output' => 'Dead Lettered Events', 'label' => 'deadlettered-events', 'nlabel' => 'eventgrid.deadlettered.events.count', 'unit' => '', 'min' => '0' }, 'droppedeventcount' => { 'output' => 'Dropped Events', 'label' => 'dropped-events', 'nlabel' => 'eventgrid.dropped.events.count', 'unit' => '', 'min' => '0' }, 'matchedeventcount' => { 'output' => 'Matched Events', 'label' => 'matched-events', 'nlabel' => 'eventgrid.matched.events.count', 'unit' => '', 'min' => '0' }, 'unmatchedeventcount' => { 'output' => 'Unmatched Events', 'label' => 'unmatched-events', 'nlabel' => 'eventgrid.unmatched.events.count', 'unit' => '', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' }, 'resource-type:s' => { name => 'resource_type', default => 'topics' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{resource_type}) || $self->{option_results}->{resource_type} !~ /topics|systemTopics|partnerTopic|partnerNamespaces|extensionTopics|eventSubscriptions|domains/) { $self->{output}->add_option_msg(short_msg => 'Please specify an existing Azure Event Grid resource type'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; my $resource_type = $self->{option_results}->{resource_type}; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.EventGrid\/(.*)\/(.*)$/) { $resource_group = $1; $resource_type = $2; $resource = $3; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = $resource_type; $self->{az_resource_namespace} = 'Microsoft.EventGrid'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } my $type; if ($resource_type =~ /topics|systemTopics|partnerTopic|partnerNamespaces/) { $type = 'topics'; } elsif ($resource_type eq 'extensionTopics') { $type = 'extensionTopics'; } else { $type = 'eventSubscriptions'; } my $resource_mapping = { 'topics' => [ 'deadletteredcount', 'droppedeventcount', 'matchedeventcount', 'unmatchedeventcount' ], 'extensionTopics' => [ 'unmatchedeventcount' ], 'eventSubscriptions' => [ 'deadletteredcount', 'droppedeventcount', 'matchedeventcount' ] }; my $metrics_mapping_transformed; foreach my $metric_type (@{$resource_mapping->{$type}}) { $metrics_mapping_transformed->{$metric_type} = $self->{metrics_mapping}->{$metric_type}; } foreach my $metric (keys %{$metrics_mapping_transformed}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Event Grid events. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::integration::eventgrid::plugin --mode=events --custommode=api --resource= --resource-group= --aggregation='average' --warning-matched-events='20' --critical-matched-events='50' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::integration::eventgrid::plugin --mode=events --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.EventGrid//' --aggregation='average' --warning-matched-events='20' --critical-matched-events='50' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--resource-type> Set resource type (Default: 'topics'). Can be 'topics', 'systemTopics', 'partnerTopics', 'partnerNamespaces', 'extensionTopics', 'extensionTopics', 'domains'). =item B<--warning-*> Warning threshold where '*' can be: 'matched-events', 'deadlettered-events', 'unmatched-events', 'dropped-events'. =item B<--critical-vault-capacity-percentage> Critical threshold where '*' can be: 'matched-events', 'deadlettered-events', 'unmatched-events', 'dropped-events'. =back =cut centreon-plugins-20220113/cloud/azure/integration/eventgrid/mode/eventstats.pm000066400000000000000000000201041417000230700274610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::integration::eventgrid::mode::eventstats; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'deliveryattemptfailcount' => { 'output' => 'Delivery Failed Events', 'label' => 'delivery-failed', 'nlabel' => 'eventgrid.delivery.failed.count', 'unit' => '', 'min' => '0' }, 'deliverysuccesscount' => { 'output' => 'Delivered Events', 'label' => 'delivery-successful', 'nlabel' => 'eventgrid.delivery.successfull.count', 'unit' => '', 'min' => '0' }, 'destinationprocessingdurationinms' => { 'output' => 'Destination Processing Duration', 'label' => 'processing-duration', 'nlabel' => 'eventgrid.processing.duration.milliseconds', 'unit' => 'ms', 'min' => '0' }, 'publishfailcount' => { 'output' => 'Publish Failed Events', 'label' => 'publish-failed', 'nlabel' => 'eventgrid.publish.failed.count', 'unit' => '', 'min' => '0' }, 'publishsuccesscount' => { 'output' => 'Published Events', 'label' => 'publish-successful', 'nlabel' => 'eventgrid.publish.successfull.count', 'unit' => '', 'min' => '0' }, 'publishsuccesslatencyinms' => { 'output' => 'Publish Success Latency', 'label' => 'publish-latency', 'nlabel' => 'eventgrid.public.success.latency.milliseconds', 'unit' => 'ms', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' }, 'resource-type:s' => { name => 'resource_type', default => 'topics' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{resource_type}) || $self->{option_results}->{resource_type} !~ /topics|systemTopics|partnerTopic|partnerNamespaces|extensionTopics|eventSubscriptions|domains/) { $self->{output}->add_option_msg(short_msg => 'Please specify an existing Azure Event Grid resource type'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; my $resource_type = $self->{option_results}->{resource_type}; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.EventGrid\/(.*)\/(.*)$/) { $resource_group = $1; $resource_type = $2; $resource = $3; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = $resource_type; $self->{az_resource_namespace} = 'Microsoft.EventGrid'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } my $type; if ($resource_type =~ /topics|systemTopics|partnerNamespaces|domains/) { $type = 'topics'; } elsif ($resource_type eq 'partnerTopics') { $type = 'partnerTopics'; } elsif ($resource_type eq 'extensionTopics') { $type = 'extensionTopics'; } else { $type = 'eventSubscriptions'; } my $resource_mapping = { 'topics' => [ 'deliveryattemptfailcount', 'deliverysuccesscount', 'destinationprocessingdurationinms', 'publishfailcount', 'publishsuccesscount', 'publishsuccesslatencyinms' ], 'partnerTopics' => [ 'deliveryattemptfailcount', 'deliverysuccesscount', 'destinationprocessingdurationinms', 'publishfailcount', 'publishsuccesscount' ], 'extensionTopics' => [ 'publishfailcount', 'publishsuccesscount', 'publishsuccesslatencyinms' ], 'eventSubscriptions' => [ 'deliveryattemptfailcount', 'deliverysuccesscount', 'destinationprocessingdurationinms' ] }; my $metrics_mapping_transformed; foreach my $metric_type (@{$resource_mapping->{$type}}) { $metrics_mapping_transformed->{$metric_type} = $self->{metrics_mapping}->{$metric_type}; } foreach my $metric (keys %{$metrics_mapping_transformed}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Event Grid delivery and publish events statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::integration::eventgrid::plugin --mode=events-stats --custommode=api --resource= --resource-group= --aggregation='average' --warning-publish-failed='20' --critical-publish-failed='50' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::integration::eventgrid::plugin --mode=events-stats --custommode=api --resource='resource='/subscriptions//resourceGroups//providers/Microsoft.EventGrid//'' --aggregation='average' --warning-publish-failed='20' --critical-publish-failed='50' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--resource-type> Set resource type (Default: 'topics'). Can be 'topics', 'systemTopics', 'partnerTopics', 'partnerNamespaces', 'extensionTopics', 'extensionTopics', 'domains'). =item B<--warning-*> Warning threshold where '*' can be: 'publish-failed', 'publish-latency', 'delivery-successful', 'publish-successful', 'delivery-failed', 'processing-duration'. =item B<--critical-*> Critical threshold where '*' can be: 'publish-failed', 'publish-latency', 'delivery-successful', 'publish-successful', 'delivery-failed', 'processing-duration'. =back =cut centreon-plugins-20220113/cloud/azure/integration/eventgrid/mode/health.pm000066400000000000000000000036631417000230700265410ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::integration::eventgrid::mode::health; use base qw(cloud::azure::management::monitor::mode::health); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{az_resource_namespace} = 'Microsoft.EventGrid'; $self->{az_resource_type} = 'namespaces'; } 1; __END__ =head1 MODE Check Event Grid namespace status. (Useful to determine host status) =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{summary} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /^Unavailable$/'). Can used special variables like: %{status}, %{summary} =item B<--unknown-status> Set unknown threshold for status (Default: '%{status} =~ /^Unknown$/'). Can used special variables like: %{status}, %{summary} =item B<--ok-status> Set ok threshold for status (Default: '%{status} =~ /^Available$/'). Can used special variables like: %{status}, %{summary} =back =cut centreon-plugins-20220113/cloud/azure/integration/eventgrid/plugin.pm000066400000000000000000000035041417000230700256400ustar00rootroot00000000000000# # Copyright 2020 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::azure::integration::eventgrid::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} = { 'discovery' => 'cloud::azure::integration::eventgrid::mode::discovery', 'events' => 'cloud::azure::integration::eventgrid::mode::events', 'events-stats' => 'cloud::azure::integration::eventgrid::mode::eventstats', 'health' => 'cloud::azure::integration::eventgrid::mode::health' }; $self->{custom_modes}->{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}->{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' }, }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure Event Grid. =cut centreon-plugins-20220113/cloud/azure/integration/servicebus/000077500000000000000000000000001417000230700241655ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/integration/servicebus/mode/000077500000000000000000000000001417000230700251115ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/integration/servicebus/mode/connections.pm000066400000000000000000000123701417000230700277740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::integration::servicebus::mode::connections; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'activeconnections' => { 'output' => 'Active Connections', 'label' => 'active-connections', 'nlabel' => 'servicebus.namespace.connections.active.count', 'unit' => '', 'min' => '0' }, 'connectionsclosed' => { 'output' => 'Connections Closed', 'label' => 'closed-connections', 'nlabel' => 'servicebus.namespace.connections.closed.count', 'unit' => '', 'min' => '0' }, 'connectionsopened' => { 'output' => 'Connections Opened', 'label' => 'opened-connections', 'nlabel' => 'servicebus.namespace.connections.opened.count', 'unit' => '', 'min' => '0' }, }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.ServiceBus\/namespaces\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'namespaces'; $self->{az_resource_namespace} = 'Microsoft.ServiceBus'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Service Bus connections statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::integration::servicebus::plugin --mode=connections --custommode=api --resource= --resource-group= --aggregation='average' --warning-servicebus-active-connections='1000' --critical-servicebus-active-connections='2000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::integration::servicebus::plugin --mode=connections --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.ServiceBus/namespaces/' --aggregation='average' --warning-servicebus-active-connections='1000' --critical-servicebus-active-connections='2000' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'closed-connection', 'active-connections', 'opened-connections'. =item B<--critical-*> Critical threshold where '*' can be: 'closed-connection', 'active-connections', 'opened-connections'. =back =cut centreon-plugins-20220113/cloud/azure/integration/servicebus/mode/discovery.pm000066400000000000000000000024531417000230700274620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::integration::servicebus::mode::discovery; use base qw(cloud::azure::management::monitor::mode::discovery); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{namespace} = 'Microsoft.ServiceBus'; $self->{type} = 'namespaces'; } 1; __END__ =head1 MODE Azure Service Bus namespaces discovery. =over 8 =item B<--resource-group> Specify resource group. =item B<--location> Specify location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/integration/servicebus/mode/health.pm000066400000000000000000000036671417000230700267300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::integration::servicebus::mode::health; use base qw(cloud::azure::management::monitor::mode::health); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{az_resource_namespace} = 'Microsoft.ServiceBus'; $self->{az_resource_type} = 'namespaces'; } 1; __END__ =head1 MODE Check Service Bus namespace status. (Usefull to determine host status) =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{summary} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /^Unavailable$/'). Can used special variables like: %{status}, %{summary} =item B<--unknown-status> Set unknown threshold for status (Default: '%{status} =~ /^Unknown$/'). Can used special variables like: %{status}, %{summary} =item B<--ok-status> Set ok threshold for status (Default: '%{status} =~ /^Available$/'). Can used special variables like: %{status}, %{summary} =back =cut centreon-plugins-20220113/cloud/azure/integration/servicebus/mode/messages.pm000066400000000000000000000142561417000230700272660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::integration::servicebus::mode::messages; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'activemessages' => { 'output' => 'Count of active messages in a Queue/Topic', 'label' => 'active-messages', 'nlabel' => 'servicebus.namespace.messages.active.count', 'unit' => '', 'min' => '0' }, 'deadletteredmessages' => { 'output' => 'Count of dead-lettered messages in a Queue/Topic', 'label' => 'deadlettered-messages', 'nlabel' => 'servicebus.namespace.messages.deadlettered.count', 'unit' => '', 'min' => '0' }, 'incomingmessages' => { 'output' => 'Incoming Messages', 'label' => 'incoming-messages', 'nlabel' => 'servicebus.namespace.messages.incoming.count', 'unit' => '', 'min' => '0' }, 'messages' => { 'output' => 'Total messages', 'label' => 'total-messages', 'nlabel' => 'servicebus.namespace.messages.total.count', 'unit' => '', 'min' => '0' }, 'outgoingmessages' => { 'output' => 'Outgoing Messages', 'label' => 'outgoing-messages', 'nlabel' => 'servicebus.namespace.messages.outgoing.count', 'unit' => '', 'min' => '0' }, 'scheduledmessages' => { 'output' => 'Count of scheduled messages in a Queue/Topic.', 'label' => 'scheduled-messages', 'nlabel' => 'servicebus.namespace.messages.scheduled.count', 'unit' => '', 'min' => '0' }, }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.ServiceBus\/namespaces\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'namespaces'; $self->{az_resource_namespace} = 'Microsoft.ServiceBus'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Service Bus messages metrics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::integration::servicebus::plugin --mode=messages --custommode=api --resource= --resource-group= --aggregation='average' --warning-servicebus-active-messages='1000' --critical-servicebus-active-messages='2000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::integration::servicebus::plugin --mode=messages --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.ServiceBus/namespaces/' --aggregation='average' --warning-servicebus-active-messages='1000' --critical-servicebus-active-messages='2000' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'active-messages', 'deadlettered-messages', 'total-messages', 'incoming-messages', 'outgoing-messages', 'scheduled-messages'. =item B<--critical-*> Critical threshold where '*' can be: 'active-messages', 'deadlettered-messages', 'total-messages', 'incoming-messages', 'outgoing-messages', 'scheduled-messages'. =back =cut centreon-plugins-20220113/cloud/azure/integration/servicebus/mode/namespaces.pm000066400000000000000000000117331417000230700275730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::integration::servicebus::mode::namespaces; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'namespacecpuusage' => { 'output' => 'CPU', 'label' => 'cpu-usage-percentage', 'nlabel' => 'servicebus.namespace.cpu.usage.percentage', 'unit' => '%', 'min' => '0', 'max' => '100' }, 'namespacememoryusage' => { 'output' => 'Memory Usage', 'label' => 'memory-usage-percentage', 'nlabel' => 'servicebus.namespace.memory.usage.percentage', 'unit' => '%', 'min' => '0', 'max' => '100' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.ServiceBus\/namespaces\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'namespaces'; $self->{az_resource_namespace} = 'Microsoft.ServiceBus'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Maximum']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Service Bus namespace resources statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::integration::servicebus::plugin --mode=namespaces --custommode=api --resource= --resource-group= --aggregation='average' --warning-cpu-usage-percentage='80' --critical-cpu-usage-percentage='90' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::integration::servicebus::plugin --mode=namespaces --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.ServiceBus/namespaces/' --aggregation='average' --warning-cpu-usage-percentage='80' --critical-cpu-usage-percentage='90' Default aggregation: 'maximum' / 'total', 'minimum' and 'average' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'cpu-usage-percentage', 'memory-usage-percentage'. =item B<--critical-*> Critical threshold where '*' can be: 'cpu-usage-percentage', 'memory-usage-percentage'. =back =cut centreon-plugins-20220113/cloud/azure/integration/servicebus/mode/requests.pm000066400000000000000000000122731417000230700273270ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::integration::servicebus::mode::requests; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'incomingrequests' => { 'output' => 'Incoming Requests', 'label' => 'incoming-requests', 'nlabel' => 'servicebus.namespace.requests.incoming.count', 'unit' => '', 'min' => '0' }, 'successfulrequests' => { 'output' => 'Successful Requests', 'label' => 'successful-requests', 'nlabel' => 'servicebus.namespace.requests.successful.count', 'unit' => '', 'min' => '0' }, 'throttledrequests' => { 'output' => 'Throttled Requests', 'label' => 'throttled-requests', 'nlabel' => 'servicebus.namespace.requests.throttled.count', 'unit' => '', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.ServiceBus\/namespaces\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'namespaces'; $self->{az_resource_namespace} = 'Microsoft.ServiceBus'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Service Bus requests statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::integration::servicebus::plugin --mode=requests --custommode=api --resource= --resource-group= --aggregation='average' --warning-throttled-requests='300' --critical-throttled-requests='400' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::integration::servicebus::plugin --mode=requests --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.ServiceBus/namespaces/' --aggregation='average' --warning-throttled-requests='300' --critical-throttled-requests='400' Default aggregation: 'total' / 'minimum', 'maximum' and 'average' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'incoming-requests', 'throttled-requests', 'successful-requests'. =item B<--critical-*> Critical threshold where '*' can be: 'incoming-requests', 'throttled-requests', 'successful-requests'. =back =cut centreon-plugins-20220113/cloud/azure/integration/servicebus/plugin.pm000066400000000000000000000040001417000230700260130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::integration::servicebus::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} = { 'connections' => 'cloud::azure::integration::servicebus::mode::connections', 'discovery' => 'cloud::azure::integration::servicebus::mode::discovery', 'health' => 'cloud::azure::integration::servicebus::mode::health', 'messages' => 'cloud::azure::integration::servicebus::mode::messages', 'namespaces' => 'cloud::azure::integration::servicebus::mode::namespaces', 'requests' => 'cloud::azure::integration::servicebus::mode::requests' }; $self->{custom_modes}->{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}->{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' }, }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure Service Bus namespaces. =cut centreon-plugins-20220113/cloud/azure/management/000077500000000000000000000000001417000230700216045ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/management/apimanagement/000077500000000000000000000000001417000230700244125ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/management/apimanagement/mode/000077500000000000000000000000001417000230700253365ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/management/apimanagement/mode/capacity.pm000066400000000000000000000111241417000230700274700ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::apimanagement::mode::capacity; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'capacity' => { 'output' => 'Capacity', 'label' => 'capacity-percentage', 'nlabel' => 'apimanagement.capacity.percentage', 'unit' => '%', 'min' => '0', 'max' => '100', }, }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.ApiManagement\/service\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'service'; $self->{az_resource_namespace} = 'Microsoft.ApiManagement'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure API Management capacity statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::management::apimanagement::plugin --mode=capacity --custommode=api --resource= --resource-group= --aggregation='average' --warning-capacity-percentage='80' --critical-capacity-percentage='90' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::management::apimanagement::plugin --mode=capacity --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.ApiManagement/service/' --aggregation='average' --warning-capacity-percentage='80' --critical-capacity-percentage='90' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-capacity-percentage> Set warning threshold for capacity. =item B<--critical-capacity-percentage> Set critical threshold for capacity. =back =cut centreon-plugins-20220113/cloud/azure/management/apimanagement/mode/discovery.pm000066400000000000000000000024551417000230700277110ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::apimanagement::mode::discovery; use base qw(cloud::azure::management::monitor::mode::discovery); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{namespace} = 'Microsoft.ApiManagement'; $self->{type} = 'service'; } 1; __END__ =head1 MODE Azure API Management service discovery. =over 8 =item B<--resource-group> Specify resource group. =item B<--location> Specify location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/management/apimanagement/mode/duration.pm000066400000000000000000000117041417000230700275240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::apimanagement::mode::duration; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'backendduration' => { 'output' => 'Duration of Backend Requests', 'label' => 'requests-backend-duration', 'nlabel' => 'apimanagement.requests.backend.duration.milliseconds', 'unit' => 'ms', 'min' => '0' }, 'duration' => { 'output' => 'Overall Duration of Gateway Requests', 'label' => 'requests-duration', 'nlabel' => 'apimanagement.requests.duration.milliseconds', 'unit' => 'ms', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.ApiManagement\/service\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'service'; $self->{az_resource_namespace} = 'Microsoft.ApiManagement'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure API Management requests duration statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::management::apimanagement::plugin --mode=duration --custommode=api --resource= --resource-group= --aggregation='average' --warning-requests-duration='1000' --critical-requests-duration='2000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::management::apimanagement::plugin --mode=requests --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.ApiManagement/service/' --aggregation='average' --warning-requests-duration='1000' --critical-requests-duration='2000' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: ''requests-backend-duration', 'requests-duration'. =item B<--critical-*> Critical threshold where '*' can be: 'requests-backend-duration', 'requests-duration'. =back =cut centreon-plugins-20220113/cloud/azure/management/apimanagement/mode/events.pm000066400000000000000000000151361417000230700272060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::apimanagement::mode::events; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'eventhubdroppedevents' => { 'output' => 'Dropped EventHub Events', 'label' => 'dropped-events', 'nlabel' => 'apimanagement.events.dropped.count', 'unit' => '', 'min' => '0' }, 'eventhubrejectedevents' => { 'output' => 'Rejected EventHub Events', 'label' => 'rejected-events', 'nlabel' => 'apimanagement.events.rejected.count', 'unit' => '', 'min' => '0' }, 'eventhubsuccessfulevents' => { 'output' => 'Successful EventHub Events', 'label' => 'successful-events', 'nlabel' => 'apimanagement.events.successful.count', 'unit' => '', 'min' => '0' }, 'eventhubthrottledevents' => { 'output' => 'Throttled EventHub Events', 'label' => 'throttled-events', 'nlabel' => 'apimanagement.events.throttled.count', 'unit' => '', 'min' => '0' }, 'eventhubtimedoutevents' => { 'output' => 'Timed Out EventHub Events', 'label' => 'timedout-events', 'nlabel' => 'apimanagement.events.timedout.count', 'unit' => '', 'min' => '0' }, 'eventhubtotalbytessent' => { 'output' => 'Size of EventHub Events', 'label' => 'events-usage', 'nlabel' => 'apimanagement.events.total.usage.bytes', 'unit' => 'B', 'min' => '0' }, 'eventhubtotalevents' => { 'output' => 'Total EventHub Events', 'label' => 'total-events', 'nlabel' => 'apimanagement.events.total.count', 'unit' => '', 'min' => '0' }, 'eventhubtotalfailedevents' => { 'output' => 'Failed EventHub Events', 'label' => 'failed-events', 'nlabel' => 'apimanagement.events.failed.count', 'unit' => '', 'min' => '0' }, }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.ApiManagement\/service\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'service'; $self->{az_resource_namespace} = 'Microsoft.ApiManagement'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure API Management events statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::management::apimanagement::plugin --mode=events --custommode=api --resource= --resource-group= --aggregation='average' --warning-total-events='1000' --critical-total-events='2000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::management::apimanagement::plugin --mode=events --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.ApiManagement/service/' --aggregation='average' --warning-total-events='1000' --critical-total-events='2000' Default aggregation: 'total' / 'average', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'dropped-events', 'rejected-events', 'successful-events', 'throttled-events', 'timedout-events', 'events-usage', 'failed-events', 'total-events'. =item B<--critical-*> Critical threshold where '*' can be: 'dropped-events', 'rejected-events', 'successful-events', 'throttled-events', 'timedout-events', 'events-usage', 'failed-events', 'total-events'. =back =cut centreon-plugins-20220113/cloud/azure/management/apimanagement/mode/requests.pm000066400000000000000000000107771417000230700275630ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::apimanagement::mode::requests; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'requests' => { 'output' => 'Requests', 'label' => 'requests', 'nlabel' => 'apimanagement.requests.count', 'unit' => '', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.ApiManagement\/service\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'service'; $self->{az_resource_namespace} = 'Microsoft.ApiManagement'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure API Management requests statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::management::apimanagement::plugin --mode=requests --custommode=api --resource= --resource-group= --aggregation='average' --warning-requests='1000' --critical-requests='2000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::management::apimanagement::plugin --mode=requests --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.ApiManagement/service/' --aggregation='average' --warning-requests='1000' --critical-requests='2000' Default aggregation: 'total' / 'average', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-requests> Warning threshold for the number of requests. =item B<--critical-requests> Critical threshold for the number of requests. =back =cut centreon-plugins-20220113/cloud/azure/management/apimanagement/plugin.pm000066400000000000000000000036551417000230700262570ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::apimanagement::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} = { 'events' => 'cloud::azure::management::apimanagement::mode::events', 'capacity' => 'cloud::azure::management::apimanagement::mode::capacity', 'discovery' => 'cloud::azure::management::apimanagement::mode::discovery', 'requests' => 'cloud::azure::management::apimanagement::mode::requests', 'duration' => 'cloud::azure::management::apimanagement::mode::duration' }; $self->{custom_modes}->{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}->{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' }, }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure API Management service. =cut centreon-plugins-20220113/cloud/azure/management/applicationinsights/000077500000000000000000000000001417000230700256605ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/management/applicationinsights/mode/000077500000000000000000000000001417000230700266045ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/management/applicationinsights/mode/availability.pm000066400000000000000000000124101417000230700316120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::applicationinsights::mode::availability; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'availabilityresults/availabilitypercentage' => { 'output' => 'Availability', 'label' => 'availability', 'nlabel' => 'appinsights.availability.percentage', 'unit' => '%', 'min' => '0', 'max' => '100' }, 'availabilityresults/count' => { 'output' => 'Availability tests', 'label' => 'tests-count', 'nlabel' => 'appinsights.availability.tests.count', 'unit' => '', 'min' => '0', 'max' => '' }, 'availabilityresults/duration' => { 'output' => 'Availability test duration', 'label' => 'tests-duration', 'nlabel' => 'appinsights.availability.tests.duration.milliseconds', 'unit' => 'ms', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Insights\/components\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'Components'; $self->{az_resource_namespace} = 'Microsoft.Insights'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Application Insights availability status. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::management::applicationinsights::plugin --mode=availability --custommode=api --resource= --resource-group= --aggregation='average' --warning-availability='80:' --critical-availability='90:' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::integration::servicebus::plugin --mode=availability --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Insights/Components/' --aggregation='average' --warning-availability='80:' --critical-availability='90:' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'availability', 'tests-count', 'tests-duration'. =item B<--critical-*> Critical threshold where '*' can be: 'availability', 'tests-count', 'tests-duration'. =back =cut centreon-plugins-20220113/cloud/azure/management/applicationinsights/mode/browsertimings.pm000066400000000000000000000137431417000230700322300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::applicationinsights::mode::browsertimings; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'browsertimings/networkduration' => { 'output' => 'Page load network connect time', 'label' => 'network-duration', 'nlabel' => 'appinsights.processing.duration.milliseconds', 'unit' => 'ms', 'min' => '0', 'max' => '' }, 'browsertimings/processingduration' => { 'output' => 'Client processing time', 'label' => 'processing-duration', 'nlabel' => 'appinsights.processing.duration.milliseconds', 'unit' => 'ms', 'min' => '0', 'max' => '' }, 'browsertimings/receiveduration' => { 'output' => 'Receiving response time', 'label' => 'receive-duration', 'nlabel' => 'appinsights.receive.duration.milliseconds', 'unit' => 'ms', 'min' => '0', 'max' => '' }, 'browsertimings/sendduration' => { 'output' => 'Send request time', 'label' => 'send-duration', 'nlabel' => 'appinsights.send.duration.milliseconds', 'unit' => 'ms', 'min' => '0', 'max' => '' }, 'browsertimings/totalduration' => { 'output' => 'Browser page load time', 'label' => 'total-duration', 'nlabel' => 'appinsights.total.duration.milliseconds', 'unit' => 'ms', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Insights\/components\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'Components'; $self->{az_resource_namespace} = 'Microsoft.Insights'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Application Insights browser timings. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::management::applicationinsights::plugin --mode=browser-timings --custommode=api --resource= --resource-group= --aggregation='average' --warning-total-duration='1' --critical-total-duration='2' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::integration::servicebus::plugin --mode=browser-timings --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Insights/Components/' --aggregation='average' --warning-total-duration='1' --critical-total-duration='2' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'network-duration', 'processing-duration', 'receive-duration', 'send-duration', 'total-duration'. =item B<--critical-*> Critical threshold where '*' can be: 'network-duration', 'processing-duration', 'receive-duration', 'send-duration', 'total-duration'. =back =cut centreon-plugins-20220113/cloud/azure/management/applicationinsights/mode/cpu.pm000066400000000000000000000117721417000230700277410ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::applicationinsights::mode::cpu; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'performancecounters/processcpupercentage' => { 'output' => 'Process CPU', 'label' => 'w3wp-utilization-percentage', 'nlabel' => 'appinsights.cpu.w3wp.utilization.percentage', 'unit' => '%', 'min' => '0', 'max' => '100' }, 'performancecounters/processorcpupercentage' => { 'output' => 'Processor time', 'label' => 'nonidle-time-percentage', 'nlabel' => 'appinsights.cpu.nonidle.time.percentage', 'unit' => '%', 'min' => '0', 'max' => '100' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Insights\/components\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'Components'; $self->{az_resource_namespace} = 'Microsoft.Insights'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Application Insights CPU utilization. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::management::applicationinsights::plugin --mode=cpu --custommode=api --resource= --resource-group= --aggregation='average' --warning-nonidle-time-percentage='80' --critical-process='90' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::integration::servicebus::plugin --mode=cpu --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Insights/Components/' --aggregation='average' --warning-nonidle-time-percentage='80' --critical-process='90' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'w3wp-utilization-percentage', 'nonidle-time-percentage'. =item B<--critical-*> Critical threshold where '*' can be: 'w3wp-utilization-percentage', 'nonidle-time-percentage'. =back =cut centreon-plugins-20220113/cloud/azure/management/applicationinsights/mode/discovery.pm000066400000000000000000000024771417000230700311630ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::applicationinsights::mode::discovery; use base qw(cloud::azure::management::monitor::mode::discovery); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{namespace} = 'Microsoft.Insights'; $self->{type} = 'Components'; } 1; __END__ =head1 MODE Discover Azure Network Application Gateway resources. =over 8 =item B<--resource-group> Specify resource group. =item B<--location> Specify location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/management/applicationinsights/mode/exceptions.pm000066400000000000000000000124561417000230700313330ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::applicationinsights::mode::exceptions; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'exceptions/browser' => { 'output' => 'Browser exceptions', 'label' => 'browser-exceptions-count', 'nlabel' => 'appinsights.exceptions.browser.count', 'unit' => '', 'min' => '0', 'max' => '' }, 'exceptions/count' => { 'output' => 'Exceptions', 'label' => 'total-exeptions-count', 'nlabel' => 'appinsights.exceptions.total.count', 'unit' => '', 'min' => '0', 'max' => '' }, 'exceptions/server' => { 'output' => 'Server exceptions', 'label' => 'server-exceptions-count', 'nlabel' => 'appinsights.exceptions.server.count', 'unit' => '', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Insights\/components\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'Components'; $self->{az_resource_namespace} = 'Microsoft.Insights'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Application Insights uncaught exceptions. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::management::applicationinsights::plugin --mode=exceptions --custommode=api --resource= --resource-group= --aggregation='total' --warning-total-exeptions-count='800' --critical-total-exeptions-count='900' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::integration::servicebus::plugin --mode=exceptions --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Insights/Components/' --aggregation='total' --warning-total-exeptions-count='800' --critical-total-exeptions-count='900' Default aggregation: 'total' / 'average', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'browser-exceptions-count', 'total-exeptions-count', 'server-exceptions-count'. =item B<--critical-*> Critical threshold where '*' can be: 'browser-exceptions-count', 'total-exeptions-count', 'server-exceptions-count'. =back =cut centreon-plugins-20220113/cloud/azure/management/applicationinsights/mode/externalcalls.pm000066400000000000000000000123401417000230700320030ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::applicationinsights::mode::externalcalls; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'dependencies/count' => { 'output' => 'Dependency calls', 'label' => 'calls-count', 'nlabel' => 'appinsights.calls.count', 'unit' => '', 'min' => '0', 'max' => '' }, 'dependencies/duration' => { 'output' => 'Dependency duration', 'label' => 'calls-duration', 'nlabel' => 'appinsights.calls.duration.milliseconds', 'unit' => 'ms', 'min' => '0', 'max' => '' }, 'dependencies/failed' => { 'output' => 'Dependency call failures', 'label' => 'calls-failure', 'nlabel' => 'appinsights.calls.failure.count', 'unit' => '', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Insights\/components\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'Components'; $self->{az_resource_namespace} = 'Microsoft.Insights'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Application Insights calls made by the application to external resources. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::management::applicationinsights::plugin --mode=externalcalls --custommode=api --resource= --resource-group= --aggregation='total' --warning-calls-count='800' --critical-calls-count='900' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::integration::servicebus::plugin --mode=externalcalls --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Insights/Components/' --aggregation='total' --warning-calls-count='800' --critical-calls-count='900' Default aggregation: 'total' / 'average', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'calls-count', 'calls-duration', 'calls-failure'. =item B<--critical-*> Critical threshold where '*' can be: 'calls-count', 'calls-duration', 'calls-failure'. =back =cut centreon-plugins-20220113/cloud/azure/management/applicationinsights/mode/iooperations.pm000066400000000000000000000113461417000230700316620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::applicationinsights::mode::iooperations; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'performancecounters/processiobytespersecond' => { 'output' => 'Process IO rate', 'label' => 'process-bytes-operations', 'nlabel' => 'appinsights.process.bytes.operations.bytesperseconds', 'unit' => 'B/s', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Insights\/components\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'Components'; $self->{az_resource_namespace} = 'Microsoft.Insights'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Application Insights io-operations status. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::management::applicationinsights::plugin --mode=io-operations --custommode=api --resource= --resource-group= --aggregation='average' --warning-process-bytes-operations='8000' --critical-process-bytes-operations='9000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::integration::servicebus::plugin --mode=io-operations --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Insights/Components/' --aggregation='average' --warning-process-bytes-operations='8000' --critical-process-bytes-operations='9000' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-process-bytes-operations> Bytes operations per second warning threshold. =item B<--critical-process-bytes-operations> Bytes operations per second critical threshold. =back =cut centreon-plugins-20220113/cloud/azure/management/applicationinsights/mode/memory.pm000066400000000000000000000117011417000230700304520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::applicationinsights::mode::memory; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'performancecounters/memoryavailablebytes' => { 'output' => 'Available memory', 'label' => 'memory-available', 'nlabel' => 'appinsights.memory.available.bytes', 'unit' => 'B', 'min' => '0', 'max' => '' }, 'performancecounters/processprivatebytes' => { 'output' => 'Process private bytes', 'label' => 'memory-private', 'nlabel' => 'appinsights.memory.private.bytes', 'unit' => 'B', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Insights\/components\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'Components'; $self->{az_resource_namespace} = 'Microsoft.Insights'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Application Insights memory usage. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::management::applicationinsights::plugin --mode=memory --custommode=api --resource= --resource-group= --aggregation='average' --warning-memory-available='8000' --critical-memory-available='900' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::integration::servicebus::plugin --mode=memory --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Insights/Components/' --aggregation='average' --warning-memory-available='8000' --critical-memory-available='900' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'memory-available', 'memory-private'. =item B<--critical-*> Critical threshold where '*' can be: 'memory-available', 'memory-private'. =back =cut centreon-plugins-20220113/cloud/azure/management/applicationinsights/mode/pageviews.pm000066400000000000000000000115511417000230700311370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::applicationinsights::mode::pageviews; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'pageviews/count' => { 'output' => 'Page views', 'label' => 'views-count', 'nlabel' => 'appinsights.pageviews.total.count', 'unit' => '', 'min' => '0', 'max' => '' }, 'pageviews/duration' => { 'output' => 'Page view load time', 'label' => 'load-time', 'nlabel' => 'appinsights.pageviews.load.milliseconds', 'unit' => 'ms', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Insights\/components\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'Components'; $self->{az_resource_namespace} = 'Microsoft.Insights'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Application Insights page views statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::management::applicationinsights::plugin --mode=pageviews --custommode=api --resource= --resource-group= --aggregation='total' --warning-views-count='800' --critical-views-count='900' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::integration::servicebus::plugin --mode=pageviews --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Insights/Components/' --aggregation='total' --warning-views-count='800' --critical-views-count='900' Default aggregation: 'total' / 'average', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'views-count', 'load-time'. =item B<--critical-*> Critical threshold where '*' can be: 'views-count', 'load-time'. =back =cut centreon-plugins-20220113/cloud/azure/management/applicationinsights/mode/requests.pm000066400000000000000000000151371417000230700310240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::applicationinsights::mode::requests; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'requests/count' => { 'output' => 'Server requests', 'label' => 'requests-count', 'nlabel' => 'appinsights.requests.total.count', 'unit' => '', 'min' => '0', 'max' => '' }, 'requests/duration' => { 'output' => 'Server response time', 'label' => 'requests-duration', 'nlabel' => 'appinsights.requests.duration.milliseconds', 'unit' => 'ms', 'min' => '0', 'max' => '' }, 'requests/failed' => { 'output' => 'Failed requests', 'label' => 'requests-failed', 'nlabel' => 'appinsights.requests.failed.count', 'unit' => '', 'min' => '0', 'max' => '' }, 'requests/rate' => { 'output' => 'Server request rate', 'label' => 'requests-rate', 'nlabel' => 'appinsights.requests.perseconds', 'unit' => 'requests/s', 'min' => '0', 'max' => '' }, 'performancecounters/requestexecutiontime' => { 'output' => 'HTTP request execution time', 'label' => 'requests-execution-time', 'nlabel' => 'appinsights.requests.execution.time.milliseconds', 'unit' => 'ms', 'min' => '0', 'max' => '' }, 'performancecounters/requestsinqueue' => { 'output' => 'HTTP requests in application queue', 'label' => 'requests-queued', 'nlabel' => 'appinsights.requests.failed.count', 'unit' => '', 'min' => '0', 'max' => '' }, 'performancecounters/requestspersecond' => { 'output' => 'HTTP request rate', 'label' => 'requests-http-rate', 'nlabel' => 'appinsights.requests.http.perseconds', 'unit' => 'requests/s', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Insights\/components\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'Components'; $self->{az_resource_namespace} = 'Microsoft.Insights'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Application Insights HTTP request statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::management::applicationinsights::plugin --mode=http-requests --custommode=api --resource= --resource-group= --aggregation='total' --warning-requests-count='800' --critical-requests-count='900' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::integration::servicebus::plugin --mode=http-requests --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Insights/Components/' --aggregation='total' --warning-requests-count='800' --critical-requests-count='900' Default aggregation: 'total' / 'average', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'requests-count', 'requests-duration', 'requests-failed', 'requests-rate', 'requests-execution-time', 'requests-queued', 'requests-http-rate'. =item B<--critical-*> Critical threshold where '*' can be: 'requests-count', 'requests-duration', 'requests-failed', 'requests-rate', 'requests-execution-time', 'requests-queued', 'requests-http-rate'. =back =cut centreon-plugins-20220113/cloud/azure/management/applicationinsights/plugin.pm000066400000000000000000000047341417000230700275240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::applicationinsights::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} = { 'availability' => 'cloud::azure::management::applicationinsights::mode::availability', 'browser-timings' => 'cloud::azure::management::applicationinsights::mode::browsertimings', 'cpu' => 'cloud::azure::management::applicationinsights::mode::cpu', 'discovery' => 'cloud::azure::management::applicationinsights::mode::discovery', 'exceptions' => 'cloud::azure::management::applicationinsights::mode::exceptions', 'external-calls' => 'cloud::azure::management::applicationinsights::mode::externalcalls', 'io-operations' => 'cloud::azure::management::applicationinsights::mode::iooperations', 'memory' => 'cloud::azure::management::applicationinsights::mode::memory', 'page-views' => 'cloud::azure::management::applicationinsights::mode::pageviews', 'requests' => 'cloud::azure::management::applicationinsights::mode::requests' }; $self->{custom_modes}->{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}->{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' }, }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure Application Insights resources. =cut centreon-plugins-20220113/cloud/azure/management/automation/000077500000000000000000000000001417000230700237645ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/management/automation/mode/000077500000000000000000000000001417000230700247105ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/management/automation/mode/discovery.pm000066400000000000000000000024461417000230700272630ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::automation::mode::discovery; use base qw(cloud::azure::management::monitor::mode::discovery); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{namespace} = 'Microsoft.Automation'; $self->{type} = 'automationAccounts'; } 1; __END__ =head1 MODE Azure Automation discovery. =over 8 =item B<--resource-group> Specify resource group. =item B<--location> Specify location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/management/automation/mode/jobs.pm000066400000000000000000000122051417000230700262030ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::automation::mode::jobs; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'totaljob' => { 'output' => 'Total Jobs', 'label' => 'jobs-total', 'nlabel' => 'automation.jobs.total.count', 'unit' => '', 'min' => '0' }, 'totalupdatedeploymentmachineruns' => { 'output' => 'Total Update Deployment Machine Runs', 'label' => 'update-deployment-machine-runs', 'nlabel' => 'automation.machineruns.total.count', 'unit' => '', 'min' => '0' }, 'totalupdatedeploymentruns' => { 'output' => 'Total Update Deployment Runs', 'label' => 'update-deployment-runs', 'nlabel' => 'automation.runs.total.count', 'unit' => '', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Automation\/automationAccounts\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'automationAccounts'; $self->{az_resource_namespace} = 'Microsoft.Automation'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Automation jobs. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::management::automation::plugin --mode=jobs --custommode=api --resource= --resource-group= --aggregation='total' --warning-jobs-total='20' --critical-jobs-total='50' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::management::automation::plugin --mode=jobs --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Automation/automationAccounts/' --aggregation='total' --warning-jobs-total='20' --critical-jobs-total='50' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'jobs-total', 'update-deployment-machine-runs', 'update-deployment-runs'. =item B<--critical-*> Critical threshold where '*' can be: 'jobs-total', 'update-deployment-machine-runs', 'update-deployment-runs'. =back =cut centreon-plugins-20220113/cloud/azure/management/automation/plugin.pm000066400000000000000000000032361417000230700256240ustar00rootroot00000000000000# # Copyright 2020 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::azure::management::automation::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} = { 'jobs' => 'cloud::azure::management::automation::mode::jobs', 'discovery' => 'cloud::azure::management::automation::mode::discovery' }; $self->{custom_modes}->{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}->{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' }, }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure Automation. =cut centreon-plugins-20220113/cloud/azure/management/discover/000077500000000000000000000000001417000230700234225ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/management/discover/plugin.pm000066400000000000000000000031431417000230700252570ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::discover::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} = '1.0'; %{$self->{modes}} = ( 'discovery' => 'cloud::azure::management::monitor::mode::discovery', ); $self->{custom_modes}->{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}->{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' }, }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Meta Plugin for Microsoft Azure resources discovery. =cut centreon-plugins-20220113/cloud/azure/management/insightsmetrics/000077500000000000000000000000001417000230700250235ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/management/insightsmetrics/mode/000077500000000000000000000000001417000230700257475ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/management/insightsmetrics/mode/cpu.pm000066400000000000000000000165711417000230700271060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::insightsmetrics::mode::cpu; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub computer_long_output { my ($self, %options) = @_; return "Computer '" . $options{instance_value}->{display} . "'"; } sub prefix_core_output { my ($self, %options) = @_; return "CPU #" . $options{instance_value}->{display} . " " ; } sub prefix_avg_output { my ($self, %options) = @_; return $options{instance_value}->{count} . " CPU(s) average utilization: " ; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'computer', type => 3, cb_long_output => 'computer_long_output', indent_long_output => ' ', message_multiple => 'All computers CPUs are OK', group => [ { name => 'cpu_avg', display_long => 1, cb_prefix_output => 'prefix_avg_output', type => 0, skipped_code => { -10 => 1 } }, { name => 'cpu_core', display_long => 1, cb_prefix_output => 'prefix_core_output', message_multiple => 'All CPUs are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{cpu_avg} = [ { label => 'average-utilization-percentage', nlabel => 'azure.insights.cpu.average.utilization.percentage', set => { key_values => [ { name => 'average' }, { name => 'count' } ], output_template => '%.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%' }, ], } }, ]; $self->{maps_counters}->{cpu_core} = [ { label => 'core-utilization-percentage', nlabel => 'azure.insights.cpu.core.utilization.percentage', set => { key_values => [ { name => 'utilizationpercentage' }, { name => 'display' } ], output_template => 'usage : %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' }, ], } } ]; } 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-computer:s' => { name => 'filter_computer' }, 'filter-cpu:s' => { name => 'filter_cpu' }, 'filter-resourceid:s' => { name => 'filter_resourceid' }, 'workspace-id:s' => { name => 'workspace_id' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; my $query = 'InsightsMetrics | where Namespace == "Processor" | summarize arg_max(TimeGenerated, *) by Tags, Name, Computer'; $query .= '| where Computer == "' . $self->{option_results}->{filter_computer} . '"' if defined $self->{option_results}->{filter_computer} && $self->{option_results}->{filter_computer} ne ''; $query .= '| where _ResourceId == "' . $self->{option_results}->{filter_resourceid} . '"' if defined $self->{option_results}->{filter_resourceid} && $self->{option_results}->{filter_resourceid} ne ''; my $results = $options{custom}->azure_get_insights_analytics( workspace_id => $self->{option_results}->{workspace_id}, query => $query, timespan => $self->{option_results}->{timespan} ); my $decoded_tag; foreach my $entry (keys %{$results->{data}}) { $decoded_tag = $options{custom}->json_decode(content => $results->{data}->{$entry}->{tags}); next if (defined($self->{option_results}->{filter_cpu}) && $decoded_tag->{"vm.azm.ms\/totalCpus"} !~ m/$self->{option_results}->{filter_cpu}/); $self->{computer}->{$results->{data}->{$entry}->{computer}}->{display} = $results->{data}->{$entry}->{computer}; $self->{computer}->{$results->{data}->{$entry}->{computer}}->{cpu_core}->{$decoded_tag->{"vm.azm.ms/totalCpus"}}->{display} = $decoded_tag->{"vm.azm.ms/totalCpus"}; } foreach my $computer (keys %{$self->{computer}}) { my $cpu_avg; foreach my $cpu (keys %{$self->{computer}->{$computer}->{cpu_core}}) { foreach my $entry (keys %{$results->{data}}) { $decoded_tag = $options{custom}->json_decode(content => $results->{data}->{$entry}->{tags}); my $cpu_id = $decoded_tag->{"vm.azm.ms/totalCpus"}; next if ($cpu_id !~ m/$cpu/); $self->{computer}->{$results->{data}->{$entry}->{computer}}->{cpu_core}->{$cpu_id}->{utilizationpercentage} = $results->{data}->{$entry}->{value}; $cpu_avg += $results->{data}->{$entry}->{value}; } if (scalar(keys %{$self->{computer}->{$computer}->{cpu_core}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No CPU found for computer " . $self->{computer}->{$computer}->{display}); $self->{output}->option_exit(); } } if (!defined($self->{option_results}->{filter_cpu}) || $self->{option_results}->{filter_cpu} eq '') { $self->{computer}->{$computer}->{cpu_avg}->{count} = scalar(keys %{$self->{computer}->{$computer}}); $self->{computer}->{$computer}->{cpu_avg}->{average} = $cpu_avg / $self->{computer}->{$computer}->{cpu_avg}->{count}; } } if (scalar(keys %{$self->{computer}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No computer found. Can be: filters, cache file."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check Aure VM CPUs using Insights metrics. Example: perl centreon_plugins.pl --plugin=cloud::azure::management::insightsmetrics::plugin --custommode=api --mode=cpu --subscription=1111 --tenant=2222 --client-id=3333 --client-secret=4444 --workspace-id=5555 --verbose =over 8 =item B<--workspace-id> (Mandatory) Specify the Azure Log Analytics Workspace ID. =item B<--filter-computer> Filter on a specific Azure "computer" name. Example: --filter-name='azure-vm1' =item B<--filter-resourceid> Filter on a specific Azure "computer" based on the full resource ID. Example: --filter-resourceid='/subscriptions/1234abcd-5678-defg-9012-3456789abcde/resourcegroups/my_resourcegroup/providers/microsoft.compute/virtualmachines/azure-vm1' =item B<--filter-cpu> Filter on specific CPU ID. =item B<--warning-*> Warning threshold where '*' can be: 'average-utilization-percentage', 'core-utilization-percentage' =item B<--critical-*> Critical threshold where '*' can be: 'average-utilization-percentage', 'core-utilization-percentage' =back =cut centreon-plugins-20220113/cloud/azure/management/insightsmetrics/mode/listlogicaldisks.pm000066400000000000000000000105501417000230700316520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::insightsmetrics::mode::listlogicaldisks; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'name' => { name => 'name' }, 'resource:s' => { name => 'resource' }, 'workspace-id:s' => { name => 'workspace_id' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --resource option."); $self->{output}->option_exit(); } } sub manage_selection { my ($self, %options) = @_; my $query = 'InsightsMetrics | where Namespace == "LogicalDisk" | distinct Tags, _ResourceId, Computer'; if (defined($self->{option_results}->{name})) { $query .= '| where Computer == "' . $self->{option_results}->{resource} . '"'; } else { $query .= '| where _ResourceId == "' . $self->{option_results}->{resource} . '"'; } my $results = $options{custom}->azure_get_insights_analytics( workspace_id => $self->{option_results}->{workspace_id}, query => $query, timespan => $self->{option_results}->{timespan}, disco => 1 ); foreach my $entry (keys %{$results->{data}}) { my $decoded_tag = $options{custom}->json_decode(content => $results->{data}->{$entry}->{tags}); $self->{logicaldisk}->{$decoded_tag->{"vm.azm.ms/mountId"}}->{name} = $decoded_tag->{"vm.azm.ms/mountId"}; } if (scalar(keys %{$self->{logicaldisk}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No logical disks found. Can be: filters, cache file."); $self->{output}->option_exit(); } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $mount (sort keys %{$self->{logicaldisk}}) { $self->{output}->output_add(long_msg => '[name = ' . $mount . ']' ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List logical 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 => [ 'name' ]); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $mount (sort keys %{$self->{logicaldisk}}) { $self->{output}->add_disco_entry(name => $self->{logicaldisk}->{$mount}->{name}); } } 1; __END__ =head1 MODE List Azure Computer logical disks. Example: perl centreon_plugins.pl --plugin=cloud::azure::management::insightsmetrics::plugin --custommode=api --mode=list-logical-disks --subscription=1111 --tenant=2222 --client-id=3333 --client-secret=4444 --workspace-id=5555 --verbose --resource='azure-vm1' --name =over 8 =item B<--workspace-id> (Mandatory) Specify the Azure Log Analytics Workspace ID. =item B<--resource> (Mandatory) Specify the Azure VM Resource ID or name. Short name can be used if the option --name is defined. Example: --resource='/subscriptions/1234abcd-5678-defg-9012-3456789abcde/resourcegroups/my_resourcegroup/providers/microsoft.compute/virtualmachines/azure-vm1' =item B<--name> (Optional) Use only the name of the VM resource rather than the full ID. Example: --resource='azure-vm1' --name =back =cut centreon-plugins-20220113/cloud/azure/management/insightsmetrics/mode/logicaldisks.pm000066400000000000000000000307001417000230700307550ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::insightsmetrics::mode::logicaldisks; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use JSON::XS; sub custom_usage_output { my ($self, %options) = @_; my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{diskSize}); my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{UsedSpace}); my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{FreeSpace}); return sprintf( 'total: %s used: %s (%.2f%%) free: %s (%.2f%%)', $total_size_value . " " . $total_size_unit, $total_used_value . " " . $total_used_unit, $self->{result_values}->{UsedSpacePercentage}, $total_free_value . " " . $total_free_unit, $self->{result_values}->{FreeSpacePercentage} ); } sub computer_long_output { my ($self, %options) = @_; return "Computer '" . $options{instance_value}->{display} . "'"; } sub prefix_logicaldisk_output { my ($self, %options) = @_; return "'" . $options{instance_value}->{display} . "' " ; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'computer', type => 3, cb_long_output => 'computer_long_output', indent_long_output => ' ', message_multiple => 'All computers disks are OK', group => [ { name => 'logicaldisk', display_long => 1, cb_prefix_output => 'prefix_logicaldisk_output', message_multiple => 'All logical disks are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{logicaldisk} = [ { label => 'status', type => 2, critical_default => '%{status} eq "NOT OK"', set => { key_values => [ { name => 'Status' }, { name => 'display' } ], output_template => "status : %s", closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'usage', nlabel => 'azure.insights.logicaldisk.used.bytes', set => { key_values => [ { name => 'UsedSpace' }, { name => 'UsedSpacePercentage' }, { name => 'FreeSpacePercentage' }, { name => 'FreeSpace' }, { name => 'diskSize'} ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%.2f', unit => 'B', min => 0, label_extra_instance => 1 } ] } }, { label => 'usage-percentage', display_ok => 0, nlabel => 'azure.insights.logicaldisk.used.percentage', set => { key_values => [ { name => 'UsedSpacePercentage' } ], output_template => "used : %.2f%%", perfdatas => [ { template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1 } ] } }, { label => 'free-percentage', display_ok => 0, nlabel => 'azure.insights.logicaldisk.free.percentage', set => { key_values => [ { name => 'FreeSpacePercentage' } ], output_template => "free : %.2f%%", perfdatas => [ { template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1 } ] } }, { label => 'reads-persecond', nlabel => 'azure.insights.logicaldisks.io.readspersecond', set => { key_values => [ { name => 'ReadsPerSecond' } ], output_template => "reads per second : %.2f/s", perfdatas => [ { template => '%d', min => 0, label_extra_instance => 1 } ] } }, { label => 'read-bytes-persecond', nlabel => 'azure.insights.logicaldisks.io.readbytespersecond', set => { key_values => [ { name => 'ReadBytesPerSecond' } ], output_change_bytes => 1, output_template => "read bytes per second : %.2f/s", perfdatas => [ { template => '%.2f', unit => 'B/s', min => 0, label_extra_instance => 1 } ] } }, { label => 'writes-persecond', nlabel => 'azure.insights.logicaldisks.io.writespersecond', set => { key_values => [ { name => 'WritesPerSecond' } ], output_template => "write per second : %.2f/s", perfdatas => [ { template => '%.2f', min => 0, label_extra_instance => 1 } ] } }, { label => 'write-bytes-persecond', nlabel => 'azure.insights.logicaldisks.io.writebytespersecond', set => { key_values => [ { name => 'WriteBytesPerSecond' } ], output_change_bytes => 1, output_template => "write bytes per second : %.2f/s", perfdatas => [ { template => '%.2f', unit => 'B/s', min => 0, label_extra_instance => 1 } ] } }, { label => 'transfers-persecond', nlabel => 'azure.insights.logicaldisks.io.transferspersecond', set => { key_values => [ { name => 'TransfersPerSecond' } ], output_template => "transfers per second : %.2f/s", perfdatas => [ { template => '%.2f', min => 0, label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-computer:s' => { name => 'filter_computer' }, 'filter-disk:s' => { name => 'filter_disk' }, 'filter-resourceid:s' => { name => 'filter_resourceid' }, 'workspace-id:s' => { name => 'workspace_id' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; my $query = 'InsightsMetrics | where Namespace == "LogicalDisk" | summarize arg_max(TimeGenerated, *) by Tags, Name, Computer'; $query .= '| where Computer == "' . $self->{option_results}->{filter_computer} . '"' if defined $self->{option_results}->{filter_computer} && $self->{option_results}->{filter_computer} ne ''; $query .= '| where _ResourceId == "' . $self->{option_results}->{filter_resourceid} . '"' if defined $self->{option_results}->{filter_resourceid} && $self->{option_results}->{filter_resourceid} ne ''; my $results = $options{custom}->azure_get_insights_analytics( workspace_id => $self->{option_results}->{workspace_id}, query => $query, timespan => $self->{option_results}->{timespan} ); my $status_mapping = { 0 => 'NOT OK', 1 => 'OK' }; my $decoded_tag; foreach my $entry (keys %{$results->{data}}) { $decoded_tag = $options{custom}->json_decode(content => $results->{data}->{$entry}->{tags}); next if (defined($self->{option_results}->{filter_disk}) && $decoded_tag->{"vm.azm.ms\/mountId"} !~ m/$self->{option_results}->{filter_disk}/); if ($results->{data}->{$entry}->{tags} =~ m/\{"vm\.azm\.ms\/mountId":"(.*)"\}/) { $self->{computer}->{$results->{data}->{$entry}->{computer}}->{logicaldisk}->{$decoded_tag->{"vm.azm.ms/mountId"}}->{display} = $decoded_tag->{"vm.azm.ms/mountId"}; } $self->{computer}->{$results->{data}->{$entry}->{computer}}->{display} = $results->{data}->{$entry}->{computer}; } foreach my $computer (keys %{$self->{computer}}) { foreach my $disk (keys %{$self->{computer}->{$computer}->{logicaldisk}}) { foreach my $entry (keys %{$results->{data}}) { $decoded_tag = $options{custom}->json_decode(content => $results->{data}->{$entry}->{tags}); my $mountid = $decoded_tag->{"vm.azm.ms/mountId"}; next if ($mountid !~ m/$disk/); next if (defined($self->{option_results}->{filter_disk}) && $decoded_tag->{"vm.azm.ms\/mountId"} !~ m/$self->{option_results}->{filter_disk}/); if ($results->{data}->{$entry}->{name} =~ m/(.*Space)MB/) { $self->{computer}->{$results->{data}->{$entry}->{computer}}->{logicaldisk}->{$mountid}->{$1} = $results->{data}->{$entry}->{value} * 1000000; } else { $self->{computer}->{$results->{data}->{$entry}->{computer}}->{logicaldisk}->{$mountid}->{$results->{data}->{$entry}->{name}} = $results->{data}->{$entry}->{value}; } if ($results->{data}->{$entry}->{name} =~ 'Status') { $self->{computer}->{$results->{data}->{$entry}->{computer}}->{logicaldisk}->{$mountid}->{$results->{data}->{$entry}->{name}} = $status_mapping->{$results->{data}->{$entry}->{value}}; } if (defined($decoded_tag->{"vm.azm.ms/diskSizeMB"})) { $self->{computer}->{$results->{data}->{$entry}->{computer}}->{logicaldisk}->{$mountid}->{diskSize} = $decoded_tag->{"vm.azm.ms/diskSizeMB"} * 1000000; } } $self->{computer}->{$computer}->{logicaldisk}->{$disk}->{UsedSpace} = $self->{computer}->{$computer}->{logicaldisk}->{$disk}->{diskSize} - $self->{computer}->{$computer}->{logicaldisk}->{$disk}->{FreeSpace}; $self->{computer}->{$computer}->{logicaldisk}->{$disk}->{UsedSpacePercentage} = 100 - $self->{computer}->{$computer}->{logicaldisk}->{$disk}->{FreeSpacePercentage}; if (scalar(keys %{$self->{computer}->{$computer}->{logicaldisk}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No logical disk found for computer " . $self->{computer}->{$computer}->{display}); $self->{output}->option_exit(); } } } if (scalar(keys %{$self->{computer}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No computer found. Can be: filters, cache file."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check Aure VM logical disks using Insights metrics. Example: perl centreon_plugins.pl --plugin=cloud::azure::management::insightsmetrics::plugin --custommode=api --mode=logical-disks --subscription=1111 --tenant=2222 --client-id=3333 --client-secret=4444 --workspace-id=5555 --verbose =over 8 =item B<--workspace-id> (Mandatory) Specify the Azure Log Analytics Workspace ID. =item B<--filter-computer> Filter on a specific Azure "computer" name. Example: --filter-name='azure-vm1' =item B<--filter-resourceid> Filter on a specific Azure "computer" based on the full resource ID. Example: --filter-resourceid='/subscriptions/1234abcd-5678-defg-9012-3456789abcde/resourcegroups/my_resourcegroup/providers/microsoft.compute/virtualmachines/azure-vm1' =item B<--filter-disk> Filter on specific logical(s) disk(s). =item B<--warning-status> Warning threshold on logical disk status (Default: none). =item B<--critical-status> Critical threshold on logical disk status (Default: '%{status} eq "NOT OK"'). =item B<--warning-*> Warning threshold where '*' can be: 'usage', 'usage-percentage', 'free-percentage', 'reads-persecond', 'read-bytes-persecond', 'writes-persecond', 'write-bytes-persecond', 'transfers-persecond' =item B<--critical-*> Critical threshold where '*' can be: 'usage', 'usage-percentage', 'free-percentage', 'reads-persecond', 'read-bytes-persecond', 'writes-persecond', 'write-bytes-persecond', 'transfers-persecond' =back =cut centreon-plugins-20220113/cloud/azure/management/insightsmetrics/mode/memory.pm000066400000000000000000000175451417000230700276310ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::insightsmetrics::mode::memory; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use List::Util qw(max); use Date::Parse; sub computer_long_output { my ($self, %options) = @_; return "Computer '" . $options{instance_value}->{display} . "'"; } sub prefix_memory_output { my ($self, %options) = @_; return "Memory usage: "; } sub custom_usage_output { my ($self, %options) = @_; return sprintf( 'Memory Total: %s %s Used: %s%s (%.2f%%) Available: %s%s (%.2f%%)', $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}), $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}), $self->{result_values}->{used_prct}, $self->{perfdata}->change_bytes(value => $self->{result_values}->{available}), $self->{result_values}->{available_prct} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'computer', type => 3, cb_long_output => 'computer_long_output', indent_long_output => ' ', message_multiple => 'All computers CPUs are OK', group => [ { name => 'memory', display_long => 1, cb_prefix_output => 'prefix_memory_output', type => 0, skipped_code => { -10 => 1 } }, ] } ]; $self->{maps_counters}->{memory} = [ { label => 'usage', nlabel => 'azure.insights.memory.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'used_prct' }, { name => 'available' }, { name => 'available_prct' }, { name => 'total' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%.2f', unit => 'B', min => 0, label_extra_instance => 1 } ] } }, { label => 'usage-percentage', display_ok => 0, nlabel => 'azure.insights.memory.usage.percentage', set => { key_values => [ { name => 'used_prct' } ], output_template => 'used %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 } ] } }, { label => 'available-percentage', display_ok => 0, nlabel => 'azure.insights.memory.available.percentage', set => { key_values => [ { name => 'available_prct' } ], output_template => 'available %.2f %%', perfdatas => [ { template => '%d', min => 0, max => 100, unit => '%', label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-computer:s' => { name => 'filter_computer' }, 'filter-resourceid:s' => { name => 'filter_resourceid' }, 'workspace-id:s' => { name => 'workspace_id' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; my $query = 'InsightsMetrics | where Namespace == "Memory" | summarize arg_max(TimeGenerated, *) by Tags, Name, Computer'; $query .= '| where Computer == "' . $self->{option_results}->{filter_computer} . '"' if defined $self->{option_results}->{filter_computer} && $self->{option_results}->{filter_computer} ne ''; $query .= '| where _ResourceId == "' . $self->{option_results}->{filter_resourceid} . '"' if defined $self->{option_results}->{filter_resourceid} && $self->{option_results}->{filter_resourceid} ne ''; my $results = $options{custom}->azure_get_insights_analytics( workspace_id => $self->{option_results}->{workspace_id}, query => $query, timespan => $self->{option_results}->{timespan} ); my $timestamps = []; foreach my $entry (keys %{$results->{data}}) { $self->{computer}->{$results->{data}->{$entry}->{computer}}->{display} = $results->{data}->{$entry}->{computer}; push @$timestamps, Date::Parse::str2time($results->{data}->{$entry}->{timegenerated}); } my $decoded_tag; foreach my $computer (keys %{$self->{computer}}) { foreach my $entry (keys %{$results->{data}}) { next if Date::Parse::str2time($results->{data}->{$entry}->{timegenerated}) != max(@$timestamps); $decoded_tag = $options{custom}->json_decode(content => $results->{data}->{$entry}->{tags}); if (defined($results->{data}->{$entry}->{value})) { $self->{computer}->{$results->{data}->{$entry}->{computer}}->{memory}->{available} = $results->{data}->{$entry}->{value} * 1000000; } $self->{computer}->{$results->{data}->{$entry}->{computer}}->{memory}->{total} = defined($decoded_tag->{"vm.azm.ms/memorySizeMB"}) ? $decoded_tag->{"vm.azm.ms/memorySizeMB"} * 1000000 : undef; } if (defined($self->{computer}->{$computer}->{memory}->{available}) && defined($self->{computer}->{$computer}->{memory}->{total})) { $self->{computer}->{$computer}->{memory}->{used} = $self->{computer}->{$computer}->{memory}->{total} - $self->{computer}->{$computer}->{memory}->{available} ; $self->{computer}->{$computer}->{memory}->{used_prct} = $self->{computer}->{$computer}->{memory}->{used} * 100 / $self->{computer}->{$computer}->{memory}->{total}; $self->{computer}->{$computer}->{memory}->{available_prct} = 100 - $self->{computer}->{$computer}->{memory}->{used_prct}; } if (scalar(keys %{$self->{computer}->{$computer}->{memory}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No memory found for computer " . $self->{computer}->{$computer}->{display}); $self->{output}->option_exit(); } } if (scalar(keys %{$self->{computer}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No computer found. Can be: filters, cache file."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check Aure VM memory usage using Insights metrics. Example: perl centreon_plugins.pl --plugin=cloud::azure::management::insightsmetrics::plugin --custommode=api --mode=memory --subscription=1111 --tenant=2222 --client-id=3333 --client-secret=4444 --workspace-id=5555 --verbose =over 8 =item B<--workspace-id> (Mandatory) Specify the Azure Log Analytics Workspace ID. =item B<--filter-computer> Filter on a specific Azure "computer" name. Example: --filter-name='azure-vm1' =item B<--filter-resourceid> Filter on a specific Azure "computer" based on the full resource ID. Example: --filter-resourceid='/subscriptions/1234abcd-5678-defg-9012-3456789abcde/resourcegroups/my_resourcegroup/providers/microsoft.compute/virtualmachines/azure-vm1' =item B<--warning-*> Warning threshold where '*' can be: 'usage', 'usage-percentage', 'available-percentage' =item B<--critical-*> Critical threshold where '*' can be: 'usage', 'usage-percentage', 'available-percentage' =back =cut centreon-plugins-20220113/cloud/azure/management/insightsmetrics/plugin.pm000066400000000000000000000035441417000230700266650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::insightsmetrics::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} = '1.0'; %{$self->{modes}} = ( 'cpu' => 'cloud::azure::management::insightsmetrics::mode::cpu', 'list-logical-disks' => 'cloud::azure::management::insightsmetrics::mode::listlogicaldisks', 'logical-disks' => 'cloud::azure::management::insightsmetrics::mode::logicaldisks', 'memory' => 'cloud::azure::management::insightsmetrics::mode::memory', ); $self->{custom_modes}->{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' }, }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure Insights metrics service using Loganalytics API. =cut centreon-plugins-20220113/cloud/azure/management/loganalytics/000077500000000000000000000000001417000230700242755ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/management/loganalytics/mode/000077500000000000000000000000001417000230700252215ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/management/loganalytics/mode/kustoquery.pm000066400000000000000000000115241417000230700300150ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::loganalytics::mode::kustoquery; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_match_output { my ($self, %options) = @_; my $msg; my $message; if (defined($self->{instance_mode}->{option_results}->{custom_output}) && $self->{instance_mode}->{option_results}->{custom_output} ne '') { eval { local $SIG{__WARN__} = sub { $message = $_[0]; }; local $SIG{__DIE__} = sub { $message = $_[0]; }; $msg = sprintf("$self->{instance_mode}->{option_results}->{custom_output}", eval $self->{result_values}->{match}); }; } else { $msg = sprintf("Total logs match '%d'", $self->{result_values}->{match}); } if (defined($message)) { $self->{output}->output_add(long_msg => 'printf substitution issue: ' . $message); } return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 } ]; $self->{maps_counters}->{global} = [ { label => 'match', nlabel => 'match.count', set => { key_values => [ { name => 'match' } ], closure_custom_output => $self->can('custom_match_output'), perfdatas => [ { template => '%s', min => 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 => { 'custom-output:s' => { name => 'custom_output'}, 'query:s' => { name => 'query'}, 'timespan:s' => { name => 'timespan' }, 'workspace-id:s' => { name => 'workspace_id' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{workspace_id}) || $self->{option_results}->{workspace_id} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --workspace-id ."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{query}) || $self->{option_results}->{query} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify a query."); $self->{output}->option_exit(); } } sub manage_selection { my ($self, %options) = @_; my ($log_results) = $options{custom}->azure_get_log_analytics( workspace_id => $self->{option_results}->{workspace_id}, query => $self->{option_results}->{query}, timespan => $self->{option_results}->{timespan} ); $self->{global} = { match => 0 }; foreach my $table (@{$log_results->{tables}}) { foreach (@{$table->{rows}}) { $self->{global}->{match}++; } } } 1; __END__ =head1 MODE Perform a Kusto query and count results Sample command: perl centreon_plugins.pl --plugin=cloud::azure::management::loganalytics::plugin \ --custommode api --management-endpoint='https://api.loganalytics.io' --mode kusto-query \ --subscription=*********************** --tenant=*********************** \ --client-id=*********************** --client-secret=*********************** --workspace-id=*********************** \ --query 'Heartbeat | summarize LastCall = max(TimeGenerated) by Computer | where LastCall > ago(3d)' \ --custom-output='Number of syslog %d' OK: Number of Syslog '2' | 'match.count'=2;;;0; =over 8 =item B<--custom-output> Set a custom message to output in printf format. Exemple: 'Number of Syslog message collected %d' =item B<--query> Set query (Required). Syntax: https://docs.microsoft.com/en-us/azure/kusto/query/ =item B<--workspace-id> Set workspace id (Required). =item B<--timespan> Set Timespan of the query (Do not use it if time filters is included in the query) (Can be : PT1M, PT5M, PT15M, PT30M, PT1H, PT6H, PT12H, PT24H). =item B<--warning-match> B<--critical-match> Thresholds. =back =cut centreon-plugins-20220113/cloud/azure/management/loganalytics/plugin.pm000066400000000000000000000031421417000230700261310ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::loganalytics::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} } = ( 'kusto-query' => 'cloud::azure::management::loganalytics::mode::kustoquery', ); $self->{custom_modes}{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' }, }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure Log Analytics =cut centreon-plugins-20220113/cloud/azure/management/monitor/000077500000000000000000000000001417000230700232735ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/management/monitor/mode/000077500000000000000000000000001417000230700242175ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/management/monitor/mode/alert.pm000066400000000000000000000117071417000230700256720ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::monitor::mode::alert; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_output { my ($self, %options) = @_; return sprintf( "alert severity: '%s', Count: '%d'", $self->{result_values}->{severity}, $self->{result_values}->{count} ); } sub custom_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => 'alerts.' . lc($self->{result_values}->{severity}) . '.count', value => $self->{result_values}->{count}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}) ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'alert', type => 1, message_multiple => 'All alerts are ok' }, ]; $self->{maps_counters}->{alert} = [ { label => 'count', set => { key_values => [ { name => 'severity' }, { name => 'count' } ], closure_custom_output => $self->can('custom_output'), threshold_use => 'count', closure_custom_perfdata => $self->can('custom_perfdata'), } }, ]; } 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 => { 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group', default => '' }, 'group-by:s' => { name => 'group_by', default => 'severity' }, 'time-range:s' => { name => 'time_range', default => '1h' }, 'filter:s' => { name => 'filter', default => '.*' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{option_results}->{api_version} = '2018-05-05'; if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify either --resource with --resource-group option or --resource ."); $self->{output}->option_exit(); } $self->{az_resource} = $self->{option_results}->{resource}; $self->{az_resource_group} = $self->{option_results}->{resource_group} if (defined($self->{option_results}->{resource_group})); $self->{az_group_by} = $self->{option_results}->{group_by} if ($self->{option_results}->{group_by} =~ /^(alertRule|alertState|monitorCondition|monitorService|severity|signalType)$/i); $self->{az_time_range} = $self->{option_results}->{time_range} if ($self->{option_results}->{time_range} =~ /^(1d|1h|30d|7d)$/); } sub manage_selection { my ($self, %options) = @_; my $resource_group = $self->{az_resource_group}; my $resource_name = $self->{az_resource}; my $time_range = $self->{az_time_range}; my $group_by = $self->{az_group_by}; if ($self->{az_resource} =~ /^\/subscriptions\/.*\/providers\/Microsoft\.AlertsManagement\/alertsSummary\?api-version=.*&groupby=(.*)\&targetResourceGroup=(.*)\&targetResourceName=(.*)\&timeRange=(.*)$/i) { $group_by = $1; $resource_group = $2; $resource_name = $3; $time_range = $4; } my $status = $options{custom}->azure_get_resource_alert( group_by => $group_by, resource => $resource_name, resource_group => $resource_group, time_range => $time_range, ); foreach my $values (@{$status->{properties}->{values}}) { next if ($values->{name} !~ /$self->{option_results}->{filter}/); $self->{alert}->{$values->{name}} = { severity => $values->{name}, count => $values->{count} }; } } 1; __END__ =head1 MODE Check alerts. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--filter> Filter on alert name Can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'count'. =back =cut centreon-plugins-20220113/cloud/azure/management/monitor/mode/discovery.pm000066400000000000000000000076311417000230700265730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::monitor::mode::discovery; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "namespace:s" => { name => 'namespace' }, "type:s" => { name => 'type' }, "resource-group:s" => { name => 'resource_group' }, "location:s" => { name => 'location' }, "prettify" => { name => 'prettify' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); $self->{namespace} = $self->{option_results}->{namespace}; $self->{type} = $self->{option_results}->{type}; $self->{location} = $self->{option_results}->{location}; $self->{resource_group} = $self->{option_results}->{resource_group}; } sub run { my ($self, %options) = @_; my @disco_data; my $disco_stats; $disco_stats->{start_time} = time(); my $resources = $options{custom}->azure_list_resources( namespace => $self->{namespace}, resource_type => $self->{type}, location => $self->{location}, resource_group => $self->{resource_group} ); $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; foreach my $resource (@{$resources}) { my $resource_group = ''; $resource_group = $resource->{resourceGroup} if (defined($resource->{resourceGroup})); $resource_group = $1 if ($resource_group eq '' && defined($resource->{id}) && $resource->{id} =~ /resourceGroups\/(.*)\/providers/); $resource->{resourceGroup} = $resource_group; foreach my $entry (keys %{$resource}) { next if (ref($resource->{$entry}) ne "HASH"); my @array; foreach my $key (keys %{$resource->{$entry}}) { push @array, { key => $key, value => $resource->{$entry}->{$key} }; } $resource->{$entry} = \@array; } push @disco_data, $resource; } $disco_stats->{discovered_items} = @disco_data; $disco_stats->{results} = \@disco_data; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE Resources discovery. =over 8 =item B<--namespace> Specify resources namespace. =item B<--type> Specify resources type. =item B<--resource-group> Specify resources resource group. =item B<--location> Specify resources location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/management/monitor/mode/getmetrics.pm000066400000000000000000000224231417000230700267260ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::monitor::mode::getmetrics; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Data::Dumper; sub custom_metric_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => $self->{result_values}->{perf_label}, value => $self->{result_values}->{value}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-metric'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-metric'), ); } sub custom_metric_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check( value => $self->{result_values}->{value}, threshold => [ { label => 'critical-metric', exit_litteral => 'critical' }, { label => 'warning-metric', exit_litteral => 'warning' } ]); return $exit; } sub custom_metric_output { my ($self, %options) = @_; my $msg = "Metric '" . $self->{result_values}->{name} . "' of resource '" . $self->{result_values}->{display} . "' and aggregation '" . $self->{result_values}->{aggregation} . "' value is " . $self->{result_values}->{value}; return $msg; } sub custom_metric_calc { my ($self, %options) = @_; $self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_value'}; $self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_name'}; $self->{result_values}->{label} = $options{new_datas}->{$self->{instance} . '_label'}; $self->{result_values}->{aggregation} = $options{new_datas}->{$self->{instance} . '_aggregation'}; $self->{result_values}->{perf_label} = $options{new_datas}->{$self->{instance} . '_perf_label'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metrics', type => 1, message_multiple => 'All metrics are ok' }, ]; $self->{maps_counters}->{metrics} = [ { label => 'metric', set => { key_values => [ { name => 'value' }, { name => 'name' }, { name => 'label' }, { name => 'aggregation' }, { name => 'perf_label' }, { name => 'display' } ], 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; $options{options}->add_options(arguments => { "resource:s" => { name => 'resource' }, "resource-group:s" => { name => 'resource_group' }, "resource-type:s" => { name => 'resource_type' }, "resource-namespace:s" => { name => 'resource_namespace' }, "metric:s@" => { name => 'metric' }, "filter-dimension:s" => { name => 'filter_dimension' }, "metric-namespace:s" => { name => 'metric_namespace' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource})) { $self->{output}->add_option_msg(short_msg => "Need to specify either --resource with --resource-group, --resource-type and --resource-namespace options or --resource ."); $self->{output}->option_exit(); } $self->{az_resource} = $self->{option_results}->{resource}; $self->{az_resource_group} = $self->{option_results}->{resource_group}; $self->{az_resource_type} = $self->{option_results}->{resource_type}; $self->{az_resource_namespace} = $self->{option_results}->{resource_namespace}; if ($self->{az_resource} =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/(.*)\/(.*)\/(.*)$/) { $self->{az_resource_group} = $1; $self->{az_resource_namespace} = $2; $self->{az_resource_type} = $3; $self->{az_resource} = $4; } $self->{az_metrics} = []; if (defined($self->{option_results}->{metric})) { $self->{az_metrics} = $self->{option_results}->{metric}; } if (scalar(@{$self->{az_metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => "Need to specify --metric option."); $self->{output}->option_exit(); } $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : "PT1M"; $self->{az_aggregation} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregation} = []; foreach my $aggregation (@{$self->{option_results}->{aggregation}}) { if ($aggregation ne '') { push @{$self->{az_aggregation}}, ucfirst(lc($aggregation)); } } } if (defined($self->{option_results}->{filter_dimension}) && $self->{option_results}->{filter_dimension} ne '') { $self->{az_metrics_dimension} = $self->{option_results}->{filter_dimension}; } if (defined($self->{option_results}->{metric_namespace}) && $self->{option_results}->{metric_namespace} ne '') { $self->{az_metric_namespace} = $self->{option_results}->{metric_namespace}; } } sub manage_selection { my ($self, %options) = @_; my ($results, $raw_results) = $options{custom}->azure_get_metrics( resource => $self->{az_resource}, resource_group => $self->{az_resource_group}, resource_type => $self->{az_resource_type}, resource_namespace => $self->{az_resource_namespace}, metrics => $self->{az_metrics}, aggregations => $self->{az_aggregation}, metric_namespace => $self->{az_metric_namespace}, timeframe => $self->{az_timeframe}, interval => $self->{az_interval}, dimension => $self->{az_metrics_dimension} ); $self->{metrics} = {}; foreach my $label (keys %{$results}) { foreach my $aggregation (('minimum', 'maximum', 'average', 'total', 'count')) { next if (!defined($results->{$label}->{$aggregation})); $self->{metrics}->{$label . '_' . $aggregation} = { display => $self->{az_resource}, name => $results->{$label}->{name}, label => $label, aggregation => $aggregation, value => $results->{$label}->{$aggregation}, perf_label => $label . '_' . $aggregation, }; } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No metric found (Are the filters properly set?)"); $self->{output}->option_exit(); } $self->{output}->output_add(long_msg => sprintf("Raw data:\n%s", Dumper($raw_results)), debug => 1); } 1; __END__ =head1 MODE Check Azure metrics. Examples: perl centreon_plugins.pl --plugin=cloud::azure::management::monitor::plugin --custommode=azcli --mode=get-metrics --resource=MYSQLINSTANCE --resource-group=MYHOSTGROUP --resource-namespace='Microsoft.Compute' --resource-type='virtualMachines' --metric='Percentage CPU' --aggregation=average –-interval=PT1M --timeframe=600 --warning-metric= --critical-metric= perl centreon_plugins.pl --plugin=cloud::azure::management::monitor::plugin --custommode=azcli --mode=get-metrics --resource='/subscriptions/d29fe431/resourceGroups/MYHOSTGROUP/providers/Microsoft.Compute/virtualMachines/MYSQLINSTANCE' --metric='Percentage CPU' --aggregation=average –-interval=PT1M --timeframe=600 --warning-metric= --critical-metric= =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--resource-namespace> Set resource namespace (Required if resource's name is used). =item B<--resource-type> Set resource type (Required if resource's name is used). =item B<--metric> Set monitor metrics (Required) (Can be multiple). =item B<--metric-namespace> Set monitor metric namespace. =item B<--filter-dimension> Specify the metric dimension (required for some specific metrics) Syntax example: --filter-dimension="$metricname eq '$metricvalue'" =item B<--warning-metric> Threshold warning. =item B<--critical-metric> Threshold critical. =back =cut centreon-plugins-20220113/cloud/azure/management/monitor/mode/health.pm000066400000000000000000000115351417000230700260270ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::monitor::mode::health; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; $self->{result_values}->{summary} = $options{new_datas}->{$self->{instance} . '_summary'}; return 0; } sub custom_output { my ($self, %options) = @_; return sprintf("Status: '%s', Summary: '%s'", $self->{result_values}->{status}, $self->{result_values}->{summary} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'health', type => 0 }, ]; $self->{maps_counters}->{health} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'summary' } ], closure_custom_calc => $self->can('custom_calc'), closure_custom_output => $self->can('custom_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold, } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource:s" => { name => 'resource' }, "resource-group:s" => { name => 'resource_group' }, "resource-type:s" => { name => 'resource_type' }, "resource-namespace:s" => { name => 'resource_namespace' }, "warning-status:s" => { name => 'warning_status', default => '' }, "critical-status:s" => { name => 'critical_status', default => '%{status} =~ /^Unavailable$/' }, "unknown-status:s" => { name => 'unknown_status', default => '' }, "ok-status:s" => { name => 'ok_status', default => '%{status} =~ /^Available$/' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource})) { $self->{output}->add_option_msg(short_msg => "Need to specify either --resource with --resource-group, --resource-type and --resource-namespace options or --resource ."); $self->{output}->option_exit(); } $self->{az_resource} = $self->{option_results}->{resource}; $self->{az_resource_group} = $self->{option_results}->{resource_group}; $self->{az_resource_type} = $self->{option_results}->{resource_type}; $self->{az_resource_namespace} = $self->{option_results}->{resource_namespace}; if ($self->{az_resource} =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/(.*)\/(.*)\/(.*)$/) { $self->{az_resource_group} = $1; $self->{az_resource_namespace} = $2; $self->{az_resource_type} = $3; $self->{az_resource} = $4; } $self->change_macros(macros => ['warning_status', 'critical_status', 'unknown_status', 'ok_status']); } sub manage_selection { my ($self, %options) = @_; my $status = $options{custom}->azure_get_resource_health( resource => $self->{az_resource}, resource_group => $self->{az_resource_group}, resource_type => $self->{az_resource_type}, resource_namespace => $self->{az_resource_namespace}, api_version => '2020-05-01' ); $self->{health} = { status => $status->{properties}->{availabilityState}, summary => $status->{properties}->{summary} }; } 1; __END__ =head1 MODE Check resource health status. Usefull to determine host status (ie UP/DOWN). =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--resource-namespace> Set resource namespace (Required if resource's name is used). =item B<--resource-type> Set resource type (Required if resource's name is used). =back =cut centreon-plugins-20220113/cloud/azure/management/monitor/plugin.pm000066400000000000000000000035431417000230700251340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::monitor::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} = '1.0'; %{$self->{modes}} = ( 'alert' => 'cloud::azure::management::monitor::mode::alert', 'discovery' => 'cloud::azure::management::monitor::mode::discovery', 'get-metrics' => 'cloud::azure::management::monitor::mode::getmetrics', 'health' => 'cloud::azure::management::monitor::mode::health', ); $self->{custom_modes}{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' }, }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure monitor service using API. =cut centreon-plugins-20220113/cloud/azure/management/recovery/000077500000000000000000000000001417000230700234425ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/management/recovery/mode/000077500000000000000000000000001417000230700243665ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/management/recovery/mode/backupitemsstatus.pm000066400000000000000000000166611417000230700305110ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::recovery::mode::backupitemsstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; return sprintf( "Pre-Check Status '%s', Last Backup Status '%s'", $self->{result_values}->{precheck_status}, $self->{result_values}->{last_backup_status} ); } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{precheck_status} = $options{new_datas}->{$self->{instance} . '_precheck_status'}; $self->{result_values}->{last_backup_status} = $options{new_datas}->{$self->{instance} . '_last_backup_status'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub prefix_global_output { my ($self, %options) = @_; return "Backup Items "; } sub prefix_item_output { my ($self, %options) = @_; return "Backup Item '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }, { name => 'items', type => 1, cb_prefix_output => 'prefix_item_output', message_multiple => 'All items are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'total-completed', set => { key_values => [ { name => 'completed' } ], output_template => "completed : %s", perfdatas => [ { label => 'total_completed', value => 'completed', template => '%d', min => 0 } ] } }, { label => 'total-failed', set => { key_values => [ { name => 'failed' } ], output_template => "failed : %s", perfdatas => [ { label => 'total_failed', value => 'failed', template => '%d', min => 0 } ] } } ]; $self->{maps_counters}->{items} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'precheck_status' }, { name => 'last_backup_status' }, { 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 => \&catalog_status_threshold } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'vault-name:s' => { name => 'vault_name' }, 'resource-group:s' => { name => 'resource_group' }, 'filter-name:s' => { name => 'filter_name' }, 'filter-vmid:s' => { name => 'filter_vmid' }, 'filter-counters:s' => { name => 'filter_counters' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{precheck_status} ne "Passed" || %{last_backup_status} eq "Failed"' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource_group}) || $self->{option_results}->{resource_group} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --resource-group option"); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{vault_name}) || $self->{option_results}->{vault_name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --vault-name option"); $self->{output}->option_exit(); } $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; my $items = $options{custom}->azure_list_backup_items( vault_name => $self->{option_results}->{vault_name}, resource_group => $self->{option_results}->{resource_group} ); $self->{global} = { completed => 0, failed => 0, inprogress => 0 }; $self->{items} = {}; foreach my $item (@{$items}) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $item->{properties}->{friendlyName} !~ /$self->{option_results}->{filter_name}/); next if (defined($self->{option_results}->{filter_vmid}) && $self->{option_results}->{filter_vmid} ne '' && $item->{properties}->{virtualMachineId} !~ /$self->{option_results}->{filter_vmid}/); $self->{items}->{$item->{id}} = { display => $item->{properties}->{friendlyName}, precheck_status => $item->{properties}->{healthStatus}, last_backup_status => $item->{properties}->{lastBackupStatus} }; $self->{global}->{ lc($item->{properties}->{lastBackupStatus}) }++ if (defined($item->{properties}->{lastBackupStatus}) && defined($self->{global}->{ lc($item->{properties}->{lastBackupStatus}) })); } if (scalar(keys %{$self->{items}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No backup items found.'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check backup items status. Example: perl centreon_plugins.pl --plugin=cloud::azure::management::recovery::plugin --custommode=azcli --mode=backup-items-status --resource-group='MYRESOURCEGROUP' --vault-name='Loki' --filter-counters='^total-failed$' --critical-total-failed='0' --verbose =over 8 =item B<--vault-name> Set vault name (Required). =item B<--resource-group> Set resource group (Required). =item B<--filter-name> Filter item name (Can be a regexp). =item B<--filter-vmid> Filter item virtualMachineId (Can be a regexp). =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^total-completed$' =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{precheck_status}, %{last_backup_status}, %{display} =item B<--critical-status> Set critical threshold for status (Default: '%{precheck_status} ne "Passed" || %{last_backup_status} eq "Failed"'). Can used special variables like: %{precheck_status}, %{last_backup_status}, %{display} =item B<--warning-*> Threshold warning. Can be: 'total-completed', 'total-failed', 'total-inprogress'. =item B<--critical-*> Threshold critical. Can be: 'total-completed', 'total-failed', 'total-inprogress'. =back =cut centreon-plugins-20220113/cloud/azure/management/recovery/mode/backupjobsstatus.pm000066400000000000000000000172151417000230700303210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::recovery::mode::backupjobsstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("Status '%s' [Duration: %s]", $self->{result_values}->{status}, $self->{result_values}->{duration}); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; $self->{result_values}->{duration} = centreon::plugins::misc::change_seconds(value => $options{new_datas}->{$self->{instance} . '_duration'}); $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub prefix_global_output { my ($self, %options) = @_; return "Backup Jobs "; } sub prefix_job_output { my ($self, %options) = @_; return "Backup Job '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', cb_init => 'skip_global' }, { name => 'jobs', type => 1, cb_prefix_output => 'prefix_job_output', message_multiple => 'All jobs are ok' }, ]; $self->{maps_counters}->{global} = [ { label => 'total-completed', set => { key_values => [ { name => 'completed' } ], output_template => "completed : %s", perfdatas => [ { label => 'total_completed', value => 'completed', template => '%d', min => 0 }, ], } }, { label => 'total-failed', set => { key_values => [ { name => 'failed' } ], output_template => "failed : %s", perfdatas => [ { label => 'total_failed', value => 'failed', template => '%d', min => 0 }, ], } }, { label => 'total-inprogress', set => { key_values => [ { name => 'inprogress' } ], output_template => "in progress : %s", perfdatas => [ { label => 'total_inprogress', value => 'inprogress', template => '%d', min => 0 }, ], } }, ]; $self->{maps_counters}->{jobs} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'duration' }, { 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 => \&catalog_status_threshold, } }, ]; } sub skip_global { my ($self, %options) = @_; scalar(keys %{$self->{jobs}}) == 1 ? return(1) : return(0); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "vault-name:s" => { name => 'vault_name' }, "resource-group:s" => { name => 'resource_group' }, "filter-name:s" => { name => 'filter_name' }, "filter-counters:s" => { name => 'filter_counters' }, "warning-status:s" => { name => 'warning_status', default => '' }, "critical-status:s" => { name => 'critical_status', default => '%{status} eq "Failed"' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource_group}) || $self->{option_results}->{resource_group} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --resource-group option"); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{vault_name}) || $self->{option_results}->{vault_name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --vault-name option"); $self->{output}->option_exit(); } $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; $self->{global} = { completed => 0, failed => 0, inprogress => 0, }; $self->{jobs} = {}; my $jobs = $options{custom}->azure_list_backup_jobs( vault_name => $self->{option_results}->{vault_name}, resource_group => $self->{option_results}->{resource_group} ); foreach my $job (@{$jobs}) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $job->{properties}->{entityFriendlyName} !~ /$self->{option_results}->{filter_name}/); my $duration = $options{custom}->convert_duration(time_string => $job->{properties}->{duration}); $self->{jobs}->{$job->{id}} = { display => $job->{properties}->{entityFriendlyName}, status => $job->{properties}->{status}, duration => $duration, }; foreach my $status (keys %{$self->{global}}) { $self->{global}->{$status}++ if ($job->{properties}->{status} =~ /$status/i); } } if (scalar(keys %{$self->{jobs}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No backup jobs found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check backup jobs status. Example: perl centreon_plugins.pl --plugin=cloud::azure::management::recovery::plugin --custommode=azcli --mode=backup-jobs-status --resource-group='MYRESOURCEGROUP' --vault-name='Loki' --filter-counters='^total-failed$' --critical-total-failed='0' --verbose =over 8 =item B<--vault-name> Set vault name (Required). =item B<--resource-group> Set resource group (Required). =item B<--filter-name> Filter job name (Can be a regexp). =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^total-completed$' =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{display} =item B<--critical-status> Set critical threshold for status (Default: '%{status} eq "Failed"'). Can used special variables like: %{status}, %{display} =item B<--warning-*> Threshold warning. Can be: 'total-completed', 'total-failed', 'total-inprogress'. =item B<--critical-*> Threshold critical. Can be: 'total-completed', 'total-failed', 'total-inprogress'. =back =cut centreon-plugins-20220113/cloud/azure/management/recovery/mode/discovery.pm000066400000000000000000000024231417000230700267340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::recovery::mode::discovery; use base qw(cloud::azure::management::monitor::mode::discovery); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{namespace} = 'Microsoft.RecoveryServices'; $self->{type} = 'vaults'; } 1; __END__ =head1 MODE Vault discovery. =over 8 =item B<--resource-group> Specify resource group. =item B<--location> Specify location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/management/recovery/mode/listbackupjobs.pm000066400000000000000000000117031417000230700277450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::recovery::mode::listbackupjobs; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "vault-name:s" => { name => 'vault_name' }, "resource-group:s" => { name => 'resource_group' }, "filter-name:s" => { name => 'filter_name' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{resource_group}) || $self->{option_results}->{resource_group} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --resource-group option"); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{vault_name}) || $self->{option_results}->{vault_name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --vault-name option"); $self->{output}->option_exit(); } } sub manage_selection { my ($self, %options) = @_; $self->{jobs} = $options{custom}->azure_list_backup_jobs( vault_name => $self->{option_results}->{vault_name}, resource_group => $self->{option_results}->{resource_group} ); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $job (@{$self->{jobs}}) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $job->{properties}->{entityFriendlyName} !~ /$self->{option_results}->{filter_name}/); my $resource_group = '-'; $resource_group = $job->{resourceGroup} if (defined($job->{resourceGroup})); $resource_group = $1 if ($resource_group eq '-' && defined($job->{id}) && $job->{id} =~ /resource[gG]roups\/(.*)\/providers/); my @tags; foreach my $tag (keys %{$job->{tags}}) { push @tags, $tag . ':' . $job->{tags}->{$tag}; } $self->{output}->output_add(long_msg => sprintf("[name = %s][resourcegroup = %s][id = %s][activity_id = %s][type = %s][status = %s][tags = %s]", $job->{properties}->{entityFriendlyName}, $resource_group, $job->{id}, $job->{properties}->{activityId}, $job->{properties}->{jobType}, $job->{properties}->{status}, join(',', @tags)) ); } $self->{output}->output_add(severity => 'OK', short_msg => 'List backup jobs:'); $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', 'resourcegroup', 'id', 'activity_id', 'type', 'status', 'tags']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $job (@{$self->{jobs}}) { my $resource_group = '-'; $resource_group = $job->{resourceGroup} if (defined($job->{resourceGroup})); $resource_group = $1 if ($resource_group eq '-' && defined($job->{id}) && $job->{id} =~ /resourceGroups\/(.*)\/providers/); my @tags; foreach my $tag (keys %{$job->{tags}}) { push @tags, $tag . ':' . $job->{tags}->{$tag}; } $self->{output}->add_disco_entry( name => $job->{properties}->{entityFriendlyName}, resourcegroup => $resource_group, id => $job->{id}, activity_id => $job->{properties}->{activityId}, type => $job->{properties}->{jobType}, status => $job->{properties}->{status}, tags => join(',', @tags), ); } } 1; __END__ =head1 MODE List backup jobs. =over 8 =item B<--vault-name> Set vault name (Mandatory). =item B<--resource-group> Set resource group (Mandatory). =item B<--filter-name> Filter job name (Can be a regexp). =back =cut centreon-plugins-20220113/cloud/azure/management/recovery/mode/listvaults.pm000066400000000000000000000102441417000230700271370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::recovery::mode::listvaults; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource-group:s" => { name => 'resource_group' }, "location:s" => { name => 'location' }, "filter-name:s" => { name => 'filter_name' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{vaults} = $options{custom}->azure_list_vaults(resource_group => $self->{option_results}->{resource_group}); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $vault (@{$self->{vaults}}) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $vault->{name} !~ /$self->{option_results}->{filter_name}/); next if (defined($self->{option_results}->{location}) && $self->{option_results}->{location} ne '' && $vault->{location} !~ /$self->{option_results}->{location}/); my $resource_group = '-'; $resource_group = $vault->{resourceGroup} if (defined($vault->{resourceGroup})); $resource_group = $1 if ($resource_group eq '-' && defined($vault->{id}) && $vault->{id} =~ /resourceGroups\/(.*)\/providers/); my @tags; foreach my $tag (keys %{$vault->{tags}}) { push @tags, $tag . ':' . $vault->{tags}->{$tag}; } $self->{output}->output_add(long_msg => sprintf("[name = %s][resourcegroup = %s][location = %s][id = %s][tags = %s]", $vault->{name}, $resource_group, $vault->{location}, $vault->{id}, join(',', @tags))); } $self->{output}->output_add(severity => 'OK', short_msg => 'List vaults:'); $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', 'resourcegroup', 'location', 'id', 'tags']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $vault (@{$self->{vaults}}) { my $resource_group = '-'; $resource_group = $vault->{resourceGroup} if (defined($vault->{resourceGroup})); $resource_group = $1 if ($resource_group eq '-' && defined($vault->{id}) && $vault->{id} =~ /resourceGroups\/(.*)\/providers/); my @tags; foreach my $tag (keys %{$vault->{tags}}) { push @tags, $tag . ':' . $vault->{tags}->{$tag}; } $self->{output}->add_disco_entry( name => $vault->{name}, resourcegroup => $resource_group, location => $vault->{location}, id => $vault->{id}, tags => join(',', @tags), ); } } 1; __END__ =head1 MODE List vaults. =over 8 =item B<--resource-group> Set resource group. =item B<--location> Set resource location. =item B<--filter-name> Filter vault name (Can be a regexp). =back =cut centreon-plugins-20220113/cloud/azure/management/recovery/plugin.pm000066400000000000000000000037371417000230700253100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::recovery::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} } = ( 'backup-items-status' => 'cloud::azure::management::recovery::mode::backupitemsstatus', 'backup-jobs-status' => 'cloud::azure::management::recovery::mode::backupjobsstatus', 'discovery' => 'cloud::azure::management::recovery::mode::discovery', 'list-backup-jobs' => 'cloud::azure::management::recovery::mode::listbackupjobs', 'list-vaults' => 'cloud::azure::management::recovery::mode::listvaults', ); $self->{custom_modes}{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-07-10' }, }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure backup service. =cut centreon-plugins-20220113/cloud/azure/management/resource/000077500000000000000000000000001417000230700234335ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/management/resource/mode/000077500000000000000000000000001417000230700243575ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/management/resource/mode/deploymentsstatus.pm000066400000000000000000000152361417000230700305330ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::resource::mode::deploymentsstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("Status '%s' [Duration: %s] [Last modified: %s]", $self->{result_values}->{status}, $self->{result_values}->{duration}, $self->{result_values}->{last_modified}); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; $self->{result_values}->{duration} = centreon::plugins::misc::change_seconds(value => $options{new_datas}->{$self->{instance} . '_duration'}); $self->{result_values}->{last_modified} = $options{new_datas}->{$self->{instance} . '_last_modified'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub prefix_global_output { my ($self, %options) = @_; return "Deployments "; } sub prefix_deployment_output { my ($self, %options) = @_; return "Deployment '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }, { name => 'deployments', type => 1, cb_prefix_output => 'prefix_deployment_output', message_multiple => 'All deployments are ok' }, ]; $self->{maps_counters}->{global} = [ { label => 'total-succeeded', set => { key_values => [ { name => 'succeeded' } ], output_template => "succeeded : %s", perfdatas => [ { label => 'total_succeeded', value => 'succeeded', template => '%d', min => 0 }, ], } }, { label => 'total-failed', set => { key_values => [ { name => 'failed' } ], output_template => "failed : %s", perfdatas => [ { label => 'total_failed', value => 'failed', template => '%d', min => 0 }, ], } }, ]; $self->{maps_counters}->{deployments} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'duration' }, { name => 'last_modified' }, { 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 => \&catalog_status_threshold, } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource-group:s" => { name => 'resource_group' }, "filter-counters:s" => { name => 'filter_counters' }, "warning-status:s" => { name => 'warning_status', default => '' }, "critical-status:s" => { name => 'critical_status', default => '%{status} ne "Succeeded"' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource_group}) || $self->{option_results}->{resource_group} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --resource-group option"); $self->{output}->option_exit(); } $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; $self->{global} = { succeeded => 0, failed => 0, }; $self->{deployments} = {}; my $deployments = $options{custom}->azure_list_deployments(resource_group => $self->{option_results}->{resource_group}); foreach my $deployment (@{$deployments}) { my $duration = $options{custom}->convert_duration(time_string => $deployment->{properties}->{duration}); $self->{deployments}->{$deployment->{id}} = { display => $deployment->{name}, status => $deployment->{properties}->{provisioningState}, duration => $duration, last_modified => ($deployment->{properties}->{timestamp} =~ /^(.*)\..*$/) ? $1 : '', }; foreach my $status (keys %{$self->{global}}) { $self->{global}->{$status}++ if ($deployment->{properties}->{provisioningState} =~ /$status/i); } } if (scalar(keys %{$self->{deployments}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No deployments found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check deployments status. Example: perl centreon_plugins.pl --plugin=cloud::azure::management::resource::plugin --custommode=azcli --mode=deployments-status --filter-counters='^total-failed$' --critical-total-failed='1' --verbose =over 8 =item B<--resource-group> Set resource group (Required). =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^total-succeeded$' =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{display} =item B<--critical-status> Set critical threshold for status (Default: '%{status} ne "Succeeded"'). Can used special variables like: %{status}, %{display} =item B<--warning-*> Threshold warning. Can be: 'total-succeeded', 'total-failed'. =item B<--critical-*> Threshold critical. Can be: 'total-succeeded', 'total-failed'. =back =cut centreon-plugins-20220113/cloud/azure/management/resource/mode/items.pm000066400000000000000000000144311417000230700260410ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::resource::mode::items; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_group_output { my ($self, %options) = @_; return "Resource group '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'groups', type => 1, cb_prefix_output => 'prefix_group_output', message_multiple => 'All groups are ok' }, ]; $self->{maps_counters}->{groups} = [ { label => 'total', set => { key_values => [ { name => 'total' } , { name => 'display' } ], output_template => "Total number of items : %s", perfdatas => [ { label => 'total', value => 'total', template => '%d', label_extra_instance => 1, instance_use => 'display', min => 0 }, ], } }, { label => 'compute', set => { key_values => [ { name => 'compute' } , { name => 'display' } ], output_template => "Compute: %s", perfdatas => [ { label => 'compute', value => 'compute', template => '%d', label_extra_instance => 1, instance_use => 'display', min => 0 }, ], } }, { label => 'storage', set => { key_values => [ { name => 'storage' } , { name => 'display' } ], output_template => "Storage: %s", perfdatas => [ { label => 'storage', value => 'storage', template => '%d', label_extra_instance => 1, instance_use => 'display', min => 0 }, ], } }, { label => 'network', set => { key_values => [ { name => 'network' } , { name => 'display' } ], output_template => "Network: %s", perfdatas => [ { label => 'network', value => 'network', template => '%d', label_extra_instance => 1, instance_use => 'display', min => 0 }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource-group:s" => { name => 'resource_group' }, "filter-name:s" => { name => 'filter_name' }, "hidden" => { name => 'hidden' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; my $resources = $options{custom}->azure_list_resources( namespace => '', resource_type => '', location => $self->{option_results}->{location}, resource_group => $self->{option_results}->{resource_group} ); my $groups; if (defined($self->{option_results}->{resource_group}) && $self->{option_results}->{resource_group} ne '') { push @{$groups}, { name => $self->{option_results}->{resource_group} }; } else { $groups = $options{custom}->azure_list_groups(); } foreach my $group (@{$groups}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $group->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $group->{name} . "': no matching filter.", debug => 1); next; } $self->{groups}->{$group->{name}} = { display => $group->{name}, total => 0, compute => 0, storage => 0, network => 0, }; foreach my $item (@{$resources}) { my $resource_group = ''; $resource_group = $item->{resourceGroup} if (defined($item->{resourceGroup})); $resource_group = $1 if (defined($item->{id}) && $item->{id} =~ /resourceGroups\/(.*)\/providers/); next if (defined($resource_group) && $resource_group !~ /$group->{name}/); next if (!defined($self->{option_results}->{hidden}) && $item->{type} =~ /^Microsoft\..*\/.*\/.*/); $self->{groups}->{$group->{name}}->{total}++; $self->{groups}->{$group->{name}}->{compute}++ if ($item->{type} =~ /^Microsoft\.Compute\//); $self->{groups}->{$group->{name}}->{storage}++ if ($item->{type} =~ /^Microsoft\.Storage\//); $self->{groups}->{$group->{name}}->{network}++ if ($item->{type} =~ /^Microsoft\.Network\//); } } if (scalar(keys %{$self->{groups}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No groups found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check number of items in resource groups. Example: perl centreon_plugins.pl --plugin=cloud::azure::management::resource::plugin --custommode=azcli --mode=items --filter-name='.*' --critical-items='10' --verbose =over 8 =item B<--resource-group> Set resource group (Optional). =item B<--filter-name> Filter resource name (Can be a regexp). =item B<--warning-*> Threshold warning. Can be: 'total', 'compute', 'storage', 'network'. =item B<--critical-*> Threshold critical. Can be: 'total', 'compute', 'storage', 'network'. =back =cut centreon-plugins-20220113/cloud/azure/management/resource/mode/listgroups.pm000066400000000000000000000066121417000230700271350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::resource::mode::listgroups; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "location:s" => { name => 'location' }, "filter-name:s" => { name => 'filter_name' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{groups} = $options{custom}->azure_list_groups(); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $group (@{$self->{groups}}) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $group->{name} !~ /$self->{option_results}->{filter_name}/); next if (defined($self->{option_results}->{location}) && $self->{option_results}->{location} ne '' && $group->{location} !~ /$self->{option_results}->{location}/); my @tags; foreach my $tag (keys %{$group->{tags}}) { push @tags, $tag . ':' . $group->{tags}->{$tag}; } $self->{output}->output_add(long_msg => sprintf("[name = %s][location = %s][id = %s][tags = %s]", $group->{name}, $group->{location}, $group->{id}, join(',', @tags))); } $self->{output}->output_add(severity => 'OK', short_msg => 'List groups:'); $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', 'location', 'id', 'tags']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $group (@{$self->{groups}}) { my @tags; foreach my $tag (keys %{$group->{tags}}) { push @tags, $tag . ':' . $group->{tags}->{$tag}; } $self->{output}->add_disco_entry( name => $group->{name}, location => $group->{location}, id => $group->{id}, tags => join(',', @tags), ); } } 1; __END__ =head1 MODE List resources groups. =over 8 =item B<--location> Set group location (Can be a regexp). =item B<--filter-name> Filter group name (Can be a regexp). =back =cut centreon-plugins-20220113/cloud/azure/management/resource/mode/listresources.pm000066400000000000000000000112021417000230700276170ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::resource::mode::listresources; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource-group:s" => { name => 'resource_group' }, "location:s" => { name => 'location' }, "filter-type:s" => { name => 'filter_type' }, "filter-name:s" => { name => 'filter_name' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{resources} = $options{custom}->azure_list_resources( namespace => '', resource_type => '', location => $self->{option_results}->{location}, resource_group => $self->{option_results}->{resource_group} ); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $resource (@{$self->{resources}}) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $resource->{name} !~ /$self->{option_results}->{filter_name}/); next if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' && $resource->{type} !~ /$self->{option_results}->{filter_type}/); my $resource_group = '-'; $resource_group = $resource->{resourceGroup} if (defined($resource->{resourceGroup})); $resource_group = $1 if (defined($resource->{id}) && $resource->{id} =~ /resourceGroups\/(.*)\/providers/); my @tags; foreach my $tag (keys %{$resource->{tags}}) { push @tags, $tag . ':' . $resource->{tags}->{$tag}; } $self->{output}->output_add(long_msg => sprintf("[name = %s][resourcegroup = %s][location = %s][id = %s][type = %s][tags = %s]", $resource->{name}, $resource_group, $resource->{location}, $resource->{id}, $resource->{type}, join(',', @tags), )); } $self->{output}->output_add(severity => 'OK', short_msg => 'List resources:'); $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', 'resourcegroup', 'location', 'id', 'type', 'tags']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $resource (@{$self->{resources}}) { my $resource_group = '-'; $resource_group = $resource->{resourceGroup} if (defined($resource->{resourceGroup})); $resource_group = $1 if (defined($resource->{id}) && $resource->{id} =~ /resourceGroups\/(.*)\/providers/); my @tags; foreach my $tag (keys %{$resource->{tags}}) { push @tags, $tag . ':' . $resource->{tags}->{$tag}; } $self->{output}->add_disco_entry( name => $resource->{name}, resourcegroup => $resource_group, location => $resource->{location}, id => $resource->{id}, type => $resource->{type}, tags => join(',', @tags), ); } } 1; __END__ =head1 MODE List resources. =over 8 =item B<--resource-group> Set resource group. =item B<--location> Set resource location. =item B<--filter-type> Filter resource type (Can be a regexp). =item B<--filter-name> Filter resource name (Can be a regexp). =back =cut centreon-plugins-20220113/cloud/azure/management/resource/plugin.pm000066400000000000000000000035731417000230700252770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::management::resource::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} } = ( 'deployments-status' => 'cloud::azure::management::resource::mode::deploymentsstatus', 'list-groups' => 'cloud::azure::management::resource::mode::listgroups', 'list-resources' => 'cloud::azure::management::resource::mode::listresources', 'items' => 'cloud::azure::management::resource::mode::items', ); $self->{custom_modes}{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' }, }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure resource manager. =cut centreon-plugins-20220113/cloud/azure/network/000077500000000000000000000000001417000230700211615ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/network/appgateway/000077500000000000000000000000001417000230700233235ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/network/appgateway/mode/000077500000000000000000000000001417000230700242475ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/network/appgateway/mode/backendhealth.pm000066400000000000000000000116411417000230700273650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::appgateway::mode::backendhealth; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'unhealthyhostcount' => { 'output' => 'Unhealthy Host Count', 'label' => 'unhealthy-host-count', 'nlabel' => 'appgateway.backend.unhealthy.host.count', 'unit' => '', 'min' => '0' }, 'healthyhostcount' => { 'output' => 'Healthy Host Count', 'label' => 'healthy-host-count', 'nlabel' => 'appgateway.backend.healthy.host.count', 'unit' => '', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Network\/applicationGateways\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'applicationGateways'; $self->{az_resource_namespace} = 'Microsoft.Network'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Application Gateway backend hosts health statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::network::appgateway::plugin --mode=backend-health --custommode=api --resource= --resource-group= --aggregation='average' --warning-unhealthy-host-count='1' --critical-unhealthy-host-count='2' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::network::appgateway::plugin --mode=backend-health --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Network/applicationGateways/' --aggregation='average' --warning-unhealthy-host-count='1' --critical-unhealthy-host-count='2' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'healthyhostcount', 'unhealthyhostcount'. =item B<--critical-*> Critical threshold where '*' can be: 'healthyhostcount', 'unhealthyhostcount'. =back =cut centreon-plugins-20220113/cloud/azure/network/appgateway/mode/backendstatus.pm000066400000000000000000000110671417000230700274450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::appgateway::mode::backendstatus; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'backendresponsestatus' => { 'output' => 'Backend Response Status', 'label' => 'response-status', 'nlabel' => 'appgateway.backend.response.status.count', 'unit' => '', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Network\/applicationGateways\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'applicationGateways'; $self->{az_resource_namespace} = 'Microsoft.Network'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Application Gateway backend response status. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::network::appgateway::plugin --mode=backend-status --custommode=api --resource= --resource-group= --aggregation='total' --warning-response-status='1000' --critical-response-status='2000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::integration::servicebus::plugin --mode=backend-status --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Network/applicationGateways/' --aggregation='total' --warning-response-status='1000' --critical-response-status='2000' Default aggregation: 'total' / 'average', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-response-status> Warning threshold. =item B<--critical-response-status> Critical threshold. =back =cut centreon-plugins-20220113/cloud/azure/network/appgateway/mode/backendtime.pm000066400000000000000000000124761417000230700270650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::appgateway::mode::backendtime; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'backendconnecttime' => { 'output' => 'Backend Connect Time', 'label' => 'connect-time', 'nlabel' => 'appgateway.backend.connect.time.milliseconds', 'unit' => 'ms', 'min' => '0' }, 'backendfirstbyteresponsetime' => { 'output' => 'Backend First Byte Response Time', 'label' => 'firstbyte-response-time', 'nlabel' => 'appgateway.backend.firstbyte.responsetime.milliseconds', 'unit' => 'ms', 'min' => '0' }, 'backendlastbyteresponsetime' => { 'output' => 'Backend Last Byte Response Time', 'label' => 'lastbyte-response-time', 'nlabel' => 'appgateway.backend.lastbyte.responsetime.milliseconds', 'unit' => 'ms', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Network\/applicationGateways\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'applicationGateways'; $self->{az_resource_namespace} = 'Microsoft.Network'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Application Gateway backend response time. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::network::appgateway::plugin --mode=backend-time --custommode=api --resource= --resource-group= --aggregation='average' --warning-lastbyte-response-time='1000' --critical-lastbyte-response-time='2000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::integration::servicebus::plugin --mode=backend-time --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Network/applicationGateways/' --aggregation='average' --warning-lastbyte-response-time='1000' --critical-lastbyte-response-time='2000' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'connect-time', 'lastbyte-response-time', 'firstbyte-response-time'. =item B<--critical-*> Critical threshold where '*' can be: 'connect-time', 'lastbyte-response-time', 'firstbyte-response-time'. =back =cut centreon-plugins-20220113/cloud/azure/network/appgateway/mode/clientstraffic.pm000066400000000000000000000116711417000230700276130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::appgateway::mode::clientstraffic; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'bytesreceived' => { 'output' => 'Clients Bytes Received', 'label' => 'clients-bytes-received', 'nlabel' => 'appgateway.traffic.clients.received.bytes', 'unit' => 'B', 'min' => '0' }, 'bytessent' => { 'output' => 'Clients Bytes Sent', 'label' => 'clients-bytes-sent', 'nlabel' => 'appgateway.traffic.clients.sent.bytes', 'unit' => 'B', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Network\/applicationGateways\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'applicationGateways'; $self->{az_resource_namespace} = 'Microsoft.Network'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Application Gateway clients traffic statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::network::appgateway::plugin --mode=clients-traffic --custommode=api --resource= --resource-group= --aggregation='total' --warning-lastbyte-response-time='1000' --critical-lastbyte-response-time='2000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::integration::servicebus::plugin --mode=clients-traffic --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Network/applicationGateways/' --aggregation='total' --warning-lastbyte-response-time='1000' --critical-lastbyte-response-time='2000' Default aggregation: 'total' / 'average', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'clients-bytes-received', 'clients-bytes-sent'. =item B<--critical-*> Critical threshold where '*' can be: 'clients-bytes-received', 'clients-bytes-sent'. =back =cut centreon-plugins-20220113/cloud/azure/network/appgateway/mode/connections.pm000066400000000000000000000111151417000230700271260ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::appgateway::mode::connections; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'currentconnections' => { 'output' => 'Current Connections', 'label' => 'current-connections', 'nlabel' => 'appgateway.backend.connections.current.count', 'unit' => '', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Network\/applicationGateways\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'applicationGateways'; $self->{az_resource_namespace} = 'Microsoft.Network'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Application Gateway connections statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::network::appgateway::plugin --mode=connections --custommode=api --resource= --resource-group= --aggregation='average' --warning-current-connections='1000' --critical-current-connections='2000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::integration::servicebus::plugin --mode=connections --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Network/applicationGateways/' --aggregation='average' --warning-current-connections='1000' --critical-current-connections='2000' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-current-connections> Warning threshold. =item B<--critical-current-connections> Critical threshold. =back =cut centreon-plugins-20220113/cloud/azure/network/appgateway/mode/discovery.pm000066400000000000000000000024731417000230700266220ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::appgateway::mode::discovery; use base qw(cloud::azure::management::monitor::mode::discovery); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{namespace} = 'Microsoft.Network'; $self->{type} = 'applicationGateways'; } 1; __END__ =head1 MODE Discover Azure Network Application Gateway resources. =over 8 =item B<--resource-group> Specify resource group. =item B<--location> Specify location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/network/appgateway/mode/gatewaytime.pm000066400000000000000000000110331417000230700271230ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::appgateway::mode::gatewaytime; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'applicationgatewaytotaltime' => { 'output' => 'Application Gateway Total Time', 'label' => 'total-time', 'nlabel' => 'appgateway.time.total.milliseconds', 'unit' => 'ms', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Network\/applicationGateways\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'applicationGateways'; $self->{az_resource_namespace} = 'Microsoft.Network'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Application Gateway total processing time. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::network::appgateway::plugin --mode=gateway-time --custommode=api --resource= --resource-group= --aggregation='average' --warning-total-time='1000' --critical-total-time='2000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::integration::servicebus::plugin --mode=gateway-time --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Network/applicationGateways/' --aggregation='average' --warning-total-time='1000' --critical-total-time='2000' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-total-time> Warning threshold. =item B<--critical-total-time> Critical threshold. =back =cut centreon-plugins-20220113/cloud/azure/network/appgateway/mode/health.pm000066400000000000000000000037041417000230700260560ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::appgateway::mode::health; use base qw(cloud::azure::management::monitor::mode::health); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{az_resource_namespace} = 'Microsoft.Network'; $self->{az_resource_type} = 'applicationGateways'; } 1; __END__ =head1 MODE Check Azure Network Application Gateway status. (Useful to determine host status) =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{summary} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /^Unavailable$/'). Can used special variables like: %{status}, %{summary} =item B<--unknown-status> Set unknown threshold for status (Default: '%{status} =~ /^Unknown$/'). Can used special variables like: %{status}, %{summary} =item B<--ok-status> Set ok threshold for status (Default: '%{status} =~ /^Available$/'). Can used special variables like: %{status}, %{summary} =back =cut centreon-plugins-20220113/cloud/azure/network/appgateway/mode/requests.pm000066400000000000000000000115121417000230700264600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::appgateway::mode::requests; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'failedrequests' => { 'output' => 'Failed Requests', 'label' => 'failed-requests', 'nlabel' => 'appgateway.requests.failed.count', 'unit' => '', 'min' => '0' }, 'totalrequests' => { 'output' => 'Total Requests', 'label' => 'total-requests', 'nlabel' => 'appgateway.requests.total.count', 'unit' => '', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Network\/applicationGateways\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'applicationGateways'; $self->{az_resource_namespace} = 'Microsoft.Network'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Application Gateway requests statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::network::appgateway::plugin --mode=requests --custommode=api --resource= --resource-group= --aggregation='total' --warning-failed-requests='1000' --critical-failed-requests='2000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::integration::servicebus::plugin --mode=requests --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Network/applicationGateways/' --aggregation='total' --warning-failed-requests='1000' --critical-failed-requests='2000' Default aggregation: 'total' / 'average', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'failed-requests', 'total-requests'. =item B<--critical-*> Critical threshold where '*' can be: 'failed-requests', 'total-requests'. =back =cut centreon-plugins-20220113/cloud/azure/network/appgateway/mode/throughput.pm000066400000000000000000000107641417000230700270260ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::appgateway::mode::throughput; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'throughput' => { 'output' => 'Throughput', 'label' => 'throughput', 'nlabel' => 'appgateway.throughput.bytespersecond', 'unit' => 'B/s', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Network\/applicationGateways\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'applicationGateways'; $self->{az_resource_namespace} = 'Microsoft.Network'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Application Gateway throughput statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::network::appgateway::plugin --mode=throughput --custommode=api --resource= --resource-group= --aggregation='average' --warning-throughput='1000' --critical-throughput='2000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::integration::servicebus::plugin --mode=throughput --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Network/applicationGateways/' --aggregation='average' --warning-throughput='1000' --critical-throughput='2000' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-throughput> Warning threshold. =item B<--critical-throughput> Critical threshold. =back =cut centreon-plugins-20220113/cloud/azure/network/appgateway/mode/units.pm000066400000000000000000000127341417000230700257560ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::appgateway::mode::units; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'capacityunits' => { 'output' => 'Capacity Units consumed', 'label' => 'capacity-units', 'nlabel' => 'appgateway.capacity.units.count', 'unit' => '', 'min' => '0' }, 'computeunits' => { 'output' => 'Compute Units consumed', 'label' => 'compute-units', 'nlabel' => 'appgateway.compute.units.count', 'unit' => '', 'min' => '0' }, 'estimatedbilledcapacityunits' => { 'output' => 'Estimated Billed Capacity Units', 'label' => 'estimated-billed-units', 'nlabel' => 'appgateway.billed.units.estimated.count', 'unit' => '', 'min' => '0' }, 'fixedbillablecapacityunits' => { 'output' => 'Fixed Billable Capacity Units', 'label' => 'fixed-billable-units', 'nlabel' => 'appgateway.billable.units.fixed.count', 'unit' => '', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Network\/applicationGateways\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'applicationGateways'; $self->{az_resource_namespace} = 'Microsoft.Network'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Application Gateway units statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::network::appgateway::plugin --mode=units --custommode=api --resource= --resource-group= --aggregation='average' --warning-compute-units='1000' --critical-compute-units='2000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::integration::servicebus::plugin --mode=units --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Network/applicationGateways/' --aggregation='average' --warning-compute-units='1000' --critical-compute-units='2000' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'estimated-billed-units', 'fixed-billable-units', 'compute-units', 'capacity-units'. =item B<--critical-*> Critical threshold where '*' can be: 'estimated-billed-units', 'fixed-billable-units', 'compute-units', 'capacity-units'. =back =cut centreon-plugins-20220113/cloud/azure/network/appgateway/plugin.pm000066400000000000000000000046701417000230700251660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::appgateway::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} = { 'backend-health' => 'cloud::azure::network::appgateway::mode::backendhealth', 'backend-status' => 'cloud::azure::network::appgateway::mode::backendstatus', 'backend-time' => 'cloud::azure::network::appgateway::mode::backendtime', 'clients-traffic' => 'cloud::azure::network::appgateway::mode::clientstraffic', 'connections' => 'cloud::azure::network::appgateway::mode::connections', 'discovery' => 'cloud::azure::network::appgateway::mode::discovery', 'gateway-time' => 'cloud::azure::network::appgateway::mode::gatewaytime', 'health' => 'cloud::azure::network::appgateway::mode::health', 'requests' => 'cloud::azure::network::appgateway::mode::requests', 'throughput' => 'cloud::azure::network::appgateway::mode::throughput', 'units' => 'cloud::azure::network::appgateway::mode::units' }; $self->{custom_modes}->{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}->{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' }, }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure Network Application Gateway resources. =cut centreon-plugins-20220113/cloud/azure/network/cdn/000077500000000000000000000000001417000230700217255ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/network/cdn/mode/000077500000000000000000000000001417000230700226515ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/network/cdn/mode/discovery.pm000066400000000000000000000024041417000230700252160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::cdn::mode::discovery; use base qw(cloud::azure::management::monitor::mode::discovery); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{namespace} = 'Microsoft.Cdn'; $self->{type} = 'profiles'; } 1; __END__ =head1 MODE Azure CDN discovery. =over 8 =item B<--resource-group> Specify resource group. =item B<--location> Specify location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/network/cdn/mode/hitratio.pm000066400000000000000000000107261417000230700250400ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::cdn::mode::hitratio; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'bytehitratio' => { 'output' => 'Byte Hit Ratio', 'label' => 'byte-hit-percentage', 'nlabel' => 'cdn.byte.hit.percentage', 'unit' => '%', 'min' => '0', 'max' => '100' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Cdn\/profiles\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'profiles'; $self->{az_resource_namespace} = 'Microsoft.Cdn'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure CDN byte hit ratio. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::network::cdn::plugin --mode=hit-ratio --custommode=api --resource= --resource-group= --aggregation='average' --warning-byte-hit-percentage='20:' --critical-byte-hit-percentage='10:' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::network::cdn::plugin --mode=hit-ratio --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Cdn/profiles/' --aggregation='average' --warning-byte-hit-percentage='20:' --critical-byte-hit-percentage='10:' Default aggregation: 'average' / 'minimum', 'maximum' and 'total' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-byte-hit-percentage> Warning threshold. =item B<--critical-byte-hit-percentage> Critical threshold. =back =cut centreon-plugins-20220113/cloud/azure/network/cdn/mode/latency.pm000066400000000000000000000106421417000230700246510ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::cdn::mode::latency; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'totallatency' => { 'output' => 'Total Latency', 'label' => 'total-latency', 'nlabel' => 'cdn.latency.total.milliseconds', 'unit' => 'ms', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Cdn\/profiles\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'profiles'; $self->{az_resource_namespace} = 'Microsoft.Cdn'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure CDN latency. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::network::cdn::plugin --mode=latency --custommode=api --resource= --resource-group= --aggregation='average' --warning-total-latency='50' --critical-total-latency='100' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::network::cdn::plugin --mode=latency --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Cdn/profiles/' --aggregation='average' --warning-total-latency='50' --critical-total-latency='100' Default aggregation: 'average' / 'minimum', 'maximum' and 'total' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-total-latency> Warning threshold. =item B<--critical-total-latency> Critical threshold. =back =cut centreon-plugins-20220113/cloud/azure/network/cdn/mode/requests.pm000066400000000000000000000111731417000230700250650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::cdn::mode::requests; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'requestcount' => { 'output' => 'Request count', 'label' => 'requests-count', 'nlabel' => 'cdn.requests.count', 'unit' => '', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Cdn\/profiles\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'profiles'; $self->{az_resource_namespace} = 'Microsoft.Cdn'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure CDN request count. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::network::cdn::plugin --mode=requests --custommode=api --resource= --resource-group= --aggregation='count' --warning-requests-count='2000' --critical-requests-count='3000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::network::cdn::plugin --mode=requests --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Cdn/profiles/' --aggregation='count' --warning-requests-count='800' --critical-requests-count='900' Default aggregation: 'total' / 'minimum', 'maximum', 'count' and 'average' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'requests-count', '4xx-requests-percentage',, '5xx-requests-percentage', 'firewall-requests-count'. =item B<--critical-*> Critical threshold where '*' can be: 'requests-count', '4xx-requests-percentage',, '5xx-requests-percentage', 'firewall-requests-count'. =back =cut centreon-plugins-20220113/cloud/azure/network/cdn/mode/response.pm000066400000000000000000000107401417000230700250470ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::cdn::mode::response; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'responsesize' => { 'output' => 'Response Size', 'label' => 'response-size', 'nlabel' => 'cdn.response.size.bytes', 'unit' => 'B', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Cdn\/profiles\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'profiles'; $self->{az_resource_namespace} = 'Microsoft.Cdn'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure CDN response size. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::network::cdn::plugin --mode=response --custommode=api --resource= --resource-group= --aggregation='average' --warning-response-size='8000000' --critical-response-size='9000000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::network::cdn::plugin --mode=response --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Cdn/profiles/' --aggregation='average' --warning-response-size='8000000' --critical-response-size='9000000' Default aggregation: 'average / 'minimum', 'maximum' and 'total' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'response-size'. =item B<--critical-*> Critical threshold where '*' can be: 'response-size'. =back =cut centreon-plugins-20220113/cloud/azure/network/cdn/plugin.pm000066400000000000000000000035341417000230700235660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::cdn::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} = { 'discovery' => 'cloud::azure::network::cdn::mode::discovery', 'hit-ratio' => 'cloud::azure::network::cdn::mode::hitratio', 'latency' => 'cloud::azure::network::cdn::mode::latency', 'requests' => 'cloud::azure::network::cdn::mode::requests', 'response' => 'cloud::azure::network::cdn::mode::response', }; $self->{custom_modes}->{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}->{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' } }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure CDN profile service. =cut centreon-plugins-20220113/cloud/azure/network/expressroute/000077500000000000000000000000001417000230700237315ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/network/expressroute/mode/000077500000000000000000000000001417000230700246555ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/network/expressroute/mode/circuitstatus.pm000066400000000000000000000146171417000230700301320ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::expressroute::mode::circuitstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("Status '%s', Provider Status '%s' [Name: %s] [Location: %s]", $self->{result_values}->{circuit_status}, $self->{result_values}->{provider_status}, $self->{result_values}->{provider_name}, $self->{result_values}->{provider_location}); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{circuit_status} = $options{new_datas}->{$self->{instance} . '_circuit_status'}; $self->{result_values}->{provider_status} = $options{new_datas}->{$self->{instance} . '_provider_status'}; $self->{result_values}->{provider_name} = $options{new_datas}->{$self->{instance} . '_provider_name'}; $self->{result_values}->{provider_location} = $options{new_datas}->{$self->{instance} . '_provider_location'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub prefix_circuit_output { my ($self, %options) = @_; return "Circuit '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'circuits', type => 1, cb_prefix_output => 'prefix_circuit_output', message_multiple => 'All circuits are ok' }, ]; $self->{maps_counters}->{circuits} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'circuit_status' }, { name => 'provider_status' }, { name => 'provider_name' }, { name => 'provider_location' }, { 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 => \&catalog_status_threshold, } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource-group:s" => { name => 'resource_group' }, "location:s" => { name => 'location' }, "filter-name:s" => { name => 'filter_name' }, "warning-status:s" => { name => 'warning_status', default => '' }, "critical-status:s" => { name => 'critical_status', default => '%{circuit_status} ne "Enabled" || %{provider_status} ne "Provisioned"' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; $self->{circuits} = {}; my $circuits = $options{custom}->azure_list_expressroute_circuits(resource_group => $self->{option_results}->{resource_group}); foreach my $circuit (@{$circuits}) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $circuit->{name} !~ /$self->{option_results}->{filter_name}/); next if (defined($self->{option_results}->{location}) && $self->{option_results}->{location} ne '' && $circuit->{location} !~ /$self->{option_results}->{location}/); $self->{circuits}->{$circuit->{id}} = { display => $circuit->{name}, circuit_status => ($circuit->{circuitProvisioningState}) ? $circuit->{circuitProvisioningState} : $circuit->{properties}->{circuitProvisioningState}, provider_status => ($circuit->{serviceProviderProvisioningState}) ? $circuit->{serviceProviderProvisioningState} : $circuit->{properties}->{serviceProviderProvisioningState}, provider_name => ($circuit->{serviceProviderProperties}->{serviceProviderName}) ? $circuit->{serviceProviderProperties}->{serviceProviderName} : $circuit->{properties}->{serviceProviderProperties}->{serviceProviderName}, provider_location => ($circuit->{serviceProviderProperties}->{peeringLocation}) ? $circuit->{serviceProviderProperties}->{peeringLocation} : $circuit->{properties}->{serviceProviderProperties}->{peeringLocation}, }; } if (scalar(keys %{$self->{circuits}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No ExpressRoute circuits found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check ExpressRoute circuits status. Example: perl centreon_plugins.pl --plugin=cloud::azure::network::expressroute::plugin --custommode=azcli --mode=circuit-status --resource-group='MYRESOURCEGROUP' --verbose =over 8 =item B<--resource-group> Set resource group. =item B<--location> Set resource location. =item B<--filter-name> Filter circuit name (Can be a regexp). =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{circuit_status}, %{provider_status}, %{display} =item B<--critical-status> Set critical threshold for status (Default: '%{circuit_status} ne "Enabled" || %{provider_status} ne "Provisioned"'). Can used special variables like: %{circuit_status}, %{provider_status}, %{display} =back =cut centreon-plugins-20220113/cloud/azure/network/expressroute/mode/discovery.pm000066400000000000000000000024411417000230700272230ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::expressroute::mode::discovery; use base qw(cloud::azure::management::monitor::mode::discovery); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{namespace} = 'Microsoft.Network'; $self->{type} = 'expressRouteCircuits'; } 1; __END__ =head1 MODE Express Route discovery. =over 8 =item B<--resource-group> Specify resource group. =item B<--location> Specify location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/network/expressroute/mode/health.pm000066400000000000000000000037021417000230700264620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::expressroute::mode::health; use base qw(cloud::azure::management::monitor::mode::health); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{az_resource_namespace} = 'Microsoft.Network'; $self->{az_resource_type} = 'expressRouteCircuits'; } 1; __END__ =head1 MODE Check ExpressRoute Circuit health status. (Usefull to determine host status) =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{summary} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /^Unavailable$/'). Can used special variables like: %{status}, %{summary} =item B<--unknown-status> Set unknown threshold for status (Default: '%{status} =~ /^Unknown$/'). Can used special variables like: %{status}, %{summary} =item B<--ok-status> Set ok threshold for status (Default: '%{status} =~ /^Available$/'). Can used special variables like: %{status}, %{summary} =back =cut centreon-plugins-20220113/cloud/azure/network/expressroute/mode/listcircuits.pm000066400000000000000000000105311417000230700277340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::expressroute::mode::listcircuits; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource-group:s" => { name => 'resource_group' }, "location:s" => { name => 'location' }, "filter-name:s" => { name => 'filter_name' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{circuits} = $options{custom}->azure_list_expressroute_circuits( resource_group => $self->{option_results}->{resource_group} ); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $circuit (@{$self->{circuits}}) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $circuit->{name} !~ /$self->{option_results}->{filter_name}/); next if (defined($self->{option_results}->{location}) && $self->{option_results}->{location} ne '' && $circuit->{location} !~ /$self->{option_results}->{location}/); my $resource_group = '-'; $resource_group = $circuit->{resourceGroup} if (defined($circuit->{resourceGroup})); $resource_group = $1 if ($resource_group eq '-' && defined($circuit->{id}) && $circuit->{id} =~ /resourceGroups\/(.*)\/providers/); my @tags; foreach my $tag (keys %{$circuit->{tags}}) { push @tags, $tag . ':' . $circuit->{tags}->{$tag}; } $self->{output}->output_add(long_msg => sprintf("[name = %s][resourcegroup = %s][location = %s][id = %s][tags = %s]", $circuit->{name}, $resource_group, $circuit->{location}, $circuit->{id}, join(',', @tags), )); } $self->{output}->output_add(severity => 'OK', short_msg => 'List ExpressRoute circuits:'); $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', 'resourcegroup', 'location', 'id', 'tags']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $circuit (@{$self->{circuits}}) { my $resource_group = '-'; $resource_group = $circuit->{resourceGroup} if (defined($circuit->{resourceGroup})); $resource_group = $1 if ($resource_group eq '-' && defined($circuit->{id}) && $circuit->{id} =~ /resourceGroups\/(.*)\/providers/); my @tags; foreach my $tag (keys %{$circuit->{tags}}) { push @tags, $tag . ':' . $circuit->{tags}->{$tag}; } $self->{output}->add_disco_entry( name => $circuit->{name}, resourcegroup => $resource_group, location => $circuit->{location}, id => $circuit->{id}, tags => join(',', @tags), ); } } 1; __END__ =head1 MODE List ExpressRoute circuits. =over 8 =item B<--resource-group> Set resource group. =item B<--location> Set resource location. =item B<--filter-name> Filter resource name (Can be a regexp). =back =cut centreon-plugins-20220113/cloud/azure/network/expressroute/mode/traffic.pm000066400000000000000000000254321417000230700266370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::expressroute::mode::traffic; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_traffic_output { my ($self, %options) = @_; return "Circuit '" . $options{instance_value}->{display} . "' " . $options{instance_value}->{stat} . " "; } sub custom_traffic_calc { my ($self, %options) = @_; $self->{result_values}->{stat} = $options{new_datas}->{$self->{instance} . '_stat'}; $self->{result_values}->{metric_perf} = lc($options{extra_options}->{metric_perf}); $self->{result_values}->{metric_label} = lc($options{extra_options}->{metric_label}); $self->{result_values}->{metric_name} = $options{new_datas}->{$self->{instance} . '_' . $self->{result_values}->{metric_perf} . '_' . $self->{result_values}->{stat} . '_name'}; $self->{result_values}->{timeframe} = $options{new_datas}->{$self->{instance} . '_timeframe'}; $self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_' . $self->{result_values}->{metric_perf} . '_' . $self->{result_values}->{stat}}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub custom_metric_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check(value => $self->{result_values}->{value}, threshold => [ { label => 'critical-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}, exit_litteral => 'warning' } ]); return $exit; } sub custom_traffic_perfdata { my ($self, %options) = @_; my $extra_label = ''; $extra_label = '_' . lc($self->{result_values}->{display}) if (!defined($options{extra_instance}) || $options{extra_instance} != 0); $self->{output}->perfdata_add(label => $self->{result_values}->{metric_perf} . "_" . $self->{result_values}->{stat} . $extra_label, unit => 'b/s', value => sprintf("%d", $self->{result_values}->{value}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}), min => 0 ); } sub custom_traffic_output { my ($self, %options) = @_; my ($value, $unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{value}, network => 1); my $msg = $self->{result_values}->{metric_name} . ": " . $value . $unit . "/s"; return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_traffic_output', message_multiple => "All traffic metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $aggregation ('minimum', 'maximum', 'average', 'total') { foreach my $metric ('BitsInPerSecond', 'BitsOutPerSecond') { my $metric_perf = lc($metric); my $metric_label = lc($metric); $metric_perf =~ s/ /_/g; $metric_label =~ s/ /-/g; my $entry = { label => $metric_label . '-' . $aggregation, set => { key_values => [ { name => $metric_perf . '_' . $aggregation }, { name => 'display' }, { name => 'stat' }, { name => 'stat' }, { name => $metric_perf . '_' . $aggregation . '_name' } ], closure_custom_calc => $self->can('custom_traffic_calc'), closure_custom_calc_extra_options => { metric_perf => $metric_perf, metric_label => $metric_label }, closure_custom_output => $self->can('custom_traffic_output'), closure_custom_perfdata => $self->can('custom_traffic_perfdata'), closure_custom_threshold_check => $self->can('custom_traffic_threshold'), } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource:s@" => { name => 'resource' }, "resource-group:s" => { name => 'resource_group' }, "filter-metric:s" => { name => 'filter_metric' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource})) { $self->{output}->add_option_msg(short_msg => "Need to specify either --resource with --resource-group option or --resource ."); $self->{output}->option_exit(); } $self->{az_resource} = $self->{option_results}->{resource}; $self->{az_resource_group} = $self->{option_results}->{resource_group} if (defined($self->{option_results}->{resource_group})); $self->{az_resource_type} = 'expressRouteCircuits'; $self->{az_resource_namespace} = 'Microsoft.Network'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : "PT5M"; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric ('BitsInPerSecond', 'BitsOutPerSecond') { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $resource (@{$self->{az_resource}}) { my $resource_group = $self->{az_resource_group}; my $resource_name = $resource; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Network\/expressRouteCircuits\/(.*)$/) { $resource_group = $1; $resource_name = $2; } ($metric_results{$resource_name}, undef, undef) = $options{custom}->azure_get_metrics( resource => $resource_name, resource_group => $resource_group, resource_type => $self->{az_resource_type}, resource_namespace => $self->{az_resource_namespace}, metrics => $self->{az_metrics}, aggregations => $self->{az_aggregations}, timeframe => $self->{az_timeframe}, interval => $self->{az_interval}, ); foreach my $metric (@{$self->{az_metrics}}) { my $metric_name = lc($metric); $metric_name =~ s/ /_/g; foreach my $aggregation (@{$self->{az_aggregations}}) { next if (!defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{display} = $resource_name; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{timeframe} = $self->{az_timeframe}; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{stat} = lc($aggregation); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{$metric_name . "_" . lc($aggregation) . '_name'} = $metric_results{$resource_name}->{$metric_name}->{name}; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{$metric_name . "_" . lc($aggregation)} = defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) ? $metric_results{$resource_name}->{$metric_name}->{lc($aggregation)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check circuit traffic metrics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::network::expressroute::plugin --custommode=azcli --mode=traffic --resource=MYCIRCUIT --resource-group=MYHOSTGROUP --aggregation='average' --critical-bitsinpersecond-average='10' --verbose Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::network::expressroute::plugin --custommode=azcli --mode=traffic --resource='/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Network/expressRouteCircuits/xxx' --aggregation='average' --critical-bitsinpersecond-average='10' --verbose Default aggregation: 'average' / 'average', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--filter-metric> Filter metrics (Can be: 'BitsInPerSecond', 'BitsOutPerSecond') (Can be a regexp). =item B<--warning-$metric$-$aggregation$> Thresholds warning ($metric$ can be: 'bitsinpersecond', 'bitsoutpersecond', $aggregation$ can be: 'minimum', 'maximum', 'average'). =item B<--critical-$metric$-$aggregation$> Thresholds critical ($metric$ can be: 'bitsinpersecond', 'bitsoutpersecond', $aggregation$ can be: 'minimum', 'maximum', 'average'). =back =cut centreon-plugins-20220113/cloud/azure/network/expressroute/plugin.pm000066400000000000000000000036751417000230700256000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::expressroute::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} } = ( 'circuit-status' => 'cloud::azure::network::expressroute::mode::circuitstatus', 'discovery' => 'cloud::azure::network::expressroute::mode::discovery', 'health' => 'cloud::azure::network::expressroute::mode::health', 'list-circuits' => 'cloud::azure::network::expressroute::mode::listcircuits', 'traffic' => 'cloud::azure::network::expressroute::mode::traffic', ); $self->{custom_modes}{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' }, }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure ExpressRoute. =cut centreon-plugins-20220113/cloud/azure/network/firewall/000077500000000000000000000000001417000230700227665ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/network/firewall/mode/000077500000000000000000000000001417000230700237125ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/network/firewall/mode/discovery.pm000066400000000000000000000024301417000230700262560ustar00rootroot00000000000000# # Copyright 2020 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::azure::network::firewall::mode::discovery; use base qw(cloud::azure::management::monitor::mode::discovery); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{namespace} = 'Microsoft.Network'; $self->{type} = 'azurefirewalls'; } 1; __END__ =head1 MODE Azure Firewall discovery. =over 8 =item B<--resource-group> Specify resource group. =item B<--location> Specify location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/network/firewall/mode/health.pm000066400000000000000000000110101417000230700255060ustar00rootroot00000000000000# # Copyright 2020 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::azure::network::firewall::mode::health; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'firewallhealth' => { 'output' => 'Firewall health state', 'label' => 'firewall-health-percentage', 'nlabel' => 'firewall.health.percentage', 'unit' => '%', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Network\/azurefirewalls\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'azurefirewalls'; $self->{az_resource_namespace} = 'Microsoft.Network'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Network Firewall health metrics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::network::firewall::plugin --mode=health --custommode=api --resource= --resource-group= --aggregation='average' --warning-firewall-health='100:' --critical-firewall-health='50:' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::network::firewall::plugin --mode=health --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Network/azurefirewalls/' --aggregation='average' --warning-firewall-health='100:' --critical-firewall-health='50:' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<---warning-firewall-health-percentage> Warning threshold. =item B<--critical-firewall-health-percentage> Critical threshold. =back =cut centreon-plugins-20220113/cloud/azure/network/firewall/mode/hits.pm000066400000000000000000000115721417000230700252250ustar00rootroot00000000000000# # Copyright 2020 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::azure::network::firewall::mode::hits; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'applicationrulehit' => { 'output' => 'Application rules hit count', 'label' => 'application-rules-hits', 'nlabel' => 'firewall.applications.rules.hits.count', 'unit' => '', 'min' => '0' }, 'networkrulehit' => { 'output' => 'Network rules hit count', 'label' => 'network-rules-hits', 'nlabel' => 'firewall.newtork.rules.hits.count', 'unit' => '', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Network\/azurefirewalls\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'azurefirewalls'; $self->{az_resource_namespace} = 'Microsoft.Network'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Network Firewall hits metrics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::network::firewall::plugin --mode=hits --custommode=api --resource= --resource-group= --aggregation='total' --warning-application-rules-hits='5000' --critical-application-rules-hits='10000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::network::firewall::plugin --mode=hits --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Network/azurefirewalls/' --aggregation='total' --warning-application-rules-hits='5000' --critical-application-rules-hits='10000' Default aggregation: 'total' / 'average', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<---warning-*> Warning threshold where '*' can be: 'application-rules-hits', 'network-rules-hits'. =item B<--critical-*> Critical threshold where '*' can be: 'application-rules-hits', 'network-rules-hits'. =back =cut centreon-plugins-20220113/cloud/azure/network/firewall/mode/throughput.pm000066400000000000000000000114241417000230700264630ustar00rootroot00000000000000# # Copyright 2020 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::azure::network::firewall::mode::throughput; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'dataprocessed' => { 'output' => 'Data processed', 'label' => 'processed-data', 'nlabel' => 'firewall.data.processed.bytes', 'unit' => 'B', 'min' => '0' }, 'Throughput' => { 'output' => 'Throughput', 'label' => 'throughput', 'nlabel' => 'firewall.throughput.bitspersecond', 'unit' => 'b/s', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Network\/azurefirewalls\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'azurefirewalls'; $self->{az_resource_namespace} = 'Microsoft.Network'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Network Firewall throughput metrics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::network::firewall::plugin --mode=throughput --custommode=api --resource= --resource-group= --aggregation='average' --warning-throughput='50000' --critical-throughput='100000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::network::firewall::plugin --mode=throughput --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Network/azurefirewalls/' --aggregation='average' --warning-throughput='50000' --critical-throughput='100000' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<---warning-*> Warning threshold where '*' can be: 'processed-data', 'throughput'. =item B<--critical-*> Critical threshold where '*' can be: 'processed-data', 'throughput'. =back =cut centreon-plugins-20220113/cloud/azure/network/firewall/plugin.pm000066400000000000000000000034461417000230700246310ustar00rootroot00000000000000# # Copyright 2020 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::azure::network::firewall::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} = { 'discovery' => 'cloud::azure::network::firewall::mode::discovery', 'health' => 'cloud::azure::network::firewall::mode::health', 'hits' => 'cloud::azure::network::firewall::mode::hits', 'throughput' => 'cloud::azure::network::firewall::mode::throughput' }; $self->{custom_modes}->{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}->{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' }, }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure Firewalls. =cut centreon-plugins-20220113/cloud/azure/network/frontdoor/000077500000000000000000000000001417000230700231755ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/network/frontdoor/mode/000077500000000000000000000000001417000230700241215ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/network/frontdoor/mode/backendhealth.pm000066400000000000000000000111471417000230700272400ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::frontdoor::mode::backendhealth; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'backendhealthpercentage' => { 'output' => 'Backend Health Percentage', 'label' => 'backend-health-percentage', 'nlabel' => 'frontdoor.backend.health.percentage', 'unit' => '%', 'min' => '0', 'max' => '100' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Network\/frontdoors\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'frontdoors'; $self->{az_resource_namespace} = 'Microsoft.Network'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Front Door backend health. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::network::frontdoor::plugin --mode=backendhealth --custommode=api --resource= --resource-group= --aggregation='average' --warning-backend-health-percentage='100:' --critical-backend-health-percentage='90:' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::network::frontdoor::plugin --mode=backendhealth --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Network/frontdoors/' --aggregation='average' --warning-backend-health-percentage='100:' --critical-backend-health-percentage='90:' Default aggregation: 'average' / 'minimum', 'maximum' and 'total' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-backend-health-percentage> Warning threshold. =item B<--critical-backend-health-percentage> Critical threshold. =back =cut centreon-plugins-20220113/cloud/azure/network/frontdoor/mode/discovery.pm000066400000000000000000000024261417000230700264720ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::frontdoor::mode::discovery; use base qw(cloud::azure::management::monitor::mode::discovery); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{namespace} = 'Microsoft.Network'; $self->{type} = 'frontdoors'; } 1; __END__ =head1 MODE Azure FrontDoor discovery. =over 8 =item B<--resource-group> Specify resource group. =item B<--location> Specify location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/network/frontdoor/mode/health.pm000066400000000000000000000036351417000230700257330ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::frontdoor::mode::health; use base qw(cloud::azure::management::monitor::mode::health); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{az_resource_namespace} = 'Microsoft.Network'; $self->{az_resource_type} = 'frontdoors'; } 1; __END__ =head1 MODE Check Azure Front Door health status. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-status> Set warning threshold for status (Default: ''). Special variables that can be used: %{status}, %{summary}. =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /^Unavailable$/'). Special variables that can be used: %{status}, %{summary}. =item B<--unknown-status> Set unknown threshold for status (Default: '%{status} =~ /^Unknown$/'). Special variables that can be used: %{status}, %{summary}. =item B<--ok-status> Set ok threshold for status (Default: '%{status} =~ /^Available$/'). Special variables that can be used: %{status}, %{summary}. =back =cut centreon-plugins-20220113/cloud/azure/network/frontdoor/mode/latency.pm000066400000000000000000000115571417000230700261270ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::frontdoor::mode::latency; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'backendrequestlatency' => { 'output' => 'Backend Request Latency', 'label' => 'backend-request-latency', 'nlabel' => 'frontdoor.latency.backend.milliseconds', 'unit' => 'ms', 'min' => '0', 'max' => '' }, 'totallatency' => { 'output' => 'Total Latency', 'label' => 'total-latency', 'nlabel' => 'frontdoor.latency.total.milliseconds', 'unit' => 'ms', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Network\/frontdoors\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'frontdoors'; $self->{az_resource_namespace} = 'Microsoft.Network'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Front Door latency. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::network::frontdoor::plugin --mode=latency --custommode=api --resource= --resource-group= --aggregation='average' --warning-total-latency='50' --critical-total-latency='100' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::network::frontdoor::plugin --mode=latency --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Network/frontdoors/' --aggregation='average' --warning-total-latency='50' --critical-total-latency='100' Default aggregation: 'average' / 'minimum', 'maximum' and 'total' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'total-latency', 'backend-request-latency'. =item B<--critical-*> Critical threshold where '*' can be: 'total-latency', 'backend-request-latency'. =back =cut centreon-plugins-20220113/cloud/azure/network/frontdoor/mode/requests.pm000066400000000000000000000123441417000230700263360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::frontdoor::mode::requests; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'backendrequestcount' => { 'output' => 'Backend Requests Count', 'label' => 'backend-requests-count', 'nlabel' => 'frontdoor.requests.backend.count', 'unit' => '', 'min' => '0', 'max' => '' }, 'requestcount' => { 'output' => 'Total Requests Count', 'label' => 'total-requests-count', 'nlabel' => 'frontdoor.requests.total.count', 'unit' => '', 'min' => '0', 'max' => '' }, 'webapplicationfirewallrequestcount' => { 'output' => 'WAF Requests Count', 'label' => 'waf-requests-count', 'nlabel' => 'frontdoor.requests.waf.count', 'unit' => '', 'min' => '0', 'max' => '' }, }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Network\/frontdoors\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'frontdoors'; $self->{az_resource_namespace} = 'Microsoft.Network'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Front Door latency. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::network::frontdoor::plugin --mode=requests --custommode=api --resource= --resource-group= --aggregation='total' --warning-total-requests-count='3000' --critical-total-requests-count='4000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::network::frontdoor::plugin --mode=requests --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Network/frontdoors/' --aggregation='total' --warning-total-requests-count='3000' --critical-total-requests-count='4000' Default aggregation: 'total' / 'minimum', 'maximum' and 'average' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'waf-requests-count', 'backend-request-count', 'total-requests-count'. =item B<--critical-*> Critical threshold where '*' can be: 'waf-requests-count', 'backend-request-count', 'total-requests-count'. =back =cut centreon-plugins-20220113/cloud/azure/network/frontdoor/mode/size.pm000066400000000000000000000122051417000230700254310ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::frontdoor::mode::size; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'billableresponsesize' => { 'output' => 'Billable Response Size', 'label' => 'billable-response-size', 'nlabel' => 'frontdoor.size.billable.bytes', 'unit' => 'B', 'min' => '0', 'max' => '' }, 'requestsize' => { 'output' => 'Requests Size', 'label' => 'requests-size', 'nlabel' => 'frontdoor.size.requests.bytes', 'unit' => 'B', 'min' => '0', 'max' => '' }, 'responsesize' => { 'output' => 'Response Size', 'label' => 'response-size', 'nlabel' => 'frontdoor.size.response.bytes', 'unit' => 'B', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Network\/frontdoors\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'frontdoors'; $self->{az_resource_namespace} = 'Microsoft.Network'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Front Door requests size. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::network::frontdoor::plugin --mode=size --custommode=api --resource= --resource-group= --aggregation='total' --warning-requests-size='300000' --critical-requests-size='400000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::network::frontdoor::plugin --mode=size --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Network/frontdoors/' --aggregation='total' --warning-requests-size='300000' --critical-requests-size='400000' Default aggregation: 'total' / 'minimum', 'maximum' and 'average' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'billable-response-size', 'response-size', 'requests-size'. =item B<--critical-*> Critical threshold where '*' can be: 'billable-response-size', 'response-size', 'requests-size'. =back =cut centreon-plugins-20220113/cloud/azure/network/frontdoor/plugin.pm000066400000000000000000000037361417000230700250420ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::frontdoor::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} = { 'backendhealth' => 'cloud::azure::network::frontdoor::mode::backendhealth', 'discovery' => 'cloud::azure::network::frontdoor::mode::discovery', 'health' => 'cloud::azure::network::frontdoor::mode::health', 'latency' => 'cloud::azure::network::frontdoor::mode::latency', 'requests' => 'cloud::azure::network::frontdoor::mode::requests', 'size' => 'cloud::azure::network::frontdoor::mode::size' }; $self->{custom_modes}->{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}->{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' } }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure FrontDoor service. =cut centreon-plugins-20220113/cloud/azure/network/loadbalancer/000077500000000000000000000000001417000230700235705ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/network/loadbalancer/mode/000077500000000000000000000000001417000230700245145ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/network/loadbalancer/mode/datapath.pm000066400000000000000000000112721417000230700266430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::loadbalancer::mode::datapath; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'vipavailability' => { 'output' => 'Data Path (VIP) Availability', 'label' => 'datapath-availability-percentage', 'nlabel' => 'loadbalancer.datapath.availability.percentage', 'unit' => '%', 'min' => '0', 'max' => '100' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Network\/loadBalancers\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'loadBalancers'; $self->{az_resource_namespace} = 'Microsoft.Network'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Network Load Balancers Data Path metrics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::network::loadbalancer::plugin --mode=datapath --custommode=azcli --resource= --resource-group= --aggregation='average' --warning-datapath-availability-percentage='100:' --critical-datapath-availability-percentage='50:' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::network::loadbalancer::plugin --mode=datapath --custommode=azcli --resource='/subscriptions//resourceGroups//providers/Microsoft.Network/loadBalancers/' --aggregation='average' --warning-datapath-availability-percentage='100:' --critical-datapath-availability-percentage='50:' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-datapath-availability-percentage> Warning threshold. =item B<--critical-datapath-availability-percentage> Critical threshold. =back =cut centreon-plugins-20220113/cloud/azure/network/loadbalancer/mode/discovery.pm000066400000000000000000000024411417000230700270620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::loadbalancer::mode::discovery; use base qw(cloud::azure::management::monitor::mode::discovery); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{namespace} = 'Microsoft.Network'; $self->{type} = 'loadBalancers'; } 1; __END__ =head1 MODE Azure Load Balancers discovery. =over 8 =item B<--resource-group> Specify resource group. =item B<--location> Specify location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/network/loadbalancer/mode/healthprobe.pm000066400000000000000000000113321417000230700273470ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::loadbalancer::mode::healthprobe; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'dipavailability' => { 'output' => 'Health probe status (DIP) availability', 'label' => 'healthprobe-availibility-percentage', 'nlabel' => 'loadbalancer.healthprobe.availability.percentage', 'unit' => '%', 'min' => '0', 'max' => '100' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Network\/loadBalancers\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'loadBalancers'; $self->{az_resource_namespace} = 'Microsoft.Network'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Network Load Balancers DIP metrics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::network::loadbalancer::plugin --mode=healthprobe --custommode=azcli --resource= --resource-group= --aggregation='average' --warning-healthprobe-availibility-percentage=100: --critical-healthprobe-availibility-percentage='50:' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::network::loadbalancer::plugin --mode=datapath --custommode=azcli --resource='/subscriptions//resourceGroups//providers/Microsoft.Network/loadBalancers/' --aggregation='average' --warning-healthprobe-availibility-percentage=100: --critical-healthprobe-availibility-percentage='50:' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<---warning-healthprobe-availibility-percentage> Warning threshold. =item B<--critical-healthprobe-availibility-percentage> Critical threshold. =back =cut centreon-plugins-20220113/cloud/azure/network/loadbalancer/mode/snat.pm000066400000000000000000000125261417000230700260250ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::loadbalancer::mode::snat; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'allocatedsnatports' => { 'output' => 'Allocated SNAT Ports', 'label' => 'snat-ports-allocated', 'nlabel' => 'loadbalancer.snat.ports.allocated.count', 'unit' => '', 'template' => '%s', 'min' => '0' }, 'snatconnectioncount' => { 'output' => 'SNAT Connection Count', 'label' => 'snat-connection-count', 'nlabel' => 'loadbalancer.snat.connection.count', 'unit' => '', 'min' => '0' }, 'usedsnatports' => { 'output' => 'Used SNAT Ports', 'label' => 'snat-ports-used', 'nlabel' => 'loadbalancer.snat.ports.used.count', 'unit' => '', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Network\/loadBalancers\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'loadBalancers'; $self->{az_resource_namespace} = 'Microsoft.Network'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Network Load Balancers SNAT metrics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::network::loadbalancer::plugin --mode=snat --custommode=azcli --resource= --resource-group= --aggregation='average' --warning-snat-connection-count='800' --critical-snat-connection-count=='900' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::network::loadbalancer::plugin --mode=datapath --custommode=azcli --resource='/subscriptions//resourceGroups//providers/Microsoft.Network/loadBalancers/' --aggregation='average' --warning-snat-connection-count='800' --critical-snat-connection-count=='900' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--filter-metric> Filter on specific metrics. The Azure format must be used, for example: 'sessions_percent' (Can be a regexp). =item B<---warning-*> Warning threshold where * can be: snat-connection-count, snat-ports-used, snat-ports-allocated. =item B<--critical-*> Critical threshold where * can be: snat-connection-count, snat-ports-used, snat-ports-allocated.. =back =cut centreon-plugins-20220113/cloud/azure/network/loadbalancer/mode/throughput.pm000066400000000000000000000114701417000230700272660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::loadbalancer::mode::throughput; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'bytecount' => { 'output' => 'Byte Count', 'label' => 'throughput-bytes', 'nlabel' => 'loadbalancer.throughput.bytes', 'unit' => 'B', 'min' => '0' }, 'packetcount' => { 'output' => 'Packet Count', 'label' => 'throughput-packets', 'nlabel' => 'loadbalancer.packets.count', 'unit' => '', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Network\/loadBalancers\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'loadBalancers'; $self->{az_resource_namespace} = 'Microsoft.Network'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Network Load Balancers throughput metrics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::network::loadbalancer::plugin --mode=throughput --custommode=azcli --resource= --resource-group= --aggregation='average' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::network::loadbalancer::plugin --mode=datapath --custommode=azcli --resource='/subscriptions//resourceGroups//providers/Microsoft.Network/loadBalancers/' --aggregation='average' Default aggregation: 'average' / 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--filter-metric> Filter on specific metrics. The Azure format must be used, for example: 'sessions_percent' (Can be a regexp). =item B<---warning-*> Warning threshold where * can be: throughput-packets, throughput-bytes. =item B<--critical-*> Critical threshold where * can be: throughput-packets, throughput-bytes. =back =cut centreon-plugins-20220113/cloud/azure/network/loadbalancer/plugin.pm000066400000000000000000000036411417000230700254300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::loadbalancer::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} = { 'datapath' => 'cloud::azure::network::loadbalancer::mode::datapath', 'discovery' => 'cloud::azure::network::loadbalancer::mode::discovery', 'healthprobe' => 'cloud::azure::network::loadbalancer::mode::healthprobe', 'snat' => 'cloud::azure::network::loadbalancer::mode::snat', 'throughput' => 'cloud::azure::network::loadbalancer::mode::throughput' }; $self->{custom_modes}->{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}->{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' }, }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure Network LoadBalancers. =cut centreon-plugins-20220113/cloud/azure/network/networkinterface/000077500000000000000000000000001417000230700245335ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/network/networkinterface/mode/000077500000000000000000000000001417000230700254575ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/network/networkinterface/mode/discovery.pm000066400000000000000000000024461417000230700300320ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::networkinterface::mode::discovery; use base qw(cloud::azure::management::monitor::mode::discovery); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{namespace} = 'Microsoft.Network'; $self->{type} = 'networkInterfaces'; } 1; __END__ =head1 MODE Network Interface discovery. =over 8 =item B<--resource-group> Specify resource group. =item B<--location> Specify location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/network/networkinterface/mode/listresources.pm000066400000000000000000000104201417000230700307200ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::networkinterface::mode::listresources; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource-group:s" => { name => 'resource_group' }, "location:s" => { name => 'location' }, "filter-name:s" => { name => 'filter_name' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{resources} = $options{custom}->azure_list_resources( namespace => 'Microsoft.Network', resource_type => 'networkInterfaces', location => $self->{option_results}->{location}, resource_group => $self->{option_results}->{resource_group} ); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $resource (@{$self->{resources}}) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $resource->{name} !~ /$self->{option_results}->{filter_name}/); my $resource_group = '-'; $resource_group = $resource->{resourceGroup} if (defined($resource->{resourceGroup})); $resource_group = $1 if (defined($resource->{id}) && $resource->{id} =~ /resourceGroups\/(.*)\/providers/); my @tags; foreach my $tag (keys %{$resource->{tags}}) { push @tags, $tag . ':' . $resource->{tags}->{$tag}; } $self->{output}->output_add(long_msg => sprintf("[name = %s][resourcegroup = %s][location = %s][id = %s][tags = %s]", $resource->{name}, $resource_group, $resource->{location}, $resource->{id}, join(',', @tags), )); } $self->{output}->output_add(severity => 'OK', short_msg => 'List network interfaces:'); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } sub disco_format { my ($self, %options) = @_; $self->{output}->add_disco_format(elements => ['name', 'resourcegroup', 'location', 'id', 'tags']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $resource (@{$self->{resources}}) { my $resource_group = '-'; $resource_group = $resource->{resourceGroup} if (defined($resource->{resourceGroup})); $resource_group = $1 if (defined($resource->{id}) && $resource->{id} =~ /resourceGroups\/(.*)\/providers/); my @tags; foreach my $tag (keys %{$resource->{tags}}) { push @tags, $tag . ':' . $resource->{tags}->{$tag}; } $self->{output}->add_disco_entry( name => $resource->{name}, resourcegroup => $resource_group, location => $resource->{location}, id => $resource->{id}, tags => join(',', @tags), ); } } 1; __END__ =head1 MODE List network interface resources. =over 8 =item B<--resource-group> Set resource group. =item B<--location> Set resource location. =item B<--filter-name> Filter resource name (Can be a regexp). =back =cut centreon-plugins-20220113/cloud/azure/network/networkinterface/mode/traffic.pm000066400000000000000000000342401417000230700274360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::networkinterface::mode::traffic; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; return "Resource '" . $options{instance_value}->{display} . "' " . $options{instance_value}->{stat} . " "; } sub custom_metric_calc { my ($self, %options) = @_; $self->{result_values}->{stat} = $options{new_datas}->{$self->{instance} . '_stat'}; $self->{result_values}->{metric_perf} = lc($options{extra_options}->{metric_perf}); $self->{result_values}->{metric_label} = lc($options{extra_options}->{metric_label}); $self->{result_values}->{metric_name} = $options{extra_options}->{metric_name}; $self->{result_values}->{timeframe} = $options{new_datas}->{$self->{instance} . '_timeframe'}; $self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_' . $self->{result_values}->{metric_perf} . '_' . $self->{result_values}->{stat}}; $self->{result_values}->{value_per_sec} = $self->{result_values}->{value} / $self->{result_values}->{timeframe}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub custom_metric_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check(value => defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}, threshold => [ { label => 'critical-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}, exit_litteral => 'warning' } ]); return $exit; } sub custom_traffic_perfdata { my ($self, %options) = @_; my $extra_label = ''; $extra_label = '_' . lc($self->{result_values}->{display}) if (!defined($options{extra_instance}) || $options{extra_instance} != 0); $self->{output}->perfdata_add(label => $self->{result_values}->{metric_perf} . "_" . $self->{result_values}->{stat} . $extra_label, unit => defined($self->{instance_mode}->{option_results}->{per_sec}) ? 'B/s' : 'B', value => sprintf("%.2f", defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}), min => 0 ); } sub custom_traffic_output { my ($self, %options) = @_; my $msg = ""; if (defined($self->{instance_mode}->{option_results}->{per_sec})) { my ($value, $unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{value_per_sec}); $msg = $self->{result_values}->{metric_name} . ": " . $value . $unit . "/s"; } else { my ($value, $unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{value}); $msg = $self->{result_values}->{metric_name} . ": " . $value . $unit; } return $msg; } sub custom_packets_perfdata { my ($self, %options) = @_; my $extra_label = ''; $extra_label = '_' . lc($self->{result_values}->{display}) if (!defined($options{extra_instance}) || $options{extra_instance} != 0); $self->{output}->perfdata_add(label => $self->{result_values}->{metric_perf} . "_" . $self->{result_values}->{stat} . $extra_label, unit => defined($self->{instance_mode}->{option_results}->{per_sec}) ? 'packets/s' : 'packets', value => sprintf("%.2f", defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}), min => 0 ); } sub custom_packets_output { my ($self, %options) = @_; my $msg =""; if (defined($self->{instance_mode}->{option_results}->{per_sec})) { $msg = sprintf("%s: %.2f packets/s", $self->{result_values}->{metric_name}, $self->{result_values}->{value_per_sec}); } else { $msg = sprintf("%s: %.2f packets", $self->{result_values}->{metric_name}, $self->{result_values}->{value}); } return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All network metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $aggregation ('minimum', 'maximum', 'average', 'total') { foreach my $metric ('BytesReceivedRate', 'BytesSentRate') { my $metric_perf = lc($metric); my $metric_label = lc($metric); $metric_perf =~ s/ /_/g; $metric_label =~ s/ /-/g; my $entry = { label => $metric_label . '-' . $aggregation, set => { key_values => [ { name => $metric_perf . '_' . $aggregation }, { name => 'display' }, { name => 'stat' }, { name => 'timeframe' } ], closure_custom_calc => $self->can('custom_metric_calc'), closure_custom_calc_extra_options => { metric_perf => $metric_perf, metric_label => $metric_label, metric_name => $metric }, closure_custom_output => $self->can('custom_traffic_output'), closure_custom_perfdata => $self->can('custom_traffic_perfdata'), closure_custom_threshold_check => $self->can('custom_metric_threshold'), } }; push @{$self->{maps_counters}->{metric}}, $entry; } foreach my $metric ('PacketsSentRate', 'PacketsReceivedRate') { my $metric_perf = lc($metric); my $metric_label = lc($metric); $metric_perf =~ s/ /_/g; $metric_label =~ s/ /-/g; my $entry = { label => $metric_label . '-' . $aggregation, set => { key_values => [ { name => $metric_perf . '_' . $aggregation }, { name => 'display' }, { name => 'stat' }, { name => 'timeframe' } ], closure_custom_calc => $self->can('custom_metric_calc'), closure_custom_calc_extra_options => { metric_perf => $metric_perf, metric_label => $metric_label, metric_name => $metric }, closure_custom_output => $self->can('custom_packets_output'), closure_custom_perfdata => $self->can('custom_packets_perfdata'), closure_custom_threshold_check => $self->can('custom_metric_threshold'), } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource:s@" => { name => 'resource' }, "resource-group:s" => { name => 'resource_group' }, "filter-metric:s" => { name => 'filter_metric' }, "per-sec" => { name => 'per_sec' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource})) { $self->{output}->add_option_msg(short_msg => "Need to specify either --resource with --resource-group option or --resource ."); $self->{output}->option_exit(); } $self->{az_resource} = $self->{option_results}->{resource}; $self->{az_resource_group} = $self->{option_results}->{resource_group} if (defined($self->{option_results}->{resource_group})); $self->{az_resource_type} = 'networkInterfaces'; $self->{az_resource_namespace} = 'Microsoft.Network'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : "PT5M"; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric ('BytesReceivedRate', 'BytesSentRate', 'PacketsSentRate', 'PacketsReceivedRate') { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $resource (@{$self->{az_resource}}) { my $resource_group = $self->{az_resource_group}; my $resource_name = $resource; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Network\/networkInterfaces\/(.*)$/) { $resource_group = $1; $resource_name = $2; } ($metric_results{$resource_name}, undef, undef) = $options{custom}->azure_get_metrics( resource => $resource_name, resource_group => $resource_group, resource_type => $self->{az_resource_type}, resource_namespace => $self->{az_resource_namespace}, metrics => $self->{az_metrics}, aggregations => $self->{az_aggregations}, timeframe => $self->{az_timeframe}, interval => $self->{az_interval}, ); foreach my $metric (@{$self->{az_metrics}}) { my $metric_name = lc($metric); $metric_name =~ s/ /_/g; foreach my $aggregation (@{$self->{az_aggregations}}) { next if (!defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{display} = $resource_name; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{timeframe} = $self->{az_timeframe}; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{stat} = lc($aggregation); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{$metric_name . "_" . lc($aggregation)} = defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) ? $metric_results{$resource_name}->{$metric_name}->{lc($aggregation)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check network interface resources traffic metrics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::network::networkinterface::plugin --custommode=azcli --mode=traffic --resource=MYNIC --resource-group=MYHOSTGROUP --aggregation='total' --critical-bytesreceivedrate-total='10' --verbose Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::network::networkinterface::plugin --custommode=azcli --mode=traffic --resource='/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Network/networkInterfaces/xxx' --aggregation='total' --critical-bytesreceivedrate-total='10' --verbose Default aggregation: 'total' / All aggregations are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--filter-metric> Filter metrics (Can be: 'BytesReceivedRate', 'BytesSentRate', 'PacketsSentRate', 'PacketsReceivedRate') (Can be a regexp). =item B<--warning-$metric$-$aggregation$> Thresholds warning ($metric$ can be: 'bytesreceivedrate', 'bytessentrate', 'packetssentrate', 'packetsreceivedrate', $aggregation$ can be: 'minimum', 'maximum', 'average', 'total'). =item B<--critical-$metric$-$aggregation$> Thresholds critical ($metric$ can be: 'bytesreceivedrate', 'bytessentrate', 'packetssentrate', 'packetsreceivedrate', $aggregation$ can be: 'minimum', 'maximum', 'average', 'total'). =item B<--per-sec> Change the data to be unit/sec. =back =cut centreon-plugins-20220113/cloud/azure/network/networkinterface/plugin.pm000066400000000000000000000034441417000230700263740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::networkinterface::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} } = ( 'discovery' => 'cloud::azure::network::networkinterface::mode::discovery', 'list-resources' => 'cloud::azure::network::networkinterface::mode::listresources', 'traffic' => 'cloud::azure::network::networkinterface::mode::traffic', ); $self->{custom_modes}{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' }, }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure network interface. =cut centreon-plugins-20220113/cloud/azure/network/publicip/000077500000000000000000000000001417000230700227705ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/network/publicip/mode/000077500000000000000000000000001417000230700237145ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/network/publicip/mode/ddostraffic.pm000066400000000000000000000141011417000230700265370ustar00rootroot00000000000000# # Copyright 2020 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::azure::network::publicip::mode::ddostraffic; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'bytesdroppedddos' => { 'output' => 'Inbound bytes dropped DDoS', 'label' => 'ddos-dropped', 'nlabel' => 'publicip.ddos.dropped.bytes', 'unit' => 'B', 'min' => '0' }, 'bytesforwardedddos' => { 'output' => 'Inbound bytes forwarded DDoS', 'label' => 'ddos-forwarded', 'nlabel' => 'publicip.ddos.forwarded.bytes', 'unit' => 'B', 'min' => '0' }, 'bytesinddos' => { 'output' => 'Inbound bytes DDoS', 'label' => 'ddos-inbound', 'nlabel' => 'publicip.ddos.inbound.bytes', 'unit' => 'B', 'min' => '0' }, 'packetsdroppedddos' => { 'output' => 'Inbound packets dropped DDoS', 'label' => 'ddos-dropped-packets', 'nlabel' => 'publicip.ddos.packets.countpersecond', 'unit' => '/s', 'min' => '0' }, 'packetsforwardedddos' => { 'output' => 'Inbound packets forwarded DDoS', 'label' => 'ddos-forwarded-packets', 'nlabel' => 'publicip.ddos.forwarded.countpersecond', 'unit' => '/s', 'min' => '0' }, 'packetsinddos' => { 'output' => 'Inbound packets DDoS', 'label' => 'ddos-inbound-packets', 'nlabel' => 'publicip.ddos.inbound.packets.countpersecond', 'unit' => '/s', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Network\/publicIPAddresses\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'publicIPAddresses'; $self->{az_resource_namespace} = 'Microsoft.Network'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Maximum']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Public IP DDOS traffic metrics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::network::publicip::plugin --mode=ddos-traffic --custommode=api --resource= --resource-group= --aggregation='maximum' --warning-ddos-inbound-packets='1000' --critical-ddos-inbound-packets='2000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::network::publicip::plugin --mode=ddos-traffic --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Network/publicIPAddresses/' --aggregation='maximum' --warning-ddos-inbound-packets='1000' --critical-ddos-inbound-packets='2000' Default aggregation: 'maximum' / 'average', 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<---warning-*> Warning threshold where '*' can be: 'ddos-dropped', 'ddos-forwarded', 'ddos-inbound', 'ddos-dropped-packets', 'ddos-forwarded-packets', 'ddos-inbound-packets'. =item B<--critical-*> Critical threshold where '*' can be: 'ddos-dropped', 'ddos-forwarded', 'ddos-inbound', 'ddos-dropped-packets', 'ddos-forwarded-packets', 'ddos-inbound-packets'. =back =cut centreon-plugins-20220113/cloud/azure/network/publicip/mode/discovery.pm000066400000000000000000000024341417000230700262640ustar00rootroot00000000000000# # Copyright 2020 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::azure::network::publicip::mode::discovery; use base qw(cloud::azure::management::monitor::mode::discovery); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{namespace} = 'Microsoft.Network'; $self->{type} = 'publicIPAddresses'; } 1; __END__ =head1 MODE Azure Public IP discovery. =over 8 =item B<--resource-group> Specify resource group. =item B<--location> Specify location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/network/publicip/mode/status.pm000066400000000000000000000156501417000230700256040ustar00rootroot00000000000000# # Copyright 2020 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::azure::network::publicip::mode::status; use base qw(centreon::plugins::templates::counter); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); $options{options}->add_help(package => __PACKAGE__, sections => 'CUSTOM MODE OPTIONS', once => 1); return $self; } sub prefix_status_output { my ($self, %options) = @_; return sprintf("Public IP instance '%s', IP: %s (%s) ", $options{instance_value}->{display}, $options{instance_value}->{ipaddress}, $options{instance_value}->{ipversion}); } sub custom_ddos_status_output { my ($self, %options) = @_; return sprintf('current DDOS status: "%s"', $self->{result_values}->{status}); } sub custom_provisioning_state_output { my ($self, %options) = @_; return sprintf('current provisioning state: "%s"', $self->{result_values}->{state}); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_status_output' } ]; $self->{maps_counters}->{global} = [ { label => 'ddos-status', type => 2, critical_default => '%{status} =~ /DDOS Attack ongoing/i', set => { key_values => [ { name => 'status' } ], closure_custom_output => $self->can('custom_ddos_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng, } }, { label => 'provisioning-state', type => 2, critical_default => '%{state} =~ /Failed/i', set => { key_values => [ { name => 'state' } ], closure_custom_output => $self->can('custom_provisioning_state_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng, } } ]; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Network\/publicIPAddresses\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'publicIPAddresses'; $self->{az_resource_namespace} = 'Microsoft.Network'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Maximum']; } sub manage_selection { my ($self, %options) = @_; my %metric_results; my $raw_results; my $publicip_properties = $options{custom}->azure_get_publicip(resource => $self->{az_resource}, resource_group => $self->{az_resource_group}); $self->{global} = { ipaddress => $publicip_properties->{properties}->{ipAddress}, ipversion => $publicip_properties->{properties}->{publicIPAddressVersion}, state => $publicip_properties->{properties}->{provisioningState} }; ($metric_results{$self->{az_resource}}, $raw_results) = $options{custom}->azure_get_metrics( aggregations => $self->{az_aggregations}, interval => $self->{az_interval}, metrics => ['IfUnderDDoSAttack'], resource => $self->{az_resource}, resource_group => $self->{az_resource_group}, resource_namespace => $self->{az_resource_namespace}, resource_type => $self->{az_resource_type}, timeframe => $self->{az_timeframe} ); $self->{global}->{display} = $self->{az_resource}; $self->{global}->{numeric_status} = defined($metric_results{$self->{az_resource}}->{IfUnderDDoSAttack}->{maximum}) ? $metric_results{$self->{az_resource}}->{IfUnderDDoSAttack}->{maximum} : 0; $self->{global}->{status} = $self->{global}->{numeric_status} > 0 ? 'DDOS Attack ongoing' : 'OK'; } 1; __END__ =head1 MODE Check Azure Public IP status. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::network::publicip::plugin --mode=status --custommode=api --resource= --resource-group= --critical-provisioning-state='%{state} =~ /Failed/i' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::network::publicip::plugin --mode=status --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Network/publicIPAddresses/' --critical-provisioning-state='%{state} =~ /Failed/i' Default aggregation: 'maximum' / 'average', 'total', 'minimum' and 'maximum' are valid. =head1 CUSTOM MODE OPTIONS =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-ddos-status> Warning threshold for DDOS attack status (Default: ''). =item B<--critical-ddos-status> Critical threshold for DDOS attack status (Default: '%{status} =~ /DDOS Attack ongoing/i'). =item B<--warning-provisioning-state> Warning threshold for provisioning state (Default: ''). =item B<--critical-provisioning-state> Critical threshold for provisioning state (Default: '%{state} =~ /Failed/i'). =back =cut centreon-plugins-20220113/cloud/azure/network/publicip/plugin.pm000066400000000000000000000033471417000230700246330ustar00rootroot00000000000000# # Copyright 2020 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::azure::network::publicip::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} = { 'discovery' => 'cloud::azure::network::publicip::mode::discovery', 'ddos-traffic' => 'cloud::azure::network::publicip::mode::ddostraffic', 'status' => 'cloud::azure::network::publicip::mode::status' }; $self->{custom_modes}->{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}->{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' }, }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure Public IPs. =cut centreon-plugins-20220113/cloud/azure/network/virtualnetwork/000077500000000000000000000000001417000230700242615ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/network/virtualnetwork/mode/000077500000000000000000000000001417000230700252055ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/network/virtualnetwork/mode/discovery.pm000066400000000000000000000024401417000230700275520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::virtualnetwork::mode::discovery; use base qw(cloud::azure::management::monitor::mode::discovery); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{namespace} = 'Microsoft.Network'; $self->{type} = 'virtualNetworks'; } 1; __END__ =head1 MODE Virtual Network discovery. =over 8 =item B<--resource-group> Specify resource group. =item B<--location> Specify location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/network/virtualnetwork/mode/listvirtualnetworks.pm000066400000000000000000000116331417000230700317260ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::virtualnetwork::mode::listvirtualnetworks; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource-group:s" => { name => 'resource_group' }, "location:s" => { name => 'location' }, "filter-name:s" => { name => 'filter_name' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{resource_group}) || $self->{option_results}->{resource_group} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --resource-group option"); $self->{output}->option_exit(); } } sub manage_selection { my ($self, %options) = @_; $self->{networks} = $options{custom}->azure_list_virtualnetworks( resource_group => $self->{option_results}->{resource_group} ); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $network (@{$self->{networks}}) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $network->{name} !~ /$self->{option_results}->{filter_name}/); next if (defined($self->{option_results}->{location}) && $self->{option_results}->{location} ne '' && $network->{location} !~ /$self->{option_results}->{location}/); my $resource_group = '-'; $resource_group = $network->{resourceGroup} if (defined($network->{resourceGroup})); $resource_group = $1 if ($resource_group eq '-' && defined($network->{id}) && $network->{id} =~ /resourceGroups\/(.*)\/providers/); my @tags; foreach my $tag (keys %{$network->{tags}}) { push @tags, $tag . ':' . $network->{tags}->{$tag}; } $self->{output}->output_add(long_msg => sprintf("[name = %s][resourcegroup = %s][location = %s][id = %s][address_space = %s][tags = %s]", $network->{name}, $resource_group, $network->{location}, $network->{id}, ($network->{addressSpace}->{addressPrefixes}) ? join(',', @{$network->{addressSpace}->{addressPrefixes}}) : join(',', @{$network->{properties}->{addressSpace}->{addressPrefixes}}), join(',', @tags), )); } $self->{output}->output_add(severity => 'OK', short_msg => 'List virtual networks:'); $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', 'resourcegroup', 'location', 'id', 'address_space', 'tags']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $network (@{$self->{networks}}) { my $resource_group = '-'; $resource_group = $network->{resourceGroup} if (defined($network->{resourceGroup})); $resource_group = $1 if ($resource_group eq '-' && defined($network->{id}) && $network->{id} =~ /resourceGroups\/(.*)\/providers/); my @tags; foreach my $tag (keys %{$network->{tags}}) { push @tags, $tag . ':' . $network->{tags}->{$tag}; } $self->{output}->add_disco_entry( name => $network->{name}, resourcegroup => $resource_group, location => $network->{location}, id => $network->{id}, address_space => ($network->{addressSpace}->{addressPrefixes}) ? join(',', @{$network->{addressSpace}->{addressPrefixes}}) : join(',', @{$network->{properties}->{addressSpace}->{addressPrefixes}}), tags => join(',', @tags), ); } } 1; __END__ =head1 MODE List virtual networks. =over 8 =item B<--resource-group> Set resource group. =item B<--location> Set resource location. =item B<--filter-name> Filter resource name (Can be a regexp). =back =cut centreon-plugins-20220113/cloud/azure/network/virtualnetwork/mode/peeringsstatus.pm000066400000000000000000000134751417000230700306350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::virtualnetwork::mode::peeringsstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("State '%s', Provisioning State '%s' [Peer: %s]", $self->{result_values}->{peering_state}, $self->{result_values}->{provisioning_state}, $self->{result_values}->{peer}); return $msg; } sub prefix_peering_output { my ($self, %options) = @_; return "Peering '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'peerings', type => 1, cb_prefix_output => 'prefix_peering_output', message_multiple => 'All peerings are ok' }, ]; $self->{maps_counters}->{peerings} = [ { label => 'status', type => 2, critical_default => '%{peering_state} ne "Connected" || %{provisioning_state} ne "Succeeded"', set => { key_values => [ { name => 'peering_state' }, { name => 'provisioning_state' }, { name => 'peer' }, { name => 'display' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource-group:s" => { name => 'resource_group' }, "resource:s" => { name => 'resource' }, "filter-name:s" => { name => 'filter_name' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Network\/virtualNetworks\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; } sub manage_selection { my ($self, %options) = @_; $self->{peerings} = {}; my $peerings = $options{custom}->azure_list_vnet_peerings( resource_group => $self->{az_resource_group}, resource => $self->{az_resource} ); foreach my $peering (@{$peerings}) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $peering->{name} !~ /$self->{option_results}->{filter_name}/); my $peer; $peer = $1 if (defined($peering->{remoteVirtualNetwork}->{id}) && $peering->{remoteVirtualNetwork}->{id} =~ /providers\/Microsoft\.Network\/virtualNetworks\/(.*)$/); $peer = $1 if (defined($peering->{properties}->{remoteVirtualNetwork}->{id}) && $peering->{properties}->{remoteVirtualNetwork}->{id} =~ /providers\/Microsoft\.Network\/virtualNetworks\/(.*)$/); $self->{peerings}->{$peering->{id}} = { display => $peering->{name}, peering_state => ($peering->{peeringState}) ? $peering->{peeringState} : $peering->{properties}->{peeringState}, provisioning_state => ($peering->{provisioningState}) ? $peering->{provisioningState} : $peering->{properties}->{provisioningState}, peer => $peer, }; } if (scalar(keys %{$self->{peerings}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No virtual network peerings found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check virtual network peerings status. Example: perl centreon_plugins.pl --plugin=cloud::azure::network::virtualnetwork::plugin --custommode=awscli --mode=peerings-status --resource-group='MYRESOURCEGROUP' --resource='MyVNetName' --verbose =over 8 =item B<--resource-group> Set resource group (Required). =item B<--resource> Set virtual network name (Required). =item B<--filter-name> Filter peering name (Can be a regexp). =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{peering_state}, %{provisioning_state}, %{peer}, %{display} =item B<--critical-status> Set critical threshold for status (Default: '%{peering_state} ne "Connected" || %{provisioning_state} ne "Succeeded"'). Can used special variables like: %{peering_state}, %{provisioning_state}, %{peer}, %{display} =back =cut centreon-plugins-20220113/cloud/azure/network/virtualnetwork/plugin.pm000066400000000000000000000034771417000230700261300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::virtualnetwork::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} } = ( 'discovery' => 'cloud::azure::network::virtualnetwork::mode::discovery', 'list-virtual-networks' => 'cloud::azure::network::virtualnetwork::mode::listvirtualnetworks', 'peerings-status' => 'cloud::azure::network::virtualnetwork::mode::peeringsstatus', ); $self->{custom_modes}{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' }, }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure Virtual Network. =cut centreon-plugins-20220113/cloud/azure/network/vpngateway/000077500000000000000000000000001417000230700233465ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/network/vpngateway/mode/000077500000000000000000000000001417000230700242725ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/network/vpngateway/mode/discovery.pm000066400000000000000000000024371417000230700266450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::vpngateway::mode::discovery; use base qw(cloud::azure::management::monitor::mode::discovery); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{namespace} = 'Microsoft.Network'; $self->{type} = 'virtualNetworkGateways'; } 1; __END__ =head1 MODE VPN Gateway discovery. =over 8 =item B<--resource-group> Specify resource group. =item B<--location> Specify location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/network/vpngateway/mode/health.pm000066400000000000000000000036751417000230700261100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::vpngateway::mode::health; use base qw(cloud::azure::management::monitor::mode::health); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{az_resource_namespace} = 'Microsoft.Network'; $self->{az_resource_type} = 'virtualNetworkGateways'; } 1; __END__ =head1 MODE Check Virtual Machine health status. (Usefull to determine host status) =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{summary} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /^Unavailable$/'). Can used special variables like: %{status}, %{summary} =item B<--unknown-status> Set unknown threshold for status (Default: '%{status} =~ /^Unknown$/'). Can used special variables like: %{status}, %{summary} =item B<--ok-status> Set ok threshold for status (Default: '%{status} =~ /^Available$/'). Can used special variables like: %{status}, %{summary} =back =cut centreon-plugins-20220113/cloud/azure/network/vpngateway/mode/sitetraffic.pm000066400000000000000000000277431417000230700271500ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::vpngateway::mode::sitetraffic; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; return "VPN Gateway '" . $options{instance_value}->{display} . "' " . $options{instance_value}->{stat} . " "; } sub custom_metric_calc { my ($self, %options) = @_; $self->{result_values}->{stat} = $options{new_datas}->{$self->{instance} . '_stat'}; $self->{result_values}->{metric_perf} = lc($options{extra_options}->{metric_perf}); $self->{result_values}->{metric_label} = lc($options{extra_options}->{metric_label}); $self->{result_values}->{metric_name} = $options{new_datas}->{$self->{instance} . '_' . $self->{result_values}->{metric_perf} . '_' . $self->{result_values}->{stat} . '_name'}; $self->{result_values}->{timeframe} = $options{new_datas}->{$self->{instance} . '_timeframe'}; $self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_' . $self->{result_values}->{metric_perf} . '_' . $self->{result_values}->{stat}}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub custom_metric_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check(value => $self->{result_values}->{value}, threshold => [ { label => 'critical-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}, exit_litteral => 'warning' } ]); return $exit; } sub custom_traffic_perfdata { my ($self, %options) = @_; my $extra_label = ''; $extra_label = '_' . lc($self->{result_values}->{display}) if (!defined($options{extra_instance}) || $options{extra_instance} != 0); $self->{output}->perfdata_add(label => $self->{result_values}->{metric_perf} . "_" . $self->{result_values}->{stat} . $extra_label, unit => 'B/s', value => sprintf("%.2f", $self->{result_values}->{value}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}), min => 0 ); } sub custom_traffic_output { my ($self, %options) = @_; my ($value, $unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{value}); my $msg = $self->{result_values}->{metric_name} . ": " . $value . $unit . "/s"; return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All traffic metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $aggregation ('average') { foreach my $metric ('AverageBandwidth', 'P2SBandwidth') { my $metric_perf = lc($metric); my $metric_label = lc($metric); $metric_perf =~ s/ /_/g; $metric_label =~ s/ /-/g; my $entry = { label => $metric_label . '-' . $aggregation, set => { key_values => [ { name => $metric_perf . '_' . $aggregation }, { name => 'display' }, { name => 'stat' }, { name => $metric_perf . '_' . $aggregation . '_name' }, { name => 'timeframe' } ], closure_custom_calc => $self->can('custom_metric_calc'), closure_custom_calc_extra_options => { metric_perf => $metric_perf, metric_label => $metric_label }, closure_custom_output => $self->can('custom_traffic_output'), closure_custom_perfdata => $self->can('custom_traffic_perfdata'), closure_custom_threshold_check => $self->can('custom_metric_threshold'), } }; push @{$self->{maps_counters}->{metric}}, $entry; } } foreach my $aggregation ('maximum') { foreach my $metric ('P2SConnectionCount') { my $metric_perf = lc($metric); my $metric_label = lc($metric); $metric_perf =~ s/ /_/g; $metric_label =~ s/ /-/g; my $entry = { label => $metric_label . '-' . $aggregation, set => { key_values => [ { name => $metric_perf . '_' . $aggregation }, { name => 'display' }, { name => $metric_perf . '_' . $aggregation . '_name' }, { name => 'stat' } ], output_template => 'P2S Connection Count: %d', perfdatas => [ { label => $metric_perf . '_' . $aggregation, value => $metric_perf . '_' . $aggregation , template => '%d', label_extra_instance => 1, instance_use => 'display', min => 0 }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource:s@" => { name => 'resource' }, "resource-group:s" => { name => 'resource_group' }, "filter-metric:s" => { name => 'filter_metric' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource})) { $self->{output}->add_option_msg(short_msg => "Need to specify either --resource with --resource-group option or --resource ."); $self->{output}->option_exit(); } $self->{az_resource} = $self->{option_results}->{resource}; $self->{az_resource_group} = $self->{option_results}->{resource_group} if (defined($self->{option_results}->{resource_group})); $self->{az_resource_type} = 'virtualNetworkGateways'; $self->{az_resource_namespace} = 'Microsoft.Network'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : "PT5M"; $self->{az_aggregations} = ['Average', 'Maximum']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric ('AverageBandwidth', 'P2SBandwidth', 'P2SConnectionCount') { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $resource (@{$self->{az_resource}}) { my $resource_group = $self->{az_resource_group}; my $resource_name = $resource; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Network\/virtualNetworkGateways\/(.*)$/) { $resource_group = $1; $resource_name = $2; } ($metric_results{$resource_name}, undef) = $options{custom}->azure_get_metrics( resource => $resource_name, resource_group => $resource_group, resource_type => $self->{az_resource_type}, resource_namespace => $self->{az_resource_namespace}, metrics => $self->{az_metrics}, aggregations => $self->{az_aggregations}, timeframe => $self->{az_timeframe}, interval => $self->{az_interval}, ); foreach my $metric (@{$self->{az_metrics}}) { my $metric_name = lc($metric); $metric_name =~ s/ /_/g; foreach my $aggregation (@{$self->{az_aggregations}}) { next if (!defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{display} = $resource_name; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{timeframe} = $self->{az_timeframe}; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{stat} = lc($aggregation); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{$metric_name . "_" . lc($aggregation) . '_name'} = $metric_results{$resource_name}->{$metric_name}->{name}; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{$metric_name . "_" . lc($aggregation)} = defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) ? $metric_results{$resource_name}->{$metric_name}->{lc($aggregation)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check VPN gateway site traffic metrics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::network::vpngateway::plugin --custommode=azcli --mode=site-traffic --resource=MyResource --resource-group=MYRGROUP --aggregation='average' --critical-averagebandwidth-average='10' --verbose Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::network::vpngateway::plugin --custommode=azcli --mode=site-traffic --resource='/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Network/virtualNetworkGateways/xxx' --aggregation='average' --critical-averagebandwidth-average='10' --verbose Default aggregation: 'average', 'maximum' / All aggregations are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--filter-metric> Filter metrics (Can be: 'AverageBandwidth', 'P2SBandwidth', 'P2SConnectionCount') (Can be a regexp). =item B<--warning-$metric$-$aggregation$> Thresholds warning ($metric$ can be: 'averagebandwidth', 'p2sbandwidth', 'p2sconnectioncount', $aggregation$ can be: 'total', 'minimum', 'maximum', 'average'). =item B<--critical-$metric$-$aggregation$> Thresholds critical ($metric$ can be: 'averagebandwidth', 'p2sbandwidth', 'p2sconnectioncount', $aggregation$ can be: 'total', 'minimum', 'maximum', 'average'). =back =cut centreon-plugins-20220113/cloud/azure/network/vpngateway/mode/tunneltraffic.pm000066400000000000000000000356651417000230700275130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::vpngateway::mode::tunneltraffic; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; return "VPN Gateway '" . $options{instance_value}->{display} . "' " . $options{instance_value}->{stat} . " "; } sub custom_metric_calc { my ($self, %options) = @_; $self->{result_values}->{stat} = $options{new_datas}->{$self->{instance} . '_stat'}; $self->{result_values}->{metric_perf} = lc($options{extra_options}->{metric_perf}); $self->{result_values}->{metric_label} = lc($options{extra_options}->{metric_label}); $self->{result_values}->{metric_name} = $options{new_datas}->{$self->{instance} . '_' . $self->{result_values}->{metric_perf} . '_' . $self->{result_values}->{stat} . '_name'}; $self->{result_values}->{timeframe} = $options{new_datas}->{$self->{instance} . '_timeframe'}; $self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_' . $self->{result_values}->{metric_perf} . '_' . $self->{result_values}->{stat}}; $self->{result_values}->{value_per_sec} = $self->{result_values}->{value} / $self->{result_values}->{timeframe}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub custom_metric_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check(value => defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}, threshold => [ { label => 'critical-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}, exit_litteral => 'warning' } ]); return $exit; } sub custom_traffic_perfdata { my ($self, %options) = @_; my $extra_label = ''; $extra_label = '_' . lc($self->{result_values}->{display}) if (!defined($options{extra_instance}) || $options{extra_instance} != 0); $self->{output}->perfdata_add(label => $self->{result_values}->{metric_perf} . "_" . $self->{result_values}->{stat} . $extra_label, unit => defined($self->{instance_mode}->{option_results}->{per_sec}) ? 'B/s' : 'B', value => sprintf("%.2f", defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}), min => 0 ); } sub custom_traffic_output { my ($self, %options) = @_; my $msg = ""; if (defined($self->{instance_mode}->{option_results}->{per_sec})) { my ($value, $unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{value_per_sec}); $msg = $self->{result_values}->{metric_name} . ": " . $value . $unit . "/s"; } else { my ($value, $unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{value}); $msg = $self->{result_values}->{metric_name} . ": " . $value . $unit; } return $msg; } sub custom_packets_perfdata { my ($self, %options) = @_; my $extra_label = ''; $extra_label = '_' . lc($self->{result_values}->{display}) if (!defined($options{extra_instance}) || $options{extra_instance} != 0); $self->{output}->perfdata_add(label => $self->{result_values}->{metric_perf} . "_" . $self->{result_values}->{stat} . $extra_label, unit => defined($self->{instance_mode}->{option_results}->{per_sec}) ? 'packets/s' : 'packets', value => sprintf("%.2f", defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}), min => 0 ); } sub custom_packets_output { my ($self, %options) = @_; my $msg =""; if (defined($self->{instance_mode}->{option_results}->{per_sec})) { $msg = sprintf("%s: %.2f packets/s", $self->{result_values}->{metric_name}, $self->{result_values}->{value_per_sec}); } else { $msg = sprintf("%s: %.2f packets", $self->{result_values}->{metric_name}, $self->{result_values}->{value}); } return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All traffic metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $aggregation ('minimum', 'maximum', 'average', 'total') { foreach my $metric ('TunnelIngressBytes', 'TunnelEgressBytes') { my $metric_perf = lc($metric); my $metric_label = lc($metric); $metric_perf =~ s/ /_/g; $metric_label =~ s/ /-/g; my $entry = { label => $metric_label . '-' . $aggregation, set => { key_values => [ { name => $metric_perf . '_' . $aggregation }, { name => 'display' }, { name => 'stat' }, { name => $metric_perf . '_' . $aggregation . '_name' }, { name => 'timeframe' } ], closure_custom_calc => $self->can('custom_metric_calc'), closure_custom_calc_extra_options => { metric_perf => $metric_perf, metric_label => $metric_label }, closure_custom_output => $self->can('custom_traffic_output'), closure_custom_perfdata => $self->can('custom_traffic_perfdata'), closure_custom_threshold_check => $self->can('custom_metric_threshold'), } }; push @{$self->{maps_counters}->{metric}}, $entry; } foreach my $metric ('TunnelIngressPackets', 'TunnelEgressPackets', 'TunnelIngressPacketDropTSMismatch', 'TunnelEgressPacketDropTSMismatch') { my $metric_perf = lc($metric); my $metric_label = lc($metric); $metric_perf =~ s/ /_/g; $metric_label =~ s/ /-/g; my $entry = { label => $metric_label . '-' . $aggregation, set => { key_values => [ { name => $metric_perf . '_' . $aggregation }, { name => 'display' }, { name => 'stat' }, { name => $metric_perf . '_' . $aggregation . '_name' }, { name => 'timeframe' } ], closure_custom_calc => $self->can('custom_metric_calc'), closure_custom_calc_extra_options => { metric_perf => $metric_perf, metric_label => $metric_label }, closure_custom_output => $self->can('custom_packets_output'), closure_custom_perfdata => $self->can('custom_packets_perfdata'), closure_custom_threshold_check => $self->can('custom_metric_threshold'), } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource:s@" => { name => 'resource' }, "resource-group:s" => { name => 'resource_group' }, "filter-metric:s" => { name => 'filter_metric' }, "per-sec" => { name => 'per_sec' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource})) { $self->{output}->add_option_msg(short_msg => "Need to specify either --resource with --resource-group option or --resource ."); $self->{output}->option_exit(); } $self->{az_resource} = $self->{option_results}->{resource}; $self->{az_resource_group} = $self->{option_results}->{resource_group} if (defined($self->{option_results}->{resource_group})); $self->{az_resource_type} = 'virtualNetworkGateways'; $self->{az_resource_namespace} = 'Microsoft.Network'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : "PT5M"; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric ('TunnelIngressBytes', 'TunnelEgressBytes', 'TunnelIngressPackets', 'TunnelEgressPackets', 'TunnelIngressPacketDropTSMismatch', 'TunnelEgressPacketDropTSMismatch') { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $resource (@{$self->{az_resource}}) { my $resource_group = $self->{az_resource_group}; my $resource_name = $resource; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Network\/virtualNetworkGateways\/(.*)$/) { $resource_group = $1; $resource_name = $2; } ($metric_results{$resource_name}, undef) = $options{custom}->azure_get_metrics( resource => $resource_name, resource_group => $resource_group, resource_type => $self->{az_resource_type}, resource_namespace => $self->{az_resource_namespace}, metrics => $self->{az_metrics}, aggregations => $self->{az_aggregations}, timeframe => $self->{az_timeframe}, interval => $self->{az_interval}, ); foreach my $metric (@{$self->{az_metrics}}) { my $metric_name = lc($metric); $metric_name =~ s/ /_/g; foreach my $aggregation (@{$self->{az_aggregations}}) { next if (!defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{display} = $resource_name; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{timeframe} = $self->{az_timeframe}; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{stat} = lc($aggregation); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{$metric_name . "_" . lc($aggregation) . '_name'} = $metric_results{$resource_name}->{$metric_name}->{name}; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{$metric_name . "_" . lc($aggregation)} = defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) ? $metric_results{$resource_name}->{$metric_name}->{lc($aggregation)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check VPN gateway tunnels traffic metrics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::network::vpngateway::plugin --custommode=azcli --mode=tunnel-traffic --resource=MyResource --resource-group=MYRGROUP --aggregation='total' --critical-tunnelingressbytes-total='10' --verbose Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::network::vpngateway::plugin --custommode=azcli --mode=tunnel-traffic --resource='/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Network/virtualNetworkGateways/xxx' --aggregation='total' --critical-tunnelingressbytes-total='10' --verbose Default aggregation: 'total' / All aggregations are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--filter-metric> Filter metrics (Can be: 'TunnelIngressBytes', 'TunnelEgressBytes', 'TunnelIngressPackets', 'TunnelEgressPackets', 'TunnelIngressPacketDropTSMismatch', 'TunnelEgressPacketDropTSMismatch') (Can be a regexp). =item B<--warning-$metric$-$aggregation$> Thresholds warning ($metric$ can be: 'tunnelingressbytes', 'tunnelegressbytes', 'tunnelingresspackets', 'tunnelegresspackets', 'tunnelingresspacketdroptsmismatch', 'tunnelegresspacketdroptsmismatch', $aggregation$ can be: 'total', 'minimum', 'maximum', 'average'). =item B<--critical-$metric$-$aggregation$> Thresholds critical ($metric$ can be: 'tunnelingressbytes', 'tunnelegressbytes', 'tunnelingresspackets', 'tunnelegresspackets', 'tunnelingresspacketdroptsmismatch', 'tunnelegresspacketdroptsmismatch', $aggregation$ can be: 'total', 'minimum', 'maximum', 'average'). =item B<--per-sec> Change the data to be unit/sec. =back =cut centreon-plugins-20220113/cloud/azure/network/vpngateway/mode/vpngatewaystatus.pm000066400000000000000000000130761417000230700302700ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::vpngateway::mode::vpngatewaystatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("Provisioning State '%s' [Gateway type: %s] [VPN type: %s]", $self->{result_values}->{provisioning_state}, $self->{result_values}->{gateway_type}, $self->{result_values}->{vpn_type}); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{provisioning_state} = $options{new_datas}->{$self->{instance} . '_provisioning_state'}; $self->{result_values}->{gateway_type} = $options{new_datas}->{$self->{instance} . '_gateway_type'}; $self->{result_values}->{vpn_type} = $options{new_datas}->{$self->{instance} . '_vpn_type'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub prefix_vpn_output { my ($self, %options) = @_; return "VPN Gateway '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'vpns', type => 1, cb_prefix_output => 'prefix_vpn_output', message_multiple => 'All VPN gateways are ok' }, ]; $self->{maps_counters}->{vpns} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'provisioning_state' }, { name => 'gateway_type' }, { name => 'vpn_type' }, { 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 => \&catalog_status_threshold, } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource-group:s" => { name => 'resource_group' }, "filter-name:s" => { name => 'filter_name' }, "warning-status:s" => { name => 'warning_status', default => '' }, "critical-status:s" => { name => 'critical_status', default => '%{provisioning_state} ne "Succeeded"' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource_group}) || $self->{option_results}->{resource_group} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --resource-group option"); $self->{output}->option_exit(); } $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; $self->{vpns} = {}; my $vpns = $options{custom}->azure_list_vpn_gateways(resource_group => $self->{option_results}->{resource_group}); foreach my $vpn (@{$vpns}) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $vpn->{name} !~ /$self->{option_results}->{filter_name}/); $self->{vpns}->{$vpn->{id}} = { display => $vpn->{name}, provisioning_state => ($vpn->{provisioningState}) ? $vpn->{provisioningState} : $vpn->{properties}->{provisioningState}, gateway_type => ($vpn->{gatewayType}) ? $vpn->{gatewayType} : $vpn->{properties}->{gatewayType}, vpn_type => ($vpn->{vpnType}) ? $vpn->{vpnType} : $vpn->{properties}->{vpnType}, }; } if (scalar(keys %{$self->{vpns}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No VPN gateways found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check VPN gateways status. Example: perl centreon_plugins.pl --plugin=cloud::azure::network::vpngateway::plugin --custommode=azcli --mode=vpn-gateways-status --resource-group='MYRESOURCEGROUP' --verbose =over 8 =item B<--resource-group> Set resource group (Required). =item B<--filter-name> Filter vpn name (Can be a regexp). =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{provisioning_state}, %{gateway_type}, %{vpn_type}, %{display} =item B<--critical-status> Set critical threshold for status (Default: '%{provisioning_state} ne "Succeeded"'). Can used special variables like: %{provisioning_state}, %{gateway_type}, %{vpn_type}, %{display} =back =cut centreon-plugins-20220113/cloud/azure/network/vpngateway/plugin.pm000066400000000000000000000037151417000230700252100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::network::vpngateway::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} } = ( 'discovery' => 'cloud::azure::network::vpngateway::mode::discovery', 'health' => 'cloud::azure::network::vpngateway::mode::health', 'site-traffic' => 'cloud::azure::network::vpngateway::mode::sitetraffic', 'tunnel-traffic' => 'cloud::azure::network::vpngateway::mode::tunneltraffic', 'vpn-gateway-status' => 'cloud::azure::network::vpngateway::mode::vpngatewaystatus', ); $self->{custom_modes}{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' }, }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure VPN gateways. =cut centreon-plugins-20220113/cloud/azure/security/000077500000000000000000000000001417000230700213375ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/security/keyvault/000077500000000000000000000000001417000230700232035ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/security/keyvault/mode/000077500000000000000000000000001417000230700241275ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/security/keyvault/mode/discovery.pm000066400000000000000000000024351417000230700265000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::security::keyvault::mode::discovery; use base qw(cloud::azure::management::monitor::mode::discovery); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{namespace} = 'Microsoft.KeyVault'; $self->{type} = 'vaults'; } 1; __END__ =head1 MODE Azure Security Key Vaults discovery. =over 8 =item B<--resource-group> Specify resource group. =item B<--location> Specify location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/security/keyvault/mode/serviceapi.pm000066400000000000000000000122271417000230700266230ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::security::keyvault::mode::serviceapi; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'serviceapihit' => { 'output' => 'Total Service Api Hits', 'label' => 'serviceapi-hits', 'nlabel' => 'keyvault.serviceapi.hits.count', 'unit' => '', 'min' => '0' }, 'serviceapilatency' => { 'output' => 'Overall Service Api Latency', 'label' => 'serviceapi-latency', 'nlabel' => 'keyvault.serviceapi.latency.milliseconds', 'unit' => 'ms', 'min' => '0' }, 'serviceapiresult' => { 'output' => 'Total Service Api Results', 'label' => 'serviceapi-results', 'nlabel' => 'keyvault.serviceapi.results.count', 'unit' => '', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.KeyVault\/vaults\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'vaults'; $self->{az_resource_namespace} = 'Microsoft.KeyVault'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Security Key Vault serviceAPI statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::security::keyvault::plugin --mode=service-api --custommode=api --resource= --resource-group= --aggregation='average' --warning-serviceapi-latency='20' --critical-serviceapi-latency='50' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::security::keyvault::plugin --mode=service-api --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.KeyVault/vaults/' --aggregation='average' --warning-serviceapi-latency='20' --critical-serviceapi-latency='50' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'serviceapihit', 'serviceapilatency', 'serviceapiresult'. =item B<--critical-vault-capacity-percentage> Critical threshold where '*' can be: 'serviceapihit', 'serviceapilatency', 'serviceapiresult'. =back =cut centreon-plugins-20220113/cloud/azure/security/keyvault/mode/vaultavailability.pm000066400000000000000000000112061417000230700302130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::security::keyvault::mode::vaultavailability; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'availability' => { 'output' => 'Overall Vault Availability', 'label' => 'vault-availability-percentage', 'nlabel' => 'keyvault.vault.availability.percentage', 'unit' => '%', 'min' => '0', 'max' => '100' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.KeyVault\/vaults\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'vaults'; $self->{az_resource_namespace} = 'Microsoft.KeyVault'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Security Key Vault availability. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::security::keyvault::plugin --mode=vault-availability --custommode=api --resource= --resource-group= --aggregation='average' --warning-vault-availability-percentage='100:' --critical-vault-availability-percentage='50:' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::security::keyvault::plugin --mode=vault-availability --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.KeyVault/vaults/' --aggregation='average' --warning-vault-availability-percentage='100:' --critical-vault-availability-percentage='50:' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-vault-availability-percentage> Warning threshold. =item B<--critical-vault-availability-percentage> Critical threshold. =back =cut centreon-plugins-20220113/cloud/azure/security/keyvault/mode/vaultcapacity.pm000066400000000000000000000111431417000230700273360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::security::keyvault::mode::vaultcapacity; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'saturationshoebox' => { 'output' => 'Overall Vault Saturation', 'label' => 'vault-saturation-percentage', 'nlabel' => 'keyvault.vault.saturation.percentage', 'unit' => '%', 'min' => '0', 'max' => '100' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.KeyVault\/vaults\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'vaults'; $self->{az_resource_namespace} = 'Microsoft.KeyVault'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Security Key Vault capacity. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::security::keyvault::plugin --mode=vault-capacity --custommode=api --resource= --resource-group= --aggregation='average' --warning-vault-saturation-percentage='80' --critical-vault-saturation-percentage='90' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::security::keyvault::plugin --mode=vault-capacity --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.KeyVault/vaults/' --aggregation='average' --warning-vault-saturation-percentage='80' --critical-vault-saturation-percentage='90' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-vault-saturation-percentage> Warning threshold. =item B<--critical-vault-saturation-percentage> Critical threshold. =back =cut centreon-plugins-20220113/cloud/azure/security/keyvault/plugin.pm000066400000000000000000000035401417000230700250410ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::security::keyvault::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} = { 'discovery' => 'cloud::azure::security::keyvault::mode::discovery', 'service-api' => 'cloud::azure::security::keyvault::mode::serviceapi', 'vault-availability' => 'cloud::azure::security::keyvault::mode::vaultavailability', 'vault-capacity' => 'cloud::azure::security::keyvault::mode::vaultcapacity' }; $self->{custom_modes}->{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}->{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' }, }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure Key Vaults. =cut centreon-plugins-20220113/cloud/azure/storage/000077500000000000000000000000001417000230700211345ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/storage/acr/000077500000000000000000000000001417000230700217015ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/storage/acr/mode/000077500000000000000000000000001417000230700226255ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/storage/acr/mode/discovery.pm000066400000000000000000000024641417000230700252000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::storage::acr::mode::discovery; use base qw(cloud::azure::management::monitor::mode::discovery); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{namespace} = 'Microsoft.ContainerRegistry'; $self->{type} = 'registries'; } 1; __END__ =head1 MODE Discover Azure Storage Container Registry resources. =over 8 =item B<--resource-group> Specify resource group. =item B<--location> Specify location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/storage/acr/mode/storageusage.pm000066400000000000000000000107631417000230700256630ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::storage::acr::mode::storageusage; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'storageused' => { 'output' => 'Storage used', 'label' => 'storage-used', 'nlabel' => 'azure.containerregistry.storage.used.bytes', 'unit' => 'B', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.ContainerRegistry\/registries\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'registries'; $self->{az_resource_namespace} = 'Microsoft.ContainerRegistry'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 3600; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT1H'; $self->{az_aggregations} = ['average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Container Registry (ACR) service. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::storage::acr::plugin --mode=storage-usage --custommode=api --resource= --resource-group= --aggregation='average' --warning-storage-used='450000000000' --warning-storage-used='470000000000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::storage::acr::plugin --mode=storage-usage --custommode=api --resource='/subscriptions//resourceGroups//providers/microsoft..containerregistry/registries/' --aggregation='average' --warning-storage-used='450000000000' --warning-storage-used='470000000000' Default aggregation: 'average'. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-storage-used> Warning threshold. =item B<--critical-storage-used> Critical threshold. =back =cut centreon-plugins-20220113/cloud/azure/storage/acr/plugin.pm000066400000000000000000000032451417000230700235410ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::storage::acr::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} = { 'discovery' => 'cloud::azure::storage::acr::mode::discovery', 'storage-usage' => 'cloud::azure::storage::acr::mode::storageusage' }; $self->{custom_modes}->{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}->{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' } }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure Container Registry (ACR) service. =cut centreon-plugins-20220113/cloud/azure/storage/storageaccount/000077500000000000000000000000001417000230700241555ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/storage/storageaccount/mode/000077500000000000000000000000001417000230700251015ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/storage/storageaccount/mode/accountusedcapacity.pm000066400000000000000000000160541417000230700315000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::storage::storageaccount::mode::accountusedcapacity; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; return "Resource '" . $options{instance_value}->{display} . "' " . $options{instance_value}->{stat} . " "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All capacity metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $aggregation ('total') { foreach my $metric ('UsedCapacity') { my $metric_label = lc($metric); my $entry = { label => $metric_label . '-' . $aggregation, set => { key_values => [ { name => $metric_label . '_' . $aggregation }, { name => 'display' }, { name => 'stat' } ], output_template => $metric . ': %s %s', output_change_bytes => 1, perfdatas => [ { label => $metric_label . '_' . $aggregation, value => $metric_label . '_' . $aggregation , template => '%s', unit => 'B', label_extra_instance => 1, instance_use => 'display', min => 0 }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource:s@" => { name => 'resource' }, "resource-group:s" => { name => 'resource_group' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource})) { $self->{output}->add_option_msg(short_msg => "Need to specify either --resource with --resource-group option or --resource ."); $self->{output}->option_exit(); } $self->{az_resource} = $self->{option_results}->{resource}; $self->{az_resource_group} = $self->{option_results}->{resource_group} if (defined($self->{option_results}->{resource_group})); $self->{az_resource_type} = 'storageAccounts'; $self->{az_resource_namespace} = 'Microsoft.Storage'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 3600; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : "PT1H"; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric ('UsedCapacity') { push @{$self->{az_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $resource (@{$self->{az_resource}}) { my $resource_group = $self->{az_resource_group}; my $resource_name = $resource; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Storage\/storageAccounts\/(.*)$/) { $resource_group = $1; $resource_name = $2; } ($metric_results{$resource_name}, undef, undef) = $options{custom}->azure_get_metrics( resource => $resource_name, resource_group => $resource_group, resource_type => $self->{az_resource_type}, resource_namespace => $self->{az_resource_namespace}, metrics => $self->{az_metrics}, aggregations => $self->{az_aggregations}, timeframe => $self->{az_timeframe}, interval => $self->{az_interval}, ); foreach my $metric (@{$self->{az_metrics}}) { my $metric_name = lc($metric); $metric_name =~ s/ /_/g; foreach my $aggregation (@{$self->{az_aggregations}}) { next if (!defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{display} = $resource_name; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{stat} = lc($aggregation); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{$metric_name . "_" . lc($aggregation)} = defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) ? $metric_results{$resource_name}->{$metric_name}->{lc($aggregation)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check storage account resources used capacity metric. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::storage::storageaccount::plugin --custommode=azcli --mode=account-used-capacity --resource=MYFILER --resource-group=MYHOSTGROUP --aggregation='total' --critical-usedcapacity-total='10' --verbose Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::storage::storageaccount::plugin --custommode=azcli --mode=account-used-capacity --resource='/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Storage/storageAccounts/xxx' --aggregation='total' --critical-usedcapacity-total='10' --verbose Default aggregation: 'total' / Only total is valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-usedcapacity-total> Thresholds warning =item B<--critical-usedcapacity-total> Thresholds critical =back =cut centreon-plugins-20220113/cloud/azure/storage/storageaccount/mode/blobcapacity.pm000066400000000000000000000161671417000230700301060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::storage::storageaccount::mode::blobcapacity; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; return "Resource '" . $options{instance_value}->{display} . "' " . $options{instance_value}->{stat} . " "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All capacity metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $aggregation ('total') { foreach my $metric ('BlobCapacity') { my $metric_label = lc($metric); my $entry = { label => $metric_label . '-' . $aggregation, set => { key_values => [ { name => $metric_label . '_' . $aggregation }, { name => 'display' }, { name => 'stat' } ], output_template => $metric . ': %s %s', output_change_bytes => 1, perfdatas => [ { label => $metric_label . '_' . $aggregation, value => $metric_label . '_' . $aggregation , template => '%s', unit => 'B', label_extra_instance => 1, instance_use => 'display', min => 0 }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource:s@" => { name => 'resource' }, "resource-group:s" => { name => 'resource_group' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource})) { $self->{output}->add_option_msg(short_msg => "Need to specify either --resource with --resource-group option or --resource ."); $self->{output}->option_exit(); } $self->{az_resource} = $self->{option_results}->{resource}; $self->{az_resource_group} = $self->{option_results}->{resource_group} if (defined($self->{option_results}->{resource_group})); $self->{az_resource_type} = 'storageAccounts'; $self->{az_resource_namespace} = 'Microsoft.Storage'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 3600; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : "PT1H"; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric ('BlobCapacity') { push @{$self->{az_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $resource (@{$self->{az_resource}}) { my $resource_group = $self->{az_resource_group}; my $resource_name = $resource; my $namespace_full = '/blobServices/default'; if ($resource_name =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Storage\/storageAccounts\/(.*)$/) { $resource_group = $1; $resource_name = $2; } ($metric_results{$resource_name}, undef, undef) = $options{custom}->azure_get_metrics( resource => $resource_name . $namespace_full, resource_group => $resource_group, resource_type => $self->{az_resource_type}, resource_namespace => $self->{az_resource_namespace}, metrics => $self->{az_metrics}, aggregations => $self->{az_aggregations}, timeframe => $self->{az_timeframe}, interval => $self->{az_interval}, ); foreach my $metric (@{$self->{az_metrics}}) { my $metric_name = lc($metric); $metric_name =~ s/ /_/g; foreach my $aggregation (@{$self->{az_aggregations}}) { next if (!defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{display} = $resource_name; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{stat} = lc($aggregation); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{$metric_name . "_" . lc($aggregation)} = defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) ? $metric_results{$resource_name}->{$metric_name}->{lc($aggregation)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check storage account resources blob capacity metric. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::storage::storageaccount::plugin --custommode=azcli --mode=blob-capacity --resource=MYFILER --resource-group=MYHOSTGROUP --aggregation='total' --critical-blobcapacity-total='10' --verbose Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::storage::storageaccount::plugin --custommode=azcli --mode=blob-capacity --resource='/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Storage/storageAccounts/xxx/blobServices/default' --aggregation='total' --critical-blobcapacity-total='10' --verbose Default aggregation: 'total' / Only total is valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-blobcapacity-total> Thresholds warning =item B<--critical-blobcapacity-total> Thresholds critical =back =cut centreon-plugins-20220113/cloud/azure/storage/storageaccount/mode/blobcontainercount.pm000066400000000000000000000162511417000230700313360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::storage::storageaccount::mode::blobcontainercount; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; return "Resource '" . $options{instance_value}->{display} . "' " . $options{instance_value}->{stat} . " "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All count metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $aggregation ('average', 'total') { foreach my $metric ('ContainerCount') { my $metric_label = lc($metric); my $entry = { label => $metric_label . '-' . $aggregation, set => { key_values => [ { name => $metric_label . '_' . $aggregation }, { name => 'display' }, { name => 'stat' } ], output_template => $metric . ': %s', perfdatas => [ { label => $metric_label . '_' . $aggregation, value => $metric_label . '_' . $aggregation , template => '%s', label_extra_instance => 1, instance_use => 'display', min => 0 }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource:s@" => { name => 'resource' }, "resource-group:s" => { name => 'resource_group' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource})) { $self->{output}->add_option_msg(short_msg => "Need to specify either --resource with --resource-group option or --resource ."); $self->{output}->option_exit(); } $self->{az_resource} = $self->{option_results}->{resource}; $self->{az_resource_group} = $self->{option_results}->{resource_group} if (defined($self->{option_results}->{resource_group})); $self->{az_resource_type} = 'storageAccounts'; $self->{az_resource_namespace} = 'Microsoft.Storage'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 3600; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : "PT1H"; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric ('ContainerCount') { push @{$self->{az_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $resource (@{$self->{az_resource}}) { my $resource_group = $self->{az_resource_group}; my $resource_name = $resource; my $namespace_full = '/blobServices/default'; if ($resource_name =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Storage\/storageAccounts\/(.*)$/) { $resource_group = $1; $resource_name = $2; } ($metric_results{$resource_name}, undef, undef) = $options{custom}->azure_get_metrics( resource => $resource_name . $namespace_full, resource_group => $resource_group, resource_type => $self->{az_resource_type}, resource_namespace => $self->{az_resource_namespace}, metrics => $self->{az_metrics}, aggregations => $self->{az_aggregations}, timeframe => $self->{az_timeframe}, interval => $self->{az_interval}, ); foreach my $metric (@{$self->{az_metrics}}) { my $metric_name = lc($metric); $metric_name =~ s/ /_/g; foreach my $aggregation (@{$self->{az_aggregations}}) { next if (!defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{display} = $resource_name; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{stat} = lc($aggregation); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{$metric_name . "_" . lc($aggregation)} = defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) ? $metric_results{$resource_name}->{$metric_name}->{lc($aggregation)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check storage account resources blob container count metric. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::storage::storageaccount::plugin --custommode=azcli --mode=blob-container-count --resource=MYFILER --resource-group=MYHOSTGROUP --aggregation='average' --critical-containercount-average='10' --verbose Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::storage::storageaccount::plugin --custommode=azcli --mode=blob-container-count --resource='/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Storage/storageAccounts/xxx/blobServices/default' --aggregation='average' --critical-containercount-average='10' --verbose Default aggregation: 'average' / Total and average are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-containercount-*> Thresholds warning (* can be: 'average', 'total'). =item B<--critical-containercount-*> Thresholds critical (* can be: 'average', 'total'). =back =cut centreon-plugins-20220113/cloud/azure/storage/storageaccount/mode/blobcount.pm000066400000000000000000000160251417000230700274320ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::storage::storageaccount::mode::blobcount; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; return "Resource '" . $options{instance_value}->{display} . "' " . $options{instance_value}->{stat} . " "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All count metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $aggregation ('total') { foreach my $metric ('BlobCount') { my $metric_label = lc($metric); my $entry = { label => $metric_label . '-' . $aggregation, set => { key_values => [ { name => $metric_label . '_' . $aggregation }, { name => 'display' }, { name => 'stat' } ], output_template => $metric . ': %s', perfdatas => [ { label => $metric_label . '_' . $aggregation, value => $metric_label . '_' . $aggregation , template => '%s', label_extra_instance => 1, instance_use => 'display', min => 0 }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource:s@" => { name => 'resource' }, "resource-group:s" => { name => 'resource_group' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource})) { $self->{output}->add_option_msg(short_msg => "Need to specify either --resource with --resource-group option or --resource ."); $self->{output}->option_exit(); } $self->{az_resource} = $self->{option_results}->{resource}; $self->{az_resource_group} = $self->{option_results}->{resource_group} if (defined($self->{option_results}->{resource_group})); $self->{az_resource_type} = 'storageAccounts'; $self->{az_resource_namespace} = 'Microsoft.Storage'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 3600; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : "PT1H"; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric ('BlobCount') { push @{$self->{az_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $resource (@{$self->{az_resource}}) { my $resource_group = $self->{az_resource_group}; my $resource_name = $resource; my $namespace_full = '/blobServices/default'; if ($resource_name =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Storage\/storageAccounts\/(.*)$/) { $resource_group = $1; $resource_name = $2; } ($metric_results{$resource_name}, undef, undef) = $options{custom}->azure_get_metrics( resource => $resource_name . $namespace_full, resource_group => $resource_group, resource_type => $self->{az_resource_type}, resource_namespace => $self->{az_resource_namespace}, metrics => $self->{az_metrics}, aggregations => $self->{az_aggregations}, timeframe => $self->{az_timeframe}, interval => $self->{az_interval}, ); foreach my $metric (@{$self->{az_metrics}}) { my $metric_name = lc($metric); $metric_name =~ s/ /_/g; foreach my $aggregation (@{$self->{az_aggregations}}) { next if (!defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{display} = $resource_name; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{stat} = lc($aggregation); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{$metric_name . "_" . lc($aggregation)} = defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) ? $metric_results{$resource_name}->{$metric_name}->{lc($aggregation)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check storage account resources blob capacity metric. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::storage::storageaccount::plugin --custommode=azcli --mode=blob-capacity --resource=MYFILER --resource-group=MYHOSTGROUP --aggregation='total' --critical-blobcount-total='10' --verbose Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::storage::storageaccount::plugin --custommode=azcli --mode=blob-capacity --resource='/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Storage/storageAccounts/xxx/blobServices/default' --aggregation='total' --critical-blobcount-total='10' --verbose Default aggregation: 'total' / Only total is valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-blobcount-total> Thresholds warning =item B<--critical-blobcount-total> Thresholds critical =back =cut centreon-plugins-20220113/cloud/azure/storage/storageaccount/mode/discovery.pm000066400000000000000000000024401417000230700274460ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::storage::storageaccount::mode::discovery; use base qw(cloud::azure::management::monitor::mode::discovery); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{namespace} = 'Microsoft.Storage'; $self->{type} = 'storageAccounts'; } 1; __END__ =head1 MODE Storage Account discovery. =over 8 =item B<--resource-group> Specify resource group. =item B<--location> Specify location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/storage/storageaccount/mode/filecapacity.pm000066400000000000000000000163221417000230700301000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::storage::storageaccount::mode::filecapacity; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; return "Resource '" . $options{instance_value}->{display} . "' " . $options{instance_value}->{stat} . " "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All capacity metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $aggregation ('average', 'total') { foreach my $metric ('FileCapacity') { my $metric_label = lc($metric); my $entry = { label => $metric_label . '-' . $aggregation, set => { key_values => [ { name => $metric_label . '_' . $aggregation }, { name => 'display' }, { name => 'stat' } ], output_template => $metric . ': %s %s', output_change_bytes => 1, perfdatas => [ { label => $metric_label . '_' . $aggregation, value => $metric_label . '_' . $aggregation , template => '%s', unit => 'B', label_extra_instance => 1, instance_use => 'display', min => 0 }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource:s@" => { name => 'resource' }, "resource-group:s" => { name => 'resource_group' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource})) { $self->{output}->add_option_msg(short_msg => "Need to specify either --resource with --resource-group option or --resource ."); $self->{output}->option_exit(); } $self->{az_resource} = $self->{option_results}->{resource}; $self->{az_resource_group} = $self->{option_results}->{resource_group} if (defined($self->{option_results}->{resource_group})); $self->{az_resource_type} = 'storageAccounts'; $self->{az_resource_namespace} = 'Microsoft.Storage'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 3600; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : "PT1H"; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric ('FileCapacity') { push @{$self->{az_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $resource (@{$self->{az_resource}}) { my $resource_group = $self->{az_resource_group}; my $resource_name = $resource; my $namespace_full = '/fileServices/default'; if ($resource_name =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Storage\/storageAccounts\/(.*)$/) { $resource_group = $1; $resource_name = $2; } ($metric_results{$resource_name}, undef, undef) = $options{custom}->azure_get_metrics( resource => $resource_name . $namespace_full, resource_group => $resource_group, resource_type => $self->{az_resource_type}, resource_namespace => $self->{az_resource_namespace}, metrics => $self->{az_metrics}, aggregations => $self->{az_aggregations}, timeframe => $self->{az_timeframe}, interval => $self->{az_interval}, ); foreach my $metric (@{$self->{az_metrics}}) { my $metric_name = lc($metric); $metric_name =~ s/ /_/g; foreach my $aggregation (@{$self->{az_aggregations}}) { next if (!defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{display} = $resource_name; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{stat} = lc($aggregation); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{$metric_name . "_" . lc($aggregation)} = defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) ? $metric_results{$resource_name}->{$metric_name}->{lc($aggregation)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check storage account resources file capacity metric. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::storage::storageaccount::plugin --custommode=azcli --mode=file-capacity --resource=MYFILER --resource-group=MYHOSTGROUP --aggregation='average' --critical-filecapacity-average='10' --verbose Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::storage::storageaccount::plugin --custommode=azcli --mode=file-capacity --resource='/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Storage/storageAccounts/xxx/fileServices/default' --aggregation='average' --critical-filecapacity-average='10' --verbose Default aggregation: 'average' / Total and average are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-filecapacity-*> Thresholds warning (* can be: 'average', 'total'). =item B<--critical-filecapacity-*> Thresholds critical (* can be: 'average', 'total'). =back =cut centreon-plugins-20220113/cloud/azure/storage/storageaccount/mode/filecount.pm000066400000000000000000000161431417000230700274340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::storage::storageaccount::mode::filecount; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; return "Resource '" . $options{instance_value}->{display} . "' " . $options{instance_value}->{stat} . " "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All count metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $aggregation ('average', 'total') { foreach my $metric ('FileCount') { my $metric_label = lc($metric); my $entry = { label => $metric_label . '-' . $aggregation, set => { key_values => [ { name => $metric_label . '_' . $aggregation }, { name => 'display' }, { name => 'stat' } ], output_template => $metric . ': %s', perfdatas => [ { label => $metric_label . '_' . $aggregation, value => $metric_label . '_' . $aggregation , template => '%s', label_extra_instance => 1, instance_use => 'display', min => 0 }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource:s@" => { name => 'resource' }, "resource-group:s" => { name => 'resource_group' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource})) { $self->{output}->add_option_msg(short_msg => "Need to specify either --resource with --resource-group option or --resource ."); $self->{output}->option_exit(); } $self->{az_resource} = $self->{option_results}->{resource}; $self->{az_resource_group} = $self->{option_results}->{resource_group} if (defined($self->{option_results}->{resource_group})); $self->{az_resource_type} = 'storageAccounts'; $self->{az_resource_namespace} = 'Microsoft.Storage'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 3600; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : "PT1H"; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric ('FileCount') { push @{$self->{az_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $resource (@{$self->{az_resource}}) { my $resource_group = $self->{az_resource_group}; my $resource_name = $resource; my $namespace_full = '/fileServices/default'; if ($resource_name =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Storage\/storageAccounts\/(.*)$/) { $resource_group = $1; $resource_name = $2; } ($metric_results{$resource_name}, undef, undef) = $options{custom}->azure_get_metrics( resource => $resource_name . $namespace_full, resource_group => $resource_group, resource_type => $self->{az_resource_type}, resource_namespace => $self->{az_resource_namespace}, metrics => $self->{az_metrics}, aggregations => $self->{az_aggregations}, timeframe => $self->{az_timeframe}, interval => $self->{az_interval}, ); foreach my $metric (@{$self->{az_metrics}}) { my $metric_name = lc($metric); $metric_name =~ s/ /_/g; foreach my $aggregation (@{$self->{az_aggregations}}) { next if (!defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{display} = $resource_name; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{stat} = lc($aggregation); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{$metric_name . "_" . lc($aggregation)} = defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) ? $metric_results{$resource_name}->{$metric_name}->{lc($aggregation)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check storage account resources file count metric. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::storage::storageaccount::plugin --custommode=azcli --mode=file-count --resource=MYFILER --resource-group=MYHOSTGROUP --aggregation='average' --critical-filecount-average='10' --verbose Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::storage::storageaccount::plugin --custommode=azcli --mode=file-count --resource='/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Storage/storageAccounts/xxx/fileServices/default' --aggregation='average' --critical-filecount-average='10' --verbose Default aggregation: 'average' / Total and average are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-filecount-*> Thresholds warning (* can be: 'average', 'total'). =item B<--critical-filecount-*> Thresholds critical (* can be: 'average', 'total'). =back =cut centreon-plugins-20220113/cloud/azure/storage/storageaccount/mode/filesharecount.pm000066400000000000000000000162341417000230700304600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::storage::storageaccount::mode::filesharecount; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; return "Resource '" . $options{instance_value}->{display} . "' " . $options{instance_value}->{stat} . " "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All count metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $aggregation ('average', 'total') { foreach my $metric ('FileShareCount') { my $metric_label = lc($metric); my $entry = { label => $metric_label . '-' . $aggregation, set => { key_values => [ { name => $metric_label . '_' . $aggregation }, { name => 'display' }, { name => 'stat' } ], output_template => $metric . ': %s', perfdatas => [ { label => $metric_label . '_' . $aggregation, value => $metric_label . '_' . $aggregation , template => '%s', label_extra_instance => 1, instance_use => 'display', min => 0 }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource:s@" => { name => 'resource' }, "resource-group:s" => { name => 'resource_group' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource})) { $self->{output}->add_option_msg(short_msg => "Need to specify either --resource with --resource-group option or --resource ."); $self->{output}->option_exit(); } $self->{az_resource} = $self->{option_results}->{resource}; $self->{az_resource_group} = $self->{option_results}->{resource_group} if (defined($self->{option_results}->{resource_group})); $self->{az_resource_type} = 'storageAccounts'; $self->{az_resource_namespace} = 'Microsoft.Storage'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 3600; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : "PT1H"; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric ('FileShareCount') { push @{$self->{az_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $resource (@{$self->{az_resource}}) { my $resource_group = $self->{az_resource_group}; my $resource_name = $resource; my $namespace_full = '/fileServices/default'; if ($resource_name =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Storage\/storageAccounts\/(.*)$/) { $resource_group = $1; $resource_name = $2; } ($metric_results{$resource_name}, undef, undef) = $options{custom}->azure_get_metrics( resource => $resource_name . $namespace_full, resource_group => $resource_group, resource_type => $self->{az_resource_type}, resource_namespace => $self->{az_resource_namespace}, metrics => $self->{az_metrics}, aggregations => $self->{az_aggregations}, timeframe => $self->{az_timeframe}, interval => $self->{az_interval}, ); foreach my $metric (@{$self->{az_metrics}}) { my $metric_name = lc($metric); $metric_name =~ s/ /_/g; foreach my $aggregation (@{$self->{az_aggregations}}) { next if (!defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{display} = $resource_name; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{stat} = lc($aggregation); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{$metric_name . "_" . lc($aggregation)} = defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) ? $metric_results{$resource_name}->{$metric_name}->{lc($aggregation)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check storage account resources file share count metric. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::storage::storageaccount::plugin --custommode=azcli --mode=file-share-count --resource=MYFILER --resource-group=MYHOSTGROUP --aggregation='average' --critical-filesharecount-average='10' --verbose Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::storage::storageaccount::plugin --custommode=azcli --mode=file-share-count --resource='/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Storage/storageAccounts/xxx/fileServices/default' --aggregation='average' --critical-filesharecount-average='10' --verbose Default aggregation: 'average' / Total and average are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-filesharecount-*> Thresholds warning (* can be: 'average', 'total'). =item B<--critical-filesharecount-*> Thresholds critical (* can be: 'average', 'total'). =back =cut centreon-plugins-20220113/cloud/azure/storage/storageaccount/mode/health.pm000066400000000000000000000036721417000230700267140ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::storage::storageaccount::mode::health; use base qw(cloud::azure::management::monitor::mode::health); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{az_resource_namespace} = 'Microsoft.Storage'; $self->{az_resource_type} = 'storageAccounts'; } 1; __END__ =head1 MODE Check Storage Account health status. (Usefull to determine host status) =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{summary} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /^Unavailable$/'). Can used special variables like: %{status}, %{summary} =item B<--unknown-status> Set unknown threshold for status (Default: '%{status} =~ /^Unknown$/'). Can used special variables like: %{status}, %{summary} =item B<--ok-status> Set ok threshold for status (Default: '%{status} =~ /^Available$/'). Can used special variables like: %{status}, %{summary} =back =cut centreon-plugins-20220113/cloud/azure/storage/storageaccount/mode/listresources.pm000066400000000000000000000104101417000230700303410ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::storage::storageaccount::mode::listresources; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource-group:s" => { name => 'resource_group' }, "location:s" => { name => 'location' }, "filter-name:s" => { name => 'filter_name' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{resources} = $options{custom}->azure_list_resources( namespace => 'Microsoft.Storage', resource_type => 'storageAccounts', location => $self->{option_results}->{location}, resource_group => $self->{option_results}->{resource_group} ); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $resource (@{$self->{resources}}) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $resource->{name} !~ /$self->{option_results}->{filter_name}/); my $resource_group = '-'; $resource_group = $resource->{resourceGroup} if (defined($resource->{resourceGroup})); $resource_group = $1 if (defined($resource->{id}) && $resource->{id} =~ /resourceGroups\/(.*)\/providers/); my @tags; foreach my $tag (keys %{$resource->{tags}}) { push @tags, $tag . ':' . $resource->{tags}->{$tag}; } $self->{output}->output_add(long_msg => sprintf("[name = %s][resourcegroup = %s][location = %s][id = %s][tags = %s]", $resource->{name}, $resource_group, $resource->{location}, $resource->{id}, join(',', @tags), )); } $self->{output}->output_add(severity => 'OK', short_msg => 'List storage accounts:'); $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', 'resourcegroup', 'location', 'id', 'tags']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $resource (@{$self->{resources}}) { my $resource_group = '-'; $resource_group = $resource->{resourceGroup} if (defined($resource->{resourceGroup})); $resource_group = $1 if (defined($resource->{id}) && $resource->{id} =~ /resourceGroups\/(.*)\/providers/); my @tags; foreach my $tag (keys %{$resource->{tags}}) { push @tags, $tag . ':' . $resource->{tags}->{$tag}; } $self->{output}->add_disco_entry( name => $resource->{name}, resourcegroup => $resource_group, location => $resource->{location}, id => $resource->{id}, tags => join(',', @tags), ); } } 1; __END__ =head1 MODE List storage account resources. =over 8 =item B<--resource-group> Set resource group. =item B<--location> Set resource location. =item B<--filter-name> Filter resource name (Can be a regexp). =back =cut centreon-plugins-20220113/cloud/azure/storage/storageaccount/mode/queuecapacity.pm000066400000000000000000000163321417000230700303060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::storage::storageaccount::mode::queuecapacity; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; return "Resource '" . $options{instance_value}->{display} . "' " . $options{instance_value}->{stat} . " "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All capacity metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $aggregation ('average', 'total') { foreach my $metric ('QueueCapacity') { my $metric_label = lc($metric); my $entry = { label => $metric_label . '-' . $aggregation, set => { key_values => [ { name => $metric_label . '_' . $aggregation }, { name => 'display' }, { name => 'stat' } ], output_template => $metric . ': %s %s', output_change_bytes => 1, perfdatas => [ { label => $metric_label . '_' . $aggregation, value => $metric_label . '_' . $aggregation , template => '%s', unit => 'B', label_extra_instance => 1, instance_use => 'display', min => 0 }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource:s@" => { name => 'resource' }, "resource-group:s" => { name => 'resource_group' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource})) { $self->{output}->add_option_msg(short_msg => "Need to specify either --resource with --resource-group option or --resource ."); $self->{output}->option_exit(); } $self->{az_resource} = $self->{option_results}->{resource}; $self->{az_resource_group} = $self->{option_results}->{resource_group} if (defined($self->{option_results}->{resource_group})); $self->{az_resource_type} = 'storageAccounts'; $self->{az_resource_namespace} = 'Microsoft.Storage'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 3600; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : "PT1H"; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric ('QueueCapacity') { push @{$self->{az_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $resource (@{$self->{az_resource}}) { my $resource_group = $self->{az_resource_group}; my $resource_name = $resource; my $namespace_full = '/queueServices/default'; if ($resource_name =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Storage\/storageAccounts\/(.*)$/) { $resource_group = $1; $resource_name = $2; } ($metric_results{$resource_name}, undef, undef) = $options{custom}->azure_get_metrics( resource => $resource_name . $namespace_full, resource_group => $resource_group, resource_type => $self->{az_resource_type}, resource_namespace => $self->{az_resource_namespace}, metrics => $self->{az_metrics}, aggregations => $self->{az_aggregations}, timeframe => $self->{az_timeframe}, interval => $self->{az_interval}, ); foreach my $metric (@{$self->{az_metrics}}) { my $metric_name = lc($metric); $metric_name =~ s/ /_/g; foreach my $aggregation (@{$self->{az_aggregations}}) { next if (!defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{display} = $resource_name; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{stat} = lc($aggregation); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{$metric_name . "_" . lc($aggregation)} = defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) ? $metric_results{$resource_name}->{$metric_name}->{lc($aggregation)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check storage account resources queue capacity metric. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::storage::storageaccount::plugin --custommode=azcli --mode=queue-capacity --resource=MYFILER --resource-group=MYHOSTGROUP --aggregation='average' --critical-queuecapacity-average='10' --verbose Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::storage::storageaccount::plugin --custommode=azcli --mode=queue-capacity --resource='/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Storage/storageAccounts/xxx/queueServices/default' --aggregation='average' --critical-queuecapacity-average='10' --verbose Default aggregation: 'average' / Total and average are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-queuecapacity-*> Thresholds warning (* can be: 'average', 'total'). =item B<--critical-queuecapacity-*> Thresholds critical (* can be: 'average', 'total'). =back =cut centreon-plugins-20220113/cloud/azure/storage/storageaccount/mode/queuecount.pm000066400000000000000000000161571417000230700276460ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::storage::storageaccount::mode::queuecount; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; return "Resource '" . $options{instance_value}->{display} . "' " . $options{instance_value}->{stat} . " "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All count metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $aggregation ('average', 'total') { foreach my $metric ('QueueCount') { my $metric_label = lc($metric); my $entry = { label => $metric_label . '-' . $aggregation, set => { key_values => [ { name => $metric_label . '_' . $aggregation }, { name => 'display' }, { name => 'stat' } ], output_template => $metric . ': %s', perfdatas => [ { label => $metric_label . '_' . $aggregation, value => $metric_label . '_' . $aggregation , template => '%s', label_extra_instance => 1, instance_use => 'display', min => 0 }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource:s@" => { name => 'resource' }, "resource-group:s" => { name => 'resource_group' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource})) { $self->{output}->add_option_msg(short_msg => "Need to specify either --resource with --resource-group option or --resource ."); $self->{output}->option_exit(); } $self->{az_resource} = $self->{option_results}->{resource}; $self->{az_resource_group} = $self->{option_results}->{resource_group} if (defined($self->{option_results}->{resource_group})); $self->{az_resource_type} = 'storageAccounts'; $self->{az_resource_namespace} = 'Microsoft.Storage'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 3600; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : "PT1H"; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric ('QueueCount') { push @{$self->{az_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $resource (@{$self->{az_resource}}) { my $resource_group = $self->{az_resource_group}; my $resource_name = $resource; my $namespace_full = '/queueServices/default'; if ($resource_name =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Storage\/storageAccounts\/(.*)$/) { $resource_group = $1; $resource_name = $2; } ($metric_results{$resource_name}, undef, undef) = $options{custom}->azure_get_metrics( resource => $resource_name . $namespace_full, resource_group => $resource_group, resource_type => $self->{az_resource_type}, resource_namespace => $self->{az_resource_namespace}, metrics => $self->{az_metrics}, aggregations => $self->{az_aggregations}, timeframe => $self->{az_timeframe}, interval => $self->{az_interval}, ); foreach my $metric (@{$self->{az_metrics}}) { my $metric_name = lc($metric); $metric_name =~ s/ /_/g; foreach my $aggregation (@{$self->{az_aggregations}}) { next if (!defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{display} = $resource_name; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{stat} = lc($aggregation); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{$metric_name . "_" . lc($aggregation)} = defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) ? $metric_results{$resource_name}->{$metric_name}->{lc($aggregation)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check storage account resources queue count metric. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::storage::storageaccount::plugin --custommode=azcli --mode=queue-count --resource=MYFILER --resource-group=MYHOSTGROUP --aggregation='average' --critical-queuecount-average='10' --verbose Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::storage::storageaccount::plugin --custommode=azcli --mode=queue-count --resource='/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Storage/storageAccounts/xxx/queueServices/default' --aggregation='average' --critical-queuecount-average='10' --verbose Default aggregation: 'average' / Total and average are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-queuecount-*> Thresholds warning (* can be: 'average', 'total'). =item B<--critical-queuecount-*> Thresholds critical (* can be: 'average', 'total'). =back =cut centreon-plugins-20220113/cloud/azure/storage/storageaccount/mode/queuemessagecount.pm000066400000000000000000000162701417000230700312070ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::storage::storageaccount::mode::queuemessagecount; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; return "Resource '" . $options{instance_value}->{display} . "' " . $options{instance_value}->{stat} . " "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All count metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $aggregation ('average', 'total') { foreach my $metric ('QueueMessageCount') { my $metric_label = lc($metric); my $entry = { label => $metric_label . '-' . $aggregation, set => { key_values => [ { name => $metric_label . '_' . $aggregation }, { name => 'display' }, { name => 'stat' } ], output_template => $metric . ': %s', perfdatas => [ { label => $metric_label . '_' . $aggregation, value => $metric_label . '_' . $aggregation , template => '%s', label_extra_instance => 1, instance_use => 'display', min => 0 }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource:s@" => { name => 'resource' }, "resource-group:s" => { name => 'resource_group' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource})) { $self->{output}->add_option_msg(short_msg => "Need to specify either --resource with --resource-group option or --resource ."); $self->{output}->option_exit(); } $self->{az_resource} = $self->{option_results}->{resource}; $self->{az_resource_group} = $self->{option_results}->{resource_group} if (defined($self->{option_results}->{resource_group})); $self->{az_resource_type} = 'storageAccounts'; $self->{az_resource_namespace} = 'Microsoft.Storage'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 3600; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : "PT1H"; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric ('QueueMessageCount') { push @{$self->{az_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $resource (@{$self->{az_resource}}) { my $resource_group = $self->{az_resource_group}; my $resource_name = $resource; my $namespace_full = '/queueServices/default'; if ($resource_name =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Storage\/storageAccounts\/(.*)$/) { $resource_group = $1; $resource_name = $2; } ($metric_results{$resource_name}, undef, undef) = $options{custom}->azure_get_metrics( resource => $resource_name . $namespace_full, resource_group => $resource_group, resource_type => $self->{az_resource_type}, resource_namespace => $self->{az_resource_namespace}, metrics => $self->{az_metrics}, aggregations => $self->{az_aggregations}, timeframe => $self->{az_timeframe}, interval => $self->{az_interval}, ); foreach my $metric (@{$self->{az_metrics}}) { my $metric_name = lc($metric); $metric_name =~ s/ /_/g; foreach my $aggregation (@{$self->{az_aggregations}}) { next if (!defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{display} = $resource_name; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{stat} = lc($aggregation); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{$metric_name . "_" . lc($aggregation)} = defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) ? $metric_results{$resource_name}->{$metric_name}->{lc($aggregation)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check storage account resources queue message count metric. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::storage::storageaccount::plugin --custommode=azcli --mode=queue-message-count --resource=MYFILER --resource-group=MYHOSTGROUP --aggregation='average' --critical-queuemessagecount-average='10' --verbose Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::storage::storageaccount::plugin --custommode=azcli --mode=queue-message-count --resource='/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Storage/storageAccounts/xxx/queueServices/default' --aggregation='average' --critical-queuemessagecount-average='10' --verbose Default aggregation: 'average' / Total and average are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-queuemessagecount-*> Thresholds warning (* can be: 'average', 'total'). =item B<--critical-queuemessagecount-*> Thresholds critical (* can be: 'average', 'total'). =back =cut centreon-plugins-20220113/cloud/azure/storage/storageaccount/mode/tablecapacity.pm000066400000000000000000000163321417000230700302510ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::storage::storageaccount::mode::tablecapacity; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; return "Resource '" . $options{instance_value}->{display} . "' " . $options{instance_value}->{stat} . " "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All capacity metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $aggregation ('average', 'total') { foreach my $metric ('TableCapacity') { my $metric_label = lc($metric); my $entry = { label => $metric_label . '-' . $aggregation, set => { key_values => [ { name => $metric_label . '_' . $aggregation }, { name => 'display' }, { name => 'stat' } ], output_template => $metric . ': %s %s', output_change_bytes => 1, perfdatas => [ { label => $metric_label . '_' . $aggregation, value => $metric_label . '_' . $aggregation , template => '%s', unit => 'B', label_extra_instance => 1, instance_use => 'display', min => 0 }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource:s@" => { name => 'resource' }, "resource-group:s" => { name => 'resource_group' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource})) { $self->{output}->add_option_msg(short_msg => "Need to specify either --resource with --resource-group option or --resource ."); $self->{output}->option_exit(); } $self->{az_resource} = $self->{option_results}->{resource}; $self->{az_resource_group} = $self->{option_results}->{resource_group} if (defined($self->{option_results}->{resource_group})); $self->{az_resource_type} = 'storageAccounts'; $self->{az_resource_namespace} = 'Microsoft.Storage'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 3600; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : "PT1H"; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric ('TableCapacity') { push @{$self->{az_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $resource (@{$self->{az_resource}}) { my $resource_group = $self->{az_resource_group}; my $resource_name = $resource; my $namespace_full = '/tableServices/default'; if ($resource_name =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Storage\/storageAccounts\/(.*)$/) { $resource_group = $1; $resource_name = $2; } ($metric_results{$resource_name}, undef, undef) = $options{custom}->azure_get_metrics( resource => $resource_name . $namespace_full, resource_group => $resource_group, resource_type => $self->{az_resource_type}, resource_namespace => $self->{az_resource_namespace}, metrics => $self->{az_metrics}, aggregations => $self->{az_aggregations}, timeframe => $self->{az_timeframe}, interval => $self->{az_interval}, ); foreach my $metric (@{$self->{az_metrics}}) { my $metric_name = lc($metric); $metric_name =~ s/ /_/g; foreach my $aggregation (@{$self->{az_aggregations}}) { next if (!defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{display} = $resource_name; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{stat} = lc($aggregation); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{$metric_name . "_" . lc($aggregation)} = defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) ? $metric_results{$resource_name}->{$metric_name}->{lc($aggregation)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check storage account resources table capacity metric. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::storage::storageaccount::plugin --custommode=azcli --mode=table-capacity --resource=MYFILER --resource-group=MYHOSTGROUP --aggregation='average' --critical-tablecapacity-average='10' --verbose Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::storage::storageaccount::plugin --custommode=azcli --mode=table-capacity --resource='/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Storage/storageAccounts/xxx/tableServices/default' --aggregation='average' --critical-tablecapacity-average='10' --verbose Default aggregation: 'average' / Total and average are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-tablecapacity-*> Thresholds warning (* can be: 'average', 'total'). =item B<--critical-tablecapacity-*> Thresholds critical (* can be: 'average', 'total'). =back =cut centreon-plugins-20220113/cloud/azure/storage/storageaccount/mode/tablecount.pm000066400000000000000000000161571417000230700276110ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::storage::storageaccount::mode::tablecount; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; return "Resource '" . $options{instance_value}->{display} . "' " . $options{instance_value}->{stat} . " "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All count metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $aggregation ('average', 'total') { foreach my $metric ('TableCount') { my $metric_label = lc($metric); my $entry = { label => $metric_label . '-' . $aggregation, set => { key_values => [ { name => $metric_label . '_' . $aggregation }, { name => 'display' }, { name => 'stat' } ], output_template => $metric . ': %s', perfdatas => [ { label => $metric_label . '_' . $aggregation, value => $metric_label . '_' . $aggregation , template => '%s', label_extra_instance => 1, instance_use => 'display', min => 0 }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource:s@" => { name => 'resource' }, "resource-group:s" => { name => 'resource_group' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource})) { $self->{output}->add_option_msg(short_msg => "Need to specify either --resource with --resource-group option or --resource ."); $self->{output}->option_exit(); } $self->{az_resource} = $self->{option_results}->{resource}; $self->{az_resource_group} = $self->{option_results}->{resource_group} if (defined($self->{option_results}->{resource_group})); $self->{az_resource_type} = 'storageAccounts'; $self->{az_resource_namespace} = 'Microsoft.Storage'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 3600; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : "PT1H"; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric ('TableCount') { push @{$self->{az_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $resource (@{$self->{az_resource}}) { my $resource_group = $self->{az_resource_group}; my $resource_name = $resource; my $namespace_full = '/tableServices/default'; if ($resource_name =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Storage\/storageAccounts\/(.*)$/) { $resource_group = $1; $resource_name = $2; } ($metric_results{$resource_name}, undef, undef) = $options{custom}->azure_get_metrics( resource => $resource_name . $namespace_full, resource_group => $resource_group, resource_type => $self->{az_resource_type}, resource_namespace => $self->{az_resource_namespace}, metrics => $self->{az_metrics}, aggregations => $self->{az_aggregations}, timeframe => $self->{az_timeframe}, interval => $self->{az_interval}, ); foreach my $metric (@{$self->{az_metrics}}) { my $metric_name = lc($metric); $metric_name =~ s/ /_/g; foreach my $aggregation (@{$self->{az_aggregations}}) { next if (!defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{display} = $resource_name; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{stat} = lc($aggregation); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{$metric_name . "_" . lc($aggregation)} = defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) ? $metric_results{$resource_name}->{$metric_name}->{lc($aggregation)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check storage account resources table count metric. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::storage::storageaccount::plugin --custommode=azcli --mode=table-count --resource=MYFILER --resource-group=MYHOSTGROUP --aggregation='average' --critical-tablecount-average='10' --verbose Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::storage::storageaccount::plugin --custommode=azcli --mode=table-count --resource='/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Storage/storageAccounts/xxx/tableServices/default' --aggregation='average' --critical-tablecount-average='10' --verbose Default aggregation: 'average' / Total and average are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-tablecount-*> Thresholds warning (* can be: 'average', 'total'). =item B<--critical-tablecount-*> Thresholds critical (* can be: 'average', 'total'). =back =cut centreon-plugins-20220113/cloud/azure/storage/storageaccount/mode/tableentitycount.pm000066400000000000000000000162561417000230700310460ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::storage::storageaccount::mode::tableentitycount; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; return "Resource '" . $options{instance_value}->{display} . "' " . $options{instance_value}->{stat} . " "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All count metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $aggregation ('average', 'total') { foreach my $metric ('TableEntityCount') { my $metric_label = lc($metric); my $entry = { label => $metric_label . '-' . $aggregation, set => { key_values => [ { name => $metric_label . '_' . $aggregation }, { name => 'display' }, { name => 'stat' } ], output_template => $metric . ': %s', perfdatas => [ { label => $metric_label . '_' . $aggregation, value => $metric_label . '_' . $aggregation , template => '%s', label_extra_instance => 1, instance_use => 'display', min => 0 }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource:s@" => { name => 'resource' }, "resource-group:s" => { name => 'resource_group' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource})) { $self->{output}->add_option_msg(short_msg => "Need to specify either --resource with --resource-group option or --resource ."); $self->{output}->option_exit(); } $self->{az_resource} = $self->{option_results}->{resource}; $self->{az_resource_group} = $self->{option_results}->{resource_group} if (defined($self->{option_results}->{resource_group})); $self->{az_resource_type} = 'storageAccounts'; $self->{az_resource_namespace} = 'Microsoft.Storage'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 3600; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : "PT1H"; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric ('TableEntityCount') { push @{$self->{az_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $resource (@{$self->{az_resource}}) { my $resource_group = $self->{az_resource_group}; my $resource_name = $resource; my $namespace_full = '/tableServices/default'; if ($resource_name =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Storage\/storageAccounts\/(.*)$/) { $resource_group = $1; $resource_name = $2; } ($metric_results{$resource_name}, undef, undef) = $options{custom}->azure_get_metrics( resource => $resource_name . $namespace_full, resource_group => $resource_group, resource_type => $self->{az_resource_type}, resource_namespace => $self->{az_resource_namespace}, metrics => $self->{az_metrics}, aggregations => $self->{az_aggregations}, timeframe => $self->{az_timeframe}, interval => $self->{az_interval}, ); foreach my $metric (@{$self->{az_metrics}}) { my $metric_name = lc($metric); $metric_name =~ s/ /_/g; foreach my $aggregation (@{$self->{az_aggregations}}) { next if (!defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{display} = $resource_name; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{stat} = lc($aggregation); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{$metric_name . "_" . lc($aggregation)} = defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) ? $metric_results{$resource_name}->{$metric_name}->{lc($aggregation)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check storage account resources table entity count metric. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::storage::storageaccount::plugin --custommode=azcli --mode=table-entity-count --resource=MYFILER --resource-group=MYHOSTGROUP --aggregation='average' --critical-tableentitycount-average='10' --verbose Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::storage::storageaccount::plugin --custommode=azcli --mode=table-entity-count --resource='/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Storage/storageAccounts/xxx/tableServices/default' --aggregation='average' --critical-tableentitycount-average='10' --verbose Default aggregation: 'average' / Total and average are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-tableentitycount-*> Thresholds warning (* can be: 'average', 'total'). =item B<--critical-tableentitycount-*> Thresholds critical (* can be: 'average', 'total'). =back =cut centreon-plugins-20220113/cloud/azure/storage/storageaccount/mode/transactionsavailability.pm000066400000000000000000000210651417000230700325460ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::storage::storageaccount::mode::transactionsavailability; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; my $msg = "Resource '" . $options{instance_value}->{display} . "'"; $msg .= " (" . $options{instance_value}->{namespace} . ")" if ($options{instance_value}->{namespace} ne ''); $msg .= " " . $options{instance_value}->{stat} . " "; return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All transactions metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $aggregation ('minimum', 'maximum', 'average') { foreach my $metric ('Availability') { my $metric_label = lc($metric); my $entry = { label => $metric_label . '-' . $aggregation, set => { key_values => [ { name => $metric_label . '_' . $aggregation }, { name => 'display' }, { name => 'stat' } ], output_template => $metric . ': %.2f %%', perfdatas => [ { label => $metric_label . '_' . $aggregation, value => $metric_label . '_' . $aggregation , template => '%.2f', label_extra_instance => 1, instance_use => 'display', unit => '%', min => 0, max => 100 }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource:s@" => { name => 'resource' }, "resource-group:s" => { name => 'resource_group' }, "resource-namespace:s" => { name => 'resource_namespace' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource})) { $self->{output}->add_option_msg(short_msg => "Need to specify either --resource with --resource-group option or --resource ."); $self->{output}->option_exit(); } $self->{az_resource} = $self->{option_results}->{resource}; $self->{az_resource_group} = $self->{option_results}->{resource_group} if (defined($self->{option_results}->{resource_group})); $self->{az_resource_type} = 'storageAccounts'; $self->{az_resource_namespace} = 'Microsoft.Storage'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : "PT5M"; $self->{az_resource_extra_namespace} = defined($self->{option_results}->{resource_namespace}) ? $self->{option_results}->{resource_namespace} : ''; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric ('Availability') { push @{$self->{az_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $resource (@{$self->{az_resource}}) { my $resource_group = $self->{az_resource_group}; my $resource_name = $resource; my $namespace = $self->{az_resource_namespace}; my $namespace_full = ($self->{az_resource_extra_namespace} ne '') ? '/' . lc($self->{az_resource_extra_namespace}) . 'Services/default' : ''; my $namespace_name = ($self->{az_resource_extra_namespace} ne '') ? $self->{az_resource_extra_namespace} : "Account"; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Storage\/storageAccounts\/(.*)\/(.*)\/default$/ || $resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Storage\/storageAccounts\/(.*)$/) { $resource_group = $1; $resource_name = $2; $namespace_full = '/' . $3 . '/default' if(defined($3)); $namespace_name = $3 if(defined($3)); } $namespace_name =~ s/Services//g; ($metric_results{$resource_name}, undef, undef) = $options{custom}->azure_get_metrics( resource => $resource_name . $namespace_full, resource_group => $resource_group, resource_type => $self->{az_resource_type}, resource_namespace => $namespace, metrics => $self->{az_metrics}, aggregations => $self->{az_aggregations}, timeframe => $self->{az_timeframe}, interval => $self->{az_interval}, ); foreach my $metric (@{$self->{az_metrics}}) { my $metric_name = lc($metric); $metric_name =~ s/ /_/g; foreach my $aggregation (@{$self->{az_aggregations}}) { next if (!defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{display} = $resource_name; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{timeframe} = $self->{az_timeframe}; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{stat} = lc($aggregation); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{namespace} = ucfirst($namespace_name); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{$metric_name . "_" . lc($aggregation)} = defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) ? $metric_results{$resource_name}->{$metric_name}->{lc($aggregation)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check storage account resources transaction availability metric. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::storage::storageaccount::plugin --custommode=azcli --mode=transactions-availability --resource=MYFILER --resource-group=MYHOSTGROUP --resource-namespace=Blob --aggregation='average' --critical-availability-average='10' --verbose Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::storage::storageaccount::plugin --custommode=azcli --mode=transactions-availability --resource='/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Storage/storageAccounts/xxx' --aggregation='average' --critical-availability-average='10' --verbose Default aggregation: 'average' / Minimum, maximum and average are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--resource-namespace> Set resource namespace (Can be: 'Blob', 'File', 'Table', 'Queue'). Leave empty for account metric. =item B<--warning-availability-*> Thresholds warning (* can be: 'minimum', 'maximum', 'average'). =item B<--critical-availability-*> Thresholds critical (* can be: 'minimum', 'maximum', 'average'). =back =cut centreon-plugins-20220113/cloud/azure/storage/storageaccount/mode/transactionscount.pm000066400000000000000000000273671417000230700312370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::storage::storageaccount::mode::transactionscount; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; my $msg = "Resource '" . $options{instance_value}->{display} . "'"; $msg .= " (" . $options{instance_value}->{namespace} . ")" if ($options{instance_value}->{namespace} ne ''); $msg .= " " . $options{instance_value}->{stat} . " "; return $msg; } sub custom_metric_calc { my ($self, %options) = @_; $self->{result_values}->{stat} = $options{new_datas}->{$self->{instance} . '_stat'}; $self->{result_values}->{metric_perf} = lc($options{extra_options}->{metric_perf}); $self->{result_values}->{metric_label} = lc($options{extra_options}->{metric_label}); $self->{result_values}->{metric_name} = $options{extra_options}->{metric_name}; $self->{result_values}->{timeframe} = $options{new_datas}->{$self->{instance} . '_timeframe'}; $self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_' . $self->{result_values}->{metric_perf} . '_' . $self->{result_values}->{stat}}; $self->{result_values}->{value_per_sec} = $self->{result_values}->{value} / $self->{result_values}->{timeframe}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{namespace} = $options{new_datas}->{$self->{instance} . '_namespace'}; return 0; } sub custom_metric_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check(value => defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}, threshold => [ { label => 'critical-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}, exit_litteral => 'warning' } ]); return $exit; } sub custom_usage_perfdata { my ($self, %options) = @_; my $extra_label = ''; $extra_label = '_' . lc($self->{result_values}->{display}) if (!defined($options{extra_instance}) || $options{extra_instance} != 0); $self->{output}->perfdata_add(label => $self->{result_values}->{metric_perf} . "_" . $self->{result_values}->{stat} . $extra_label, unit => defined($self->{instance_mode}->{option_results}->{per_sec}) ? 'transactions/s' : 'transactions', value => sprintf("%.2f", defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}), min => 0 ); } sub custom_usage_output { my ($self, %options) = @_; my $msg = ""; if (defined($self->{instance_mode}->{option_results}->{per_sec})) { $msg = sprintf("%s: %.2f transactions/s", $self->{result_values}->{metric_name}, $self->{result_values}->{value_per_sec}); } else { $msg = sprintf("%s: %.2f transactions", $self->{result_values}->{metric_name}, $self->{result_values}->{value}); } return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All transactions metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $aggregation ('total') { foreach my $metric ('Transactions') { my $metric_label = lc($metric); my $entry = { label => $metric_label . '-' . $aggregation, set => { key_values => [ { name => $metric_label . '_' . $aggregation }, { name => 'display' }, { name => 'stat' }, { name => 'timeframe' }, { name => 'namespace' } ], closure_custom_calc => $self->can('custom_metric_calc'), closure_custom_calc_extra_options => { metric_perf => $metric_label, metric_label => $metric_label, metric_name => $metric }, closure_custom_output => $self->can('custom_usage_output'), closure_custom_perfdata => $self->can('custom_usage_perfdata'), closure_custom_threshold_check => $self->can('custom_metric_threshold'), } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource:s@" => { name => 'resource' }, "resource-group:s" => { name => 'resource_group' }, "resource-namespace:s" => { name => 'resource_namespace' }, "per-sec" => { name => 'per_sec' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource})) { $self->{output}->add_option_msg(short_msg => "Need to specify either --resource with --resource-group option or --resource ."); $self->{output}->option_exit(); } $self->{az_resource} = $self->{option_results}->{resource}; $self->{az_resource_group} = $self->{option_results}->{resource_group} if (defined($self->{option_results}->{resource_group})); $self->{az_resource_type} = 'storageAccounts'; $self->{az_resource_namespace} = 'Microsoft.Storage'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : "PT5M"; $self->{az_resource_extra_namespace} = defined($self->{option_results}->{resource_namespace}) ? $self->{option_results}->{resource_namespace} : ''; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric ('Transactions') { push @{$self->{az_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $resource (@{$self->{az_resource}}) { my $resource_group = $self->{az_resource_group}; my $resource_name = $resource; my $namespace = $self->{az_resource_namespace}; my $namespace_full = ($self->{az_resource_extra_namespace} ne '') ? '/' . lc($self->{az_resource_extra_namespace}) . 'Services/default' : ''; my $namespace_name = ($self->{az_resource_extra_namespace} ne '') ? $self->{az_resource_extra_namespace} : "Account"; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Storage\/storageAccounts\/(.*)\/(.*)\/default$/ || $resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Storage\/storageAccounts\/(.*)$/) { $resource_group = $1; $resource_name = $2; $namespace_full = '/' . $3 . '/default' if(defined($3)); $namespace_name = $3 if(defined($3)); } $namespace_name =~ s/Services//g; ($metric_results{$resource_name}, undef, undef) = $options{custom}->azure_get_metrics( resource => $resource_name . $namespace_full, resource_group => $resource_group, resource_type => $self->{az_resource_type}, resource_namespace => $namespace, metrics => $self->{az_metrics}, aggregations => $self->{az_aggregations}, timeframe => $self->{az_timeframe}, interval => $self->{az_interval}, ); foreach my $metric (@{$self->{az_metrics}}) { my $metric_name = lc($metric); $metric_name =~ s/ /_/g; foreach my $aggregation (@{$self->{az_aggregations}}) { next if (!defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{display} = $resource_name; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{timeframe} = $self->{az_timeframe}; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{stat} = lc($aggregation); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{namespace} = ucfirst($namespace_name); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{$metric_name . "_" . lc($aggregation)} = defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) ? $metric_results{$resource_name}->{$metric_name}->{lc($aggregation)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check storage account resources transaction count metric. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::storage::storageaccount::plugin --custommode=azcli --mode=transactions-count --resource=MYFILER --resource-group=MYHOSTGROUP --resource-namespace=Blob --aggregation='total' --critical-transactions-total='10' --verbose Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::storage::storageaccount::plugin --custommode=azcli --mode=transactions-count --resource='/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Storage/storageAccounts/xxx' --aggregation='total' --critical-transactions-total='10' --verbose Default aggregation: 'total' / Only total is valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--resource-namespace> Set resource namespace (Can be: 'Blob', 'File', 'Table', 'Queue'). Leave empty for account metric. =item B<--warning-transactions-total> Thresholds warning. =item B<--critical-transactions-total> Thresholds critical. =item B<--per-sec> Change the data to be unit/sec. =back =cut centreon-plugins-20220113/cloud/azure/storage/storageaccount/mode/transactionslatency.pm000066400000000000000000000217601417000230700315350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::storage::storageaccount::mode::transactionslatency; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; my $msg = "Resource '" . $options{instance_value}->{display} . "'"; $msg .= " (" . $options{instance_value}->{namespace} . ")" if ($options{instance_value}->{namespace} ne ''); $msg .= " " . $options{instance_value}->{stat} . " "; return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All transactions metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $aggregation ('minimum', 'maximum', 'average', 'total') { foreach my $metric ('SuccessServerLatency', 'SuccessE2ELatency') { my $metric_label = lc($metric); my $entry = { label => $metric_label . '-' . $aggregation, set => { key_values => [ { name => $metric_label . '_' . $aggregation }, { name => 'display' }, { name => 'stat' } ], output_template => $metric . ': %.2f ms', perfdatas => [ { label => $metric_label . '_' . $aggregation, value => $metric_label . '_' . $aggregation , template => '%.2f', unit => 'ms', label_extra_instance => 1, instance_use => 'display', min => 0 }, ], } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource:s@" => { name => 'resource' }, "resource-group:s" => { name => 'resource_group' }, "resource-namespace:s" => { name => 'resource_namespace' }, "filter-metric:s" => { name => 'filter_metric' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource})) { $self->{output}->add_option_msg(short_msg => "Need to specify either --resource with --resource-group option or --resource ."); $self->{output}->option_exit(); } $self->{az_resource} = $self->{option_results}->{resource}; $self->{az_resource_group} = $self->{option_results}->{resource_group} if (defined($self->{option_results}->{resource_group})); $self->{az_resource_type} = 'storageAccounts'; $self->{az_resource_namespace} = 'Microsoft.Storage'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : "PT5M"; $self->{az_resource_extra_namespace} = defined($self->{option_results}->{resource_namespace}) ? $self->{option_results}->{resource_namespace} : ''; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric ('SuccessServerLatency', 'SuccessE2ELatency') { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $resource (@{$self->{az_resource}}) { my $resource_group = $self->{az_resource_group}; my $resource_name = $resource; my $namespace = $self->{az_resource_namespace}; my $namespace_full = ($self->{az_resource_extra_namespace} ne '') ? '/' . lc($self->{az_resource_extra_namespace}) . 'Services/default' : ''; my $namespace_name = ($self->{az_resource_extra_namespace} ne '') ? $self->{az_resource_extra_namespace} : "Account"; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Storage\/storageAccounts\/(.*)\/(.*)\/default$/ || $resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Storage\/storageAccounts\/(.*)$/) { $resource_group = $1; $resource_name = $2; $namespace_full = '/' . $3 . '/default' if(defined($3)); $namespace_name = $3 if(defined($3)); } $namespace_name =~ s/Services//g; ($metric_results{$resource_name}, undef, undef) = $options{custom}->azure_get_metrics( resource => $resource_name . $namespace_full, resource_group => $resource_group, resource_type => $self->{az_resource_type}, resource_namespace => $namespace, metrics => $self->{az_metrics}, aggregations => $self->{az_aggregations}, timeframe => $self->{az_timeframe}, interval => $self->{az_interval}, ); foreach my $metric (@{$self->{az_metrics}}) { my $metric_name = lc($metric); $metric_name =~ s/ /_/g; foreach my $aggregation (@{$self->{az_aggregations}}) { next if (!defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{display} = $resource_name; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{timeframe} = $self->{az_timeframe}; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{stat} = lc($aggregation); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{namespace} = ucfirst($namespace_name); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{$metric_name . "_" . lc($aggregation)} = defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) ? $metric_results{$resource_name}->{$metric_name}->{lc($aggregation)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check storage account resources transaction latency metrics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::storage::storageaccount::plugin --custommode=azcli --mode=transactions-latency --resource=MYFILER --resource-group=MYHOSTGROUP --resource-namespace=Blob --aggregation='average' --critical-successserverlatency-average='10' --verbose Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::storage::storageaccount::plugin --custommode=azcli --mode=transactions-latency --resource='/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Storage/storageAccounts/xxx' --aggregation='average' --critical-successserverlatency-average='10' --verbose Default aggregation: 'average' / All aggregations are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--resource-namespace> Set resource namespace (Can be: 'Blob', 'File', 'Table', 'Queue'). Leave empty for account metric. =item B<--filter-metric> Filter metrics (Can be: 'SuccessServerLatency', 'SuccessE2ELatency') (Can be a regexp). =item B<--warning-$metric$-$aggregation$> Thresholds warning ($metric$ can be: 'successserverlatency', 'successe2elatency', $aggregation$ can be: 'minimum', 'maximum', 'average', 'total'). =item B<--critical-$metric$-$aggregation$> Thresholds critical ($metric$ can be: 'successserverlatency', 'successe2elatency', $aggregation$ can be: 'minimum', 'maximum', 'average', 'total'). =back =cut centreon-plugins-20220113/cloud/azure/storage/storageaccount/mode/transactionsthroughput.pm000066400000000000000000000307251417000230700323100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::storage::storageaccount::mode::transactionsthroughput; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_metric_output { my ($self, %options) = @_; my $msg = "Resource '" . $options{instance_value}->{display} . "'"; $msg .= " (" . $options{instance_value}->{namespace} . ")" if ($options{instance_value}->{namespace} ne ''); $msg .= " " . $options{instance_value}->{stat} . " "; return $msg; } sub custom_metric_calc { my ($self, %options) = @_; $self->{result_values}->{stat} = $options{new_datas}->{$self->{instance} . '_stat'}; $self->{result_values}->{metric_perf} = lc($options{extra_options}->{metric_perf}); $self->{result_values}->{metric_label} = lc($options{extra_options}->{metric_label}); $self->{result_values}->{metric_name} = $options{extra_options}->{metric_name}; $self->{result_values}->{timeframe} = $options{new_datas}->{$self->{instance} . '_timeframe'}; $self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_' . $self->{result_values}->{metric_perf} . '_' . $self->{result_values}->{stat}}; $self->{result_values}->{value_per_sec} = $self->{result_values}->{value} / $self->{result_values}->{timeframe}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{namespace} = $options{new_datas}->{$self->{instance} . '_namespace'}; return 0; } sub custom_metric_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check(value => defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}, threshold => [ { label => 'critical-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}, exit_litteral => 'warning' } ]); return $exit; } sub custom_usage_perfdata { my ($self, %options) = @_; my $extra_label = ''; $extra_label = '_' . lc($self->{result_values}->{display}) if (!defined($options{extra_instance}) || $options{extra_instance} != 0); $self->{output}->perfdata_add(label => $self->{result_values}->{metric_perf} . "_" . $self->{result_values}->{stat} . $extra_label, unit => defined($self->{instance_mode}->{option_results}->{per_sec}) ? 'B/s' : 'B', value => sprintf("%.2f", defined($self->{instance_mode}->{option_results}->{per_sec}) ? $self->{result_values}->{value_per_sec} : $self->{result_values}->{value}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{result_values}->{metric_label} . "-" . $self->{result_values}->{stat}), min => 0 ); } sub custom_usage_output { my ($self, %options) = @_; my $msg = ""; if (defined($self->{instance_mode}->{option_results}->{per_sec})) { my ($value, $unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{value_per_sec}); $msg = $self->{result_values}->{metric_name} . ": " . $value . ' ' . $unit . "/s"; } else { my ($value, $unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{value}); $msg = $self->{result_values}->{metric_name} . ": " . $value . ' ' . $unit; } return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metric', type => 1, cb_prefix_output => 'prefix_metric_output', message_multiple => "All transactions metrics are ok", skipped_code => { -10 => 1 } }, ]; foreach my $aggregation ('minimum', 'maximum', 'average', 'total') { foreach my $metric ('Ingress', 'Egress') { my $metric_label = lc($metric); my $entry = { label => $metric_label . '-' . $aggregation, set => { key_values => [ { name => $metric_label . '_' . $aggregation }, { name => 'display' }, { name => 'stat' }, { name => 'timeframe' }, { name => 'namespace' } ], closure_custom_calc => $self->can('custom_metric_calc'), closure_custom_calc_extra_options => { metric_perf => $metric_label, metric_label => $metric_label, metric_name => $metric }, closure_custom_output => $self->can('custom_usage_output'), closure_custom_perfdata => $self->can('custom_usage_perfdata'), closure_custom_threshold_check => $self->can('custom_metric_threshold'), } }; push @{$self->{maps_counters}->{metric}}, $entry; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "resource:s@" => { name => 'resource' }, "resource-group:s" => { name => 'resource_group' }, "resource-namespace:s" => { name => 'resource_namespace' }, "filter-metric:s" => { name => 'filter_metric' }, "per-sec" => { name => 'per_sec' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource})) { $self->{output}->add_option_msg(short_msg => "Need to specify either --resource with --resource-group option or --resource ."); $self->{output}->option_exit(); } $self->{az_resource} = $self->{option_results}->{resource}; $self->{az_resource_group} = $self->{option_results}->{resource_group} if (defined($self->{option_results}->{resource_group})); $self->{az_resource_type} = 'storageAccounts'; $self->{az_resource_namespace} = 'Microsoft.Storage'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : "PT5M"; $self->{az_resource_extra_namespace} = defined($self->{option_results}->{resource_namespace}) ? $self->{option_results}->{resource_namespace} : ''; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric ('Ingress', 'Egress') { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; my %metric_results; foreach my $resource (@{$self->{az_resource}}) { my $resource_group = $self->{az_resource_group}; my $resource_name = $resource; my $namespace = $self->{az_resource_namespace}; my $namespace_full = ($self->{az_resource_extra_namespace} ne '') ? '/' . lc($self->{az_resource_extra_namespace}) . 'Services/default' : ''; my $namespace_name = ($self->{az_resource_extra_namespace} ne '') ? $self->{az_resource_extra_namespace} : "Account"; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Storage\/storageAccounts\/(.*)\/(.*)\/default$/ || $resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Storage\/storageAccounts\/(.*)$/) { $resource_group = $1; $resource_name = $2; $namespace_full = '/' . $3 . '/default' if(defined($3)); $namespace_name = $3 if(defined($3)); } $namespace_name =~ s/Services//g; ($metric_results{$resource_name}, undef, undef) = $options{custom}->azure_get_metrics( resource => $resource_name . $namespace_full, resource_group => $resource_group, resource_type => $self->{az_resource_type}, resource_namespace => $namespace, metrics => $self->{az_metrics}, aggregations => $self->{az_aggregations}, timeframe => $self->{az_timeframe}, interval => $self->{az_interval}, ); foreach my $metric (@{$self->{az_metrics}}) { my $metric_name = lc($metric); $metric_name =~ s/ /_/g; foreach my $aggregation (@{$self->{az_aggregations}}) { next if (!defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) && !defined($self->{option_results}->{zeroed})); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{display} = $resource_name; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{timeframe} = $self->{az_timeframe}; $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{stat} = lc($aggregation); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{namespace} = ucfirst($namespace_name); $self->{metric}->{$resource_name . "_" . lc($aggregation)}->{$metric_name . "_" . lc($aggregation)} = defined($metric_results{$resource_name}->{$metric_name}->{lc($aggregation)}) ? $metric_results{$resource_name}->{$metric_name}->{lc($aggregation)} : 0; } } } if (scalar(keys %{$self->{metric}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check storage account resources transaction throughput metrics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::storage::storageaccount::plugin --custommode=azcli --mode=transactions-throughput --resource=MYFILER --resource-group=MYHOSTGROUP--resource-namespace=Blob --aggregation='total' --critical-egress-total='10' --verbose Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::storage::storageaccount::plugin --custommode=azcli --mode=transactions-throughput --resource='/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Storage/storageAccounts/xxx' --aggregation='total' --critical-egress-total='10' --verbose Default aggregation: 'total' / All aggregations are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--resource-namespace> Set resource namespace (Can be: 'Blob', 'File', 'Table', 'Queue'). Leave empty for account metric. =item B<--filter-metric> Filter metrics (Can be: 'Ingress', 'Egress') (Can be a regexp). =item B<--warning-$metric$-$aggregation$> Thresholds warning ($metric$ can be: 'ingress', 'egress', $aggregation$ can be: 'minimum', 'maximum', 'average', 'total'). =item B<--critical-$metric$-$aggregation$> Thresholds critical ($metric$ can be: 'ingress', 'egress', $aggregation$ can be: 'minimum', 'maximum', 'average', 'total'). =item B<--per-sec> Change the data to be unit/sec. =back =cut centreon-plugins-20220113/cloud/azure/storage/storageaccount/plugin.pm000066400000000000000000000070071417000230700260150ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::storage::storageaccount::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} } = ( 'account-used-capacity' => 'cloud::azure::storage::storageaccount::mode::accountusedcapacity', 'blob-capacity' => 'cloud::azure::storage::storageaccount::mode::blobcapacity', 'blob-container-count' => 'cloud::azure::storage::storageaccount::mode::blobcontainercount', 'blob-count' => 'cloud::azure::storage::storageaccount::mode::blobcount', 'discovery' => 'cloud::azure::storage::storageaccount::mode::discovery', 'file-capacity' => 'cloud::azure::storage::storageaccount::mode::filecapacity', 'file-count' => 'cloud::azure::storage::storageaccount::mode::filecount', 'file-share-count' => 'cloud::azure::storage::storageaccount::mode::filesharecount', 'health' => 'cloud::azure::storage::storageaccount::mode::health', 'list-resources' => 'cloud::azure::storage::storageaccount::mode::listresources', 'queue-capacity' => 'cloud::azure::storage::storageaccount::mode::queuecapacity', 'queue-count' => 'cloud::azure::storage::storageaccount::mode::queuecount', 'queue-message-count' => 'cloud::azure::storage::storageaccount::mode::queuemessagecount', 'table-capacity' => 'cloud::azure::storage::storageaccount::mode::tablecapacity', 'table-count' => 'cloud::azure::storage::storageaccount::mode::tablecount', 'table-entity-count' => 'cloud::azure::storage::storageaccount::mode::tableentitycount', 'transactions-availability' => 'cloud::azure::storage::storageaccount::mode::transactionsavailability', 'transactions-count' => 'cloud::azure::storage::storageaccount::mode::transactionscount', 'transactions-latency' => 'cloud::azure::storage::storageaccount::mode::transactionslatency', 'transactions-throughput' => 'cloud::azure::storage::storageaccount::mode::transactionsthroughput', ); $self->{custom_modes}{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' }, }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure storage account. =cut centreon-plugins-20220113/cloud/azure/storage/storagesync/000077500000000000000000000000001417000230700234755ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/storage/storagesync/mode/000077500000000000000000000000001417000230700244215ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/storage/storagesync/mode/discovery.pm000066400000000000000000000024601417000230700267700ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::storage::storagesync::mode::discovery; use base qw(cloud::azure::management::monitor::mode::discovery); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{namespace} = 'microsoft.storagesync'; $self->{type} = 'storageSyncServices'; } 1; __END__ =head1 MODE Azure Storage Sync Service discovery. =over 8 =item B<--resource-group> Specify resource group. =item B<--location> Specify location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/storage/storagesync/mode/filessync.pm000066400000000000000000000123141417000230700267570ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::storage::storagesync::mode::filessync; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'storagesyncsyncsessionappliedfilescount' => { 'output' => 'Files Synced', 'label' => 'files-synced', 'nlabel' => 'storagesync.files.synced.count', 'unit' => '', 'min' => '0', 'max' => '' }, 'storagesyncsyncsessionperitemerrorscount' => { 'output' => 'Item errors', 'label' => 'item-errors', 'nlabel' => 'storagesync.item.errors.count', 'unit' => '', 'min' => '0', 'max' => '' }, 'storagesyncbatchtransferredfilebytes' => { 'output' => 'Bytes synced', 'label' => 'bytes-synced', 'nlabel' => 'storagesync.bytes.synced.bytes', 'unit' => 'B', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/microsoft\.storagesync\/storageSyncServices\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'storageSyncServices'; $self->{az_resource_namespace} = 'microsoft.storagesync'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Storage Sync Service Files Synced and Errors. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::storage::storagesync::plugin --mode=files-synced --custommode=api --resource= --resource-group= --aggregation='total' --warning-item-errors='15' --critical-item-errors='20' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::storage::storagesync::plugin --mode=files-synced --custommode=api --resource='/subscriptions//resourceGroups//providers/microsoft.storagesync/storageSyncServices/' --aggregation='total' --warning-item-errors='15' --critical-item-errors='20' Default aggregation: 'total' / 'minimum', 'maximum' and 'average' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'item-errors', 'files-synced', 'bytes-synced'. =item B<--critical-*> Critical threshold where '*' can be: 'item-errors', 'files-synced', 'bytes-synced'. =back =cut centreon-plugins-20220113/cloud/azure/storage/storagesync/mode/recalls.pm000066400000000000000000000141101417000230700264010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::storage::storagesync::mode::recalls; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'storagesyncrecallcomputedsuccessrate' => { 'output' => 'Cloud tiering recall success rate', 'label' => 'successful-recalls', 'nlabel' => 'storagesync.recalls.succesful.percentage', 'unit' => '%', 'min' => '0', 'max' => '100' }, 'storagesyncrecallednetworkbytesbyapplication' => { 'output' => 'Cloud tiering recall size by application', 'label' => 'application-recalls-size', 'nlabel' => 'storagesync.recalls.application.size.bytes', 'unit' => 'B', 'min' => '0', 'max' => '' }, 'storagesyncrecalledtotalnetworkbytes' => { 'output' => 'Cloud tiering recall size', 'label' => 'recalls-size', 'nlabel' => 'storagesync.recalls.size.bytes', 'unit' => 'B', 'min' => '0', 'max' => '' }, 'storagesyncrecalliototalsizebytes' => { 'output' => 'Cloud tiering recall', 'label' => 'total-recalls-size', 'nlabel' => 'storagesync.recalls.total.size.bytes', 'unit' => 'B', 'min' => '0', 'max' => '' }, 'storagesyncrecallthroughputbytespersecond' => { 'output' => 'Cloud tiering recall throughput', 'label' => 'throughput-recalls-size', 'nlabel' => 'storagesync.recalls.throughput.size.bytespersecond', 'unit' => 'B/s', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/microsoft\.storagesync\/storageSyncServices\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'storageSyncServices'; $self->{az_resource_namespace} = 'microsoft.storagesync'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Storage Sync Service Files data recalls statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::storage::storagesync::plugin --mode=recalls --custommode=api --resource= --resource-group= --aggregation='total' --warning-recalls-size='15' --critical-recalls-size='20' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::storage::storagesync::plugin --mode=recalls --custommode=api --resource='/subscriptions//resourceGroups//providers/microsoft.storagesync/storageSyncServices/' --aggregation='total' --warning-recalls-size='15' --critical-recalls-size='20' Default aggregation: 'total' / 'minimum', 'maximum' and 'average' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'successful-recalls', 'application-recalls-size', 'recalls-size', 'total-recalls-size', 'throughput-recalls-size'. =item B<--critical-*> Critical threshold where '*' can be: 'successful-recalls', 'application-recalls-size', 'recalls-size', 'total-recalls-size', 'throughput-recalls-size'. =back =cut centreon-plugins-20220113/cloud/azure/storage/storagesync/mode/serverstatus.pm000066400000000000000000000107411417000230700275340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::storage::storagesync::mode::serverstatus; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'storagesyncserverheartbeat' => { 'output' => 'Heartbeat', 'label' => 'heartbeat', 'nlabel' => 'storagesync.heartbeat.count', 'unit' => '', 'min' => '0', 'max' => '' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/microsoft\.storagesync\/storageSyncServices\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'storageSyncServices'; $self->{az_resource_namespace} = 'microsoft.storagesync'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Maximum']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Storage Sync server online status. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::storage::storagesync::plugin --mode=server-status --custommode=api --resource= --resource-group= --aggregation='maximum' --critical-heartbeat='1:1' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::storage::storagesync::plugin --mode=server-status --custommode=api --resource='/subscriptions//resourceGroups//providers/microsoft.storagesync/storageSyncServices/' --aggregation='maximum' --critical-heartbeat='1:1' Default aggregation: 'maximum' / 'minimum', 'average' and 'total' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-heartbeat> Warning threshold. =item B<--critical-heartbeat> Critical threshold. =back =cut centreon-plugins-20220113/cloud/azure/storage/storagesync/plugin.pm000066400000000000000000000035231417000230700253340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::storage::storagesync::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} = { 'discovery' => 'cloud::azure::storage::storagesync::mode::discovery', 'files-synced' => 'cloud::azure::storage::storagesync::mode::filessync', 'recalls' => 'cloud::azure::storage::storagesync::mode::recalls', 'server-status' => 'cloud::azure::storage::storagesync::mode::serverstatus' }; $self->{custom_modes}->{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}->{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' } }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure Storage Sync service. =cut centreon-plugins-20220113/cloud/azure/web/000077500000000000000000000000001417000230700202455ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/web/appservice/000077500000000000000000000000001417000230700224065ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/web/appservice/plugin.pm000066400000000000000000000047431417000230700242520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::web::appservice::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} = { 'data' => 'cloud::azure::common::appservice::mode::data', 'health' => 'cloud::azure::common::appservice::mode::health', 'memory' => 'cloud::azure::common::appservice::mode::memory', 'status' => 'cloud::azure::common::appservice::mode::status', 'cpu-time' => 'cloud::azure::common::appservice::mode::cputime', 'gc-usage' => 'cloud::azure::common::appservice::mode::gcusage', 'app-usage' => 'cloud::azure::common::appservice::mode::appusage', 'discovery' => 'cloud::azure::common::appservice::mode::discovery', 'io-operations' => 'cloud::azure::common::appservice::mode::iooperations', 'http-requests' => 'cloud::azure::common::appservice::mode::httprequests', 'response-time' => 'cloud::azure::common::appservice::mode::responsetime', 'filesystem-usage' => 'cloud::azure::common::appservice::mode::filesystem' }; $self->{custom_modes}->{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}->{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' } }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure App Service. =cut centreon-plugins-20220113/cloud/azure/web/appserviceplan/000077500000000000000000000000001417000230700232615ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/web/appserviceplan/mode/000077500000000000000000000000001417000230700242055ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/web/appserviceplan/mode/cpu.pm000066400000000000000000000110161417000230700253310ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::web::appserviceplan::mode::cpu; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'cpupercentage' => { 'output' => 'CPU Percentage', 'label' => 'cpu-usage-percentage', 'nlabel' => 'appserviceplan.cpu.usage.percentage', 'unit' => '%', 'min' => '0', 'max' => '100' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Web\/serverFarms\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'serverFarms'; $self->{az_resource_namespace} = 'Microsoft.Web'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure App Service Plan CPU statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::web::appserviceplan::plugin --mode=cpu --custommode=api --resource= --resource-group= --aggregation='average' --warning-cpu-usage-percentage='80' --critical-cpu-usage-percentage='90' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::web::appserviceplan::plugin --mode=cpu --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Web/serverFarms/' --aggregation='average' --warning-cpu-usage-percentage='80' --critical-cpu-usage-percentage='90' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-cpu-usage-percentage> Warning threshold. =item B<--critical-cpu-usage-percentage> Critical threshold. =back =cut centreon-plugins-20220113/cloud/azure/web/appserviceplan/mode/data.pm000066400000000000000000000112621417000230700254560ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::web::appserviceplan::mode::data; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'bytesreceived' => { 'output' => 'Data In', 'label' => 'data-in', 'nlabel' => 'appserviceplan.data.in.bytes', 'unit' => 'B', 'min' => '0' }, 'bytessent' => { 'output' => 'Data Out', 'label' => 'data-out', 'nlabel' => 'appserviceplan.data.out.bytes', 'unit' => 'B', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Web\/serverFarms\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'serverFarms'; $self->{az_resource_namespace} = 'Microsoft.Web'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure App Service Plan data statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::web::appserviceplan::plugin --mode=data --custommode=api --resource= --resource-group= --aggregation='total' --warning-data-in='10000' --critical-data-in='20000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::web::appserviceplan::plugin --mode=data --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Web/serverFarms/' --aggregation='total' --warning-data-in='10000' --critical-data-in='20000' Default aggregation: 'total' / 'average', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'data-in', 'data-out'. =item B<--critical-*> Critical threshold where '*' can be: 'data-in', 'data-out'. =back =cut centreon-plugins-20220113/cloud/azure/web/appserviceplan/mode/discovery.pm000066400000000000000000000024501417000230700265530ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::web::appserviceplan::mode::discovery; use base qw(cloud::azure::management::monitor::mode::discovery); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{namespace} = 'Microsoft.Web'; $self->{type} = 'serverfarms'; } 1; __END__ =head1 MODE Discover Azure Web App Service Plan resources. =over 8 =item B<--resource-group> Specify resource group. =item B<--location> Specify location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/web/appserviceplan/mode/health.pm000066400000000000000000000036611417000230700260160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::web::appserviceplan::mode::health; use base qw(cloud::azure::management::monitor::mode::health); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{az_resource_namespace} = 'Microsoft.Web'; $self->{az_resource_type} = 'serverfarms'; } 1; __END__ =head1 MODE Check Azure Web App Service Plan status. (Useful to determine host status) =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{summary} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /^Unavailable$/'). Can used special variables like: %{status}, %{summary} =item B<--unknown-status> Set unknown threshold for status (Default: '%{status} =~ /^Unknown$/'). Can used special variables like: %{status}, %{summary} =item B<--ok-status> Set ok threshold for status (Default: '%{status} =~ /^Available$/'). Can used special variables like: %{status}, %{summary} =back =cut centreon-plugins-20220113/cloud/azure/web/appserviceplan/mode/memory.pm000066400000000000000000000110101417000230700260440ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::web::appserviceplan::mode::memory; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'memorypercentage' => { 'output' => 'Memory Percentage', 'label' => 'memory-percentage', 'nlabel' => 'appserviceplan.memory.percentage', 'unit' => '%', 'min' => '0', 'max' => '100' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Web\/serverFarms\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'serverFarms'; $self->{az_resource_namespace} = 'Microsoft.Web'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure App Service Plan memory statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::web::appserviceplan::plugin --mode=memory --custommode=api --resource= --resource-group= --aggregation='average' --warning-memory-percentage='80' --critical-memory-percentage='90' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::web::appserviceplan::plugin --mode=memory --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Web/serverFarms/' --aggregation='average' --warning-memory-percentage='80' --critical-memory-percentage='90' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-memory-percentage> Warning threshold. =item B<--critical-memory-percentage> Critical threshold. =back =cut centreon-plugins-20220113/cloud/azure/web/appserviceplan/mode/queue.pm000066400000000000000000000116151417000230700256730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::web::appserviceplan::mode::queue; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'diskqueuelength' => { 'output' => 'Disk Queue Length', 'label' => 'disk-queue-length', 'nlabel' => 'appserviceplan.disk.queue.length.count', 'unit' => '', 'min' => '0', 'template' => '%d' }, 'httpqueuelength' => { 'output' => 'Http Queue Length', 'label' => 'http-queue-length', 'nlabel' => 'appserviceplan.http.queue.length.count', 'unit' => '', 'min' => '0', 'template' => '%d' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Web\/serverFarms\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'serverFarms'; $self->{az_resource_namespace} = 'Microsoft.Web'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure App Service Plan queue statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::web::appserviceplan::plugin --mode=queue --custommode=api --resource= --resource-group= --aggregation='average' --warning-disk-queue-length='8' --critical-disk-queue-length='9' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::web::appserviceplan::plugin --mode=queue --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Web/serverFarms/' --aggregation='average' --warning-disk-queue-length='8' --critical-disk-queue-length='9' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'disk-queue-length', 'http-queue-length'. =item B<--critical-*> Critical threshold where '*' can be: 'disk-queue-length', 'http-queue-length'. =back =cut centreon-plugins-20220113/cloud/azure/web/appserviceplan/mode/socket.pm000066400000000000000000000140251417000230700260350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::web::appserviceplan::mode::socket; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'socketinboundall' => { 'output' => 'SocketInboundAll', 'label' => 'socket-inbound-all', 'nlabel' => 'appserviceplan.socket.inboundall.count', 'unit' => '', 'min' => '0', 'template' => '%d' }, 'socketoutboundall' => { 'output' => 'SocketOutboundAll', 'label' => 'socket-outbound-all', 'nlabel' => 'appserviceplan.socket.outboundall.count', 'unit' => '', 'min' => '0', 'template' => '%d' }, 'socketloopback' => { 'output' => 'SocketLoopback', 'label' => 'socket-loopback', 'nlabel' => 'appserviceplan.socket.loopback.count', 'unit' => '', 'min' => '0', 'template' => '%d' }, 'socketoutboundestablished' => { 'output' => 'SocketOutboundEstablished', 'label' => 'socket-outbound-established', 'nlabel' => 'appserviceplan.socket.outboundestablished.count', 'unit' => '', 'min' => '0', 'template' => '%d' }, 'socketoutboundtimewait' => { 'output' => 'SocketOutboundTimeWait', 'label' => 'socket-outbound-timewait', 'nlabel' => 'appserviceplan.socket.outboundtimewait.count', 'unit' => '', 'min' => '0', 'template' => '%d' }, }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Web\/serverFarms\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'serverFarms'; $self->{az_resource_namespace} = 'Microsoft.Web'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure App Service Plan socket statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::web::appserviceplan::plugin --mode=socket --custommode=api --resource= --resource-group= --aggregation='average' --warning-socket-outbound-timewait='10000' --critical-socket-outbound-timewait='20000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::web::appserviceplan::plugin --mode=socket --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Web/serverFarms/' --aggregation='average' --warning-socket-outbound-timewait='10000' --critical-socket-outbound-timewait='20000' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'socket-loopback', 'socket-outbound-established', 'socket-inbound-all', 'socket-outbound-all', 'socket-outbound-timewait'. =item B<--critical-*> Critical threshold where '*' can be: 'socket-loopback', 'socket-outbound-established', 'socket-inbound-all', 'socket-outbound-all', 'socket-outbound-timewait'. =back =cut centreon-plugins-20220113/cloud/azure/web/appserviceplan/mode/tcpconnections.pm000066400000000000000000000142611417000230700276000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::web::appserviceplan::mode::tcpconnections; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'tcpclosewait' => { 'output' => 'TCP Close Wait', 'label' => 'tcp-closewait', 'nlabel' => 'appserviceplan.connections.tcp.closewait.count', 'unit' => '', 'min' => '0', 'template' => '%d' }, 'tcpclosing' => { 'output' => 'TCP Closing', 'label' => 'tcp-closing', 'nlabel' => 'appserviceplan.connections.tcp.closing.count', 'unit' => '', 'min' => '0', 'template' => '%d' }, 'tcpfinwait1' => { 'output' => 'TCP Fin Wait 1', 'label' => 'tcp-fin-wait1', 'nlabel' => 'appserviceplan.connections.tcp.finwait1.count', 'unit' => '', 'min' => '0', 'template' => '%d' }, 'tcpfinwait2' => { 'output' => 'TCP Fin Wait 2', 'label' => 'tcp-fin-wait2', 'nlabel' => 'appserviceplan.connections.tcp.finwait2.count', 'unit' => '', 'min' => '0', 'template' => '%d' }, 'tcplastack' => { 'output' => 'TCP Last Ack', 'label' => 'tcp-ack-last', 'nlabel' => 'appserviceplan.connections.tcp.lastack.count', 'unit' => '', 'min' => '0', 'template' => '%d' }, 'tcpsynreceived' => { 'output' => 'TCP Syn Received', 'label' => 'tcp-syn-received', 'nlabel' => 'appserviceplan.connections.tcp.synreceived.count', 'unit' => '', 'min' => '0', 'template' => '%d' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.Web\/serverFarms\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'serverFarms'; $self->{az_resource_namespace} = 'Microsoft.Web'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Average']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure App Service Plan TCP connections statistics. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::web::appserviceplan::plugin --mode=tcp-connections --custommode=api --resource= --resource-group= --aggregation='average' --warning-tcp-closewait='1000' --critical-tcp-closewait='2000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::web::appserviceplan::plugin --mode=tcp-connections --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.Web/serverFarms/' --aggregation='average' --warning-tcp-closewait='1000' --critical-tcp-closewait='2000' Default aggregation: 'average' / 'total', 'minimum' and 'maximum' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'tcp-syn-received', 'tcp-ack-last', 'tcp-fin-wait2', 'tcp-fin-wait1', 'tcp-closewait', 'tcp-closing'. =item B<--critical-*> Critical threshold where '*' can be: 'tcp-syn-received', 'tcp-ack-last', 'tcp-fin-wait2', 'tcp-fin-wait1', 'tcp-closewait', 'tcp-closing'. =back =cut centreon-plugins-20220113/cloud/azure/web/appserviceplan/plugin.pm000066400000000000000000000042311417000230700251150ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::web::appserviceplan::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} = { 'cpu' => 'cloud::azure::web::appserviceplan::mode::cpu', 'data' => 'cloud::azure::web::appserviceplan::mode::data', 'discovery' => 'cloud::azure::web::appserviceplan::mode::discovery', 'health' => 'cloud::azure::web::appserviceplan::mode::health', 'memory' => 'cloud::azure::web::appserviceplan::mode::memory', 'queue' => 'cloud::azure::web::appserviceplan::mode::queue', 'socket' => 'cloud::azure::web::appserviceplan::mode::socket', 'tcp-connections' => 'cloud::azure::web::appserviceplan::mode::tcpconnections' }; $self->{custom_modes}->{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}->{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' }, }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure Web App Service Plan resources. =cut centreon-plugins-20220113/cloud/azure/web/signalr/000077500000000000000000000000001417000230700217045ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/web/signalr/mode/000077500000000000000000000000001417000230700226305ustar00rootroot00000000000000centreon-plugins-20220113/cloud/azure/web/signalr/mode/discovery.pm000066400000000000000000000024261417000230700252010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::web::signalr::mode::discovery; use base qw(cloud::azure::management::monitor::mode::discovery); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{namespace} = 'Microsoft.SignalRService'; $self->{type} = 'SignalR'; } 1; __END__ =head1 MODE Azure Web SignalR discovery. =over 8 =item B<--resource-group> Specify resource group. =item B<--location> Specify location. =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/azure/web/signalr/mode/errors.pm000066400000000000000000000114301417000230700245010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::web::signalr::mode::errors; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'systemerrors' => { 'output' => 'System Errors', 'label' => 'system-errors', 'nlabel' => 'signalr.errors.system.percentage', 'unit' => '%', 'min' => '0', 'max' => '100' }, 'usererrors' => { 'output' => 'User Errors', 'label' => 'user-errors', 'nlabel' => 'signalr.errors.user.percentage', 'unit' => '%', 'min' => '0', 'max' => '100' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.SignalRService\/SignalR\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'SignalR'; $self->{az_resource_namespace} = 'Microsoft.SignalRService'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Maximum']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Web SignalR errors. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::web::signalr::plugin --mode=errors --custommode=api --resource= --resource-group= --aggregation='maximum' --warning-user-errors='800' --critical-user-errors='900' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::web::signalr::plugin --mode=errors --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.SignalRService/SignalR/' --aggregation='maximum' --warning-user-errors='800' --warning-user-errors='900' Default aggregation: 'maximum' / 'minimum', 'total' and 'average' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'system-errors', 'user-errors'. =item B<--critical-*> Critical threshold where '*' can be: 'system-errors', 'user-errors'. =back =cut centreon-plugins-20220113/cloud/azure/web/signalr/mode/health.pm000066400000000000000000000036141417000230700244370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::web::signalr::mode::health; use base qw(cloud::azure::management::monitor::mode::health); use strict; use warnings; sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{az_resource_namespace} = 'Microsoft.SignalRService'; $self->{az_resource_type} = 'SignalR'; } 1; __END__ =head1 MODE Check Azure Web SignalR health status. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{summary} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /^Unavailable$/'). Can used special variables like: %{status}, %{summary} =item B<--unknown-status> Set unknown threshold for status (Default: '%{status} =~ /^Unknown$/'). Can used special variables like: %{status}, %{summary} =item B<--ok-status> Set ok threshold for status (Default: '%{status} =~ /^Available$/'). Can used special variables like: %{status}, %{summary} =back =cut centreon-plugins-20220113/cloud/azure/web/signalr/mode/traffic.pm000066400000000000000000000114231417000230700246050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::web::signalr::mode::traffic; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'inboundtraffic' => { 'output' => 'Inbound Traffic', 'label' => 'inbound-traffic', 'nlabel' => 'signalr.traffic.inbound.bytes', 'unit' => 'B', 'min' => '0', }, 'outboundtraffic' => { 'output' => 'Outbound Traffic', 'label' => 'outbound-traffic', 'nlabel' => 'signalr.traffic.outbound.bytes', 'unit' => 'B', 'min' => '0', } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.SignalRService\/SignalR\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'SignalR'; $self->{az_resource_namespace} = 'Microsoft.SignalRService'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Web SignalR traffic. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::web::signalr::plugin --mode=traffic --custommode=api --resource= --resource-group= --aggregation='total' --warning-inbound-traffic='80000' --critical-inbound-traffic='90000' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::web::signalr::plugin --mode=traffic --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.SignalRService/SignalR/' --aggregation='total' --warning-inbound-traffic='80000' --critical-inbound-traffic='90000' Default aggregation: 'total' / 'minimum', 'maximum' and 'average' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'inbound-traffic', 'outbound-traffic'. =item B<--critical-*> Critical threshold where '*' can be: 'inbound-traffic', 'outbound-traffic'. =back =cut centreon-plugins-20220113/cloud/azure/web/signalr/mode/usage.pm000066400000000000000000000113541417000230700242760ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::web::signalr::mode::usage; use base qw(cloud::azure::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'connectioncount' => { 'output' => 'Connection Count', 'label' => 'connection-count', 'nlabel' => 'signalr.connections.count', 'unit' => '', 'min' => '0', }, 'messagecount' => { 'output' => 'Message Count', 'label' => 'message-count', 'nlabel' => 'signalr.messages.count', 'unit' => '', 'min' => '0' } }; return $metrics_mapping; } 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-metric:s' => { name => 'filter_metric' }, 'resource:s' => { name => 'resource' }, 'resource-group:s' => { name => 'resource_group' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{resource}) || $self->{option_results}->{resource} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify either --resource with --resource-group option or --resource .'); $self->{output}->option_exit(); } my $resource = $self->{option_results}->{resource}; my $resource_group = defined($self->{option_results}->{resource_group}) ? $self->{option_results}->{resource_group} : ''; if ($resource =~ /^\/subscriptions\/.*\/resourceGroups\/(.*)\/providers\/Microsoft\.SignalRService\/SignalR\/(.*)$/) { $resource_group = $1; $resource = $2; } $self->{az_resource} = $resource; $self->{az_resource_group} = $resource_group; $self->{az_resource_type} = 'SignalR'; $self->{az_resource_namespace} = 'Microsoft.SignalRService'; $self->{az_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{az_interval} = defined($self->{option_results}->{interval}) ? $self->{option_results}->{interval} : 'PT5M'; $self->{az_aggregations} = ['Total']; if (defined($self->{option_results}->{aggregation})) { $self->{az_aggregations} = []; foreach my $stat (@{$self->{option_results}->{aggregation}}) { if ($stat ne '') { push @{$self->{az_aggregations}}, ucfirst(lc($stat)); } } } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{az_metrics}}, $metric; } } 1; __END__ =head1 MODE Check Azure Web SignalR usage. Example: Using resource name : perl centreon_plugins.pl --plugin=cloud::azure::web::signalr::plugin --mode=usage --custommode=api --resource= --resource-group= --aggregation='total' --warning-connection-count='800' --critical-connection-count='900' Using resource id : perl centreon_plugins.pl --plugin=cloud::azure::web::signalr::plugin --mode=usage --custommode=api --resource='/subscriptions//resourceGroups//providers/Microsoft.SignalRService/SignalR/' --aggregation='total' --warning-connection-count='800' --critical-connection-count='900' Default aggregation: 'total' / 'minimum', 'maximum' and 'average' are valid. =over 8 =item B<--resource> Set resource name or id (Required). =item B<--resource-group> Set resource group (Required if resource's name is used). =item B<--warning-*> Warning threshold where '*' can be: 'message-count', connection-count'. =item B<--critical-*> Critical threshold where '*' can be: 'message-count', connection-count'. =back =cut centreon-plugins-20220113/cloud/azure/web/signalr/plugin.pm000066400000000000000000000035341417000230700235450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::azure::web::signalr::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} = { 'discovery' => 'cloud::azure::web::signalr::mode::discovery', 'errors' => 'cloud::azure::web::signalr::mode::errors', 'health' => 'cloud::azure::web::signalr::mode::health', 'usage' => 'cloud::azure::web::signalr::mode::usage', 'traffic' => 'cloud::azure::web::signalr::mode::traffic' }; $self->{custom_modes}->{azcli} = 'cloud::azure::custom::azcli'; $self->{custom_modes}->{api} = 'cloud::azure::custom::api'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'api-version:s' => { name => 'api_version', default => '2018-01-01' }, }); $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Azure SignalR resources. =cut centreon-plugins-20220113/cloud/cadvisor/000077500000000000000000000000001417000230700201545ustar00rootroot00000000000000centreon-plugins-20220113/cloud/cadvisor/restapi/000077500000000000000000000000001417000230700216235ustar00rootroot00000000000000centreon-plugins-20220113/cloud/cadvisor/restapi/custom/000077500000000000000000000000001417000230700231355ustar00rootroot00000000000000centreon-plugins-20220113/cloud/cadvisor/restapi/custom/api.pm000066400000000000000000000274621417000230700242570ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::cadvisor::restapi::custom::api; use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::http; use JSON::XS; use FileHandle; 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 => { 'hostname:s@' => { name => 'hostname' }, 'port:s' => { name => 'port', default => 8080 }, 'proto:s' => { name => 'proto', default => 'http' }, 'api-path:s' => { name => 'api_path', default => '/containers/docker/' }, 'credentials' => { name => 'credentials' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'timeout:s' => { name => 'timeout', default => 10 }, 'cert-file:s' => { name => 'cert_file' }, 'key-file:s' => { name => 'key_file' }, 'cacert-file:s' => { name => 'cacert_file' }, 'cert-pwd:s' => { name => 'cert_pwd' }, 'cert-pkcs12' => { name => 'cert_pkcs12' }, 'api-version:s' => { name => 'api_version', default => 'v1.3' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{http} = centreon::plugins::http->new(%options); $self->{output} = $options{output}; return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : undef; if (!defined($self->{hostname})) { $self->{output}->add_option_msg(short_msg => "Need to specify hostname option."); $self->{output}->option_exit(); } $self->{node_names} = []; foreach my $node_name (@{$self->{hostname}}) { if ($node_name ne '') { push @{$self->{node_names}}, $node_name; } } $self->{http}->set_options(%{$self->{option_results}}); return 0; } sub get_hostnames { my ($self, %options) = @_; return $self->{hostname}; } sub get_port { my ($self, %options) = @_; return $self->{option_results}->{port}; } sub internal_api_list_nodes { my ($self, %options) = @_; my $response = $self->{http}->request( hostname => $options{node_name}, url_path => '/api/' . $self->{option_results}->{api_version} . $self->{option_results}->{api_path}, unknown_status => '', critical_status => '', warning_status => ''); my $nodes; eval { $nodes = JSON::XS->new->utf8->decode($response); }; if ($@) { $nodes = {}; $self->{output}->output_add( severity => 'UNKNOWN', short_msg => "Node '$options{node_name}': cannot decode json list nodes response: $@" ); } else { $nodes = {} if (ref($nodes) eq 'ARRAY'); # nodes is not in a swarm } return $nodes; } sub internal_api_info { my ($self, %options) = @_; my $response = $self->{http}->request( hostname => $options{node_name}, url_path => '/api/' . $self->{option_results}->{api_version} . '/machine/', unknown_status => '', critical_status => '', warning_status => ''); my $nodes; eval { $nodes = JSON::XS->new->utf8->decode($response); }; if ($@) { $nodes = []; $self->{output}->output_add( severity => 'UNKNOWN', short_msg => "Node '$options{node_name}': cannot decode json info response: $@" ); } return $nodes; } sub internal_api_list_containers { my ($self, %options) = @_; my $response = $self->{http}->request( hostname => $options{node_name}, url_path => '/api/' . $self->{option_results}->{api_version} . $self->{option_results}->{api_path}, unknown_status => '', critical_status => '', warning_status => ''); my $containers = []; my $containers_ids; eval { $containers_ids = JSON::XS->new->utf8->decode($response); }; if ($@) { $containers = []; $self->{output}->output_add( severity => 'UNKNOWN', short_msg => "Node '$options{node_name}': cannot decode json get containers response: $@" ); } foreach my $container (@{$containers_ids->{subcontainers}}) { my $json_response = JSON::XS->new->utf8->decode( $self->{http}->request( hostname => $options{node_name}, url_path => '/api/' . $self->{option_results}->{api_version} . '/containers/' . $container->{name} ) ); push @$containers, { id => defined($json_response->{id}) ? $json_response->{id} : $json_response->{name}, names => defined($json_response->{aliases}) ? $json_response->{aliases} : [$json_response->{name}], node => $options{node_name} }; } return $containers; } sub internal_api_get_machine_stats { my ($self, %options) = @_; my $response = $self->{http}->request( hostname => $options{node_name}, url_path => '/api/' . $self->{option_results}->{api_version} . '/machine', unknown_status => '', critical_status => '', warning_status => ''); my $machine_stats; my $full_machine_stats; eval { $full_machine_stats = JSON::XS->new->utf8->decode($response); }; if ($@) { $machine_stats = {}; $self->{output}->output_add( severity => 'UNKNOWN', short_msg => "Node '$options{node_name}': cannot decode json get container stats response: $@" ); } else { $machine_stats->{num_cores} = $full_machine_stats->{num_cores}; $machine_stats->{memory_capacity} = $full_machine_stats->{memory_capacity}; } return $machine_stats; } sub internal_api_get_container_stats { my ($self, %options) = @_; my $response = $self->{http}->request( hostname => $options{node_name}, url_path => '/api/' . $self->{option_results}->{api_version} . $self->{option_results}->{api_path} . '/' . $options{container_id}, unknown_status => '', critical_status => '', warning_status => ''); my $container_stats; my $full_container_stats; eval { $full_container_stats = JSON::XS->new->utf8->decode($response); }; if ($@) { $container_stats = []; $self->{output}->output_add( severity => 'UNKNOWN', short_msg => "Node '$options{node_name}': cannot decode json get container stats response: $@" ); } else { $container_stats->[0] = $full_container_stats->{stats}[0]; $container_stats->[1] = $full_container_stats->{stats}[scalar(@{$full_container_stats->{stats}}) - 1]; } return $container_stats; } sub api_list_containers { my ($self, %options) = @_; my $containers = {}; foreach my $node_name (@{$self->{node_names}}) { my $list_containers = $self->internal_api_list_containers(node_name => $node_name); foreach my $container (@$list_containers) { $containers->{$container->{id}} = { NodeName => $node_name, Name => $container->{names}->[0], }; } } return $containers; } sub api_get_machine_stats { my ($self, %options) = @_; my $machine_stats = {}; foreach my $node_name (@{$self->{node_names}}) { $machine_stats->{$node_name} = $self->internal_api_get_machine_stats(node_name => $node_name); } return $machine_stats; } sub api_list_nodes { my ($self, %options) = @_; my $nodes = {}; foreach my $node_name (@{$self->{node_names}}) { my $info_node = $self->internal_api_info(node_name => $node_name); my $list_nodes = $self->internal_api_list_nodes(node_name => $node_name); $nodes->{$node_name} = { nodes => [], num_cores => $info_node->{num_cores}, cpu_frequency_khz => $info_node->{cpu_frequency_khz}, memory_capacity => $info_node->{memory_capacity}, }; foreach my $node (@{$list_nodes->{subcontainers}}) { push @{$nodes->{$node_name}->{nodes}}, { name => $node->{name} } } } return $nodes; } sub api_get_containers { my ($self, %options) = @_; my $content_total = $self->api_list_containers(); if (defined($options{container_id}) && $options{container_id} ne '') { if (defined($content_total->{$options{container_id}})) { $content_total->{$options{container_id}}->{Stats} = $self->internal_api_get_container_stats(node_name => $content_total->{$options{container_id}}->{NodeName}, container_id => $options{container_id}); } } elsif (defined($options{container_name}) && $options{container_name} ne '') { my $container_id; foreach (keys %$content_total) { if ($content_total->{$_}->{Name} eq $options{container_name}) { $container_id = $_; last; } } if (defined($container_id)) { $content_total->{$container_id}->{Stats} = $self->internal_api_get_container_stats(node_name => $content_total->{$container_id}->{NodeName}, container_id => $container_id); } } else { foreach my $container_id (keys %{$content_total}) { $content_total->{$container_id}->{Stats} = $self->internal_api_get_container_stats(node_name => $content_total->{$container_id}->{NodeName}, container_id => $container_id); } } return $content_total; } 1; __END__ =head1 NAME cadvisor REST API =head1 SYNOPSIS CAdvisor Rest API custom mode =head1 REST API OPTIONS =over 8 =item B<--hostname> IP Addr/FQDN of the cadvisor node (can be multiple). =item B<--port> Port used (Default: 8080) =item B<--proto> Specify https if needed (Default: 'http') =item B<--api-path> Path used (Default: '/containers/docker') =item B<--credentials> Specify this option if you access webpage over basic authentification =item B<--username> Specify username for basic authentification (Mandatory if --credentials is specidied) =item B<--password> Specify password for basic authentification (Mandatory if --credentials is specidied) =item B<--timeout> Threshold for HTTP timeout (Default: 10) =item B<--cert-file> Specify certificate to send to the webserver =item B<--key-file> Specify key to send to the webserver =item B<--cacert-file> Specify root certificate to send to the webserver =item B<--cert-pwd> Specify certificate's password =item B<--cert-pkcs12> Specify type of certificate (PKCS12) =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/cloud/cadvisor/restapi/mode/000077500000000000000000000000001417000230700225475ustar00rootroot00000000000000centreon-plugins-20220113/cloud/cadvisor/restapi/mode/containerusage.pm000066400000000000000000000251171417000230700261220ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::cadvisor::restapi::mode::containerusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use DateTime; sub custom_memory_output { my ($self, %options) = @_; my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{memory_total}); my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{memory_used}); return sprintf( "Memory Used: %s (%.2f%%) Total: %s" , $total_used_value . " " . $total_used_unit, 100 * $self->{result_values}->{memory_used} / $self->{result_values}->{memory_total}, $total_size_value . " " . $total_size_unit ); } sub prefix_containers_output { my ($self, %options) = @_; return "Container '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'containers', type => 1, cb_prefix_output => 'prefix_containers_output', message_multiple => 'All containers are ok', skipped_code => { -11 => 1 } }, ]; $self->{maps_counters}->{containers} = [ { label => 'cpu-number', nlabel => 'container.cpu.count', set => { key_values => [ { name => 'cpu_number'}, { name => 'display' } ], output_template => 'CPU: %d core(s)', perfdatas => [ { label => 'cpu_number', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'cpu-total', nlabel => 'container.cpu.utilization.percentage', set => { key_values => [ { name => 'cpu_total'}, { name => 'display' } ], output_template => 'CPU Usage: %.2f %%', perfdatas => [ { label => 'cpu_total', template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'cpu-user', nlabel => 'container.cpu.user.utilization.percentage', set => { key_values => [ { name => 'cpu_user'}, { name => 'display' } ], output_template => 'CPU User: %.2f %%', perfdatas => [ { label => 'cpu_user', template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'cpu-system', nlabel => 'container.cpu.system.utilization.percentage', set => { key_values => [ { name => 'cpu_system' }, { name => 'display' } ], output_template => 'CPU System: %.2f %%', perfdatas => [ { label => 'cpu_system', template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'memory', nlabel => 'container.memory.usage.bytes', set => { key_values => [ { name => 'memory_used' }, { name => 'memory_total' }, { name => 'display' } ], closure_custom_output => $self->can('custom_memory_output'), output_change_bytes => 1, perfdatas => [ { label => 'memory_used', template => '%s', min => 0, max => 'memory_total',unit => 'B', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'memory-cache', nlabel => 'container.memory.cache.usage.bytes', set => { key_values => [ { name => 'memory_cache' }, { name => 'display' } ], output_template => 'Memory Cache: %s %s', output_change_bytes => 1, perfdatas => [ { label => 'memory_cache', template => '%s', min => 0, unit => 'B', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'memory-rss', nlabel => 'container.memory.rss.usage.bytes', set => { key_values => [ { name => 'memory_rss' }, { name => 'display' } ], output_template => 'Memory RSS: %s %s', output_change_bytes => 1, perfdatas => [ { label => 'memory_rss', template => '%s', min => 0, unit => 'B', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'swap', nlabel => 'container.swap.usage.bytes', set => { key_values => [ { name => 'swap' }, { name => 'display' } ], output_template => 'Swap: %s %s', output_change_bytes => 1, perfdatas => [ { label => 'swap', template => '%s', min => 0, unit => 'B', label_extra_instance => 1, instance_use => 'display' } ] } } ]; } 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 => { 'container-id:s' => { name => 'container_id' }, 'container-name:s' => { name => 'container_name' }, 'filter-name:s' => { name => 'filter_name' }, 'use-name' => { name => 'use_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{containers} = {}; my $result = $options{custom}->api_get_containers( container_id => $self->{option_results}->{container_id}, container_name => $self->{option_results}->{container_name} ); my $machine_stats = $options{custom}->api_get_machine_stats(); foreach my $container_id (keys %{$result}) { next if (!defined($result->{$container_id}->{Stats})); my $name = $result->{$container_id}->{Name}; 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; } my $first_index = 0; my $first_stat = $result->{$container_id}->{Stats}[$first_index]; my $first_ts = $first_stat->{timestamp}; my $first_dt = $self->parse_date(date => $first_ts); my $first_cpu_total = $first_stat->{cpu}{usage}{total}; my $first_cpu_user = $first_stat->{cpu}{usage}{user}; my $first_cpu_system = $first_stat->{cpu}{usage}{system}; my $last_index = scalar @{$result->{$container_id}->{Stats}} - 1; my $last_stat = $result->{$container_id}->{Stats}[$last_index]; my $last_ts = $last_stat->{timestamp}; my $last_dt = $self->parse_date(date => $last_ts); my $last_cpu_total = $last_stat->{cpu}{usage}{total}; my $last_cpu_user = $last_stat->{cpu}{usage}{user}; my $last_cpu_system = $last_stat->{cpu}{usage}{system}; my $diff_ts = $last_dt - $first_dt; my $cpu_number = $machine_stats->{$result->{$container_id}->{NodeName}}->{num_cores}; $self->{containers}->{$container_id} = { node_name => $result->{$container_id}->{NodeName}, display => defined($self->{option_results}->{use_name}) ? $name : $container_id, name => $name, cpu_total => ($last_cpu_total - $first_cpu_total) / ($diff_ts * 1_000_000_000) * 100 / $cpu_number, cpu_user => ($last_cpu_user - $first_cpu_user) / ($diff_ts * 1_000_000_000) * 100 / $cpu_number, cpu_system => ($last_cpu_system - $first_cpu_system) / ($diff_ts * 1_000_000_000) * 100 / $cpu_number, cpu_number => $cpu_number, memory_used => $last_stat->{memory}{usage}, memory_cache => $last_stat->{memory}{cache}, memory_rss => $last_stat->{memory}{rss}, swap => $last_stat->{memory}{swap}, memory_total => $machine_stats->{$result->{$container_id}->{NodeName}}->{memory_capacity}, }; } if (scalar(keys %{$self->{containers}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No containers found."); $self->{output}->option_exit(); } my $hostnames = $options{custom}->get_hostnames(); } sub parse_date { my ($self, %options) = @_; if ($options{date} !~ /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})\.(\d*)([^\d]+)$/) { $self->{output}->add_option_msg(short_msg => "Wrong time found '" . $options{date} . "'."); $self->{output}->option_exit(); } my $dt = DateTime->new( year => $1, month => $2, day => $3, hour => $4, minute => $5, second => $6, time_zone => $8 ); # return epoch time with nanoseconds return $dt->epoch.".".$7; } 1; __END__ =head1 MODE Check container usage. =over 8 =item B<--container-id> Exact container ID. =item B<--container-name> Exact container name (if multiple names: names separated by ':'). =item B<--use-name> Use name for perfdata and display. =item B<--filter-name> Filter by container name (can be a regexp). =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='cpu' =item B<--warning-*> Threshold warning. Can be: 'read-iops', 'write-iops', 'traffic-in', 'traffic-out', 'cpu' (%), 'memory' (%). =item B<--critical-*> Threshold critical. Can be: 'read-iops', 'write-iops', 'traffic-in', 'traffic-out', 'cpu' (%), 'memory' (%). =back =cut centreon-plugins-20220113/cloud/cadvisor/restapi/mode/diskio.pm000066400000000000000000000175361417000230700244030ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::cadvisor::restapi::mode::diskio; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use DateTime; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'containers_diskio', type => 1, cb_prefix_output => 'prefix_containers_diskio_output', message_multiple => 'All container disk IOps are ok', skipped_code => { -11 => 1 } }, ]; $self->{maps_counters}->{containers_diskio} = [ { label => 'diskio-read', nlabel => 'disk.io.read.bytespersecond', set => { key_values => [ { name => 'diskio_read' }, { name => 'display' } ], output_change_bytes => 1, output_template => 'Disk IO Read: %s %s/s', perfdatas => [ { label => 'diskio_read', template => '%.2f', min => 0, unit => 'B/s', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'diskio-write', nlabel => 'disk.io.write.bytespersecond', set => { key_values => [ { name => 'diskio_write' }, { name => 'display' } ], output_change_bytes => 1, output_template => 'Disk IO Write: %s %s/s', perfdatas => [ { label => 'diskio_write', template => '%.2f', min => 0, unit => 'B/s', label_extra_instance => 1, instance_use => 'display' } ] } } ]; } 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 => { 'container-id:s' => { name => 'container_id' }, 'container-name:s' => { name => 'container_name' }, 'filter-name:s' => { name => 'filter_name' }, 'use-name' => { name => 'use_name' } }); return $self; } sub prefix_containers_diskio_output { my ($self, %options) = @_; return "Container '" . $options{instance_value}->{display} . "' "; } sub manage_selection { my ($self, %options) = @_; $self->{containers_diskio} = {}; my $result = $options{custom}->api_get_containers( container_id => $self->{option_results}->{container_id}, container_name => $self->{option_results}->{container_name} ); my $machine_stats = $options{custom}->api_get_machine_stats(); foreach my $container_id (keys %{$result}) { next if (!defined($result->{$container_id}->{Stats})); my $name = $result->{$container_id}->{Name}; 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; } my $first_index = 0; my $first_stat = $result->{$container_id}->{Stats}[$first_index]; my $first_ts = $first_stat->{timestamp}; my $first_dt = $self->parse_date(date => $first_ts); my $last_index = scalar @{$result->{$container_id}->{Stats}} - 1; my $last_stat = $result->{$container_id}->{Stats}[$last_index]; my $last_ts = $last_stat->{timestamp}; my $last_dt = $self->parse_date(date => $last_ts); my $diff_ts = $last_dt - $first_dt; my $read_io = {}; my $write_io = {}; if (defined($first_stat->{diskio})) { $self->{containers}->{$container_id} = { node_name => $result->{$container_id}->{NodeName}, display => defined($self->{option_results}->{use_name}) ? $name : $container_id, name => $name, }; # The API does not present the devices in the same order between the first and the last stats sample, so we can't just compare [0] with [0] and [1] with [1], we have to check the name of the device foreach my $diskio_index (0..(scalar(@{$first_stat->{diskio}->{io_service_bytes}}) - 1)) { my $name = defined($self->{option_results}->{use_name}) ? $name : $container_id; my $device = $first_stat->{diskio}->{io_service_bytes}->[$diskio_index]->{device}; $name .= ':' . $device; $read_io->{$name} = {first => $first_stat->{diskio}->{io_service_bytes}->[$diskio_index]->{stats}->{Read}}; $write_io->{$name} = {first => $first_stat->{diskio}->{io_service_bytes}->[$diskio_index]->{stats}->{Write}}; } foreach my $diskio_index (0..(scalar(@{$last_stat->{diskio}->{io_service_bytes}}) - 1)) { my $name = defined($self->{option_results}->{use_name}) ? $name : $container_id; my $device = $last_stat->{diskio}->{io_service_bytes}->[$diskio_index]->{device}; $name .= ':' . $device; $read_io->{$name}->{last} = $last_stat->{diskio}->{io_service_bytes}->[$diskio_index]->{stats}->{Read}; $write_io->{$name}->{last} = $last_stat->{diskio}->{io_service_bytes}->[$diskio_index]->{stats}->{Write}; } foreach my $diskio_disk (keys %$read_io) { $self->{containers_diskio}->{$diskio_disk} = { display => $diskio_disk, diskio_read => ($read_io->{$diskio_disk}->{last} - $read_io->{$diskio_disk}->{first}) / $diff_ts , diskio_write => ($write_io->{$diskio_disk}->{last} - $write_io->{$diskio_disk}->{first}) / $diff_ts, }; } } } if (scalar(keys %{$self->{containers}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No containers found or no data available for diskio metrics."); $self->{output}->option_exit(); } my $hostnames = $options{custom}->get_hostnames(); } sub parse_date { my ($self, %options) = @_; if ($options{date} !~ /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})\.(\d*)([^\d]+)$/) { $self->{output}->add_option_msg(short_msg => "Wrong time found '" . $options{date} . "'."); $self->{output}->option_exit(); } my $dt = DateTime->new( year => $1, month => $2, day => $3, hour => $4, minute => $5, second => $6, time_zone => $8 ); # return epoch time with nanoseconds return $dt->epoch.".".$7; } 1; __END__ =head1 MODE Check container disk io. =over 8 =item B<--container-id> Exact container ID. =item B<--container-name> Exact container name (if multiple names: names separated by ':'). =item B<--use-name> Use name for perfdata and display. =item B<--filter-name> Filter by container name (can be a regexp). =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^diskio-read$' =item B<--warning-*> Threshold warning. Can be: 'diskio-read', 'diskio-write'. =item B<--critical-*> Threshold critical. Can be: 'diskio-read', 'diskio-write'. =back =cut centreon-plugins-20220113/cloud/cadvisor/restapi/mode/listcontainers.pm000066400000000000000000000051641417000230700261540ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::cadvisor::restapi::mode::listcontainers; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{containers} = $options{custom}->api_list_containers(); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $container_id (sort keys %{$self->{containers}}) { $self->{output}->output_add(long_msg => '[id = ' . $container_id . "] [name = '" . $self->{containers}->{$container_id}->{Name} . "']" . " [node = '" . $self->{containers}->{$container_id}->{NodeName} . "']"); } $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 => ['id', 'name', 'node', 'state']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $container_id (sort keys %{$self->{containers}}) { $self->{output}->add_disco_entry(name => $self->{containers}->{$container_id}->{Name}, node => $self->{containers}->{$container_id}->{NodeName}, state => $self->{containers}->{$container_id}->{State}, id => $container_id, ); } } 1; __END__ =head1 MODE List containers. =over 8 =back =cut centreon-plugins-20220113/cloud/cadvisor/restapi/mode/nodestatus.pm000066400000000000000000000105311417000230700252760ustar00rootroot00000000000000# # Copyright 2018 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::cadvisor::restapi::mode::nodestatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_node_output { my ($self, %options) = @_; return "Node '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'node', type => 1, cb_prefix_output => 'prefix_node_output', message_multiple => 'All node informations are ok', skipped_code => { -11 => 1 } } ]; $self->{maps_counters}->{node} = [ { label => 'containers-running', nlabel => 'node.containers.running.count', set => { key_values => [ { name => 'containers_running' }, { name => 'display' } ], output_template => 'Containers running: %s', perfdatas => [ { label => 'containers_running', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'num-cores', nlabel => 'node.core.count', set => { key_values => [ { name => 'num_cores' }, { name => 'display' } ], output_template => 'CPU cores: %s', perfdatas => [ { label => 'num_cores', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'memory-capacity', nlabel => 'node.memory.bytes', set => { key_values => [ { name => 'memory_capacity' }, { name => 'display' } ], output_template => 'Mem capacity %s %s', perfdatas => [ { label => 'memory_capacity', unit => 'B', output_change_bytes => 1, template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'cpu-frequency', nlabel => 'node.cpu.frequency.hertz', set => { key_values => [ { name => 'cpu_frequency' }, { name => 'display' } ], output_template => 'CPU frequency %s %s', perfdatas => [ { label => 'cpu_frequency', unit => 'Hz', output_change_bytes => 1, template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{node} = {}; my $result = $options{custom}->api_list_nodes(); foreach my $node_name (keys %{$result}) { $self->{node}->{$node_name} = { display => $node_name, num_cores => $result->{$node_name}->{num_cores}, cpu_frequency => $result->{$node_name}->{cpu_frequency_khz} * 1000, memory_capacity => $result->{$node_name}->{memory_capacity}, containers_running => scalar(@{$result->{$node_name}->{nodes}}), }; } if (scalar(keys %{$self->{node}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No node found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check node status. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'containers-running', 'num-cores', 'memory-capacity', 'cpu-frequency'. =back =cut centreon-plugins-20220113/cloud/cadvisor/restapi/mode/traffic.pm000066400000000000000000000163451417000230700245340ustar00rootroot00000000000000# # Copyright 2018 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::cadvisor::restapi::mode::traffic; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use DateTime; sub prefix_containers_traffic_output { my ($self, %options) = @_; return "Container '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'containers_traffic', type => 1, cb_prefix_output => 'prefix_containers_traffic_output', message_multiple => 'All container traffics are ok', skipped_code => { -11 => 1 } } ]; $self->{maps_counters}->{containers_traffic} = [ { label => 'traffic-in', nlabel => 'container.traffic.in.bitspersecond', set => { key_values => [ { name => 'traffic_in' }, { name => 'display' } ], output_template => 'Traffic In: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'traffic_in', template => '%.2f', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'traffic-out', nlabel => 'container.traffic.out.bitspersecond', set => { key_values => [ { name => 'traffic_out' }, { name => 'display' } ], output_template => 'Traffic Out: %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'traffic_out', template => '%.2f', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display' } ] } } ]; } 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 => { 'container-id:s' => { name => 'container_id' }, 'container-name:s' => { name => 'container_name' }, 'filter-name:s' => { name => 'filter_name' }, 'use-name' => { name => 'use_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{containers} = {}; $self->{containers_traffic} = {}; $self->{containers_diskio} = {}; my $result = $options{custom}->api_get_containers( container_id => $self->{option_results}->{container_id}, container_name => $self->{option_results}->{container_name} ); my $machine_stats = $options{custom}->api_get_machine_stats(); foreach my $container_id (keys %{$result}) { next if (!defined($result->{$container_id}->{Stats})); my $name = $result->{$container_id}->{Name}; 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; } my $first_index = 0; my $first_stat = $result->{$container_id}->{Stats}[$first_index]; my $first_ts = $first_stat->{timestamp}; my $first_dt = $self->parse_date(date => $first_ts); my $last_index = scalar @{$result->{$container_id}->{Stats}} - 1; my $last_stat = $result->{$container_id}->{Stats}[$last_index]; my $last_ts = $last_stat->{timestamp}; my $last_dt = $self->parse_date(date => $last_ts); my $diff_ts = $last_dt - $first_dt; $self->{containers}->{$container_id} = { node_name => $result->{$container_id}->{NodeName}, display => defined($self->{option_results}->{use_name}) ? $name : $container_id, name => $name, }; $name = defined($self->{option_results}->{use_name}) ? $name : $container_id; if (defined($first_stat->{network}->{interfaces})) { foreach my $interface_index (0..(scalar(@{$first_stat->{network}->{interfaces}}) - 1)) { $self->{containers_traffic}->{$name} = { display => $name . '.' . $first_stat->{network}->{interfaces}->[$interface_index]->{name}, traffic_in => ($last_stat->{network}->{interfaces}->[$interface_index]->{rx_packets} - $first_stat->{network}->{interfaces}->[$interface_index]->{rx_packets}) / $diff_ts * 8, traffic_out => ($last_stat->{network}->{interfaces}->[$interface_index]->{tx_packets} - $first_stat->{network}->{interfaces}->[$interface_index]->{tx_packets}) / $diff_ts * 8, }; } } elsif (defined($first_stat->{network}->{rx_packets})) { $self->{containers_traffic}->{$name} = { display => $name . '.default', traffic_in => ($last_stat->{network}->{rx_packets} - $first_stat->{network}->{rx_packets}) / $diff_ts * 8, traffic_out => ($last_stat->{network}->{tx_packets} - $first_stat->{network}->{tx_packets}) / $diff_ts * 8, }; } } if (scalar(keys %{$self->{containers}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No containers found."); $self->{output}->option_exit(); } my $hostnames = $options{custom}->get_hostnames(); } sub parse_date { my ($self, %options) = @_; if ($options{date} !~ /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})\.(\d*)([^\d]+)$/) { $self->{output}->add_option_msg(short_msg => "Wrong time found '" . $options{date} . "'."); $self->{output}->option_exit(); } my $dt = DateTime->new( year => $1, month => $2, day => $3, hour => $4, minute => $5, second => $6, time_zone => $8 ); # return epoch time with nanoseconds return $dt->epoch.".".$7; } 1; __END__ =head1 MODE Check container traffic usage. =over 8 =item B<--container-id> Exact container ID. =item B<--container-name> Exact container name (if multiple names: names separated by ':'). =item B<--use-name> Use docker name for perfdata and display. =item B<--filter-name> Filter by container name (can be a regexp). =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^traffic-in$' =item B<--warning-*> Threshold warning. Can be: 'traffic-in', 'traffic-out'. =item B<--critical-*> Threshold critical. Can be: 'traffic-in', 'traffic-out'. =back =cut centreon-plugins-20220113/cloud/cadvisor/restapi/plugin.pm000066400000000000000000000032471417000230700234650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::cadvisor::restapi::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.3'; $self->{modes} = { 'container-usage' => 'cloud::cadvisor::restapi::mode::containerusage', 'disk-io' => 'cloud::cadvisor::restapi::mode::diskio', 'traffic' => 'cloud::cadvisor::restapi::mode::traffic', 'list-containers' => 'cloud::cadvisor::restapi::mode::listcontainers', 'node-status' => 'cloud::cadvisor::restapi::mode::nodestatus' }; $self->{custom_modes}->{api} = 'cloud::cadvisor::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check nodes and containers through cAdvisor API. Requirements: cAdvisor supporting API version 1.3+ =cut centreon-plugins-20220113/cloud/cloudfoundry/000077500000000000000000000000001417000230700210575ustar00rootroot00000000000000centreon-plugins-20220113/cloud/cloudfoundry/restapi/000077500000000000000000000000001417000230700225265ustar00rootroot00000000000000centreon-plugins-20220113/cloud/cloudfoundry/restapi/custom/000077500000000000000000000000001417000230700240405ustar00rootroot00000000000000centreon-plugins-20220113/cloud/cloudfoundry/restapi/custom/api.pm000066400000000000000000000226331417000230700251550ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::cloudfoundry::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use JSON::XS; use URI::Encode; 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'timeout:s' => { name => 'timeout' }, 'api-path:s' => { name => 'api_path' }, 'api-username:s' => { name => 'api_username' }, 'api-password:s' => { name => 'api_password' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : undef; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{username} = (defined($self->{option_results}->{username})) ? $self->{option_results}->{username} : 'cf'; $self->{password} = (defined($self->{option_results}->{password})) ? $self->{option_results}->{password} : ''; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{api_path} = (defined($self->{option_results}->{api_path})) ? $self->{option_results}->{api_path} : '/v2'; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : undef; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : undef; if (!defined($self->{hostname})) { $self->{output}->add_option_msg(short_msg => "Need to specify hostname option."); $self->{output}->option_exit(); } if (!defined($self->{api_username})) { $self->{output}->add_option_msg(short_msg => "Need to specify API username option."); $self->{output}->option_exit(); } if (!defined($self->{api_password})) { $self->{output}->add_option_msg(short_msg => "Need to specify API password option."); $self->{output}->option_exit(); } return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{username} = $self->{username}; $self->{option_results}->{password} = $self->{password}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{warning_status} = ''; $self->{option_results}->{critical_status} = ''; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->add_header(key => 'Content-Type', value => 'application/x-www-form-urlencoded'); if (defined($self->{access_token})) { $self->{http}->add_header(key => 'Authorization', value => 'Bearer ' . $self->{access_token}); } $self->{http}->set_options(%{$self->{option_results}}); } sub request_api { my ($self, %options) = @_; my $content = $self->{http}->request(method => $options{method}, url_path => $self->{api_path} . $options{url_path}, query_form_post => $options{query_form_post}, critical_status => '', warning_status => '', unknown_status => ''); my $decoded; eval { $decoded = decode_json($content); }; if ($@) { $self->{output}->output_add(long_msg => $content, debug => 1); $self->{output}->add_option_msg(short_msg => "Cannot decode json response"); $self->{output}->option_exit(); } if ($self->{http}->get_code() != 200) { $self->{output}->add_option_msg(short_msg => "Error code: " . $decoded->{error_code} . ". Description: " . $decoded->{description}); $self->{output}->option_exit(); } return $decoded; } sub get_info { my ($self, %options) = @_; $self->settings(); return $self->request_api(method => 'GET', url_path => '/info'); } sub get_access_token { my ($self, %options) = @_; my $info = $self->get_info(); my $uri = URI::Encode->new({encode_reserved => 1}); my $encoded_username = $uri->encode($self->{api_username}); my $encoded_password = $uri->encode($self->{api_password}); my $content = $self->{http}->request(method => 'POST', query_form_post => 'username=' . $encoded_username . '&password=' . $encoded_password . '&grant_type=password', full_url => $info->{authorization_endpoint} . '/oauth/token', hostname => '', basic => 1, credentials => 1, username => $self->{username}, password => $self->{password}); my $decoded; eval { $decoded = decode_json($content); }; if ($@) { $self->{output}->output_add(long_msg => $content, debug => 1); $self->{output}->add_option_msg(short_msg => "Cannot decode json response"); $self->{output}->option_exit(); } return $decoded->{access_token}; } sub get_object_v2 { my ($self, %options) = @_; $self->settings(); my $url_path = $options{url_path}; my @result; while(my $content = $self->request_api(%options)) { if (defined($content->{resources})) { push @result, @{$content->{resources}}; last if (!defined($content->{next_url}) || $content->{next_url} !~ /^$self->{api_path}$url_path.*&page=(.*).*/ || $content->{next_url} !~ /^$self->{api_path}$url_path.*?page=(.*).*/); my $page = $1; $options{url_path} = $url_path . '?page=' . $page; } else { return $content; last; } } return \@result; } sub get_object_v3 { my ($self, %options) = @_; $self->settings(); my $url_path = $options{url_path}; my @result; while(my $content = $self->request_api(%options)) { if (defined($content->{resources})) { push @result, @{$content->{resources}}; last if (!defined($content->{pagination}->{next}->{href}) || $content->{pagination}->{next}->{href} !~ /^$self->{proto}\:\/\/$self->{hostname}$self->{api_path}$url_path.*&page=(.*).*/ || $content->{pagination}->{next}->{href} !~ /^$self->{proto}\:\/\/$self->{hostname}$self->{api_path}$url_path.*?page=(.*).*/); my $page = $1; $options{url_path} = $url_path . '?page=' . $page; } else { push @result, $content; last; } } return \@result; } sub get_object { my ($self, %options) = @_; if (!defined($self->{access_token})) { $self->{access_token} = $self->get_access_token(); } my $info = $self->get_info(); if ($info->{api_version} =~ /^2\..*/) { return $self->get_object_v2(%options); } else { return $self->get_object_v3(%options); # Not tested } return undef; } 1; __END__ =head1 NAME Cloud Foundry REST API =head1 SYNOPSIS Cloud Foundry Rest API custom mode =head1 REST API OPTIONS =over 8 =item B<--hostname> Cloud Foundry API hostname. =item B<--api-path> Cloud Foundry API url path (Default: '/v2') =item B<--api-username> Cloud Foundry API username. =item B<--api-password> Cloud Foundry API password. =item B<--port> Cloud Foundry API port (Default: 443) =item B<--proto> Specify https if needed (Default: 'https') =item B<--username> Authorization endpoint username (Default: 'cf') =item B<--password> Authorization endpoint password (Default: '') =item B<--timeout> Set HTTP timeout =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/cloud/cloudfoundry/restapi/mode/000077500000000000000000000000001417000230700234525ustar00rootroot00000000000000centreon-plugins-20220113/cloud/cloudfoundry/restapi/mode/appsstate.pm000066400000000000000000000125161417000230700260210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::cloudfoundry::restapi::mode::appsstate; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_state_output { my ($self, %options) = @_; return sprintf("state is '%s'", $self->{result_values}->{state}); } sub prefix_output { my ($self, %options) = @_; return "App '" . $options{instance_value}->{name} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'apps', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All apps state are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'started', nlabel => 'applications.started.count', set => { key_values => [ { name => 'started' } ], output_template => 'Started : %d', perfdatas => [ { label => 'started', template => '%d', min => 0 } ] } }, { label => 'stopped', nlabel => 'applications.stopped.count', set => { key_values => [ { name => 'stopped' } ], output_template => 'Stopped : %d', perfdatas => [ { label => 'stopped', template => '%d', min => 0 } ] } } ]; $self->{maps_counters}->{apps} = [ { label => 'state', type => 2, critical_default => '%{state} !~ /STARTED/i', set => { key_values => [ { name => 'state' }, { name => 'name' } ], closure_custom_output => $self->can('custom_state_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'organization-guid:s' => { name => 'organization_guid' }, 'space-guid:s' => { name => 'space_guid' }, 'filter-name:s' => { name => 'filter_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $apps; if (defined($self->{option_results}->{organization_guid}) && $self->{option_results}->{organization_guid} ne '') { my $spaces = $options{custom}->get_object(url_path => '/organizations/' . $self->{option_results}->{organization_guid} . '/spaces'); foreach my $space (@{$spaces}) { next if (!defined($space->{entity}->{apps_url}) || $space->{entity}->{apps_url} !~ /^\/v2(.*)/); my $result = $options{custom}->get_object(url_path => $1); push @{$apps}, @{$result}; } } elsif (defined($self->{option_results}->{space_guid}) && $self->{option_results}->{space_guid} ne '') { $apps = $options{custom}->get_object(url_path => '/spaces/' . $self->{option_results}->{space_guid} . '/apps'); } else { $apps = $options{custom}->get_object(url_path => '/apps'); } $self->{global}->{started} = 0; $self->{global}->{stopped} = 0; foreach my $app (@{$apps}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $app->{entity}->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping app '" . $app->{entity}->{name} . "': no matching filter name.", debug => 1); next; } $self->{apps}->{$app->{metadata}->{guid}} = { name => $app->{entity}->{name}, state => $app->{entity}->{state} }; $self->{global}->{lc($app->{entity}->{state})}++; } if (scalar(keys %{$self->{apps}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No entry found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check Cloud Foundry app state. =over 8 =item B<--organization-guid> Only looks for apps from an organization. =item B<--space-guid> Only looks for apps from a space. =item B<--filter-name> Filter apps name (can be a regexp). =item B<--warning-state> Threshold warning. =item B<--critical-state> Threshold critical (Default: '%{state} !~ /STARTED/i'). =item B<--warning-*> Threshold warning for apps count based on state (Can be: 'started', 'stopped') =item B<--critical-*> Threshold critical for apps count based on state (Can be: 'started', 'stopped'). =back =cut centreon-plugins-20220113/cloud/cloudfoundry/restapi/mode/instancesstate.pm000066400000000000000000000134671417000230700270530ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::cloudfoundry::restapi::mode::instancesstate; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_app_state_output { my ($self, %options) = @_; return sprintf( "App '%s' state is '%s'", $self->{result_values}->{name}, $self->{result_values}->{state} ); } sub custom_inst_state_output { my ($self, %options) = @_; return sprintf("state is '%s'", $self->{result_values}->{state}); } sub prefix_output { my ($self, %options) = @_; return "Instance '" . $options{instance_value}->{id} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'app', type => 0 }, { name => 'global', type => 0 }, { name => 'instances', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All instances state are ok' }, ]; $self->{maps_counters}->{app} = [ { label => 'app-state', type => 2, critical_default => '%{state} !~ /STARTED/i', set => { key_values => [ { name => 'state' }, { name => 'name' } ], closure_custom_output => $self->can('custom_app_state_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{global} = [ { label => 'running', nlabel => 'instances.running.count', set => { key_values => [ { name => 'running' } ], output_template => 'Running : %d', perfdatas => [ { label => 'running', template => '%d', min => 0 } ] } }, { label => 'stopped', nlabel => 'instances.stopped.count', set => { key_values => [ { name => 'stopped' } ], output_template => 'Stopped : %d', perfdatas => [ { label => 'stopped', template => '%d', min => 0 } ] } }, { label => 'crashed', nlabel => 'instances.crashed.count', set => { key_values => [ { name => 'crashed' } ], output_template => 'Crashed : %d', perfdatas => [ { label => 'crashed', template => '%d', min => 0 } ] } } ]; $self->{maps_counters}->{instances} = [ { label => 'instance-state', type => 2, critical_default => '%{state} !~ /RUNNING/i', set => { key_values => [ { name => 'state' }, { name => 'id' } ], closure_custom_output => $self->can('custom_inst_state_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => $self->can('custom_inst_state_threshold'), } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'app-guid:s' => { name => 'app_guid' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{app_guid}) || $self->{option_results}->{app_guid} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify app-guid option."); $self->{output}->option_exit(); } } sub manage_selection { my ($self, %options) = @_; my $app = $options{custom}->get_object(url_path => '/apps/' . $self->{option_results}->{app_guid}); $self->{app}->{name} = $app->{entity}->{name}; $self->{app}->{state} = $app->{entity}->{state}; if ($self->{app}->{state} =~ /^STARTED$/) { $self->{global}->{running} = 0; $self->{global}->{stopped} = 0; $self->{global}->{crashed} = 0; my $instances = $options{custom}->get_object(url_path => '/apps/' . $self->{option_results}->{app_guid} . '/stats'); foreach my $instance (keys %{$instances}) { $self->{instances}->{$instance} = { id => $instance, state => $instances->{$instance}->{state}, }; $self->{global}->{lc($instances->{$instance}->{state})}++; } } } 1; __END__ =head1 MODE Check Cloud Foundry app state and instances usage. =over 8 =item B<--app-guid> App guid to look for. =item B<--warning-app-state> Threshold warning for app state. =item B<--critical-app-state> Threshold critical for app state (Default: '%{state} !~ /STARTED/i'). =item B<--warning-instance-state> Threshold warning for instances state. =item B<--critical-instance-state> Threshold critical for instances state (Default: '%{state} !~ /RUNNING/i'). =item B<--warning-*> Threshold warning for instances count based on state (Can be: 'running', 'stopped', 'crashed') =item B<--critical-*> Threshold critical for instances count based on state (Can be: 'running', 'stopped', 'crashed'). =back =cut centreon-plugins-20220113/cloud/cloudfoundry/restapi/mode/listapps.pm000066400000000000000000000131361417000230700256530ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::cloudfoundry::restapi::mode::listapps; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "filter-space:s" => { name => 'filter_space' }, "filter-organization:s" => { name => 'filter_organization' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; my %orgs; my %spaces; my $result = $options{custom}->get_object(url_path => '/apps'); foreach my $app (@{$result}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $app->{entity}->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $app->{entity}->{name} . "': no matching filter name.", debug => 1); next; } next if ($app->{entity}->{space_url} !~ /^\/v2(.*)/); my $space_url = $1; if (!defined($spaces{$space_url})) { my $space = $options{custom}->get_object(url_path => $space_url); $spaces{$space_url}->{name} = $space->{entity}->{name}; $spaces{$space_url}->{organization_url} = $space->{entity}->{organization_url}; } if (defined($self->{option_results}->{filter_space}) && $self->{option_results}->{filter_space} ne '' && $spaces{$space_url}->{name} !~ /$self->{option_results}->{filter_space}/) { $self->{output}->output_add(long_msg => "skipping space '" . $spaces{$space_url}->{name} . "': no matching filter name.", debug => 1); next; } next if ($spaces{$space_url}->{organization_url} !~ /^\/v2(.*)/); my $organization_url = $1; if (!defined($orgs{$organization_url})) { my $org = $options{custom}->get_object(url_path => $organization_url); $orgs{$organization_url}->{name} = $org->{entity}->{name}; } if (defined($self->{option_results}->{filter_organization}) && $self->{option_results}->{filter_organization} ne '' && $orgs{$organization_url}->{name} !~ /$self->{option_results}->{filter_organization}/) { $self->{output}->output_add(long_msg => "skipping organization '" . $orgs{$organization_url}->{name} . "': no matching filter name.", debug => 1); next; } $self->{apps}->{$app->{metadata}->{guid}} = { name => $app->{entity}->{name}, state => $app->{entity}->{state}, space => $spaces{$space_url}->{name}, organization => $orgs{$organization_url}->{name}, }; } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $app (sort keys %{$self->{apps}}) { $self->{output}->output_add(long_msg => sprintf("[guid = %s] [name = %s] [state = %s] [space = %s] [organization = %s]", $app, $self->{apps}->{$app}->{name}, $self->{apps}->{$app}->{state}, $self->{apps}->{$app}->{space}, $self->{apps}->{$app}->{organization})); } $self->{output}->output_add(severity => 'OK', short_msg => 'List apps:'); $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 => ['guid', 'name', 'state', 'space', 'organization']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $app (sort keys %{$self->{apps}}) { $self->{output}->add_disco_entry( guid => $app, name => $self->{apps}->{$app}->{name}, state => $self->{apps}->{$app}->{state}, space => $self->{apps}->{$app}->{space}, organization => $self->{apps}->{$app}->{organization}, ); } } 1; __END__ =head1 MODE List apps. =over 8 =item B<--filter-name> Filter apps name (can be a regexp). =item B<--filter-space> Filter spaces name (can be a regexp). =item B<--filter-organization> Filter organizations name (can be a regexp). =back =cut centreon-plugins-20220113/cloud/cloudfoundry/restapi/mode/listorganizations.pm000066400000000000000000000070531417000230700276000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::cloudfoundry::restapi::mode::listorganizations; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->get_object(url_path => '/organizations'); foreach my $organization (@{$result}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $organization->{entity}->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping organization '" . $organization->{entity}->{name} . "': no matching filter name.", debug => 1); next; } $self->{organizations}->{$organization->{metadata}->{guid}} = { name => $organization->{entity}->{name}, status => $organization->{entity}->{status}, }; } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $organization (sort keys %{$self->{organizations}}) { $self->{output}->output_add(long_msg => sprintf("[guid = %s] [name = %s] [status = %s]", $organization, $self->{organizations}->{$organization}->{name}, $self->{organizations}->{$organization}->{status})); } $self->{output}->output_add(severity => 'OK', short_msg => 'List organizations:'); $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 => ['guid', 'name', 'status']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $organization (sort keys %{$self->{organizations}}) { $self->{output}->add_disco_entry( guid => $organization, name => $self->{organizations}->{$organization}->{name}, status => $self->{organizations}->{$organization}->{status}, ); } } 1; __END__ =head1 MODE List organizations. =over 8 =item B<--filter-name> Filter organizations name (can be a regexp). =back =cut centreon-plugins-20220113/cloud/cloudfoundry/restapi/mode/listspaces.pm000066400000000000000000000104721417000230700261660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::cloudfoundry::restapi::mode::listspaces; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "filter-organization:s" => { name => 'filter_organization' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; my %orgs; my $result = $options{custom}->get_object(url_path => '/spaces'); foreach my $space (@{$result}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $space->{entity}->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping space '" . $space->{entity}->{name} . "': no matching filter name.", debug => 1); next; } next if ($space->{entity}->{organization_url} !~ /^\/v2(.*)/); my $organization_url = $1; if (!defined($orgs{$organization_url})) { my $org = $options{custom}->get_object(url_path => $organization_url); $orgs{$organization_url}->{name} = $org->{entity}->{name}; } if (defined($self->{option_results}->{filter_organization}) && $self->{option_results}->{filter_organization} ne '' && $orgs{$organization_url}->{name} !~ /$self->{option_results}->{filter_organization}/) { $self->{output}->output_add(long_msg => "skipping organization '" . $orgs{$organization_url}->{name} . "': no matching filter name.", debug => 1); next; } $self->{spaces}->{$space->{metadata}->{guid}} = { name => $space->{entity}->{name}, organization => $orgs{$organization_url}->{name}, }; } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $space (sort keys %{$self->{spaces}}) { $self->{output}->output_add(long_msg => sprintf("[guid = %s] [name = %s] [organization = %s]", $space, $self->{spaces}->{$space}->{name}, $self->{spaces}->{$space}->{organization})); } $self->{output}->output_add(severity => 'OK', short_msg => 'List spaces:'); $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 => ['guid', 'name', 'organization']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $space (sort keys %{$self->{spaces}}) { $self->{output}->add_disco_entry( guid => $space, name => $self->{spaces}->{$space}->{name}, organization => $self->{spaces}->{$space}->{organization}, ); } } 1; __END__ =head1 MODE List spaces. =over 8 =item B<--filter-name> Filter spaces name (can be a regexp). =item B<--filter-organization> Filter organizations name (can be a regexp). =back =cut centreon-plugins-20220113/cloud/cloudfoundry/restapi/plugin.pm000066400000000000000000000032351417000230700243650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::cloudfoundry::restapi::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} = '1.0'; $self->{modes} = { 'apps-state' => 'cloud::cloudfoundry::restapi::mode::appsstate', 'instances-state' => 'cloud::cloudfoundry::restapi::mode::instancesstate', 'list-apps' => 'cloud::cloudfoundry::restapi::mode::listapps', 'list-organizations' => 'cloud::cloudfoundry::restapi::mode::listorganizations', 'list-spaces' => 'cloud::cloudfoundry::restapi::mode::listspaces' }; $self->{custom_modes}->{restapi} = 'cloud::cloudfoundry::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Cloud Foundry using API. =cut centreon-plugins-20220113/cloud/docker/000077500000000000000000000000001417000230700176115ustar00rootroot00000000000000centreon-plugins-20220113/cloud/docker/restapi/000077500000000000000000000000001417000230700212605ustar00rootroot00000000000000centreon-plugins-20220113/cloud/docker/restapi/custom/000077500000000000000000000000001417000230700225725ustar00rootroot00000000000000centreon-plugins-20220113/cloud/docker/restapi/custom/api.pm000066400000000000000000000404771417000230700237150ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::docker::restapi::custom::api; use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::http; use JSON::XS; use FileHandle; 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 => { 'hostname:s@' => { name => 'hostname' }, 'port:s' => { name => 'port', default => 8080 }, 'proto:s' => { name => 'proto' }, 'credentials' => { name => 'credentials' }, 'basic' => { name => 'basic' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'timeout:s' => { name => 'timeout', default => 10 }, 'cert-file:s' => { name => 'cert_file' }, 'key-file:s' => { name => 'key_file' }, 'cacert-file:s' => { name => 'cacert_file' }, 'cert-pwd:s' => { name => 'cert_pwd' }, 'cert-pkcs12' => { name => 'cert_pkcs12' }, 'api-display' => { name => 'api_display' }, 'api-write-file:s' => { name => 'api_write_file' }, 'api-read-file:s' => { name => 'api_read_file' }, 'reload-cache-time:s' => { name => 'reload_cache_time', default => 300 } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{http} = centreon::plugins::http->new(%options); $self->{output} = $options{output}; return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : undef; return 0 if (defined($self->{option_results}->{api_read_file}) && $self->{option_results}->{api_read_file} ne ''); if (!defined($self->{hostname})) { $self->{output}->add_option_msg(short_msg => "Need to specify hostname option."); $self->{output}->option_exit(); } $self->{node_names} = []; foreach my $node_name (@{$self->{hostname}}) { if ($node_name ne '') { push @{$self->{node_names}}, $node_name; } } $self->{http}->set_options(%{$self->{option_results}}); return 0; } sub api_display { my ($self, %options) = @_; if (defined($self->{option_results}->{api_display})) { if (!defined($self->{option_results}->{api_write_file}) || $self->{option_results}->{api_write_file} eq '') { $self->{output}->output_add( severity => 'OK', short_msg => $options{content} ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } if (!open (FH, '>', $self->{option_results}->{api_write_file})) { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => "cannot open file '" . $self->{option_results}->{api_write_file} . "': $!" ); } FH->autoflush(1); print FH $options{content}; close FH; $self->{output}->output_add( severity => 'OK', short_msg => "Data written in file '" . $self->{option_results}->{api_write_file} . "': $!" ); $self->{output}->exit(); } } sub api_read_file { my ($self, %options) = @_; my $file_content = do { local $/ = undef; if (!open my $fh, "<", $self->{option_results}->{api_read_file}) { $self->{output}->add_option_msg(short_msg => "Could not open file $self->{option_results}->{api_read_file} : $!"); $self->{output}->option_exit(); } <$fh>; }; my $content; eval { $content = JSON::XS->new->utf8->decode($file_content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } return $content; } sub get_hostnames { my ($self, %options) = @_; return $self->{hostname}; } sub get_port { my ($self, %options) = @_; return $self->{option_results}->{port}; } sub internal_get_by_id{ my ($self, %options) = @_; foreach my $obj (@{$options{list}}) { if ($obj->{ID} eq $options{Id}) { return $obj; } } return undef; } sub cache_containers { my ($self, %options) = @_; my $has_cache_file = $options{statefile}->read(statefile => 'cache_docker_containers_' . join(':', @{$self->{hostname}}) . '_' . $self->{option_results}->{port}); my $timestamp_cache = $options{statefile}->get(name => 'last_timestamp'); my $containers = $options{statefile}->get(name => 'containers'); if ($has_cache_file == 0 || !defined($timestamp_cache) || ((time() - $timestamp_cache) > (($options{reload_cache_time})))) { $containers = {}; my $datas = { last_timestamp => time(), containers => $containers }; foreach my $node_name (@{$self->{node_names}}) { my $list_containers = $self->internal_api_list_containers(node_name => $node_name); foreach my $container (@$list_containers) { $containers->{$container->{Id}} = { State => $container->{State}, NodeName => $node_name, Name => join(':', @{$container->{Names}}), }; } } $options{statefile}->write(data => $containers); } return $containers; } sub internal_api_list_nodes { my ($self, %options) = @_; my $response = $self->{http}->request( hostname => $options{node_name}, url_path => '/nodes', unknown_status => '', critical_status => '', warning_status => '' ); my $nodes; eval { $nodes = JSON::XS->new->utf8->decode($response); }; if ($@) { $nodes = []; $self->{output}->output_add( severity => 'UNKNOWN', short_msg => "Node '$options{node_name}': cannot decode json list nodes response: $@" ); } else { $nodes = [] if (ref($nodes) eq 'HASH'); # nodes is not in a swarm } return $nodes; } sub internal_api_info { my ($self, %options) = @_; my $response = $self->{http}->request( hostname => $options{node_name}, url_path => '/info', unknown_status => '', critical_status => '', warning_status => '' ); my $nodes; eval { $nodes = JSON::XS->new->utf8->decode($response); }; if ($@) { $nodes = []; $self->{output}->output_add( severity => 'UNKNOWN', short_msg => "Node '$options{node_name}': cannot decode json info response: $@" ); } return $nodes; } sub internal_api_list_containers { my ($self, %options) = @_; my $response = $self->{http}->request( hostname => $options{node_name}, url_path => '/containers/json?all=true', unknown_status => '', critical_status => '', warning_status => '' ); my $containers; eval { $containers = JSON::XS->new->utf8->decode($response); }; if ($@) { $containers = []; $self->{output}->output_add( severity => 'UNKNOWN', short_msg => "Node '$options{node_name}': cannot decode json get containers response: $@" ); } return $containers; } sub internal_api_get_container_stats { my ($self, %options) = @_; my $response = $self->{http}->request( hostname => $options{node_name}, url_path => '/containers/' . $options{container_id} . '/stats?stream=false', unknown_status => '', critical_status => '', warning_status => '' ); my $container_stats; eval { $container_stats = JSON::XS->new->utf8->decode($response); }; if ($@) { $container_stats = {}; $self->{output}->output_add( severity => 'UNKNOWN', short_msg => "Node '$options{node_name}': cannot decode json get container stats response: $@" ); } return $container_stats; } sub internal_api_list_services { my ($self, %options) = @_; my $response = $self->{http}->request( hostname => $options{node_name}, url_path => '/services', unknown_status => '', critical_status => '', warning_status => ''); my $services; eval { $services = JSON::XS->new->utf8->decode($response); }; if ($@) { $services = []; $self->{output}->output_add( severity => 'UNKNOWN', short_msg => "Service '$options{node_name}': cannot decode json list services response: $@" ); } return $services; } sub internal_api_list_tasks { my ($self, %options) = @_; my $response = $self->{http}->request( hostname => $options{node_name}, url_path => '/tasks', unknown_status => '', critical_status => '', warning_status => '' ); my $tasks; eval { $tasks = JSON::XS->new->utf8->decode($response); }; if ($@) { $tasks = []; $self->{output}->output_add( severity => 'UNKNOWN', short_msg => "Task '$options{node_name}': cannot decode json list services response: $@" ); } return $tasks; } sub api_list_services { my ($self, %options) = @_; my $services = {}; foreach my $node_name (@{$self->{node_names}}) { # 406 or 503 - node is not part of a swarm my $list_tasks = $self->internal_api_list_tasks(node_name => $node_name); next if ($self->{http}->get_code() == 406 || $self->{http}->get_code() == 503); my $list_services = $self->internal_api_list_services(node_name => $node_name); foreach my $task (@$list_tasks) { $services->{ $task->{ServiceID} } = {} if (!defined($services->{ $task->{ServiceID} })); my $service = $self->internal_get_by_id(list => $list_services, Id => $task->{ServiceID}); $services->{ $task->{ServiceID} }->{ $task->{ID} } = { node_id => $task->{NodeID}, node_name => $node_name, service_name => $service->{Spec}->{Name}, container_id => $task->{Status}->{ContainerStatus}->{ContainerID}, desired_state => defined($task->{DesiredState}) && $task->{DesiredState} ne '' ? $task->{DesiredState} : '-', state => defined($task->{Status}->{State}) && $task->{Status}->{State} ne '' ? $task->{Status}->{State} : '-', state_message => defined($task->{Status}->{Message}) && $task->{Status}->{Message} ne '' ? $task->{Status}->{Message} : '-' }; } } return $services; } sub api_list_containers { my ($self, %options) = @_; my $containers = {}; foreach my $node_name (@{$self->{node_names}}) { my $list_containers = $self->internal_api_list_containers(node_name => $node_name); foreach my $container (@$list_containers) { $containers->{$container->{Id}} = { State => $container->{State}, NodeName => $node_name, Name => join(':', @{$container->{Names}}), }; } } return $containers; } sub api_list_nodes { my ($self, %options) = @_; my $nodes = {}; foreach my $node_name (@{$self->{node_names}}) { my $info_node = $self->internal_api_info(node_name => $node_name); my $list_nodes = $self->internal_api_list_nodes(node_name => $node_name); $nodes->{$node_name} = { nodes => [], containers_running => $info_node->{ContainersRunning}, containers_stopped => $info_node->{ContainersStopped}, containers_paused => $info_node->{ContainersPaused}, }; foreach my $node (@$list_nodes) { push @{$nodes->{$node_name}->{nodes}}, { Status => $node->{Status}->{State}, ManagerStatus => $node->{ManagerStatus}->{Reachability}, Addr => $node->{Status}->{Addr} }; } } return $nodes; } sub api_get_containers { my ($self, %options) = @_; if (defined($self->{option_results}->{api_read_file}) && $self->{option_results}->{api_read_file} ne '') { return $self->api_read_file(); } my $content_total = $self->cache_containers(statefile => $options{statefile}); if (defined($options{container_id}) && $options{container_id} ne '') { if (defined($content_total->{$options{container_id}})) { $content_total->{$options{container_id}}->{Stats} = $self->internal_api_get_container_stats(node_name => $content_total->{$options{container_id}}->{NodeName}, container_id => $options{container_id}); } } elsif (defined($options{container_name}) && $options{container_name} ne '') { my $container_id; foreach (keys %$content_total) { if ($content_total->{$_}->{Name} eq $options{container_name}) { $container_id = $_; last; } } if (defined($container_id)) { $content_total->{$container_id}->{Stats} = $self->internal_api_get_container_stats(node_name => $content_total->{$container_id}->{NodeName}, container_id => $container_id); } } else { foreach my $container_id (keys %{$content_total}) { $content_total->{$container_id}->{Stats} = $self->internal_api_get_container_stats(node_name => $content_total->{$container_id}->{NodeName}, container_id => $container_id); } } $self->api_display(); return $content_total; } 1; __END__ =head1 NAME Docker REST API =head1 SYNOPSIS Docker Rest API custom mode =head1 REST API OPTIONS =over 8 =item B<--hostname> IP Addr/FQDN of the docker node (can be multiple). =item B<--port> Port used (Default: 8080) =item B<--proto> Specify https if needed (Default: 'http') =item B<--credentials> Specify this option if you access server-status page with authentication =item B<--username> Specify username for authentication (Mandatory if --credentials is specified) =item B<--password> Specify password for authentication (Mandatory if --credentials is specified) =item B<--basic> Specify this option if you access server-status page over basic authentication and don't want a '401 UNAUTHORIZED' error to be logged on your webserver. Specify this option if you access server-status page over hidden basic authentication or you'll get a '404 NOT FOUND' error. (Use with --credentials) =item B<--timeout> Threshold for HTTP timeout (Default: 10) =item B<--cert-file> Specify certificate to send to the webserver =item B<--key-file> Specify key to send to the webserver =item B<--cacert-file> Specify root certificate to send to the webserver =item B<--cert-pwd> Specify certificate's password =item B<--cert-pkcs12> Specify type of certificate (PKCS12) =item B<--api-display> Print json api. =item B<--api-write-display> Print json api in a file (to be used with --api-display). =item B<--api-read-file> Read API from file. =item B<--reload-cache-time> Time in seconds before reloading list containers cache (default: 300) =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/cloud/docker/restapi/mode/000077500000000000000000000000001417000230700222045ustar00rootroot00000000000000centreon-plugins-20220113/cloud/docker/restapi/mode/containerusage.pm000066400000000000000000000343431417000230700255600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::docker::restapi::mode::containerusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return 'state : ' . $self->{result_values}->{state}; } sub custom_cpu_calc { my ($self, %options) = @_; my $delta_cpu_total = $options{new_datas}->{$self->{instance} . '_cpu_total_usage'} - $options{old_datas}->{$self->{instance} . '_cpu_total_usage'}; my $delta_cpu_system = $options{new_datas}->{$self->{instance} . '_cpu_system_usage'} - $options{old_datas}->{$self->{instance} . '_cpu_system_usage'}; # container is not running return -10 if ($options{new_datas}->{$self->{instance} . '_cpu_system_usage'} == 0); if ($delta_cpu_system == 0) { $self->{result_values}->{prct_cpu} = 0; } else { $self->{result_values}->{prct_cpu} = (($delta_cpu_total / $delta_cpu_system) * $options{new_datas}->{$self->{instance} . '_cpu_number'}) * 100; } $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub custom_memory_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => 'memory_used', nlabel => 'container.memory.usage.bytes', unit => 'B', instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, value => $self->{result_values}->{used}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), min => 0, max => $self->{result_values}->{total} ); } sub custom_memory_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check( value => $self->{result_values}->{prct_used}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_memory_output { my ($self, %options) = @_; my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); return sprintf( "Memory Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", $total_size_value . " " . $total_size_unit, $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}, $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free} ); } sub custom_memory_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_memory_total'}; $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_memory_usage'}; # container is not running return -10 if ($self->{result_values}->{used} == 0); $self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used}; $self->{result_values}->{prct_free} = $self->{result_values}->{free} * 100 / $self->{result_values}->{total}; $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'containers', type => 1, cb_prefix_output => 'prefix_containers_output', message_multiple => 'All containers are ok', skipped_code => { -10 => 1, -11 => 1 } }, { name => 'containers_traffic', type => 1, cb_prefix_output => 'prefix_containers_traffic_output', message_multiple => 'All container traffics are ok', skipped_code => { -11 => 1 } } ]; $self->{maps_counters}->{containers} = [ { label => 'container-status', type => 2, set => { key_values => [ { name => 'state' }, { name => 'name' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'cpu', nlabel => 'container.cpu.utilization.percentage', set => { key_values => [ { name => 'cpu_total_usage', diff => 1 }, { name => 'cpu_system_usage', diff => 1 }, { name => 'cpu_number' }, { name => 'display' } ], output_template => 'CPU Usage : %.2f %%', closure_custom_calc => $self->can('custom_cpu_calc'), output_use => 'prct_cpu', threshold_use => 'prct_cpu', perfdatas => [ { label => 'cpu', value => 'prct_cpu', template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'memory', nlabel => 'container.memory.usage.bytes', set => { key_values => [ { name => 'memory_usage' }, { name => 'memory_total' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_memory_calc'), closure_custom_output => $self->can('custom_memory_output'), closure_custom_perfdata => $self->can('custom_memory_perfdata'), closure_custom_threshold_check => $self->can('custom_memory_threshold') } }, { label => 'read-iops', nlabel => 'container.disk.io.read.usage.iops', set => { key_values => [ { name => 'read_io', per_second => 1 }, { name => 'display' } ], output_template => 'Read IOPs : %.2f', output_error_template => "Read IOPs : %s", perfdatas => [ { label => 'read_iops', template => '%.2f', unit => 'iops', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'write-iops', nlabel => 'container.disk.io.write.usage.iops', set => { key_values => [ { name => 'write_io', per_second => 1 }, { name => 'display' } ], output_template => 'Write IOPs : %.2f', output_error_template => "Write IOPs : %s", perfdatas => [ { label => 'write_iops', template => '%.2f', unit => 'iops', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } } ]; $self->{maps_counters}->{containers_traffic} = [ { label => 'traffic-in', nlabel => 'container.traffic.in.bitspersecond', set => { key_values => [ { name => 'traffic_in', per_second => 1 }, { name => 'display' } ], output_change_bytes => 2, output_template => 'Traffic In : %s %s/s', perfdatas => [ { label => 'traffic_in', template => '%.2f', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'traffic-out', nlabel => 'container.traffic.out.bitspersecond', set => { key_values => [ { name => 'traffic_out', per_second => 1 }, { name => 'display' } ], output_change_bytes => 2, output_template => 'Traffic Out : %s %s/s', perfdatas => [ { label => 'traffic_out', template => '%.2f', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'container-id:s' => { name => 'container_id' }, 'container-name:s' => { name => 'container_name' }, 'filter-name:s' => { name => 'filter_name' }, 'use-name' => { name => 'use_name' } }); $self->{statefile_cache_containers} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{statefile_cache_containers}->check_options(%options); } sub prefix_containers_traffic_output { my ($self, %options) = @_; return "Container '" . $options{instance_value}->{display} . "' "; } sub prefix_containers_output { my ($self, %options) = @_; return "Container '" . $options{instance_value}->{display} . "' "; } sub manage_selection { my ($self, %options) = @_; $self->{containers} = {}; $self->{containers_traffic} = {}; my $result = $options{custom}->api_get_containers(container_id => $self->{option_results}->{container_id}, container_name => $self->{option_results}->{container_name}, statefile => $self->{statefile_cache_containers}); foreach my $container_id (keys %{$result}) { next if (!defined($result->{$container_id}->{Stats})); my $name = $result->{$container_id}->{Name}; 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; } my $read_io = $result->{$container_id}->{Stats}->{blkio_stats}->{io_service_bytes_recursive}->[0]->{value}; my $write_io = $result->{$container_id}->{Stats}->{blkio_stats}->{io_service_bytes_recursive}->[1]->{value}; $self->{containers}->{$container_id} = { display => defined($self->{option_results}->{use_name}) ? $name : $container_id, name => $name, state => $result->{$container_id}->{State}, read_io => $read_io, write_io => $write_io, cpu_total_usage => $result->{$container_id}->{Stats}->{cpu_stats}->{cpu_usage}->{total_usage}, cpu_system_usage => $result->{$container_id}->{Stats}->{cpu_stats}->{system_cpu_usage}, cpu_number => defined($result->{$container_id}->{Stats}->{cpu_stats}->{cpu_usage}->{percpu_usage}) ? scalar(@{$result->{$container_id}->{Stats}->{cpu_stats}->{cpu_usage}->{percpu_usage}}) : 1, memory_usage => $result->{$container_id}->{Stats}->{memory_stats}->{usage}, memory_total => $result->{$container_id}->{Stats}->{memory_stats}->{limit} }; foreach my $interface (keys %{$result->{$container_id}->{Stats}->{networks}}) { my $name = defined($self->{option_results}->{use_name}) ? $name : $container_id; $name .= '.' . $interface; $self->{containers_traffic}->{$name} = { display => $name, traffic_in => $result->{$container_id}->{Stats}->{networks}->{$interface}->{rx_bytes} * 8, traffic_out => $result->{$container_id}->{Stats}->{networks}->{$interface}->{tx_bytes} * 8, }; } } if (scalar(keys %{$self->{containers}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No container found."); $self->{output}->option_exit(); } my $hostnames = $options{custom}->get_hostnames(); $self->{cache_name} = "docker_" . $self->{mode} . '_' . join('_', @$hostnames) . '_' . $options{custom}->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')) . '_' . (defined($self->{option_results}->{container_id}) ? md5_hex($self->{option_results}->{container_id}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{container_name}) ? md5_hex($self->{option_results}->{container_name}) : md5_hex('all')); } 1; __END__ =head1 MODE Check container usage. =over 8 =item B<--container-id> Exact container ID. =item B<--container-name> Exact container name (if multiple names: names separated by ':'). =item B<--use-name> Use docker name for perfdata and display. =item B<--filter-name> Filter by container name (can be a regexp). =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^container-status$' =item B<--warning-*> Threshold warning. Can be: 'read-iops', 'write-iops', 'traffic-in', 'traffic-out', 'cpu' (%), 'memory' (%). =item B<--critical-*> Threshold critical. Can be: 'read-iops', 'write-iops', 'traffic-in', 'traffic-out', 'cpu' (%), 'memory' (%). =item B<--warning-container-status> Set warning threshold for status (Default: -) Can used special variables like: %{name}, %{state}. =item B<--critical-container-status> Set critical threshold for status (Default: -). Can used special variables like: %{name}, %{state}. =back =cut centreon-plugins-20220113/cloud/docker/restapi/mode/listcontainers.pm000066400000000000000000000053161417000230700256100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::docker::restapi::mode::listcontainers; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{containers} = $options{custom}->api_list_containers(); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $container_id (sort keys %{$self->{containers}}) { $self->{output}->output_add(long_msg => '[id = ' . $container_id . "] [name = '" . $self->{containers}->{$container_id}->{Name} . "']" . " [node = '" . $self->{containers}->{$container_id}->{NodeName} . "']" . " [state = '" . $self->{containers}->{$container_id}->{State} . "']" ); } $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 => ['id', 'name', 'node', 'state']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $container_id (sort keys %{$self->{containers}}) { $self->{output}->add_disco_entry(name => $self->{containers}->{$container_id}->{Name}, node => $self->{containers}->{$container_id}->{NodeName}, state => $self->{containers}->{$container_id}->{State}, id => $container_id, ); } } 1; __END__ =head1 MODE List containers. =over 8 =back =cut centreon-plugins-20220113/cloud/docker/restapi/mode/nodestatus.pm000066400000000000000000000130711417000230700247350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::docker::restapi::mode::nodestatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return 'status : ' . $self->{result_values}->{status} . ' [manager status: ' . $self->{result_values}->{manager_status} . ']'; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'node', type => 1, cb_prefix_output => 'prefix_node_output', message_multiple => 'All node informations are ok', skipped_code => { -11 => 1 } }, { name => 'nodes', type => 1, cb_prefix_output => 'prefix_node_output', message_multiple => 'All node status are ok', skipped_code => { -11 => 1 } } ]; $self->{maps_counters}->{nodes} = [ { label => 'node-status', type => 2, critical_default => '%{status} !~ /ready/ || %{manager_status} !~ /reachable|-/', set => { key_values => [ { name => 'status' }, { name => 'manager_status' }, { name => 'display' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{node} = [ { label => 'containers-running', nlabel => 'node.containers.running.count', set => { key_values => [ { name => 'containers_running' }, { name => 'display' } ], output_template => 'Containers Running : %s', perfdatas => [ { label => 'containers_running', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'containers-stopped', nlabel => 'node.containers.stopped.count', set => { key_values => [ { name => 'containers_stopped' }, { name => 'display' } ], output_template => 'Containers Stopped : %s', perfdatas => [ { label => 'containers_stopped', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'containers-paused', nlabel => 'node.containers.paused.count', set => { key_values => [ { name => 'containers_paused' }, { name => 'display' } ], output_template => 'Containers Paused : %s', perfdatas => [ { label => 'containers_paused', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub prefix_node_output { my ($self, %options) = @_; return "Node '" . $options{instance_value}->{display} . "' "; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->api_list_nodes(); $self->{node} = {}; $self->{nodes} = {}; foreach my $node_name (keys %{$result}) { $self->{node}->{$node_name} = { display => $node_name, containers_running => $result->{$node_name}->{containers_running}, containers_stopped => $result->{$node_name}->{containers_stopped}, containers_paused => $result->{$node_name}->{containers_paused}, }; foreach my $entry (@{$result->{$node_name}->{nodes}}) { my $name = $node_name . '/' . $entry->{Addr}; $self->{nodes}->{$name} = { display => $name , status => $entry->{Status}, manager_status => defined($entry->{ManagerStatus}) ? $entry->{ManagerStatus} : '-', }; } } if (scalar(keys %{$self->{node}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No node found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check node status. =over 8 =item B<--warning-node-status> Set warning threshold for status (Default: -) Can used special variables like: %{display}, %{status}, %{manager_status}. =item B<--critical-node-status> Set critical threshold for status (Default: '%{status} !~ /ready/ || %{manager_status} !~ /reachable|-/'). Can used special variables like: %{display}, %{status}, %{manager_status}. =item B<--warning-*> Threshold warning. Can be: 'containers-running', 'containers-paused', 'containers-stopped'. =item B<--critical-*> Threshold critical. Can be: 'containers-running', 'containers-paused', 'containers-stopped'., =back =cut centreon-plugins-20220113/cloud/docker/restapi/mode/servicestatus.pm000066400000000000000000000140231417000230700254460ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::docker::restapi::mode::servicestatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; return sprintf( 'state: %s [node: %s (%s)] [container: %s] [desired state: %s] [message: %s]', $self->{result_values}->{state}, $self->{result_values}->{node_name}, $self->{result_values}->{node_id}, $self->{result_values}->{container_id}, $self->{result_values}->{desired_state}, $self->{result_values}->{state_message} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'services', type => 2, message_multiple => 'All services running well', format_output => '%s services not in desired stated', display_counter_problem => { nlabel => 'services.tasks.problems.count', min => 0 }, group => [ { name => 'service', cb_prefix_output => 'prefix_service_output', skipped_code => { -11 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'tasks-total', nlabel => 'services.tasks.total.count', set => { key_values => [ { name => 'total' } ], output_template => 'total tasks of services: %s', perfdatas => [ { template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{service} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'service_name' }, { name => 'task_id' }, { name => 'node_name' }, { name => 'node_id' }, { name => 'desired_state' }, { name => 'state_message' }, { name => 'service_id' }, { name => 'container_id' }, { name => 'state' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold, } }, ]; } sub prefix_service_output { my ($self, %options) = @_; return "service '" . $options{instance_value}->{service_name} . "' task '" . $options{instance_value}->{task_id} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $self->{version} = '1.0'; $options{options}->add_options(arguments => { 'filter-service-name:s' => { name => 'filter_service_name' }, 'unknown-status:s' => { name => 'unknown_status', default => '' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{desired_state} ne %{state} and %{state} !~ /complete|preparing|assigned/' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => [ 'warning_status', 'critical_status', 'unknown_status', ]); } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->api_list_services(); $self->{global} = { total => 0 }; $self->{services}->{global} = { service => {} }; foreach my $service_id (keys %$results) { foreach my $task_id (keys %{$results->{$service_id}}) { if (defined($self->{option_results}->{filter_service_name}) && $self->{option_results}->{filter_service_name} ne '' && $results->{$service_id}->{$task_id}->{service_name} !~ /$self->{option_results}->{filter_service_name}/) { $self->{output}->output_add(long_msg => "skipping service '" . $results->{$service_id}->{$task_id}->{service_name} . "': no matching filter type.", debug => 1); next; } $self->{services}->{global}->{service}->{ $task_id } = { service_id => $service_id, task_id => $task_id, %{$results->{$service_id}->{$task_id}} }; $self->{global}->{total}++; } } } 1; __END__ =head1 MODE Check service status. =over 8 =item B<--filter-service-name> Filter service by service name (can be a regexp). =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{service_id}, %{task_id}, %{service_name}, %{node_name}, %{node_id}, %{desired_state}, %{state_message}, %{container_id}. =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{service_id}, %{task_id}, %{service_name}, %{node_name}, %{node_id}, %{desired_state}, %{state_message}, %{container_id}. =item B<--critical-status> Set critical threshold for status (Default: '%{desired_state} ne %{state} and %{state} !~ /complete|preparing|assigned/'). Can used special variables like: %{service_id}, %{task_id}, %{service_name}, %{node_name}, %{node_id}, %{desired_state}, %{state_message}, %{container_id}. =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'tasks-total'. =back =cut centreon-plugins-20220113/cloud/docker/restapi/plugin.pm000066400000000000000000000032331417000230700231150ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::docker::restapi::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.3'; $self->{modes} = { 'container-usage' => 'cloud::docker::restapi::mode::containerusage', 'list-containers' => 'cloud::docker::restapi::mode::listcontainers', 'node-status' => 'cloud::docker::restapi::mode::nodestatus', 'service-status' => 'cloud::docker::restapi::mode::servicestatus' }; $self->{custom_modes}->{api} = 'cloud::docker::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Docker and containers through its HTTPS Remote API (https://docs.docker.com/reference/api/docker_remote_api/). Requirements: Docker 1.12.0+ and Docker API 1.24+ =cut centreon-plugins-20220113/cloud/google/000077500000000000000000000000001417000230700176165ustar00rootroot00000000000000centreon-plugins-20220113/cloud/google/gcp/000077500000000000000000000000001417000230700203675ustar00rootroot00000000000000centreon-plugins-20220113/cloud/google/gcp/cloudsql/000077500000000000000000000000001417000230700222155ustar00rootroot00000000000000centreon-plugins-20220113/cloud/google/gcp/cloudsql/common/000077500000000000000000000000001417000230700235055ustar00rootroot00000000000000centreon-plugins-20220113/cloud/google/gcp/cloudsql/common/mode/000077500000000000000000000000001417000230700244315ustar00rootroot00000000000000centreon-plugins-20220113/cloud/google/gcp/cloudsql/common/mode/cpu.pm000066400000000000000000000103301417000230700255530ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::google::gcp::cloudsql::common::mode::cpu; use base qw(cloud::google::gcp::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'database/cpu/utilization' => { output_string => 'cpu utilization: %.2f', perfdata => { absolute => { nlabel => 'database.cpu.utilization.percentage', min => 0, max => 100, unit => '%', format => '%.2f' } }, threshold => 'utilization', calc => '* 100', order => 1 }, 'database/cpu/reserved_cores' => { output_string => 'cpu reserved cores: %.2f', perfdata => { absolute => { nlabel => 'database.cpu.reserved_cores.count', format => '%.2f' } }, threshold => 'cores-reserved', order => 2 } }; return $metrics_mapping; } 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 => { 'dimension-name:s' => { name => 'dimension_name', default => 'resource.labels.database_id' }, 'dimension-operator:s' => { name => 'dimension_operator', default => 'equals' }, 'dimension-value:s' => { name => 'dimension_value' }, 'filter-metric:s' => { name => 'filter_metric' }, 'timeframe:s' => { name => 'timeframe' }, 'aggregation:s@' => { name => 'aggregation' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{gcp_api} = 'cloudsql.googleapis.com'; $self->{gcp_dimension_name} = (!defined($self->{option_results}->{dimension_name}) || $self->{option_results}->{dimension_name} eq '') ? 'resource.labels.database_id' : $self->{option_results}->{dimension_name}; $self->{gcp_dimension_zeroed} = 'resource.labels.database_id'; $self->{gcp_instance_key} = 'resource.labels.database_id'; $self->{gcp_dimension_operator} = $self->{option_results}->{dimension_operator}; $self->{gcp_dimension_value} = $self->{option_results}->{dimension_value}; } 1; __END__ =head1 MODE Check database CPU metrics. Example: perl centreon_plugins.pl --plugin=cloud::google::gcp::cloudsql::mysql::plugin --mode=cpu --dimension-value=mydatabaseid --filter-metric='utilization' --aggregation='average' --critical-cpu-utilization-average='10' --verbose Default aggregation: 'average' / All aggregations are valid. =over 8 =item B<--dimension-name> Set dimension name (Default: 'resource.labels.database_id'). Can be: 'resources.labels.region'. =item B<--dimension-operator> Set dimension operator (Default: 'equals'. Can also be: 'regexp', 'starts'). =item B<--dimension-value> Set dimension value (Required). =item B<--filter-metric> Filter metrics (Can be: 'database/cpu/utilization', 'database/cpu/reserved_cores') (Can be a regexp). =item B<--timeframe> Set timeframe in seconds (i.e. 3600 to check last hour). =item B<--aggregation> Set monitor aggregation (Can be multiple, Can be: 'minimum', 'maximum', 'average', 'total'). =item B<--warning-*> B<--critical-*> Thresholds (Can be: 'utilization', 'cores-reserved'). =back =cut centreon-plugins-20220113/cloud/google/gcp/cloudsql/common/mode/network.pm000066400000000000000000000126201417000230700264610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::google::gcp::cloudsql::common::mode::network; use base qw(cloud::google::gcp::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'database/network/connections' => { output_string => 'connections: %.2f', perfdata => { absolute => { nlabel => 'database.network.connections.count', format => '%.2f', min => 0 } }, threshold => 'connections', order => 1 }, 'database/network/received_bytes_count' => { output_string => 'received: %.2f', perfdata => { absolute => { nlabel => 'database.network.received.volume.bytes', format => '%.2f', min => 0, unit => 'B', change_bytes => 1 }, per_second => { nlabel => 'database.network.received.volume.bytespersecond', format => '%.2f', min => 0, unit => 'B/s', change_bytes => 1 } }, threshold => 'received-volume', order => 2 }, 'database/network/sent_bytes_count' => { output_string => 'sent: %.2f', perfdata => { absolute => { nlabel => 'database.network.sent.volume.bytes', format => '%.2f', min => 0, unit => 'B', change_bytes => 1 }, per_second => { nlabel => 'database.network.sent.volume.bytespersecond', format => '%.2f', min => 0, unit => 'B/s', change_bytes => 1 } }, threshold => 'sent-volume', order => 3 } }; return $metrics_mapping; } 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 => { 'dimension-name:s' => { name => 'dimension_name', default => 'resource.labels.database_id' }, 'dimension-operator:s' => { name => 'dimension_operator', default => 'equals' }, 'dimension-value:s' => { name => 'dimension_value' }, 'filter-metric:s' => { name => 'filter_metric' }, "per-second" => { name => 'per_second' }, 'timeframe:s' => { name => 'timeframe' }, 'aggregation:s@' => { name => 'aggregation' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{gcp_api} = 'cloudsql.googleapis.com'; $self->{gcp_dimension_name} = (!defined($self->{option_results}->{dimension_name}) || $self->{option_results}->{dimension_name} eq '') ? 'resource.labels.database_id' : $self->{option_results}->{dimension_name}; $self->{gcp_dimension_zeroed} = 'resource.labels.database_id'; $self->{gcp_instance_key} = 'resource.labels.database_id'; $self->{gcp_dimension_operator} = $self->{option_results}->{dimension_operator}; $self->{gcp_dimension_value} = $self->{option_results}->{dimension_value}; } 1; __END__ =head1 MODE Check database instances network metrics. Example: perl centreon_plugins.pl --plugin=cloud::google::gcp::cloudsql::mysql::plugin --mode=network --dimension-value=mydatabaseid --filter-metric='bytes' --aggregation='average' --critical-received-volume='10' --verbose Default aggregation: 'average' / All aggregations are valid. =over 8 =item B<--dimension-name> Set dimension name (Default: 'resource.labels.database_id'). Can be: 'resources.labels.region'. =item B<--dimension-operator> Set dimension operator (Default: 'equals'. Can also be: 'regexp', 'starts'). =item B<--dimension-value> Set dimension value (Required). =item B<--filter-metric> Filter metrics (Can be: 'database/network/received_bytes_count', 'database/network/sent_bytes_count', 'database/network/connections') (Can be a regexp). =item B<--timeframe> Set timeframe in seconds (i.e. 3600 to check last hour). =item B<--aggregation> Set monitor aggregation (Can be multiple, Can be: 'minimum', 'maximum', 'average', 'total'). =item B<--warning-*> B<--critical-*> Thresholds (Can be: 'received-volume', 'sent-volume', 'connections'). =item B<--per-second> Change the data to be unit/sec. =back =cut centreon-plugins-20220113/cloud/google/gcp/cloudsql/common/mode/storage.pm000066400000000000000000000117701417000230700264410ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::google::gcp::cloudsql::common::mode::storage; use base qw(cloud::google::gcp::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'database/disk/bytes_used' => { output_string => 'disk space usage: %.2f', perfdata => { absolute => { nlabel => 'database.space.usage.bytes', format => '%d', unit => 'B', change_bytes => 1 } }, threshold => 'space-usage', order => 1 }, 'database/disk/read_ops_count' => { output_string => 'disk read IO operations: %.2f', perfdata => { absolute => { nlabel => 'database.disk.read.io.operations.count', format => '%.2f' }, per_second => { nlabel => 'database.disk.read.io.operations.persecond', format => '%.2f' } }, threshold => 'read-operations', order => 2 }, 'database/disk/write_ops_count' => { output_string => 'disk write IO operations: %.2f', perfdata => { absolute => { nlabel => 'database.disk.write.io.operations.count', format => '%.2f' }, per_second => { nlabel => 'database.disk.write.io.operations.persecond', format => '%.2f' } }, threshold => 'write-operations', order => 3 } }; return $metrics_mapping; } 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 => { 'dimension-name:s' => { name => 'dimension_name', default => 'resource.labels.database_id' }, 'dimension-operator:s' => { name => 'dimension_operator', default => 'equals' }, 'dimension-value:s' => { name => 'dimension_value' }, 'filter-metric:s' => { name => 'filter_metric' }, "per-second" => { name => 'per_second' }, 'timeframe:s' => { name => 'timeframe' }, 'aggregation:s@' => { name => 'aggregation' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{gcp_api} = 'cloudsql.googleapis.com'; $self->{gcp_dimension_name} = (!defined($self->{option_results}->{dimension_name}) || $self->{option_results}->{dimension_name} eq '') ? 'resource.labels.database_id' : $self->{option_results}->{dimension_name}; $self->{gcp_dimension_zeroed} = 'resource.labels.database_id'; $self->{gcp_instance_key} = 'resource.labels.database_id'; $self->{gcp_dimension_operator} = $self->{option_results}->{dimension_operator}; $self->{gcp_dimension_value} = $self->{option_results}->{dimension_value}; } 1; __END__ =head1 MODE Check database storage metrics. Example: perl centreon_plugins.pl --plugin=cloud::google::gcp::cloudsql::mysql::plugin --mode=diskio --dimension-value=mydatabaseid --filter-metric='space' --aggregation='average' --verbose Default aggregation: 'average' / All aggregations are valid. =over 8 =item B<--dimension-name> Set dimension name (Default: 'resource.labels.database_id'). Can be: 'resources.labels.region'. =item B<--dimension-operator> Set dimension operator (Default: 'equals'. Can also be: 'regexp', 'starts'). =item B<--dimension-value> Set dimension value (Required). =item B<--filter-metric> Filter metrics (Can be: 'database/disk/bytes_used', 'database/disk/read_ops_count', 'databse/disk/write_ops_count') (Can be a regexp). =item B<--timeframe> Set timeframe in seconds (i.e. 3600 to check last hour). =item B<--aggregation> Set monitor aggregation (Can be multiple, Can be: 'minimum', 'maximum', 'average', 'total'). =item B<--warning-*> B<--critical-*> Thresholds (Can be: 'space-usage', 'read-operations', 'write-operations'). =item B<--per-second> Change the data to be unit/sec. =back =cut centreon-plugins-20220113/cloud/google/gcp/cloudsql/mysql/000077500000000000000000000000001417000230700233625ustar00rootroot00000000000000centreon-plugins-20220113/cloud/google/gcp/cloudsql/mysql/mode/000077500000000000000000000000001417000230700243065ustar00rootroot00000000000000centreon-plugins-20220113/cloud/google/gcp/cloudsql/mysql/mode/discovery.pm000066400000000000000000000061461417000230700266620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::google::gcp::cloudsql::mysql::mode::discovery; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'prettify' => { name => 'prettify' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my $disco_data; my $disco_stats; $disco_stats->{start_time} = time(); my $instances = $options{custom}->gcp_list_cloudsql_instances(); foreach my $instance (@$instances) { next if ($instance->{databaseVersion} !~ /mysql/i); my $item = {}; $item->{name} = $instance->{name}; $item->{database_id} = $instance->{project} . ':' . $instance->{name}; $item->{project} = $instance->{project}; $item->{version} = $instance->{databaseVersion}; $item->{state} = $instance->{state}; $item->{region} = $instance->{region}; $item->{tier} = $instance->{settings}->{tier}; $item->{instance_type} = $instance->{settings}->{instance_type}; $item->{ip_addresses} = []; foreach (@{$instance->{ipAddresses}}) { push @{$item->{ip_addresses}}, { ip_address => $_->{ipAddress}, type => $_->{type} }; } push @$disco_data, $item; } $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; $disco_stats->{discovered_items} = scalar(@$disco_data); $disco_stats->{results} = $disco_data; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE MySQL instance discovery. =over 8 =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/google/gcp/cloudsql/mysql/mode/innodb.pm000066400000000000000000000137031417000230700261210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::google::gcp::cloudsql::mysql::mode::innodb; use base qw(cloud::google::gcp::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'database/mysql/innodb_data_fsyncs' => { output_string => 'fsync calls: %.2f', perfdata => { absolute => { nlabel => 'database.mysql.innodb.data_fsyncs.count', format => '%.2f', min => 0 }, per_second => { nlabel => 'database.mysql.innodb.data_fsyncs.persecond', format => '%.2f', min => 0 } }, threshold => 'fsyncs-calls', order => 1 }, 'database/mysql/innodb_os_log_fsyncs' => { output_string => 'fsync calls to the log file: %.2f', perfdata => { absolute => { nlabel => 'database.mysql.innodb.os_log_fsyncs.count', format => '%.2f', min => 0 }, per_second => { nlabel => 'database.mysql.innodb.os_log_fsyncs.persecond', format => '%.2f', min => 0 } }, threshold => 'fsync-calls-logfile', order => 2 }, 'database/mysql/innodb_pages_read' => { output_string => 'pages read: %.2f', perfdata => { absolute => { nlabel => 'database.mysql.innodb.pages_read.count', format => '%.2f', min => 0 }, per_second => { nlabel => 'database.mysql.innodb.pages_read.persecond', format => '%.2f', min => 0 } }, threshold => 'pages-read', order => 3 }, 'database/mysql/innodb_pages_written' => { output_string => 'pages written: %.2f', perfdata => { absolute => { nlabel => 'database.mysql.innodb.pages_written.count', format => '%.2f', min => 0 }, per_second => { nlabel => 'database.mysql.innodb.pages_written.persecond', format => '%.2f', min => 0 } }, threshold => 'pages-written', order => 4 } }; return $metrics_mapping; } 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 => { 'dimension-name:s' => { name => 'dimension_name', default => 'resource.labels.database_id' }, 'dimension-operator:s' => { name => 'dimension_operator', default => 'equals' }, 'dimension-value:s' => { name => 'dimension_value' }, 'filter-metric:s' => { name => 'filter_metric' }, "per-second" => { name => 'per_second' }, 'timeframe:s' => { name => 'timeframe' }, 'aggregation:s@' => { name => 'aggregation' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{gcp_api} = 'cloudsql.googleapis.com'; $self->{gcp_dimension_name} = (!defined($self->{option_results}->{dimension_name}) || $self->{option_results}->{dimension_name} eq '') ? 'resource.labels.database_id' : $self->{option_results}->{dimension_name}; $self->{gcp_dimension_zeroed} = 'resource.labels.database_id'; $self->{gcp_instance_key} = 'resource.labels.database_id'; $self->{gcp_dimension_operator} = $self->{option_results}->{dimension_operator}; $self->{gcp_dimension_value} = $self->{option_results}->{dimension_value}; } 1; __END__ =head1 MODE Check mysql innodb metrics. Example: perl centreon_plugins.pl --plugin=cloud::google::gcp::cloudsql::mysql::plugin --mode=diskio --dimension-value=mydatabaseid --filter-metric='queries' --aggregation='average' --verbose Default aggregation: 'average' / All aggregations are valid. =over 8 =item B<--dimension-name> Set dimension name (Default: 'resource.labels.database_id'). Can be: 'resources.labels.region'. =item B<--dimension-operator> Set dimension operator (Default: 'equals'. Can also be: 'regexp', 'starts'). =item B<--dimension-value> Set dimension value (Required). =item B<--filter-metric> Filter metrics (Can be: 'database/mysql/innodb_data_fsyncs', 'database/mysql/innodb_os_log_fsyncs', 'database/mysql/innodb_pages_read', 'database/mysql/innodb_pages_write') (Can be a regexp). =item B<--timeframe> Set timeframe in seconds (i.e. 3600 to check last hour). =item B<--aggregation> Set monitor aggregation (Can be multiple, Can be: 'minimum', 'maximum', 'average', 'total'). =item B<--warning-*> B<--critical-*> Thresholds (Can be: 'fsyncs-calls', 'fsync-calls-logfile', 'pages-read', 'pages-written'). =item B<--per-second> Change the data to be unit/sec. =back =cut centreon-plugins-20220113/cloud/google/gcp/cloudsql/mysql/mode/queries.pm000066400000000000000000000110421417000230700263170ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::google::gcp::cloudsql::mysql::mode::queries; use base qw(cloud::google::gcp::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'database/mysql/questions' => { output_string => 'questions: %.2f', perfdata => { absolute => { nlabel => 'database.mysql.questions.count', format => '%.2f', min => 0 }, per_second => { nlabel => 'database.mysql.questions.persecond', format => '%.2f', min => 0 } }, threshold => 'questions', order => 1 }, 'database/mysql/queries' => { output_string => 'queries: %.2f', perfdata => { absolute => { nlabel => 'database.mysql.queries.count', format => '%.2f', min => 0 }, per_second => { nlabel => 'database.mysql.queries.persecond', format => '%.2f', min => 0 } }, threshold => 'queries', order => 2 } }; return $metrics_mapping; } 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 => { 'dimension-name:s' => { name => 'dimension_name', default => 'resource.labels.database_id' }, 'dimension-operator:s' => { name => 'dimension_operator', default => 'equals' }, 'dimension-value:s' => { name => 'dimension_value' }, 'filter-metric:s' => { name => 'filter_metric' }, "per-second" => { name => 'per_second' }, 'timeframe:s' => { name => 'timeframe' }, 'aggregation:s@' => { name => 'aggregation' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{gcp_api} = 'cloudsql.googleapis.com'; $self->{gcp_dimension_name} = (!defined($self->{option_results}->{dimension_name}) || $self->{option_results}->{dimension_name} eq '') ? 'resource.labels.database_id' : $self->{option_results}->{dimension_name}; $self->{gcp_dimension_zeroed} = 'resource.labels.database_id'; $self->{gcp_instance_key} = 'resource.labels.database_id'; $self->{gcp_dimension_operator} = $self->{option_results}->{dimension_operator}; $self->{gcp_dimension_value} = $self->{option_results}->{dimension_value}; } 1; __END__ =head1 MODE Check mysql queries metrics. Example: perl centreon_plugins.pl --plugin=cloud::google::gcp::cloudsql::mysql::plugin --mode=diskio --dimension-value=mydatabaseid --filter-metric='queries' --aggregation='average' --verbose Default aggregation: 'average' / All aggregations are valid. =over 8 =item B<--dimension-name> Set dimension name (Default: 'resource.labels.database_id'). Can be: 'resources.labels.region'. =item B<--dimension-operator> Set dimension operator (Default: 'equals'. Can also be: 'regexp', 'starts'). =item B<--dimension-value> Set dimension value (Required). =item B<--filter-metric> Filter metrics (Can be: 'database/mysql/questions', 'database/mysql/queries') (Can be a regexp). =item B<--timeframe> Set timeframe in seconds (i.e. 3600 to check last hour). =item B<--aggregation> Set monitor aggregation (Can be multiple, Can be: 'minimum', 'maximum', 'average', 'total'). =item B<--warning-*> B<--critical-*> Thresholds (Can be: 'queries', 'questions'). =item B<--per-second> Change the data to be unit/sec. =back =cut centreon-plugins-20220113/cloud/google/gcp/cloudsql/mysql/plugin.pm000066400000000000000000000032651417000230700252240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::google::gcp::cloudsql::mysql::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} = { 'cpu' => 'cloud::google::gcp::cloudsql::common::mode::cpu', 'discovery' => 'cloud::google::gcp::cloudsql::mysql::mode::discovery', 'innodb' => 'cloud::google::gcp::cloudsql::mysql::mode::innodb', 'network' => 'cloud::google::gcp::cloudsql::common::mode::network', 'queries' => 'cloud::google::gcp::cloudsql::mysql::mode::queries', 'storage' => 'cloud::google::gcp::cloudsql::common::mode::storage' }; $self->{custom_modes}->{api} = 'cloud::google::gcp::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Google CloudSQL MySQL. =cut centreon-plugins-20220113/cloud/google/gcp/compute/000077500000000000000000000000001417000230700220435ustar00rootroot00000000000000centreon-plugins-20220113/cloud/google/gcp/compute/computeengine/000077500000000000000000000000001417000230700247055ustar00rootroot00000000000000centreon-plugins-20220113/cloud/google/gcp/compute/computeengine/mode/000077500000000000000000000000001417000230700256315ustar00rootroot00000000000000centreon-plugins-20220113/cloud/google/gcp/compute/computeengine/mode/cpu.pm000066400000000000000000000103401417000230700267540ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::google::gcp::compute::computeengine::mode::cpu; use base qw(cloud::google::gcp::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'instance/cpu/utilization' => { output_string => 'cpu utilization: %.2f', perfdata => { absolute => { nlabel => 'computeengine.cpu.utilization.percentage', min => 0, max => 100, unit => '%', format => '%.2f' } }, threshold => 'utilization', calc => '* 100', order => 1 }, 'instance/cpu/reserved_cores' => { output_string => 'cpu reserved cores: %.2f', perfdata => { absolute => { nlabel => 'computeengine.cpu.reserved_cores.count', format => '%.2f' } }, threshold => 'cores-reserved', order => 2 } }; return $metrics_mapping; } 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 => { 'dimension-name:s' => { name => 'dimension_name', default => 'metric.labels.instance_name' }, 'dimension-operator:s' => { name => 'dimension_operator', default => 'equals' }, 'dimension-value:s' => { name => 'dimension_value' }, 'filter-metric:s' => { name => 'filter_metric' }, 'timeframe:s' => { name => 'timeframe' }, 'aggregation:s@' => { name => 'aggregation' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{gcp_api} = 'compute.googleapis.com'; $self->{gcp_dimension_name} = (!defined($self->{option_results}->{dimension_name}) || $self->{option_results}->{dimension_name} eq '') ? 'metric.labels.instance_name' : $self->{option_results}->{dimension_name}; $self->{gcp_dimension_zeroed} = 'metric.labels.instance_name'; $self->{gcp_instance_key} = 'metric.labels.instance_name'; $self->{gcp_dimension_operator} = $self->{option_results}->{dimension_operator}; $self->{gcp_dimension_value} = $self->{option_results}->{dimension_value}; } 1; __END__ =head1 MODE Check Compute Engine instances CPU metrics. Example: perl centreon_plugins.pl --plugin=cloud::google::gcp::compute::computeengine::plugin --mode=cpu --dimension-value=mycomputeinstance --filter-metric='utilization' --aggregation='average' --critical-cpu-utilization-average='10' --verbose Default aggregation: 'average' / All aggregations are valid. =over 8 =item B<--dimension-name> Set dimension name (Default: 'metric.labels.instance_name'). =item B<--dimension-operator> Set dimension operator (Default: 'equals'. Can also be: 'regexp', 'starts'). =item B<--dimension-value> Set dimension value (Required). =item B<--filter-metric> Filter metrics (Can be: 'instance/cpu/utilization', 'instance/cpu/reserved_cores') (Can be a regexp). =item B<--timeframe> Set timeframe in seconds (i.e. 3600 to check last hour). =item B<--aggregation> Set monitor aggregation (Can be multiple, Can be: 'minimum', 'maximum', 'average', 'total'). =item B<--warning-*> B<--critical-*> Thresholds (Can be: 'utilization', 'cores-reserved'). =back =cut centreon-plugins-20220113/cloud/google/gcp/compute/computeengine/mode/discovery.pm000066400000000000000000000063501417000230700302020ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::google::gcp::compute::computeengine::mode::discovery; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'prettify' => { name => 'prettify' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my $disco_data; my $disco_stats; $disco_stats->{start_time} = time(); my $instances = $options{custom}->gcp_list_compute_engine_instances(); foreach my $instance (@$instances) { my $item = {}; $item->{id} = $instance->{id}; $item->{name} = $instance->{name}; $item->{description} = $instance->{description}; $item->{status} = $instance->{status}; $item->{cpu_platform} = $instance->{cpuPlatform}; if ($instance->{machineType} =~ /machineTypes\/(.*?)$/) { $item->{machine_type} = $1; } if ($instance->{zone} =~ /zones\/(.*?)$/) { $item->{zone} = $1; } $item->{network_interfaces} = []; foreach (@{$instance->{networkInterfaces}}) { push @{$item->{network_interfaces}}, { name => $_->{name}, ip => $_->{networkIP} }; } $item->{tags} = []; if (defined($instance->{tags}->{items})) { push @{$item->{tags}}, @{$instance->{tags}->{items}}; } push @$disco_data, $item; } $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; $disco_stats->{discovered_items} = scalar(@$disco_data); $disco_stats->{results} = $disco_data; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE Compute engine discovery. =over 8 =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/google/gcp/compute/computeengine/mode/diskio.pm000066400000000000000000000167351417000230700274650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::google::gcp::compute::computeengine::mode::diskio; use base qw(cloud::google::gcp::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'instance/disk/read_bytes_count' => { output_string => 'read: %.2f', perfdata => { absolute => { nlabel => 'computeengine.disk.read.volume.bytes', format => '%.2f', unit => 'B', change_bytes => 1 }, per_second => { nlabel => 'computeengine.disk.read.volume.bytespersecond', format => '%.2f', unit => 'B/s', change_bytes => 1 } }, threshold => 'read-volume', order => 1 }, 'instance/disk/throttled_read_bytes_count' => { output_string => 'throttled read: %.2f', perfdata => { absolute => { nlabel => 'computeengine.disk.throttled.read.volume.bytes', format => '%.2f', unit => 'B', change_bytes => 1 }, per_second => { nlabel => 'computeengine.disk.throttled.read.volume.bytespersecond', format => '%.2f', unit => 'B/s', change_bytes => 1 } }, threshold => 'throttled-read-volume', order => 2 }, 'instance/disk/write_bytes_count' => { output_string => 'write: %.2f', perfdata => { absolute => { nlabel => 'computeengine.disk.write.volume.bytes', format => '%.2f', unit => 'B', change_bytes => 1 }, per_second => { nlabel => 'computeengine.disk.write.volume.bytespersecond', format => '%.2f', unit => 'B/s', change_bytes => 1 } }, threshold => 'write-volume', order => 3 }, 'instance/disk/throttled_write_bytes_count' => { output_string => 'throttled write: %.2f', perfdata => { absolute => { nlabel => 'computeengine.disk.throttled.write.volume.bytes', format => '%.2f', unit => 'B', change_bytes => 1 }, per_second => { nlabel => 'computeengine.disk.throttled.write.volume.bytespersecond', format => '%.2f', unit => 'B/s', change_bytes => 1 } }, threshold => 'throttled-write-volume', order => 4 }, 'instance/disk/read_ops_count' => { output_string => 'read OPS: %.2f', perfdata => { absolute => { nlabel => 'computeengine.disk.read.ops.count', format => '%.2f' }, per_second => { nlabel => 'computeengine.disk.read.ops.persecond', format => '%.2f' } }, threshold => 'read-ops', order => 5 }, 'instance/disk/write_ops_count' => { output_string => 'write OPS: %.2f', perfdata => { absolute => { nlabel => 'computeengine.disk.write.ops.count', format => '%.2f' }, per_second => { nlabel => 'computeengine.disk.write.ops.persecond', format => '%.2f' } }, threshold => 'write-ops', order => 6 } }; return $metrics_mapping; } 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 => { 'dimension-name:s' => { name => 'dimension_name', default => 'metric.labels.instance_name' }, 'dimension-operator:s' => { name => 'dimension_operator', default => 'equals' }, 'dimension-value:s' => { name => 'dimension_value' }, 'filter-metric:s' => { name => 'filter_metric' }, "per-second" => { name => 'per_second' }, 'timeframe:s' => { name => 'timeframe' }, 'aggregation:s@' => { name => 'aggregation' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{gcp_api} = 'compute.googleapis.com'; $self->{gcp_dimension_name} = (!defined($self->{option_results}->{dimension_name}) || $self->{option_results}->{dimension_name} eq '') ? 'metric.labels.instance_name' : $self->{option_results}->{dimension_name}; $self->{gcp_dimension_zeroed} = 'metric.labels.instance_name'; $self->{gcp_instance_key} = 'metric.labels.instance_name'; $self->{gcp_dimension_operator} = $self->{option_results}->{dimension_operator}; $self->{gcp_dimension_value} = $self->{option_results}->{dimension_value}; } 1; __END__ =head1 MODE Check Compute Engine instances disk IO metrics. Example: perl centreon_plugins.pl --plugin=cloud::google::gcp::compute::computeengine::plugin --mode=diskio --dimension-value=mycomputeinstance --filter-metric='throttled' --aggregation='average' --critical-throttled-write-volume='10' --verbose Default aggregation: 'average' / All aggregations are valid. =over 8 =item B<--dimension-name> Set dimension name (Default: 'metric.labels.instance_name'). =item B<--dimension-operator> Set dimension operator (Default: 'equals'. Can also be: 'regexp', 'starts'). =item B<--dimension-value> Set dimension value (Required). =item B<--filter-metric> Filter metrics (Can be: 'instance/disk/read_bytes_count', 'instance/disk/throttled_read_bytes_count', 'instance/disk/write_bytes_count', 'instance/disk/throttled_write_bytes_count', 'instance/disk/read_ops_count', 'instance/disk/write_ops_count') (Can be a regexp). =item B<--timeframe> Set timeframe in seconds (i.e. 3600 to check last hour). =item B<--aggregation> Set monitor aggregation (Can be multiple, Can be: 'minimum', 'maximum', 'average', 'total'). =item B<--warning-*> B<--critical-*> Thresholds (Can be: 'read-volume', 'throttled-read-volume', 'write-volume', 'throttled-write-volume', 'read-ops', 'write-ops'). =item B<--per-second> Change the data to be unit/sec. =back =cut centreon-plugins-20220113/cloud/google/gcp/compute/computeengine/mode/network.pm000066400000000000000000000143211417000230700276610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::google::gcp::compute::computeengine::mode::network; use base qw(cloud::google::gcp::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'instance/network/received_bytes_count' => { output_string => 'received: %.2f', perfdata => { absolute => { nlabel => 'computeengine.network.received.volume.bytes', format => '%.2f', unit => 'B', change_bytes => 1 }, per_second => { nlabel => 'computeengine.network.received.volume.bytespersecond', format => '%.2f', unit => 'B/s', change_bytes => 1 } }, threshold => 'received-volume', order => 1 }, 'instance/network/sent_bytes_count' => { output_string => 'sent: %.2f', perfdata => { absolute => { nlabel => 'computeengine.network.sent.volume.bytes', format => '%.2f', unit => 'B', change_bytes => 1 }, per_second => { nlabel => 'computeengine.network.sent.volume.bytespersecond', format => '%.2f', unit => 'B/s', change_bytes => 1 } }, threshold => 'sent-volume', order => 2 }, 'instance/network/received_packets_count' => { output_string => 'received packets: %.2f', perfdata => { absolute => { nlabel => 'computeengine.network.received.packets.count', format => '%.2f', unit => 'packets' }, per_second => { nlabel => 'computeengine.network.received.packets.persecond', format => '%.2f', unit => 'packets/s' } }, threshold => 'received-packets', order => 3 }, 'instance/network/sent_packets_count' => { output_string => 'sent packets: %.2f', perfdata => { absolute => { nlabel => 'computeengine.network.sent.packets.count', format => '%.2f', unit => 'packets' }, per_second => { nlabel => 'computeengine.network.sent.packets.persecond', format => '%.2f', unit => 'packets/s' } }, threshold => 'sent-packets', order => 4 } }; return $metrics_mapping; } 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 => { 'dimension-name:s' => { name => 'dimension_name', default => 'metric.labels.instance_name' }, 'dimension-operator:s' => { name => 'dimension_operator', default => 'equals' }, 'dimension-value:s' => { name => 'dimension_value' }, 'filter-metric:s' => { name => 'filter_metric' }, "per-second" => { name => 'per_second' }, 'timeframe:s' => { name => 'timeframe' }, 'aggregation:s@' => { name => 'aggregation' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{gcp_api} = 'compute.googleapis.com'; $self->{gcp_dimension_name} = (!defined($self->{option_results}->{dimension_name}) || $self->{option_results}->{dimension_name} eq '') ? 'metric.labels.instance_name' : $self->{option_results}->{dimension_name}; $self->{gcp_dimension_zeroed} = 'metric.labels.instance_name'; $self->{gcp_instance_key} = 'metric.labels.instance_name'; $self->{gcp_dimension_operator} = $self->{option_results}->{dimension_operator}; $self->{gcp_dimension_value} = $self->{option_results}->{dimension_value}; } 1; __END__ =head1 MODE Check Compute Engine instances network metrics. Example: perl centreon_plugins.pl --plugin=cloud::google::gcp::compute::computeengine::plugin --mode=network --dimension-value=mycomputeinstance --filter-metric='bytes' --aggregation='average' --critical-received-volume='10' --verbose Default aggregation: 'average' / All aggregations are valid. =over 8 =item B<--dimension-name> Set dimension name (Default: 'metric.labels.instance_name'). =item B<--dimension-operator> Set dimension operator (Default: 'equals'. Can also be: 'regexp', 'starts'). =item B<--dimension-value> Set dimension value (Required). =item B<--filter-metric> Filter metrics (Can be: 'instance/network/received_bytes_count', 'instance/network/sent_bytes_count', 'instance/network/received_packets_count', 'instance/network/sent_packets_count') (Can be a regexp). =item B<--timeframe> Set timeframe in seconds (i.e. 3600 to check last hour). =item B<--aggregation> Set monitor aggregation (Can be multiple, Can be: 'minimum', 'maximum', 'average', 'total'). =item B<--warning-*> B<--critical-*> Thresholds (Can be: 'received-volume', 'sent-volume', 'received-packets', 'sent-packets'). =item B<--per-second> Change the data to be unit/sec. =back =cut centreon-plugins-20220113/cloud/google/gcp/compute/computeengine/plugin.pm000066400000000000000000000031121417000230700265360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::google::gcp::compute::computeengine::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} = { 'cpu' => 'cloud::google::gcp::compute::computeengine::mode::cpu', 'discovery' => 'cloud::google::gcp::compute::computeengine::mode::discovery', 'diskio' => 'cloud::google::gcp::compute::computeengine::mode::diskio', 'network' => 'cloud::google::gcp::compute::computeengine::mode::network' }; $self->{custom_modes}->{api} = 'cloud::google::gcp::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Google Cloud Platform Compute Engine. =cut centreon-plugins-20220113/cloud/google/gcp/custom/000077500000000000000000000000001417000230700217015ustar00rootroot00000000000000centreon-plugins-20220113/cloud/google/gcp/custom/api.pm000066400000000000000000000414221417000230700230130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::google::gcp::custom::api; use strict; use warnings; use DateTime; use centreon::plugins::http; use centreon::plugins::statefile; use JSON::XS; use Digest::MD5 qw(md5_hex); use JSON::WebToken; 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 => { 'key-file:s' => { name => 'key_file' }, 'authorization-endpoint:s' => { name => 'authorization_endpoint' }, 'monitoring-endpoint:s' => { name => 'monitoring_endpoint' }, 'scope-endpoint:s' => { name => 'scope_endpoint' }, 'zeroed' => { name => 'zeroed' }, 'timeout:s' => { name => 'timeout' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); $self->{cache} = centreon::plugins::statefile->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{key_file} = (defined($self->{option_results}->{key_file})) ? $self->{option_results}->{key_file} : undef; $self->{authorization_endpoint} = (defined($self->{option_results}->{authorization_endpoint})) ? $self->{option_results}->{authorization_endpoint} : 'https://www.googleapis.com/oauth2/v4/token'; $self->{monitoring_endpoint} = (defined($self->{option_results}->{monitoring_endpoint})) ? $self->{option_results}->{monitoring_endpoint} : 'https://monitoring.googleapis.com/v3'; $self->{scope_endpoint} = (defined($self->{option_results}->{scope_endpoint})) ? $self->{option_results}->{scope_endpoint} : 'https://www.googleapis.com/auth/cloud-platform'; if (!defined($self->{key_file}) || $self->{key_file} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --key-file option."); $self->{output}->option_exit(); } $self->{cache}->check_options(option_results => $self->{option_results}); return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{warning_status} = ''; $self->{option_results}->{critical_status} = ''; $self->{option_results}->{unknown_status} = ''; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->set_options(%{$self->{option_results}}); } sub get_access_token { my ($self, %options) = @_; my $has_cache_file = $options{statefile}->read(statefile => 'gcp_api_' . md5_hex($self->{key_file} . ':' . $self->{authorization_endpoint})); my $expires_on = $options{statefile}->get(name => 'expires_on'); my $access_token = $options{statefile}->get(name => 'access_token'); if ($has_cache_file == 0 || !defined($access_token) || (($expires_on - time()) < 10)) { local $/ = undef; if (!open(FILE, "<", $self->{key_file})) { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => sprintf("Cannot read file '%s': %s", $self->{key_file}, $!) ); $self->{output}->display(); $self->{output}->exit(); } my $key_file = ; close FILE; my $iat = time(); my $exp = $iat + 3600; my $decoded_key_file; eval { $decoded_key_file = JSON::XS->new->utf8->decode($key_file); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode key file"); $self->{output}->option_exit(); } my $jwt = JSON::WebToken->encode({ iss => $decoded_key_file->{client_email}, scope => $self->{scope_endpoint}, aud => $self->{authorization_endpoint}, exp => $exp, iat => $iat, }, $decoded_key_file->{private_key}, 'RS256'); my $content = $self->{http}->request( method => 'POST', full_url => $self->{authorization_endpoint}, hostname => '', post_param => [ 'grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer', 'assertion=' . $jwt ] ); if (!defined($content) || $content eq '') { $self->{output}->add_option_msg( short_msg => "Authorization endpoint API returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']" ); $self->{output}->option_exit(); } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->output_add(long_msg => $content, debug => 1); $self->{output}->add_option_msg( short_msg => "Cannot decode json response (add --debug option to display returned content)" ); $self->{output}->option_exit(); } if (defined($decoded->{error})) { $self->{output}->output_add(long_msg => "Error message : " . $decoded->{error_description}, debug => 1); $self->{output}->add_option_msg( short_msg => "Authorization endpoint API return error code '" . $decoded->{error} . "' (add --debug option for detailed message)" ); $self->{output}->option_exit(); } $access_token = $decoded->{access_token}; my $datas = { last_timestamp => time(), access_token => $decoded->{access_token}, expires_on => $exp }; $options{statefile}->write(data => $datas); } $self->{access_token} = $access_token; $self->{http}->add_header(key => 'Authorization', value => 'Bearer ' . $self->{access_token}); } sub get_project_id { my ($self, %options) = @_; local $/ = undef; if (!open(FILE, "<", $self->{key_file})) { $self->{output}->add_option_msg( short_msg => sprintf("Cannot read file '%s': %s", $self->{key_file}, $!) ); $self->{output}->option_exit(); } my $key_file = ; close FILE; my $decoded_key_file; eval { $decoded_key_file = JSON::XS->new->utf8->decode($key_file); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode key file"); $self->{output}->option_exit(); } return $decoded_key_file->{project_id}; } sub request_api { my ($self, %options) = @_; $self->settings(); if (!defined($self->{access_token})) { $self->get_access_token(statefile => $self->{cache}); } my $content = $self->{http}->request(%options); if (!defined($content) || $content eq '') { $self->{output}->add_option_msg( short_msg => "Monitoring endpoint API returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']" ); $self->{output}->option_exit(); } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->output_add(long_msg => $content, debug => 1); $self->{output}->add_option_msg( short_msg => "Cannot decode response (add --debug option to display returned content)" ); $self->{output}->option_exit(); } if (defined($decoded->{error})) { $self->{output}->output_add(long_msg => "Error message : " . $decoded->{error}->{message}, debug => 1); $self->{output}->add_option_msg( short_msg => "Monitoring endpoint API return error code '" . $decoded->{error}->{code} . "' (add --debug option for detailed message)" ); $self->{output}->option_exit(); } return $decoded; } sub gcp_get_metrics_set_url { my ($self, %options) = @_; my $filter_instance = $options{dimension_name}; if (defined($options{dimension_operator}) && $options{dimension_operator} eq 'starts') { $filter_instance .= ' = starts_with("' . $options{dimension_value} . '")'; } elsif (defined($options{dimension_operator}) && $options{dimension_operator} eq 'regexp') { $filter_instance .= ' = monitoring.regex.full_match("' . $options{dimension_value} . '")'; } else { $filter_instance .= ' = "' . $options{dimension_value} . '"'; } my $filter = 'metric.type = "' . $options{api} . '/' . $options{metric} . '" AND ' . $filter_instance; $filter .= ' AND ' . join(' AND ', @{$options{extra_filters}}) if (defined($options{extra_filters}) && $options{extra_filters} ne ''); my $get_param = [ 'filter=' . $filter, 'interval.startTime=' . $options{start_time}, 'interval.endTime=' . $options{end_time} ]; my $project_id = $self->get_project_id(); my $url = $self->{monitoring_endpoint} . '/projects/' . $project_id . '/timeSeries/'; return ($url, $get_param); } sub get_instance { my ($self, %options) = @_; my $timeserie = $options{timeserie}; foreach (@{$options{instance_key}}) { $timeserie = $timeserie->{$_}; } if (ref($timeserie) !~ /ARRAY|HASH/) { return $timeserie; } return undef; } sub gcp_get_metrics { my ($self, %options) = @_; my $start_time = DateTime->now->subtract(seconds => $options{timeframe})->iso8601() . '.000000Z'; my $end_time = DateTime->now->iso8601() . '.000000Z'; my ($url, $get_param) = $self->gcp_get_metrics_set_url(%options, start_time => $start_time, end_time => $end_time); my $response = $self->request_api( method => 'GET', full_url => $url, hostname => '', get_param => $get_param ); my %aggregations = map { $_ => 1 } @{$options{aggregations}}; my $instance_key = [split /\./, $options{instance_key}]; my $results = {}; foreach my $timeserie (@{$response->{timeSeries}}) { my $instance = $self->get_instance( timeserie => $timeserie, instance_key => $instance_key ); next if (!defined($instance)); my $metric_name = lc($timeserie->{metric}->{type}); $metric_name =~ s/$options{api}\///; if (!defined($results->{$instance})) { $results->{$instance} = {}; } my $metric_calc = { points => 0 }; foreach my $point (@{$timeserie->{points}}) { if (defined($point->{value})) { my $value = $point->{value}->{ lc($timeserie->{valueType}) . 'Value' }; if (defined($aggregations{average})) { $metric_calc->{average} = 0 if (!defined($metric_calc->{average})); $metric_calc->{average} += $value; $metric_calc->{points}++; } if (defined($aggregations{minimum})) { $metric_calc->{minimum} = $value if (!defined($metric_calc->{$metric_name}->{minimum}) || $value < $$metric_calc->{minimum}); } if (defined($aggregations{maximum})) { $metric_calc->{maximum} = $value if (!defined($metric_calc->{maximum}) || $value > $metric_calc->{maximum}); } if (defined($aggregations{total})) { $metric_calc->{total} = 0 if (!defined($metric_calc->{total})); $metric_calc->{total} += $value; $metric_calc->{points}++; } } } if (defined($metric_calc->{average})) { $metric_calc->{average} /= $metric_calc->{points}; } $results->{$instance}->{$metric_name} = $metric_calc; $results->{$instance}->{resource} = $timeserie->{resource}; $results->{$instance}->{labels} = $timeserie->{metric}->{labels}; } if (defined($self->{option_results}->{zeroed}) && (!defined($options{dimension_operator}) || $options{dimension_operator} eq '' || $options{dimension_operator} eq 'equals')) { if ($options{dimension_name} eq $options{dimension_zeroed} && !defined($results->{ $options{dimension_value} })) { $results->{ $options{dimension_value} } = { $options{metric} => { average => 0, minimum => 0, maximum => 0, total => 0 } }; } } return $results; } sub request_api_paginate { my ($self, %options) = @_; my $items = []; my $get_param = []; $get_param = $options{get_param} if (defined($options{get_param})); while (1) { my $response = $self->request_api( method => 'GET', full_url => $options{url}, hostname => '', get_param => $get_param ); last if (!defined($response->{items})); push @$items, @{$response->{items}}; last if (!defined($response->{nextPageToken})); $get_param = [@{$options{get_param}}, 'pageToken=' . $response->{nextPageToken}]; } return $items; } sub gcp_compute_engine_set_base_url { my ($self, %options) = @_; my $project_id = $self->get_project_id(); my $url = 'https://compute.googleapis.com/compute/v1/projects/' . $project_id; return $url; } sub gcp_list_compute_engine_zones { my ($self, %options) = @_; my $url = $self->gcp_compute_engine_set_base_url(); my $zones = $self->request_api_paginate( url => $url . '/zones' ); return $zones; } sub gcp_list_compute_engine_instances { my ($self, %options) = @_; my $results = []; my $url = $self->gcp_compute_engine_set_base_url(); my $zones = $self->gcp_list_compute_engine_zones(); foreach (@$zones) { my $instances = $self->request_api_paginate( url => $url . '/zones/' . $_->{name} . '/instances' ); push @$results, @$instances; } return $results; } sub gcp_cloudsql_set_base_url { my ($self, %options) = @_; my $project_id = $self->get_project_id(); my $url = 'https://sqladmin.googleapis.com/sql/v1beta4/projects/' . $project_id; return $url; } sub gcp_list_cloudsql_instances { my ($self, %options) = @_; my $url = $self->gcp_cloudsql_set_base_url(); my $instances = $self->request_api_paginate( url => $url . '/instances' ); return $instances; } sub gcp_list_storage_buckets { my ($self, %options) = @_; my $buckets = $self->request_api_paginate( url => 'https://storage.googleapis.com/storage/v1/b', get_param => ['project=' . $self->get_project_id()] ); return $buckets; } 1; __END__ =head1 NAME Google Cloud Platform Rest API =head1 REST API OPTIONS Google Cloud Platform Rest API To connect to the GCP Rest API, you need to create an API key. Follow the 'How-to guide' in https://cloud.google.com/video-intelligence/docs/common/auth =over 8 =item B<--key-file> Set GCP key file path. =item B<--authorization-endpoint> Set GCP authorization endpoint URL (Default: 'https://www.googleapis.com/oauth2/v4/token') =item B<--monitoring-endpoint> Set GCP monitoring endpoint URL (Default: 'https://monitoring.googleapis.com/v3') =item B<--scope-endpoint> Set GCP scope endpoint URL (Default: 'https://www.googleapis.com/auth/cloud-platform') =item B<--zeroed> Set metrics value to 0 if none. Usefull when Stackdriver does not return value when not defined. =item B<--timeout> Set timeout in seconds (Default: 10). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/cloud/google/gcp/custom/mode.pm000066400000000000000000000245301417000230700231670ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::google::gcp::custom::mode; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_output { my ($self, %options) = @_; return "Instance '" . $options{instance_value}->{display} . "' "; } sub prefix_aggregations_output { my ($self, %options) = @_; return "aggregation '" . $options{instance_value}->{display} . "' metrics "; } sub long_output { my ($self, %options) = @_; return "Checking '" . $options{instance_value}->{display} . "' "; } sub custom_calc { my ($self, %options) = @_; $self->{result_values}->{timeframe} = $options{new_datas}->{ $self->{instance} . '_timeframe' }; $self->{result_values}->{value}->{absolute} = $options{new_datas}->{ $self->{instance} . '_' . $options{extra_options}->{metric} }; $self->{result_values}->{value}->{absolute} = eval $self->{result_values}->{value}->{absolute} . $self->{instance_mode}->{metrics_mapping}->{$options{extra_options}->{metric}}->{calc} if (defined($self->{instance_mode}->{metrics_mapping}->{$options{extra_options}->{metric}}->{calc})); $self->{result_values}->{value}->{per_second} = $self->{result_values}->{value}->{absolute} / $self->{result_values}->{timeframe}; $self->{result_values}->{metric} = $options{extra_options}->{metric}; return 0; } sub custom_threshold { my ($self, %options) = @_; my $threshold = $self->{instance_mode}->{metrics_mapping}->{ $self->{result_values}->{metric} }->{threshold}; my $value = $self->{result_values}->{value}->{absolute}; if (defined($self->{instance_mode}->{option_results}->{per_second})) { $value = $self->{result_values}->{value}->{per_second}; } my $exit = $self->{perfdata}->threshold_check( value => $value, threshold => [ { label => 'critical-' . $threshold, exit_litteral => 'critical' }, { label => 'warning-' . $threshold, exit_litteral => 'warning' } ] ); return $exit; } sub custom_perfdata { my ($self, %options) = @_; my $threshold = $self->{instance_mode}->{metrics_mapping}->{ $self->{result_values}->{metric} }->{threshold}; my $options = $self->{instance_mode}->{metrics_mapping}->{ $self->{result_values}->{metric} }->{perfdata}->{absolute}; my $value = sprintf( $self->{instance_mode}->{metrics_mapping}->{ $self->{result_values}->{metric} }->{perfdata}->{absolute}->{format}, $self->{result_values}->{value}->{absolute} ); if (defined($self->{instance_mode}->{option_results}->{per_second}) && defined($self->{instance_mode}->{metrics_mapping}->{ $self->{result_values}->{metric} }->{perfdata}->{per_second})) { $value = sprintf( $self->{instance_mode}->{metrics_mapping}->{ $self->{result_values}->{metric} }->{perfdata}->{per_second}->{format}, $self->{result_values}->{value}->{per_second} ); $options = $self->{instance_mode}->{metrics_mapping}->{ $self->{result_values}->{metric} }->{perfdata}->{per_second}; } $self->{output}->perfdata_add( instances => $self->{instance}, value => $value, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $threshold), critical => $self->{perfdata}->get_perfdata_for_output( label => 'critical-' . $threshold), %{$options} ); } sub custom_output { my ($self, %options) = @_; my $unit = $self->{instance_mode}->{metrics_mapping}->{$self->{result_values}->{metric}}->{perfdata}->{absolute}->{unit}; my $output = $self->{instance_mode}->{metrics_mapping}->{$self->{result_values}->{metric}}->{output_string}; my $value = $self->{result_values}->{value}->{absolute}; if (defined($self->{instance_mode}->{metrics_mapping}->{$self->{result_values}->{metric}}->{perfdata}->{absolute}->{change_bytes})) { ($value, $unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{value}->{absolute}); } if (defined($self->{instance_mode}->{option_results}->{per_second}) && defined($self->{instance_mode}->{metrics_mapping}->{$self->{result_values}->{metric}}->{perfdata}->{per_second})) { $unit = $self->{instance_mode}->{metrics_mapping}->{$self->{result_values}->{metric}}->{perfdata}->{per_second}->{unit}; $value = $self->{result_values}->{value}->{per_second}; if (defined($self->{instance_mode}->{metrics_mapping}->{$self->{result_values}->{metric}}->{perfdata}->{per_second}->{change_bytes})) { ($value, $unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{value}->{per_second}); $unit .= "/s"; } } my $msg = sprintf($output, $value); $msg .= " " . $unit if (defined($unit) && $unit ne ""); return $msg; } sub set_counters { my ($self, %options) = @_; $self->{metrics_mapping} = $self->get_metrics_mapping(); $self->{maps_counters_type} = [ { type => 3, name => 'metrics', cb_prefix_output => 'prefix_output', cb_long_output => 'long_output', message_multiple => 'All metrics are ok', indent_long_output => ' ', group => [ { type => 1, name => 'aggregations', cb_prefix_output => 'prefix_aggregations_output', display_long => 1, message_multiple => 'all metrics are ok', skipped_code => { -10 => 1 } } ] } ]; foreach my $metric (sort { $self->{metrics_mapping}->{$a}->{order} <=> $self->{metrics_mapping}->{$b}->{order} } keys %{$self->{metrics_mapping}}) { my $entry = { label => $self->{metrics_mapping}->{$metric}->{threshold}, set => { key_values => [ { name => $metric }, { name => 'timeframe' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_calc'), closure_custom_calc_extra_options => { metric => $metric }, closure_custom_output => $self->can('custom_output'), closure_custom_perfdata => $self->can('custom_perfdata'), closure_custom_threshold_check => $self->can('custom_threshold') } }; push @{$self->{maps_counters}->{aggregations}}, $entry; } } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{dimension_value})) { $self->{output}->add_option_msg(short_msg => "Need to specify --dimension-value ."); $self->{output}->option_exit(); } $self->{gcp_timeframe} = (defined($self->{option_results}->{timeframe})) ? $self->{option_results}->{timeframe} : 900; my $aggregations = []; if (defined($self->{option_results}->{aggregation})) { foreach my $aggregation (@{$self->{option_results}->{aggregation}}) { if ($aggregation !~ /average|maximum|minimum|total/i) { $self->{output}->add_option_msg(short_msg => "Aggregation '" . $aggregation . "' is not handled"); $self->{output}->option_exit(); } push @$aggregations, $aggregation; } } $self->{gcp_aggregations} = ['average']; if (scalar(@$aggregations) > 0) { $self->{gcp_aggregations} = $aggregations; } foreach my $metric (keys %{$self->{metrics_mapping}}) { next if (defined($self->{option_results}->{filter_metric}) && $self->{option_results}->{filter_metric} ne '' && $metric !~ /$self->{option_results}->{filter_metric}/); push @{$self->{gcp_metrics}}, $metric; } } sub manage_selection { my ($self, %options) = @_; $self->{metrics} = {}; foreach my $metric (@{$self->{gcp_metrics}}) { my ($metric_results) = $options{custom}->gcp_get_metrics( dimension_name => $self->{gcp_dimension_name}, dimension_operator => $self->{gcp_dimension_operator}, dimension_value => $self->{gcp_dimension_value}, instance_key => $self->{gcp_instance_key}, metric => $metric, api => $self->{gcp_api}, aggregations => $self->{gcp_aggregations}, timeframe => $self->{gcp_timeframe}, dimension_zeroed => $self->{gcp_dimension_zeroed} ); foreach my $instance_name (keys %$metric_results) { foreach my $aggregation (@{$self->{gcp_aggregations}}) { if (!defined($self->{metrics}->{$instance_name})) { $self->{metrics}->{$instance_name} = { display => $instance_name, aggregations => {} }; } if (!defined($self->{metrics}->{$instance_name}->{aggregations}->{lc($aggregation)})) { $self->{metrics}->{$instance_name}->{aggregations}->{lc($aggregation)} = { display => $aggregation, timeframe => $self->{gcp_timeframe} }; } $self->{metrics}->{$instance_name}->{aggregations}->{lc($aggregation)}->{$metric} = defined($metric_results->{$instance_name}->{$metric}->{lc($aggregation)}) ? $metric_results->{$instance_name}->{$metric}->{lc($aggregation)} : 0 } } } if (scalar(keys %{$self->{metrics}}) <= 0) { $self->{output}->add_option_msg( short_msg => 'No metrics. Check your options or use --zeroed option to set 0 on undefined values' ); $self->{output}->option_exit(); } } 1; __END__ centreon-plugins-20220113/cloud/google/gcp/management/000077500000000000000000000000001417000230700225035ustar00rootroot00000000000000centreon-plugins-20220113/cloud/google/gcp/management/stackdriver/000077500000000000000000000000001417000230700250245ustar00rootroot00000000000000centreon-plugins-20220113/cloud/google/gcp/management/stackdriver/mode/000077500000000000000000000000001417000230700257505ustar00rootroot00000000000000centreon-plugins-20220113/cloud/google/gcp/management/stackdriver/mode/getmetrics.pm000066400000000000000000000204551417000230700304620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::google::gcp::management::stackdriver::mode::getmetrics; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_metric_perfdata { my ($self, %options) = @_; my $label = $self->{result_values}->{label}; $label =~ s/\//./g; $self->{output}->perfdata_add( nlabel => $label, instances => $self->{result_values}->{aggregation}, value => $self->{result_values}->{value}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-metric'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-metric') ); } sub custom_metric_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check( value => $self->{result_values}->{value}, threshold => [ { label => 'critical-metric', exit_litteral => 'critical' }, { label => 'warning-metric', exit_litteral => 'warning' } ] ); return $exit; } sub custom_metric_output { my ($self, %options) = @_; return "Metric '" . $self->{result_values}->{label} . "' of resource '" . $self->{result_values}->{display} . "' value is " . $self->{result_values}->{value}; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'metrics', type => 1, message_multiple => 'All metrics are ok' } ]; $self->{maps_counters}->{metrics} = [ { label => 'metric', set => { key_values => [ { name => 'label' }, { name => 'value' }, { name => 'aggregation' }, { name => 'display' } ], 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, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'dimension-name:s' => { name => 'dimension_name' }, 'dimension-operator:s' => { name => 'dimension_operator', default => 'equals' }, 'dimension-value:s' => { name => 'dimension_value' }, 'instance-key:s' => { name => 'instance_key' }, 'metric:s' => { name => 'metric' }, 'api:s' => { name => 'api' }, 'extra-filter:s@' => { name => 'extra_filter' }, 'timeframe:s' => { name => 'timeframe' }, 'aggregation:s@' => { name => 'aggregation' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{dimension_name}) || $self->{option_results}->{dimension_name} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --dimension-name ."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{dimension_value}) || $self->{option_results}->{dimension_value} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --dimension-value ."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{metric})) { $self->{output}->add_option_msg(short_msg => "Need to specify --metric ."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{api})) { $self->{output}->add_option_msg(short_msg => "Need to specify --api ."); $self->{output}->option_exit(); } $self->{gcp_dimension_name} = $self->{option_results}->{dimension_name}; $self->{gcp_dimension_operator} = $self->{option_results}->{dimension_operator}; $self->{gcp_dimension_value} = $self->{option_results}->{dimension_value}; $self->{gcp_instance_key} = defined($self->{option_results}->{instance_key}) && $self->{option_results}->{instance_key} ne '' ? $self->{option_results}->{instance_key} : $self->{option_results}->{dimension_name}; $self->{gcp_metric} = $self->{option_results}->{metric}; $self->{gcp_api} = $self->{option_results}->{api}; $self->{gcp_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 600; if (defined($self->{option_results}->{extra_filter})) { $self->{gcp_extra_filters} = []; foreach my $extra_filter (@{$self->{option_results}->{extra_filter}}) { if ($extra_filter ne '') { push @{$self->{gcp_extra_filters}}, $extra_filter; } } } my $aggregations = []; if (defined($self->{option_results}->{aggregation})) { foreach my $aggregation (@{$self->{option_results}->{aggregation}}) { if ($aggregation ne '') { push @$aggregations, lc($aggregation); } } } $self->{gcp_aggregations} = ['average']; if (scalar(@$aggregations) > 0) { $self->{gcp_aggregations} = $aggregations; } } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->gcp_get_metrics( dimension_name => $self->{gcp_dimension_name}, dimension_operator => $self->{gcp_dimension_operator}, dimension_value => $self->{gcp_dimension_value}, instance_key => $self->{gcp_instance_key}, metric => $self->{gcp_metric}, api => $self->{gcp_api}, extra_filters => $self->{gcp_extra_filters}, aggregations => $self->{gcp_aggregations}, timeframe => $self->{gcp_timeframe} ); $self->{metrics} = {}; foreach my $instance_name (keys %$results) { foreach my $label (keys %{$results->{$instance_name}}) { foreach my $aggregation (@{$self->{gcp_aggregations}}) { next if (!defined($results->{$instance_name}->{$label}->{$aggregation})); $self->{metrics}->{ $label . '_' . $aggregation } = { display => $instance_name, label => $label, aggregation => $aggregation, value => $results->{$instance_name}->{$label}->{$aggregation} }; } } } } 1; __END__ =head1 MODE Check GCP metrics. Example: perl centreon_plugins.pl --plugin=cloud::google::gcp::management::stackdriver::plugin --custommode=api --mode=get-metrics --api='compute.googleapis.com' --metric='instance/cpu/utilization' --dimension-name='metric.labels.instance_name' --dimension-operator=equals --dimension-value=mycomputeinstance --aggregation=average --timeframe=600 --warning-metric= --critical-metric= =over 8 =item B<--api> Set GCP API (Required). =item B<--metric> Set stackdriver metric (Required). =item B<--dimension-name> Set dimension name (Required). =item B<--dimension-operator> Set dimension operator (Default: 'equals'. Can also be: 'regexp', 'starts'). =item B<--dimension-value> Set dimension value (Required). =item B<--instance-key> Set instance key (By default, --dimension-name option is used). =item B<--timeframe> Set timeframe in seconds (i.e. 3600 to check last hour). =item B<--aggregation> Set monitor aggregation (Can be multiple, Can be: 'minimum', 'maximum', 'average', 'total'). =item B<--warning-metric> Threshold warning. =item B<--critical-metric> Threshold critical. =item B<--extra-filter> Set extra filters (Can be multiple). Example: --extra-filter='metric.labels.mylabel = "LABELBLEUE"' =back =cut centreon-plugins-20220113/cloud/google/gcp/management/stackdriver/plugin.pm000066400000000000000000000025751417000230700266710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::google::gcp::management::stackdriver::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} = '1.0'; $self->{modes} = { 'get-metrics' => 'cloud::google::gcp::management::stackdriver::mode::getmetrics' }; $self->{custom_modes}->{api} = 'cloud::google::gcp::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Google Cloud Plateform Stackdriver service using API. =cut centreon-plugins-20220113/cloud/google/gcp/storage/000077500000000000000000000000001417000230700220335ustar00rootroot00000000000000centreon-plugins-20220113/cloud/google/gcp/storage/mode/000077500000000000000000000000001417000230700227575ustar00rootroot00000000000000centreon-plugins-20220113/cloud/google/gcp/storage/mode/bucket.pm000066400000000000000000000124651417000230700246020ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::google::gcp::storage::mode::bucket; use base qw(cloud::google::gcp::custom::mode); use strict; use warnings; sub get_metrics_mapping { my ($self, %options) = @_; my $metrics_mapping = { 'storage/object_count' => { output_string => 'objects: %.2f', perfdata => { absolute => { nlabel => 'storage.bucket.objects.count', format => '%.2f', min => 0 } }, threshold => 'bucket-objects', order => 1 }, 'network/received_bytes_count' => { output_string => 'received: %.2f', perfdata => { absolute => { nlabel => 'storage.network.received.volume.bytes', format => '%.2f', min => 0, unit => 'B', change_bytes => 1 }, per_second => { nlabel => 'storage.network.received.volume.bytespersecond', format => '%.2f', min => 0, unit => 'B/s', change_bytes => 1 } }, threshold => 'received-volume', order => 2 }, 'network/sent_bytes_count' => { output_string => 'sent: %.2f', perfdata => { absolute => { nlabel => 'storage.network.sent.volume.bytes', format => '%.2f', min => 0, unit => 'B', change_bytes => 1 }, per_second => { nlabel => 'storage.network.sent.volume.bytespersecond', format => '%.2f', min => 0, unit => 'B/s', change_bytes => 1 } }, threshold => 'sent-volume', order => 3 } }; return $metrics_mapping; } 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 => { 'dimension-name:s' => { name => 'dimension_name', default => 'resource.labels.bucket_name' }, 'dimension-operator:s' => { name => 'dimension_operator', default => 'equals' }, 'dimension-value:s' => { name => 'dimension_value' }, 'filter-metric:s' => { name => 'filter_metric' }, "per-second" => { name => 'per_second' }, 'timeframe:s' => { name => 'timeframe' }, 'aggregation:s@' => { name => 'aggregation' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{gcp_api} = 'storage.googleapis.com'; $self->{gcp_dimension_name} = (!defined($self->{option_results}->{dimension_name}) || $self->{option_results}->{dimension_name} eq '') ? 'resource.labels.bucket_name' : $self->{option_results}->{dimension_name}; $self->{gcp_dimension_zeroed} = 'resource.labels.bucket_name'; $self->{gcp_instance_key} = 'resource.labels.bucket_name'; $self->{gcp_dimension_operator} = $self->{option_results}->{dimension_operator}; $self->{gcp_dimension_value} = $self->{option_results}->{dimension_value}; } 1; __END__ =head1 MODE Check storage bucket metrics. Example: perl centreon_plugins.pl --plugin=cloud::google::gcp::storage::plugin --mode=bucket --dimension-value=mybucketname --filter-metric='sent' --aggregation='average' --critical-received-volume='10' --verbose Default aggregation: 'average' / All aggregations are valid. =over 8 =item B<--dimension-name> Set dimension name (Default: 'resource.labels.bucket_name'). Can be: 'resources.labels.location'. =item B<--dimension-operator> Set dimension operator (Default: 'equals'. Can also be: 'regexp', 'starts'). =item B<--dimension-value> Set dimension value (Required). =item B<--filter-metric> Filter metrics (Can be: 'storage/object_count', 'network/received_bytes_count', 'network/sent_bytes_count') (Can be a regexp). =item B<--timeframe> Set timeframe in seconds (i.e. 3600 to check last hour). =item B<--aggregation> Set monitor aggregation (Can be multiple, Can be: 'minimum', 'maximum', 'average', 'total'). =item B<--warning-*> B<--critical-*> Thresholds (Can be: 'bucket-objects', 'received-volume', 'sent-volume'). =item B<--per-second> Change the data to be unit/sec. =back =cut centreon-plugins-20220113/cloud/google/gcp/storage/mode/discovery.pm000066400000000000000000000053071417000230700253310ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::google::gcp::storage::mode::discovery; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'prettify' => { name => 'prettify' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my $disco_data; my $disco_stats; $disco_stats->{start_time} = time(); my $buckets = $options{custom}->gcp_list_storage_buckets(); foreach my $bucket (@$buckets) { my $item = {}; $item->{id} = $bucket->{id}; $item->{name} = $bucket->{name}; $item->{project_number} = $bucket->{projectNumber}; $item->{location} = $bucket->{location}; $item->{location_type} = $bucket->{locationType}; $item->{storage_class} = $bucket->{storageClass}; push @$disco_data, $item; } $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; $disco_stats->{discovered_items} = scalar(@$disco_data); $disco_stats->{results} = $disco_data; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE Storage discovery. =over 8 =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/google/gcp/storage/plugin.pm000066400000000000000000000025621417000230700236740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::google::gcp::storage::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} = { 'bucket' => 'cloud::google::gcp::storage::mode::bucket', 'discovery' => 'cloud::google::gcp::storage::mode::discovery' }; $self->{custom_modes}->{api} = 'cloud::google::gcp::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Google Cloud Platform Storage. =cut centreon-plugins-20220113/cloud/ibm/000077500000000000000000000000001417000230700171115ustar00rootroot00000000000000centreon-plugins-20220113/cloud/ibm/softlayer/000077500000000000000000000000001417000230700211215ustar00rootroot00000000000000centreon-plugins-20220113/cloud/ibm/softlayer/custom/000077500000000000000000000000001417000230700224335ustar00rootroot00000000000000centreon-plugins-20220113/cloud/ibm/softlayer/custom/xmlapi.pm000066400000000000000000000152551417000230700242730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::ibm::softlayer::custom::xmlapi; use strict; use warnings; use centreon::plugins::http; use XML::Simple; 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 => { 'hostname:s' => { name => 'hostname' }, 'url-path:s' => { name => 'url_path' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'timeout:s' => { name => 'timeout' }, 'api-username:s' => { name => 'api_username' }, 'api-key:s' => { name => 'api_key' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'XMLAPI OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : 'api.softlayer.com'; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{url_path} = (defined($self->{option_results}->{url_path})) ? $self->{option_results}->{url_path} : '/soap/v3'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; if (!defined($self->{option_results}->{api_username}) || $self->{option_results}->{api_username} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-username option."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{api_key}) || $self->{option_results}->{api_key} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-key option."); $self->{output}->option_exit(); } return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{warning_status} = ''; $self->{option_results}->{critical_status} = ''; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'text/xml'); $self->{http}->add_header(key => 'Accept', value => 'multipart/*'); $self->{http}->add_header(key => 'Accept', value => 'text/xmlapplication/soap'); $self->{http}->add_header(key => 'Content-Type', value => 'text/xml; charset=utf-8'); $self->{http}->set_options(%{$self->{option_results}}); } sub get_connection_info { my ($self, %options) = @_; return $self->{hostname} . ":" . $self->{port}; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub get_port { my ($self, %options) = @_; return $self->{port}; } sub get_api_username { my ($self, %options) = @_; return $self->{option_results}->{api_username}; } sub get_api_key { my ($self, %options) = @_; return $self->{option_results}->{api_key}; } sub get_endpoint { my ($self, %options) = @_; $self->settings; $self->{http}->add_header(key => 'SOAPAction', value => 'http://api.service.softlayer.com/soap/v3/#' . $options{method}); my $content = ' ' . $self->get_api_key() . ' ' . $self->get_api_username() . ' ' . $options{extra_content} . ' '; my $response = $self->{http}->request(url_path => $self->{url_path} . '/' . $options{service}, method => 'POST', query_form_post => $content); my $xml_hash = XMLin($response, ForceArray => ['item']); if (defined($xml_hash->{'SOAP-ENV:Body'}->{'SOAP-ENV:Fault'})) { $self->{output}->output_add(long_msg => "Returned message: " . $response, debug => 1); $self->{output}->add_option_msg(short_msg => "API returned error code '" . $xml_hash->{'SOAP-ENV:Body'}->{'SOAP-ENV:Fault'}->{faultcode} . "' with message '" . $xml_hash->{'SOAP-ENV:Body'}->{'SOAP-ENV:Fault'}->{faultstring} . "'"); $self->{output}->option_exit(); } return $xml_hash->{'SOAP-ENV:Body'}; } 1; __END__ =head1 NAME IBM SoftLayer XML API =head1 SYNOPSIS IBM SoftLayer XML API =head1 XMLAPI OPTIONS =over 8 =item B<--hostname> API hostname (Default: 'api.softlayer.com'). =item B<--url-path> API url path (Default: '/soap/v3') =item B<--port> API port (Default: 443) =item B<--proto> Specify https if needed (Default: 'https') =item B<--api-username> Set API username =item B<--api-key> Set API Key =item B<--timeout> Set HTTP timeout =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/cloud/ibm/softlayer/mode/000077500000000000000000000000001417000230700220455ustar00rootroot00000000000000centreon-plugins-20220113/cloud/ibm/softlayer/mode/events.pm000066400000000000000000000203711417000230700237120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::ibm::softlayer::mode::events; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use DateTime; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_event_output { my ($self, %options) = @_; return sprintf( "Status is '%s', Impacted items: %d, Start date: %s, End date: %s", $self->{result_values}->{status}, $self->{result_values}->{items}, ($self->{result_values}->{start_date} ne "-") ? $self->{result_values}->{start_date} . ' (' . centreon::plugins::misc::change_seconds(value => $self->{result_values}->{since_start}) . ' ago)' : '-', ($self->{result_values}->{end_date} ne "-") ? $self->{result_values}->{end_date} . ' (' . centreon::plugins::misc::change_seconds(value => $self->{result_values}->{since_end}) . ' ago)' : '-' ); } sub prefix_global_output { my ($self, %options) = @_; return "Number of events "; } sub prefix_events_output { my ($self, %options) = @_; return "Event '" . $options{instance_value}->{id} . "' with subject '" . $options{instance_value}->{subject} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } }, { name => 'events', type => 1, cb_prefix_output => 'prefix_events_output' }, ]; $self->{maps_counters}->{global} = [ { label => 'active', nlabel => 'events.active.count', set => { key_values => [ { name => 'active' } ], output_template => 'Active : %d', perfdatas => [ { label => 'active_events', template => '%d', min => 0 } ] } }, { label => 'completed', nlabel => 'events.completed.count', set => { key_values => [ { name => 'completed' } ], output_template => 'Completed : %d', perfdatas => [ { label => 'completed_events', template => '%d', min => 0 } ] } }, { label => 'published',nlabel => 'events.published.count', set => { key_values => [ { name => 'published' } ], output_template => 'Published : %d', perfdatas => [ { label => 'published_events', template => '%d', min => 0 } ] } } ]; $self->{maps_counters}->{events} = [ { label => 'event', type => 2, critical_default => '%{status} =~ /Active/ && %{items} > 0', set => { key_values => [ { name => 'id' }, { name => 'subject' }, { name => 'status' }, { name => 'items' }, { name => 'start_date' }, { name => 'since_start' }, { name => 'end_date' }, { name => 'since_end' } ], closure_custom_output => $self->can('custom_event_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-status:s' => { name => 'filter_status', default => 'Active' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $current_time = time(); my %status_hash; my $events = $options{custom}->get_endpoint(service => 'SoftLayer_Notification_Occurrence_Event', method => 'getAllObjects', extra_content => ''); foreach my $event (@{$events->{'ns1:getAllObjectsResponse'}->{'getAllObjectsReturn'}->{'item'}}) { my $status; $status = $event->{statusCode}->{name}->{content} if (defined($event->{statusCode}->{name}->{content})); $status_hash{'#' . $event->{statusCode}->{id}} = $event->{statusCode}->{name}->{content} if (defined($event->{statusCode}->{name}->{content})); $status = $status_hash{$event->{statusCode}->{href}} if (!defined($event->{statusCode}->{name}->{content}) && defined($event->{statusCode}->{href})); next if (defined($self->{option_results}->{filter_status}) && $status !~ /$self->{option_results}->{filter_status}/); my $extra_content = ' ' . $event->{id}->{content} . ' '; my $ressources = $options{custom}->get_endpoint(service => 'SoftLayer_Notification_Occurrence_Event', method => 'getImpactedResources', extra_content => $extra_content); my $items = 0; if (defined($ressources->{'ns1:getImpactedResourcesResponse'}->{'getImpactedResourcesReturn'}->{'item'})) { $items = 1; $items = scalar(@{$ressources->{'ns1:getImpactedResourcesResponse'}->{'getImpactedResourcesReturn'}->{'item'}}) if (ref($ressources->{'ns1:getImpactedResourcesResponse'}->{'getImpactedResourcesReturn'}->{'item'}) eq 'ARRAY'); } my $start_epoch = ''; my $end_epoch = ''; if (defined($event->{startDate}->{content}) && $event->{startDate}->{content} =~ /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(.*)$/) { # 2018-10-18T15:36:54+00:00 my $dt = DateTime->new( year => $1, month => $2, day => $3, hour => $4, minute => $5, second => $6, time_zone => $7 ); $start_epoch = $dt->epoch; } if (defined($event->{endDate}->{content}) && $event->{endDate}->{content} =~ /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(.*)$/) { # 2018-10-18T15:36:54+00:00 my $dt = DateTime->new( year => $1, month => $2, day => $3, hour => $4, minute => $5, second => $6, time_zone => $7 ); $end_epoch = $dt->epoch; } $self->{events}->{$event->{id}->{content}} = { id => $event->{id}->{content}, subject => $event->{subject}->{content}, status => $status, items => $items, start_date => (defined($event->{startDate}->{content})) ? $event->{startDate}->{content} : "-", since_start => ($start_epoch ne '') ? $current_time - $start_epoch : "-", end_date => (defined($event->{endDate}->{content})) ? $event->{endDate}->{content} : "-", since_end => ($end_epoch ne '') ? $current_time - $end_epoch : "-", }; $self->{global}->{lc($status)}++; } } 1; __END__ =head1 MODE Check events status and number of impacted ressources =over 8 =item B<--filter-status> Filter events status (Default: 'Active') =item B<--warning-status> Set warning threshold for status (Default: '') Can used special variables like: %{id}, %{subject}, %{status}, %{items}, %{start_date}, %{since_start}, %{end_date}, %{since_end}. =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /Active/ && %{items} > 0'). Can used special variables like: %{id}, %{subject}, %{status}, %{items}, %{start_date}, %{since_start}, %{end_date}, %{since_end}. =item B<--warning-*> Threshold warning. Can be: 'active', 'completed', 'published'. =item B<--critical-*> Threshold critical. Can be: 'active', 'completed', 'published'. =back =cut centreon-plugins-20220113/cloud/ibm/softlayer/mode/opentickets.pm000066400000000000000000000132401417000230700247330ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::ibm::softlayer::mode::opentickets; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use DateTime; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_ticket_output { my ($self, %options) = @_; return sprintf( "Title: '%s', Group: '%s', Priority: %s, Create Date: %s (%s ago)", $self->{result_values}->{title}, $self->{result_values}->{group}, $self->{result_values}->{priority}, $self->{result_values}->{create_date}, centreon::plugins::misc::change_seconds(value => $self->{result_values}->{since}) ); } sub prefix_tickets_output { my ($self, %options) = @_; return "Ticket '" . $options{instance_value}->{id} . "' is open with "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'tickets', type => 1, cb_prefix_output => 'prefix_tickets_output' } ]; $self->{maps_counters}->{global} = [ { label => 'open', nlabel => 'tickets.open.count', set => { key_values => [ { name => 'open' } ], output_template => 'Number of open tickets : %d', perfdatas => [ { label => 'open_tickets', template => '%d', min => 0 } ] } } ]; $self->{maps_counters}->{tickets} = [ { label => 'ticket', type => 2, set => { key_values => [ { name => 'id' }, { name => 'title' }, { name => 'priority' }, { name => 'create_date' }, { name => 'group' }, { name => 'since' } ], closure_custom_output => $self->can('custom_ticket_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'ticket-group:s' => { name => 'ticket_group' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{global}->{open} = 0; $self->{tickets} = {}; my $group_id = ''; my %groups_hash; my $groups = $options{custom}->get_endpoint(service => 'SoftLayer_Ticket', method => 'getAllTicketGroups', extra_content => ''); foreach my $group (@{$groups->{'ns1:getAllTicketGroupsResponse'}->{'getAllTicketGroupsReturn'}->{'item'}}) { $groups_hash{$group->{id}->{content}} = $group->{name}->{content}; if (defined($self->{option_results}->{ticket_group}) && $self->{option_results}->{ticket_group} ne '' && $group->{name}->{content} =~ /^$self->{option_results}->{ticket_group}$/) { $group_id = $group->{id}->{content}; } } if (defined($self->{option_results}->{ticket_group}) && $self->{option_results}->{ticket_group} ne '' && $group_id eq '') { $self->{output}->add_option_msg(short_msg => "Ticket group ID not found from API."); $self->{output}->option_exit(); } my $current_time = time(); my $tickets = $options{custom}->get_endpoint(service => 'SoftLayer_Account', method => 'getOpenTickets', extra_content => ''); foreach my $ticket (@{$tickets->{'ns1:getOpenTicketsResponse'}->{'getOpenTicketsReturn'}->{'item'}}) { next if (defined($group_id) && $group_id ne '' && $ticket->{groupId}->{content} ne $group_id); next if ($ticket->{createDate}->{content} !~ /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(.*)$/); # 2018-10-18T15:36:54+00:00 my $dt = DateTime->new( year => $1, month => $2, day => $3, hour => $4, minute => $5, second => $6, time_zone => $7 ); $self->{tickets}->{$ticket->{id}->{content}} = { id => $ticket->{id}->{content}, title => $ticket->{title}->{content}, priority => $ticket->{priority}->{content}, create_date => $ticket->{createDate}->{content}, group => $groups_hash{$ticket->{groupId}->{content}}, since => $current_time - $dt->epoch, }; $self->{global}->{open}++; } } 1; __END__ =head1 MODE Check if there is open tickets =over 8 =item B<--ticket-group> Name of the ticket group (Can be a regexp). =item B<--warning-status> Set warning threshold for status (Default: '') Can used special variables like: %{id}, %{title}, %{priority}, %{create_date}, %{group}, %{since}. =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{id}, %{title}, %{priority}, %{create_date}, %{group}, %{since}. =item B<--warning-open> Threshold warning for open tickets. =item B<--critical-open> Threshold critical for open tickets. =back =cut centreon-plugins-20220113/cloud/ibm/softlayer/plugin.pm000066400000000000000000000025371417000230700227640ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::ibm::softlayer::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} = { 'events' => 'cloud::ibm::softlayer::mode::events', 'open-tickets' => 'cloud::ibm::softlayer::mode::opentickets' }; $self->{custom_modes}->{xmlapi} = 'cloud::ibm::softlayer::custom::xmlapi'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check IBM Softlayer =cut centreon-plugins-20220113/cloud/kubernetes/000077500000000000000000000000001417000230700205115ustar00rootroot00000000000000centreon-plugins-20220113/cloud/kubernetes/custom/000077500000000000000000000000001417000230700220235ustar00rootroot00000000000000centreon-plugins-20220113/cloud/kubernetes/custom/api.pm000066400000000000000000000231661417000230700231420ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::kubernetes::custom::api; use strict; use warnings; use centreon::plugins::http; use DateTime; use JSON::XS; use URI::Encode; 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'token:s' => { name => 'token' }, 'timeout:s' => { name => 'timeout' }, 'limit:s' => { name => 'limit' }, 'config-file:s' => { name => 'config_file' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : undef; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{timeout} = (defined($self->{option_results}->{timeout})) && $self->{option_results}->{timeout} =~ /(\d+)/ ? $1 : 10; $self->{token} = (defined($self->{option_results}->{token})) ? $self->{option_results}->{token} : ''; $self->{limit} = (defined($self->{option_results}->{limit})) && $self->{option_results}->{limit} =~ /(\d+)/ ? $1 : 100; if (!defined($self->{hostname}) || $self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } if (!defined($self->{token}) || $self->{token} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --token option."); $self->{output}->option_exit(); } return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{warning_status} = ''; $self->{option_results}->{critical_status} = ''; $self->{option_results}->{unknown_status} = ''; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); if (defined($self->{token})) { $self->{http}->add_header(key => 'Authorization', value => 'Bearer ' . $self->{token}); } $self->{http}->set_options(%{$self->{option_results}}); } sub request_api { my ($self, %options) = @_; $self->settings; $self->{output}->output_add(long_msg => "URL: '" . $self->{proto} . '://' . $self->{hostname} . ':' . $self->{port} . $options{url_path} . "'", debug => 1); my $response = $self->{http}->request(%options); if ($self->{http}->get_code() != 200) { my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($response); }; if ($@) { $self->{output}->output_add(long_msg => $response, debug => 1); $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $response"); $self->{output}->option_exit(); } if (defined($decoded->{code})) { $self->{output}->output_add(long_msg => "Error message: " . $decoded->{message}, debug => 1); $self->{output}->add_option_msg(short_msg => "API return error code '" . $decoded->{code} . "' (add --debug option for detailed message)"); $self->{output}->option_exit(); } else { $self->{output}->output_add(long_msg => "Error message: " . $decoded, debug => 1); $self->{output}->add_option_msg(short_msg => "API return error code '" . $self->{http}->get_code() . "' (add --debug option for detailed message)"); $self->{output}->option_exit(); } } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($response); }; if ($@) { $self->{output}->output_add(long_msg => $response, debug => 1); $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $response"); $self->{output}->option_exit(); } return $decoded; } sub request_api_paginate { my ($self, %options) = @_; my @items; my @get_param = ( 'limit=' . $self->{limit} ); push @get_param, @{$options{get_param}} if (defined($options{get_param})); while (1) { my $response = $self->request_api( method => $options{method}, url_path => $options{url_path}, get_param => \@get_param ); last if (!defined($response->{items})); push @items, @{$response->{items}}; last if (!defined($response->{metadata}->{continue})); @get_param = ( 'limit=' . $self->{limit}, 'continue=' . $response->{metadata}->{continue} ); push @get_param, @{$options{get_param}} if (defined($options{get_param})); } return \@items; } sub kubernetes_list_cronjobs { my ($self, %options) = @_; my $response = $self->request_api_paginate(method => 'GET', url_path => '/apis/batch/v1beta1/cronjobs'); return $response; } sub kubernetes_list_daemonsets { my ($self, %options) = @_; my $response = $self->request_api_paginate(method => 'GET', url_path => '/apis/apps/v1/daemonsets'); return $response; } sub kubernetes_list_deployments { my ($self, %options) = @_; my $response = $self->request_api_paginate(method => 'GET', url_path => '/apis/apps/v1/deployments'); return $response; } sub kubernetes_list_events { my ($self, %options) = @_; my $response = $self->request_api_paginate(method => 'GET', url_path => '/api/v1/events'); return $response; } sub kubernetes_list_ingresses { my ($self, %options) = @_; my $response = $self->request_api_paginate(method => 'GET', url_path => '/apis/extensions/v1beta1/ingresses'); return $response; } sub kubernetes_list_namespaces { my ($self, %options) = @_; my $response = $self->request_api_paginate(method => 'GET', url_path => '/api/v1/namespaces'); return $response; } sub kubernetes_list_nodes { my ($self, %options) = @_; my $response = $self->request_api_paginate(method => 'GET', url_path => '/api/v1/nodes'); return $response; } sub kubernetes_list_rcs { my ($self, %options) = @_; my $response = $self->request_api_paginate(method => 'GET', url_path => '/api/v1/replicationcontrollers'); return $response; } sub kubernetes_list_replicasets { my ($self, %options) = @_; my $response = $self->request_api_paginate(method => 'GET', url_path => '/apis/apps/v1/replicasets'); return $response; } sub kubernetes_list_services { my ($self, %options) = @_; my $response = $self->request_api_paginate(method => 'GET', url_path => '/apis/v1/services'); return $response; } sub kubernetes_list_statefulsets { my ($self, %options) = @_; my $response = $self->request_api_paginate(method => 'GET', url_path => '/apis/apps/v1/statefulsets'); return $response; } sub kubernetes_list_pods { my ($self, %options) = @_; my $response = $self->request_api_paginate(method => 'GET', url_path => '/api/v1/pods'); return $response; } sub kubernetes_list_pvs { my ($self, %options) = @_; my $response = $self->request_api_paginate(method => 'GET', url_path => '/api/v1/persistentvolumes'); return $response; } 1; __END__ =head1 NAME Kubernetes Rest API =head1 SYNOPSIS Kubernetes Rest API custom mode =head1 REST API OPTIONS Kubernetes Rest API =over 8 =item B<--hostname> Kubernetes API hostname. =item B<--port> API port (Default: 443) =item B<--proto> Specify https if needed (Default: 'https') =item B<--timeout> Set HTTP timeout =item B<--limit> Number of responses to return for each list calls. See https://kubernetes.io/docs/reference/kubernetes-api/common-parameters/common-parameters/#limit =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/cloud/kubernetes/custom/kubectl.pm000066400000000000000000000264311417000230700240200ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::kubernetes::custom::kubectl; use strict; use warnings; use JSON::XS; 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'token:s' => { name => 'token' }, 'timeout:s' => { name => 'timeout', default => 10 }, 'config-file:s' => { name => 'config_file', default => '~/.kube/config' }, 'context:s' => { name => 'context' }, 'sudo' => { name => 'sudo' }, 'command:s' => { name => 'command', default => 'kubectl' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '' }, 'proxyurl:s' => { name => 'proxyurl' }, }); } $options{options}->add_help(package => __PACKAGE__, sections => 'CLI OPTIONS', once => 1); $self->{output} = $options{output}; return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{config_file} = (defined($self->{option_results}->{config_file})) ? $self->{option_results}->{config_file} : ''; $self->{context} = (defined($self->{option_results}->{context})) ? $self->{option_results}->{context} : ''; $self->{timeout} = (defined($self->{option_results}->{timeout})) && $self->{option_results}->{timeout} =~ /(\d+)/ ? $1 : 10; if (!defined($self->{config_file}) || $self->{config_file} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --config-file option."); $self->{output}->option_exit(); } if ($self->{config_file} =~ /^~/) { centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'File::HomeDir', error_msg => "Cannot load module 'File::HomeDir'." ); my $home = File::HomeDir->my_home; $self->{config_file} =~ s/\~/$home/; } if (defined($self->{option_results}->{proxyurl}) && $self->{option_results}->{proxyurl} ne '') { $ENV{HTTP_PROXY} = $self->{option_results}->{proxyurl}; $ENV{HTTPS_PROXY} = $self->{option_results}->{proxyurl}; } return 0; } sub execute { my ($self, %options) = @_; my $cmd_options = $options{cmd_options}; # See https://kubernetes.io/docs/reference/kubectl/cheatsheet/#kubectl-output-verbosity-and-debugging $cmd_options .= " --v='9'" if ($self->{output}->is_debug()); $self->{output}->output_add(long_msg => "Command line: '" . $self->{option_results}->{command} . " " . $cmd_options . "'", debug => 1); my ($response, $exit_code) = 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 => $cmd_options, redirect_stderr => ($self->{output}->is_debug()) ? 0 : 1, no_quit => 1 ); if ($exit_code != 0) { $self->{output}->output_add(long_msg => "Error message: " . $response, debug => 1); $self->{output}->add_option_msg(short_msg => "CLI return error code '" . $exit_code . "' (add --debug option for detailed message)"); $self->{output}->option_exit(); } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($response); }; if ($@) { $self->{output}->output_add(long_msg => $response, debug => 1); $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } return $decoded->{items}; } sub kubernetes_list_cronjobs { my ($self, %options) = @_; my $cmd = "get cronjobs --all-namespaces --output='json' --kubeconfig='" . $self->{config_file} . "'" . " --request-timeout='" . $self->{timeout} . "'"; $cmd .= " --context='" . $self->{context} . "'" if (defined($self->{context}) && $self->{context} ne ''); my $response = $self->execute(cmd_options => $cmd); return $response; } sub kubernetes_list_daemonsets { my ($self, %options) = @_; my $cmd = "get daemonsets --all-namespaces --output='json' --kubeconfig='" . $self->{config_file} . "'" . " --request-timeout='" . $self->{timeout} . "'"; $cmd .= " --context='" . $self->{context} . "'" if (defined($self->{context}) && $self->{context} ne ''); my $response = $self->execute(cmd_options => $cmd); return $response; } sub kubernetes_list_deployments { my ($self, %options) = @_; my $cmd = "get deployments --all-namespaces --output='json' --kubeconfig='" . $self->{config_file} . "'" . " --request-timeout='" . $self->{timeout} . "'"; $cmd .= " --context='" . $self->{context} . "'" if (defined($self->{context}) && $self->{context} ne ''); my $response = $self->execute(cmd_options => $cmd); return $response; } sub kubernetes_list_events { my ($self, %options) = @_; my $cmd = "get events --all-namespaces --output='json' --kubeconfig='" . $self->{config_file} . "'" . " --request-timeout='" . $self->{timeout} . "'"; $cmd .= " --context='" . $self->{context} . "'" if (defined($self->{context}) && $self->{context} ne ''); my $response = $self->execute(cmd_options => $cmd); return $response; } sub kubernetes_list_ingresses { my ($self, %options) = @_; my $cmd = "get ingresses --all-namespaces --output='json' --kubeconfig='" . $self->{config_file} . "'" . " --request-timeout='" . $self->{timeout} . "'"; $cmd .= " --context='" . $self->{context} . "'" if (defined($self->{context}) && $self->{context} ne ''); my $response = $self->execute(cmd_options => $cmd); return $response; } sub kubernetes_list_namespaces { my ($self, %options) = @_; my $cmd = "get namespaces --all-namespaces --output='json' --kubeconfig='" . $self->{config_file} . "'" . " --request-timeout='" . $self->{timeout} . "'"; $cmd .= " --context='" . $self->{context} . "'" if (defined($self->{context}) && $self->{context} ne ''); my $response = $self->execute(cmd_options => $cmd); return $response; } sub kubernetes_list_nodes { my ($self, %options) = @_; my $cmd = "get nodes --all-namespaces --output='json' --kubeconfig='" . $self->{config_file} . "'" . " --request-timeout='" . $self->{timeout} . "'"; $cmd .= " --context='" . $self->{context} . "'" if (defined($self->{context}) && $self->{context} ne ''); my $response = $self->execute(cmd_options => $cmd); return $response; } sub kubernetes_list_rcs { my ($self, %options) = @_; my $cmd = "get replicationcontroller --all-namespaces --output='json' --kubeconfig='" . $self->{config_file} . "'" . " --request-timeout='" . $self->{timeout} . "'"; $cmd .= " --context='" . $self->{context} . "'" if (defined($self->{context}) && $self->{context} ne ''); my $response = $self->execute(cmd_options => $cmd); return $response; } sub kubernetes_list_replicasets { my ($self, %options) = @_; my $cmd = "get replicasets --all-namespaces --output='json' --kubeconfig='" . $self->{config_file} . "'" . " --request-timeout='" . $self->{timeout} . "'"; $cmd .= " --context='" . $self->{context} . "'" if (defined($self->{context}) && $self->{context} ne ''); my $response = $self->execute(cmd_options => $cmd); return $response; } sub kubernetes_list_services { my ($self, %options) = @_; my $cmd = "get services --all-namespaces --output='json' --kubeconfig='" . $self->{config_file} . "'" . " --request-timeout='" . $self->{timeout} . "'"; $cmd .= " --context='" . $self->{context} . "'" if (defined($self->{context}) && $self->{context} ne ''); my $response = $self->execute(cmd_options => $cmd); return $response; } sub kubernetes_list_statefulsets { my ($self, %options) = @_; my $cmd = "get statefulsets --all-namespaces --output='json' --kubeconfig='" . $self->{config_file} . "'" . " --request-timeout='" . $self->{timeout} . "'"; $cmd .= " --context='" . $self->{context} . "'" if (defined($self->{context}) && $self->{context} ne ''); my $response = $self->execute(cmd_options => $cmd); return $response; } sub kubernetes_list_pods { my ($self, %options) = @_; my $cmd = "get pods --all-namespaces --output='json' --kubeconfig='" . $self->{config_file} . "'" . " --request-timeout='" . $self->{timeout} . "'"; $cmd .= " --context='" . $self->{context} . "'" if (defined($self->{context}) && $self->{context} ne ''); my $response = $self->execute(cmd_options => $cmd); return $response; } sub kubernetes_list_pvs { my ($self, %options) = @_; my $cmd = "get pv --all-namespaces --output='json' --kubeconfig='" . $self->{config_file} . "'" . " --request-timeout='" . $self->{timeout} . "'"; $cmd .= " --context='" . $self->{context} . "'" if (defined($self->{context}) && $self->{context} ne ''); my $response = $self->execute(cmd_options => $cmd); return $response; } 1; __END__ =head1 NAME Kubernetes CLI (kubectl) =head1 SYNOPSIS Kubernetes CLI (kubectl) custom mode =head1 CLI OPTIONS Kubernetes CLI (kubectl) =over 8 =item B<--config-file> Kubernetes configuration file path (Default: '~/.kube/config'). (Example: --config-file='/root/.kube/config'). =item B<--context> Context to use in configuration file. =item B<--timeout> Set timeout in seconds (Default: 10). =item B<--sudo> Use 'sudo' to execute the command. =item B<--command> Command to get information (Default: 'kubectl'). 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: none). =item B<--proxyurl> Proxy URL if any =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/cloud/kubernetes/mode/000077500000000000000000000000001417000230700214355ustar00rootroot00000000000000centreon-plugins-20220113/cloud/kubernetes/mode/clusterevents.pm000066400000000000000000000175641417000230700247160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::kubernetes::mode::clusterevents; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use DateTime; use centreon::plugins::misc; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_event_calc { my ($self, %options) = @_; $self->{result_values}->{type} = $options{new_datas}->{$self->{instance} . '_type'}; $self->{result_values}->{object} = $options{new_datas}->{$self->{instance} . '_object'}; $self->{result_values}->{message} = $options{new_datas}->{$self->{instance} . '_message'}; $self->{result_values}->{count} = $options{new_datas}->{$self->{instance} . '_count'}; $self->{result_values}->{first_seen_time} = $options{new_datas}->{$self->{instance} . '_first_seen'}; $self->{result_values}->{last_seen_time} = $options{new_datas}->{$self->{instance} . '_last_seen'}; # 2021-03-09T11:01:00Z, UTC timezone if ($self->{result_values}->{first_seen_time} =~ /^\s*(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)Z/) { my $dt = DateTime->new( year => $1, month => $2, day => $3, hour => $4, minute => $5, second => $6 ); $self->{result_values}->{first_seen} = time() - $dt->epoch; } if ($self->{result_values}->{last_seen_time} =~ /^\s*(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)Z/) { my $dt = DateTime->new( year => $1, month => $2, day => $3, hour => $4, minute => $5, second => $6 ); $self->{result_values}->{last_seen} = time() - $dt->epoch; } return 0; } sub custom_event_output { my ($self, %options) = @_; my $msg = sprintf("Event '%s' for object '%s' with message '%s'", $self->{result_values}->{type}, $self->{result_values}->{object}, $self->{result_values}->{message} ); $msg .= sprintf(", Count: %s, First seen: %s ago (%s), Last seen: %s ago (%s)", $self->{result_values}->{count}, centreon::plugins::misc::change_seconds(value => $self->{result_values}->{first_seen}), $self->{result_values}->{first_seen_time}, centreon::plugins::misc::change_seconds(value => $self->{result_values}->{last_seen}), $self->{result_values}->{last_seen_time} ) if (defined($self->{result_values}->{count}) && $self->{result_values}->{count} ne ''); return $msg; } sub prefix_global_output { my ($self, %options) = @_; return "Number of events "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } }, { name => 'events', type => 1 }, ]; $self->{maps_counters}->{global} = [ { label => 'warning', nlabel => 'events.type.warning.count', set => { key_values => [ { name => 'warning' } ], output_template => 'Warning : %d', perfdatas => [ { label => 'warning_events', template => '%d', min => 0 } ] } }, { label => 'normal', nlabel => 'events.type.normal.count', set => { key_values => [ { name => 'normal' } ], output_template => 'Normal : %d', perfdatas => [ { label => 'normal_events', template => '%d', min => 0 } ] } }, ]; $self->{maps_counters}->{events} = [ { label => 'status', type => 2, warning_default => '%{type} =~ /warning/i', critical_default => '%{type} =~ /error/i', set => { key_values => [ { name => 'object' }, { name => 'count' }, { name => 'first_seen' }, { name => 'last_seen' }, { name => 'message' }, { name => 'reason' }, { name => 'type' } ], closure_custom_calc => $self->can('custom_event_calc'), closure_custom_output => $self->can('custom_event_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { "filter-type:s" => { name => 'filter_type' }, "filter-namespace:s" => { name => 'filter_namespace' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; $self->{events} = {}; my $results = $options{custom}->kubernetes_list_events(); $self->{global} = { normal => 0, warning => 0 }; foreach my $event (@{$results}) { if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' && $event->{type} !~ /$self->{option_results}->{filter_type}/) { $self->{output}->output_add(long_msg => "skipping '" . $event->{type} . "': no matching filter type.", debug => 1); next; } if (defined($self->{option_results}->{filter_namespace}) && $self->{option_results}->{filter_namespace} ne '' && $event->{metadata}->{namespace} !~ /$self->{option_results}->{filter_namespace}/) { $self->{output}->output_add(long_msg => "skipping '" . $event->{metadata}->{namespace} . "': no matching filter namespace.", debug => 1); next; } $self->{global}->{lc($event->{type})}++; $self->{events}->{$event->{metadata}->{uid}} = { name => $event->{metadata}->{name}, namespace => $event->{metadata}->{namespace}, object => $event->{involvedObject}->{kind} . "/" . $event->{involvedObject}->{name}, count => (defined($event->{count})) ? $event->{count} : "", first_seen => (defined($event->{firstTimestamp})) ? $event->{firstTimestamp} : "", last_seen => (defined($event->{lastTimestamp})) ? $event->{lastTimestamp} : "", message => $event->{message}, reason => $event->{reason}, type => $event->{type} } } } 1; __END__ =head1 MODE Check cluster events. =over 8 =item B<--filter-type> Filter event type (can be a regexp). =item B<--filter-namespace> Filter namespace (can be a regexp). =item B<--warning-status> Set warning threshold for status (Default: '%{type} =~ /warning/i') Can use special variables like: %{name}, %{namespace}, %{type}, %{object}, %{message}, %{count}, %{first_seen}, %{last_seen}. =item B<--critical-status> Set critical threshold for status (Default: '%{type} =~ /error/i'). Can use special variables like: %{name}, %{namespace}, %{type}, %{object}, %{message}, %{count}, %{first_seen}, %{last_seen}. =back =cut centreon-plugins-20220113/cloud/kubernetes/mode/cronjobstatus.pm000066400000000000000000000143731417000230700247030ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::kubernetes::mode::cronjobstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use DateTime; use centreon::plugins::misc; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => 'active', nlabel => 'cronjob.jobs.active.count', value => $self->{result_values}->{active}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{name} : undef, ); } sub custom_status_output { my ($self, %options) = @_; return sprintf("Jobs Active: %s, Last schedule time: %s ago (%s)", $self->{result_values}->{active}, centreon::plugins::misc::change_seconds(value => $self->{result_values}->{last_schedule}), $self->{result_values}->{last_schedule_time}); } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_name'}; $self->{result_values}->{namespace} = $options{new_datas}->{$self->{instance} . '_namespace'}; $self->{result_values}->{active} = $options{new_datas}->{$self->{instance} . '_active'}; $self->{result_values}->{last_schedule_time} = $options{new_datas}->{$self->{instance} . '_last_schedule_time'}; # 2021-03-09T11:01:00Z, UTC timezone if ($self->{result_values}->{last_schedule_time} =~ /^\s*(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)Z/) { my $dt = DateTime->new( year => $1, month => $2, day => $3, hour => $4, minute => $5, second => $6 ); $self->{result_values}->{last_schedule} = time() - $dt->epoch; } return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'cronjobs', type => 1, cb_prefix_output => 'prefix_cronjob_output', message_multiple => 'All CronJobs status are ok', skipped_code => { -11 => 1 } }, ]; $self->{maps_counters}->{cronjobs} = [ { label => 'status', set => { key_values => [ { name => 'active' }, { name => 'last_schedule_time' }, { name => 'name' }, { name => 'namespace' } ], closure_custom_calc => $self->can('custom_status_calc'), closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => $self->can('custom_status_perfdata'), closure_custom_threshold_check => \&catalog_status_threshold, } }, ]; } sub prefix_cronjob_output { my ($self, %options) = @_; return "CronJob '" . $options{instance_value}->{name} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "filter-namespace:s" => { name => 'filter_namespace' }, "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); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; $self->{cronjobs} = {}; my $results = $options{custom}->kubernetes_list_cronjobs(); foreach my $cronjob (@{$results}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $cronjob->{metadata}->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $cronjob->{metadata}->{name} . "': no matching filter name.", debug => 1); next; } if (defined($self->{option_results}->{filter_namespace}) && $self->{option_results}->{filter_namespace} ne '' && $cronjob->{metadata}->{namespace} !~ /$self->{option_results}->{filter_namespace}/) { $self->{output}->output_add(long_msg => "skipping '" . $cronjob->{metadata}->{namespace} . "': no matching filter namespace.", debug => 1); next; } $self->{cronjobs}->{$cronjob->{metadata}->{uid}} = { name => $cronjob->{metadata}->{name}, namespace => $cronjob->{metadata}->{namespace}, active => (defined($cronjob->{status}->{active})) ? scalar(@{$cronjob->{status}->{active}}) : 0, last_schedule_time => $cronjob->{status}->{lastScheduleTime} } } if (scalar(keys %{$self->{cronjobs}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No CronJobs found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check CronJob status. =over 8 =item B<--filter-name> Filter CronJob name (can be a regexp). =item B<--filter-namespace> Filter CronJob namespace (can be a regexp). =item B<--warning-status> Set warning threshold for status (Default: '') Can used special variables like: %{name}, %{namespace}, %{active}, %{last_schedule}. =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{name}, %{namespace}, %{active}, %{last_schedule}. =back =cut centreon-plugins-20220113/cloud/kubernetes/mode/daemonsetstatus.pm000066400000000000000000000214321417000230700252200ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::kubernetes::mode::daemonsetstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => 'desired', nlabel => 'daemonset.pods.desired.count', value => $self->{result_values}->{desired}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{name} : undef, ); $self->{output}->perfdata_add( label => 'current', nlabel => 'daemonset.pods.current.count', value => $self->{result_values}->{current}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{name} : undef, ); $self->{output}->perfdata_add( label => 'available', nlabel => 'daemonset.pods.available.count', value => $self->{result_values}->{available}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{name} : undef, ); $self->{output}->perfdata_add( label => 'up_to_date', nlabel => 'daemonset.pods.uptodate.count', value => $self->{result_values}->{up_to_date}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{name} : undef, ); $self->{output}->perfdata_add( label => 'ready', nlabel => 'daemonset.pods.ready.count', value => $self->{result_values}->{ready}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{name} : undef, ); $self->{output}->perfdata_add( label => 'misscheduled', nlabel => 'daemonset.pods.misscheduled.count', value => $self->{result_values}->{misscheduled}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{name} : undef, ); } sub custom_status_output { my ($self, %options) = @_; return sprintf("Pods Desired: %s, Current: %s, Available: %s, Up-to-date: %s, Ready: %s, Misscheduled: %s", $self->{result_values}->{desired}, $self->{result_values}->{current}, $self->{result_values}->{available}, $self->{result_values}->{up_to_date}, $self->{result_values}->{ready}, $self->{result_values}->{misscheduled}); } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_name'}; $self->{result_values}->{namespace} = $options{new_datas}->{$self->{instance} . '_namespace'}; $self->{result_values}->{desired} = $options{new_datas}->{$self->{instance} . '_desired'}; $self->{result_values}->{current} = $options{new_datas}->{$self->{instance} . '_current'}; $self->{result_values}->{available} = $options{new_datas}->{$self->{instance} . '_available'}; $self->{result_values}->{up_to_date} = $options{new_datas}->{$self->{instance} . '_up_to_date'}; $self->{result_values}->{ready} = $options{new_datas}->{$self->{instance} . '_ready'}; $self->{result_values}->{misscheduled} = $options{new_datas}->{$self->{instance} . '_misscheduled'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'daemonsets', type => 1, cb_prefix_output => 'prefix_daemonset_output', message_multiple => 'All DaemonSets status are ok', skipped_code => { -11 => 1 } }, ]; $self->{maps_counters}->{daemonsets} = [ { label => 'status', set => { key_values => [ { name => 'desired' }, { name => 'current' }, { name => 'up_to_date' }, { name => 'available' }, { name => 'ready' }, { name => 'misscheduled' }, { name => 'name' }, { name => 'namespace' } ], closure_custom_calc => $self->can('custom_status_calc'), closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => $self->can('custom_status_perfdata'), closure_custom_threshold_check => \&catalog_status_threshold, } }, ]; } sub prefix_daemonset_output { my ($self, %options) = @_; return "DaemonSet '" . $options{instance_value}->{name} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "filter-namespace:s" => { name => 'filter_namespace' }, "warning-status:s" => { name => 'warning_status', default => '%{up_to_date} < %{desired}' }, "critical-status:s" => { name => 'critical_status', default => '%{available} < %{desired}' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; $self->{daemonsets} = {}; my $results = $options{custom}->kubernetes_list_daemonsets(); foreach my $daemonset (@{$results}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $daemonset->{metadata}->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $daemonset->{metadata}->{name} . "': no matching filter name.", debug => 1); next; } if (defined($self->{option_results}->{filter_namespace}) && $self->{option_results}->{filter_namespace} ne '' && $daemonset->{metadata}->{namespace} !~ /$self->{option_results}->{filter_namespace}/) { $self->{output}->output_add(long_msg => "skipping '" . $daemonset->{metadata}->{namespace} . "': no matching filter namespace.", debug => 1); next; } $self->{daemonsets}->{$daemonset->{metadata}->{uid}} = { name => $daemonset->{metadata}->{name}, namespace => $daemonset->{metadata}->{namespace}, desired => (defined($daemonset->{status}->{desiredNumberScheduled})) && $daemonset->{status}->{desiredNumberScheduled} =~ /(\d+)/ ? $1 : 0, current => (defined($daemonset->{status}->{currentNumberScheduled})) && $daemonset->{status}->{currentNumberScheduled} =~ /(\d+)/ ? $1 : 0, up_to_date => (defined($daemonset->{status}->{updatedNumberScheduled})) && $daemonset->{status}->{updatedNumberScheduled} =~ /(\d+)/ ? $1 : 0, available => (defined($daemonset->{status}->{numberAvailable})) && $daemonset->{status}->{numberAvailable} =~ /(\d+)/ ? $1 : 0, ready => (defined($daemonset->{status}->{numberReady})) && $daemonset->{status}->{numberReady} =~ /(\d+)/ ? $1 : 0, misscheduled => (defined($daemonset->{status}->{numberMisscheduled})) && $daemonset->{status}->{numberMisscheduled} =~ /(\d+)/ ? $1 : 0 } } if (scalar(keys %{$self->{daemonsets}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No DaemonSets found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check DaemonSet status. =over 8 =item B<--filter-name> Filter DaemonSet name (can be a regexp). =item B<--filter-namespace> Filter DaemonSet namespace (can be a regexp). =item B<--warning-status> Set warning threshold for status (Default: '%{up_to_date} < %{desired}') Can used special variables like: %{name}, %{namespace}, %{desired}, %{current}, %{available}, %{unavailable}, %{up_to_date}, %{ready}, %{misscheduled}. =item B<--critical-status> Set critical threshold for status (Default: '%{available} < %{desired}'). Can used special variables like: %{name}, %{namespace}, %{desired}, %{current}, %{available}, %{unavailable}, %{up_to_date}, %{ready}, %{misscheduled}. =back =cut centreon-plugins-20220113/cloud/kubernetes/mode/deploymentstatus.pm000066400000000000000000000177671417000230700254410ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::kubernetes::mode::deploymentstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => 'desired', nlabel => 'deployment.replicas.desired.count', value => $self->{result_values}->{desired}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{name} : undef, ); $self->{output}->perfdata_add( label => 'current', nlabel => 'deployment.replicas.current.count', value => $self->{result_values}->{current}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{name} : undef, ); $self->{output}->perfdata_add( label => 'available', nlabel => 'deployment.replicas.available.count', value => $self->{result_values}->{available}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{name} : undef, ); $self->{output}->perfdata_add( label => 'ready', nlabel => 'deployment.replicas.ready.count', value => $self->{result_values}->{ready}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{name} : undef, ); $self->{output}->perfdata_add( label => 'up_to_date', nlabel => 'deployment.replicas.uptodate.count', value => $self->{result_values}->{up_to_date}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{name} : undef, ); } sub custom_status_output { my ($self, %options) = @_; return sprintf("Replicas Desired: %s, Current: %s, Available: %s, Ready: %s, Up-to-date: %s", $self->{result_values}->{desired}, $self->{result_values}->{current}, $self->{result_values}->{available}, $self->{result_values}->{ready}, $self->{result_values}->{up_to_date}); } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_name'}; $self->{result_values}->{namespace} = $options{new_datas}->{$self->{instance} . '_namespace'}; $self->{result_values}->{desired} = $options{new_datas}->{$self->{instance} . '_desired'}; $self->{result_values}->{current} = $options{new_datas}->{$self->{instance} . '_current'}; $self->{result_values}->{available} = $options{new_datas}->{$self->{instance} . '_available'}; $self->{result_values}->{ready} = $options{new_datas}->{$self->{instance} . '_ready'}; $self->{result_values}->{up_to_date} = $options{new_datas}->{$self->{instance} . '_up_to_date'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'deployments', type => 1, cb_prefix_output => 'prefix_deployment_output', message_multiple => 'All Deployments status are ok', skipped_code => { -11 => 1 } }, ]; $self->{maps_counters}->{deployments} = [ { label => 'status', set => { key_values => [ { name => 'desired' }, { name => 'current' }, { name => 'up_to_date' }, { name => 'available' }, { name => 'ready' }, { name => 'name' }, { name => 'namespace' } ], closure_custom_calc => $self->can('custom_status_calc'), closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => $self->can('custom_status_perfdata'), closure_custom_threshold_check => \&catalog_status_threshold, } }, ]; } sub prefix_deployment_output { my ($self, %options) = @_; return "Deployment '" . $options{instance_value}->{name} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "filter-namespace:s" => { name => 'filter_namespace' }, "warning-status:s" => { name => 'warning_status', default => '%{up_to_date} < %{desired}' }, "critical-status:s" => { name => 'critical_status', default => '%{available} < %{desired}' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; $self->{deployments} = {}; my $results = $options{custom}->kubernetes_list_deployments(); foreach my $deployment (@{$results}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $deployment->{metadata}->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $deployment->{metadata}->{name} . "': no matching filter name.", debug => 1); next; } if (defined($self->{option_results}->{filter_namespace}) && $self->{option_results}->{filter_namespace} ne '' && $deployment->{metadata}->{namespace} !~ /$self->{option_results}->{filter_namespace}/) { $self->{output}->output_add(long_msg => "skipping '" . $deployment->{metadata}->{namespace} . "': no matching filter namespace.", debug => 1); next; } $self->{deployments}->{$deployment->{metadata}->{uid}} = { name => $deployment->{metadata}->{name}, namespace => $deployment->{metadata}->{namespace}, desired => $deployment->{spec}->{replicas}, current => (defined($deployment->{status}->{replicas})) && $deployment->{status}->{replicas} =~ /(\d+)/ ? $1 : 0, ready => (defined($deployment->{status}->{readyReplicas})) && $deployment->{status}->{readyReplicas} =~ /(\d+)/ ? $1 : 0, up_to_date => (defined($deployment->{status}->{updatedReplicas})) && $deployment->{status}->{updatedReplicas} =~ /(\d+)/ ? $1 : 0, available => (defined($deployment->{status}->{availableReplicas})) && $deployment->{status}->{availableReplicas} =~ /(\d+)/ ? $1 : 0 } } if (scalar(keys %{$self->{deployments}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No Deployments found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check deployment status. =over 8 =item B<--filter-name> Filter deployment name (can be a regexp). =item B<--filter-namespace> Filter deployment namespace (can be a regexp). =item B<--warning-status> Set warning threshold for status (Default: '%{up_to_date} < %{desired}') Can used special variables like: %{name}, %{namespace}, %{desired}, %{current}, %{available}, %{unavailable}, %{up_to_date}. =item B<--critical-status> Set critical threshold for status (Default: '%{available} < %{desired}'). Can used special variables like: %{name}, %{namespace}, %{desired}, %{current}, %{available}, %{unavailable}, %{up_to_date}. =back =cut centreon-plugins-20220113/cloud/kubernetes/mode/discoverynodes.pm000066400000000000000000000064711417000230700250430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::kubernetes::mode::discoverynodes; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "prettify" => { name => 'prettify' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my @disco_data; my $disco_stats; $disco_stats->{start_time} = time(); my $nodes = $options{custom}->kubernetes_list_nodes(); foreach my $node (@{$nodes}) { my %node; $node{name} = $node->{metadata}->{name}; $node{uid} = $node->{metadata}->{uid}; $node{os_image} = $node->{status}->{nodeInfo}->{osImage}; $node{kubelet_version} = $node->{status}->{nodeInfo}->{kubeletVersion}; if (defined($node->{metadata}->{labels}->{'node-role.kubernetes.io/control-plane'})) { $node{node_role} = "control-plane"; } elsif (defined($node->{metadata}->{labels}->{'node-role.kubernetes.io/master'})) { $node{node_role} = "master"; } else { $node{node_role} = "worker"; } foreach my $address (@{$node->{status}->{addresses}}) { $node{internal_ip} = $address->{address} if ($address->{type} eq "InternalIP"); $node{external_ip} = $address->{address} if ($address->{type} eq "ExternalIP"); $node{hostname} = $address->{address} if ($address->{type} eq "Hostname"); } push @disco_data, \%node; } $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; $disco_stats->{discovered_items} = @disco_data; $disco_stats->{results} = \@disco_data; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE Nodes discovery. =over 8 =item B<--prettify> Prettify JSON output. =back =cut centreon-plugins-20220113/cloud/kubernetes/mode/listcronjobs.pm000066400000000000000000000075351417000230700245200ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::kubernetes::mode::listcronjobs; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "filter-namespace:s" => { name => 'filter_namespace' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->kubernetes_list_cronjobs(); foreach my $cronjob (@{$results}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $cronjob->{metadata}->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $cronjob->{metadata}->{name} . "': no matching filter name.", debug => 1); next; } if (defined($self->{option_results}->{filter_namespace}) && $self->{option_results}->{filter_namespace} ne '' && $cronjob->{metadata}->{namespace} !~ /$self->{option_results}->{filter_namespace}/) { $self->{output}->output_add(long_msg => "skipping '" . $cronjob->{metadata}->{namespace} . "': no matching filter namespace.", debug => 1); next; } $self->{cronjobs}->{$cronjob->{metadata}->{uid}} = { uid => $cronjob->{metadata}->{uid}, name => $cronjob->{metadata}->{name}, namespace => $cronjob->{metadata}->{namespace}, } } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $cronjob (sort keys %{$self->{cronjobs}}) { $self->{output}->output_add(long_msg => sprintf("[uid = %s] [name = %s] [namespace = %s]", $self->{cronjobs}->{$cronjob}->{uid}, $self->{cronjobs}->{$cronjob}->{name}, $self->{cronjobs}->{$cronjob}->{namespace}) ); } $self->{output}->output_add(severity => 'OK', short_msg => 'List cronjobs:'); $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 => ['uid', 'name', 'namespace']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $cronjob (sort keys %{$self->{cronjobs}}) { $self->{output}->add_disco_entry( uid => $self->{cronjobs}->{$cronjob}->{uid}, name => $self->{cronjobs}->{$cronjob}->{name}, namespace => $self->{cronjobs}->{$cronjob}->{namespace}, ); } } 1; __END__ =head1 MODE List cronjobs. =over 8 =item B<--filter-name> Filter cronjob name (can be a regexp). =item B<--filter-namespace> Filter cronjob namespace (can be a regexp). =back =cut centreon-plugins-20220113/cloud/kubernetes/mode/listdaemonsets.pm000066400000000000000000000100331417000230700250260ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::kubernetes::mode::listdaemonsets; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "filter-namespace:s" => { name => 'filter_namespace' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->kubernetes_list_daemonsets(); foreach my $daemonset (@{$results}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $daemonset->{metadata}->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $daemonset->{metadata}->{name} . "': no matching filter name.", debug => 1); next; } if (defined($self->{option_results}->{filter_namespace}) && $self->{option_results}->{filter_namespace} ne '' && $daemonset->{metadata}->{namespace} !~ /$self->{option_results}->{filter_namespace}/) { $self->{output}->output_add(long_msg => "skipping '" . $daemonset->{metadata}->{namespace} . "': no matching filter namespace.", debug => 1); next; } $self->{daemonsets}->{$daemonset->{metadata}->{uid}} = { uid => $daemonset->{metadata}->{uid}, name => $daemonset->{metadata}->{name}, namespace => $daemonset->{metadata}->{namespace}, } } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $daemonset (sort keys %{$self->{daemonsets}}) { $self->{output}->output_add(long_msg => sprintf("[uid = %s] [name = %s] [namespace = %s]", $self->{daemonsets}->{$daemonset}->{uid}, $self->{daemonsets}->{$daemonset}->{name}, $self->{daemonsets}->{$daemonset}->{namespace})); } $self->{output}->output_add(severity => 'OK', short_msg => 'List daemonsets:'); $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 => ['uid', 'name', 'namespace']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $daemonset (sort keys %{$self->{daemonsets}}) { $self->{output}->add_disco_entry( uid => $self->{daemonsets}->{$daemonset}->{uid}, name => $self->{daemonsets}->{$daemonset}->{name}, namespace => $self->{daemonsets}->{$daemonset}->{namespace}, ); } } 1; __END__ =head1 MODE List daemonsets. =over 8 =item B<--filter-name> Filter daemonset name (can be a regexp). =item B<--filter-namespace> Filter daemonset namespace (can be a regexp). =back =cut centreon-plugins-20220113/cloud/kubernetes/mode/listdeployments.pm000066400000000000000000000100731417000230700252330ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::kubernetes::mode::listdeployments; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "filter-namespace:s" => { name => 'filter_namespace' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->kubernetes_list_deployments(); foreach my $deployment (@{$results}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $deployment->{metadata}->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $deployment->{metadata}->{name} . "': no matching filter name.", debug => 1); next; } if (defined($self->{option_results}->{filter_namespace}) && $self->{option_results}->{filter_namespace} ne '' && $deployment->{metadata}->{namespace} !~ /$self->{option_results}->{filter_namespace}/) { $self->{output}->output_add(long_msg => "skipping '" . $deployment->{metadata}->{namespace} . "': no matching filter namespace.", debug => 1); next; } $self->{deployments}->{$deployment->{metadata}->{uid}} = { uid => $deployment->{metadata}->{uid}, name => $deployment->{metadata}->{name}, namespace => $deployment->{metadata}->{namespace}, } } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $deployment (sort keys %{$self->{deployments}}) { $self->{output}->output_add(long_msg => sprintf("[uid = %s] [name = %s] [namespace = %s]", $self->{deployments}->{$deployment}->{uid}, $self->{deployments}->{$deployment}->{name}, $self->{deployments}->{$deployment}->{namespace})); } $self->{output}->output_add(severity => 'OK', short_msg => 'List deployments:'); $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 => ['uid', 'name', 'namespace']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $deployment (sort keys %{$self->{deployments}}) { $self->{output}->add_disco_entry( uid => $self->{deployments}->{$deployment}->{uid}, name => $self->{deployments}->{$deployment}->{name}, namespace => $self->{deployments}->{$deployment}->{namespace}, ); } } 1; __END__ =head1 MODE List deployments. =over 8 =item B<--filter-name> Filter deployment name (can be a regexp). =item B<--filter-namespace> Filter deployment namespace (can be a regexp). =back =cut centreon-plugins-20220113/cloud/kubernetes/mode/listingresses.pm000066400000000000000000000077501417000230700247020ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::kubernetes::mode::listingresses; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "filter-namespace:s" => { name => 'filter_namespace' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->kubernetes_list_ingresses(); foreach my $ingress (@{$results}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $ingress->{metadata}->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $ingress->{metadata}->{name} . "': no matching filter name.", debug => 1); next; } if (defined($self->{option_results}->{filter_namespace}) && $self->{option_results}->{filter_namespace} ne '' && $ingress->{metadata}->{namespace} !~ /$self->{option_results}->{filter_namespace}/) { $self->{output}->output_add(long_msg => "skipping '" . $ingress->{metadata}->{namespace} . "': no matching filter namespace.", debug => 1); next; } $self->{ingresses}->{$ingress->{metadata}->{uid}} = { uid => $ingress->{metadata}->{uid}, name => $ingress->{metadata}->{name}, namespace => $ingress->{metadata}->{namespace}, } } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $ingress (sort keys %{$self->{ingresses}}) { $self->{output}->output_add(long_msg => sprintf("[uid = %s] [name = %s] [namespace = %s]", $self->{ingresses}->{$ingress}->{uid}, $self->{ingresses}->{$ingress}->{name}, $self->{ingresses}->{$ingress}->{namespace})); } $self->{output}->output_add(severity => 'OK', short_msg => 'List ingresses:'); $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 => ['uid', 'name', 'namespace']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $ingress (sort keys %{$self->{ingresses}}) { $self->{output}->add_disco_entry( uid => $self->{ingresses}->{$ingress}->{uid}, name => $self->{ingresses}->{$ingress}->{name}, namespace => $self->{ingresses}->{$ingress}->{namespace}, ); } } 1; __END__ =head1 MODE List ingresses. =over 8 =item B<--filter-name> Filter ingress name (can be a regexp). =item B<--filter-namespace> Filter ingress namespace (can be a regexp). =back =cut centreon-plugins-20220113/cloud/kubernetes/mode/listnamespaces.pm000066400000000000000000000063431417000230700250140ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::kubernetes::mode::listnamespaces; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->kubernetes_list_namespaces(); foreach my $namespace (@{$results}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $namespace->{metadata}->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $namespace->{metadata}->{name} . "': no matching filter name.", debug => 1); next; } $self->{namespaces}->{$namespace->{metadata}->{uid}} = { uid => $namespace->{metadata}->{uid}, name => $namespace->{metadata}->{name}, } } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $namespace (sort keys %{$self->{namespaces}}) { $self->{output}->output_add(long_msg => sprintf("[uid = %s] [name = %s]", $self->{namespaces}->{$namespace}->{uid}, $self->{namespaces}->{$namespace}->{name})); } $self->{output}->output_add(severity => 'OK', short_msg => 'List namespaces:'); $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 => ['uid', 'name']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $namespace (sort keys %{$self->{namespaces}}) { $self->{output}->add_disco_entry( uid => $self->{namespaces}->{$namespace}->{uid}, name => $self->{namespaces}->{$namespace}->{name}, ); } } 1; __END__ =head1 MODE List namespaces. =over 8 =item B<--filter-name> Filter namespace name (can be a regexp). =back =cut centreon-plugins-20220113/cloud/kubernetes/mode/listnodes.pm000066400000000000000000000061531417000230700240040ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::kubernetes::mode::listnodes; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->kubernetes_list_nodes(); foreach my $node (@{$results}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $node->{metadata}->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $node->{metadata}->{name} . "': no matching filter name.", debug => 1); next; } $self->{nodes}->{$node->{metadata}->{uid}} = { uid => $node->{metadata}->{uid}, name => $node->{metadata}->{name}, } } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $node (sort keys %{$self->{nodes}}) { $self->{output}->output_add(long_msg => sprintf("[uid = %s] [name = %s]", $self->{nodes}->{$node}->{uid}, $self->{nodes}->{$node}->{name})); } $self->{output}->output_add(severity => 'OK', short_msg => 'List nodes:'); $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 => ['uid', 'name']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $node (sort keys %{$self->{nodes}}) { $self->{output}->add_disco_entry( uid => $self->{nodes}->{$node}->{uid}, name => $self->{nodes}->{$node}->{name}, ); } } 1; __END__ =head1 MODE List nodes. =over 8 =item B<--filter-name> Filter node name (can be a regexp). =back =cut centreon-plugins-20220113/cloud/kubernetes/mode/listpersistentvolumes.pm000066400000000000000000000060531417000230700265060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::kubernetes::mode::listpersistentvolumes; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->kubernetes_list_pvs(); foreach my $pv (@{$results}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $pv->{metadata}->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $pv->{metadata}->{name} . "': no matching filter name.", debug => 1); next; } $self->{pvs}->{$pv->{metadata}->{uid}} = { uid => $pv->{metadata}->{uid}, name => $pv->{metadata}->{name} } } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $pv (sort keys %{$self->{pvs}}) { $self->{output}->output_add(long_msg => sprintf("[uid = %s] [name = %s]", $self->{pvs}->{$pv}->{uid}, $self->{pvs}->{$pv}->{name}) ); } $self->{output}->output_add(severity => 'OK', short_msg => 'List persistent volumes:'); $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 => ['uid', 'name']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $pv (sort keys %{$self->{pvs}}) { $self->{output}->add_disco_entry( uid => $self->{pvs}->{$pv}->{uid}, name => $self->{pvs}->{$pv}->{name} ); } } 1; __END__ =head1 MODE List persistent volumes. =over 8 =item B<--filter-name> Filter persistent volumes name (can be a regexp). =back =cut centreon-plugins-20220113/cloud/kubernetes/mode/listpods.pm000066400000000000000000000107171417000230700236420ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::kubernetes::mode::listpods; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "filter-namespace:s" => { name => 'filter_namespace' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->kubernetes_list_pods(); foreach my $pod (@{$results}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $pod->{metadata}->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $pod->{metadata}->{name} . "': no matching filter name.", debug => 1); next; } if (defined($self->{option_results}->{filter_namespace}) && $self->{option_results}->{filter_namespace} ne '' && $pod->{metadata}->{namespace} !~ /$self->{option_results}->{filter_namespace}/) { $self->{output}->output_add(long_msg => "skipping '" . $pod->{metadata}->{namespace} . "': no matching filter namespace.", debug => 1); next; } $self->{pods}->{$pod->{metadata}->{uid}} = { uid => $pod->{metadata}->{uid}, name => $pod->{metadata}->{name}, namespace => $pod->{metadata}->{namespace}, node => $pod->{spec}->{nodeName}, status => $pod->{status}->{phase}, ip => $pod->{status}->{podIP}, } } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $pod (sort keys %{$self->{pods}}) { $self->{output}->output_add(long_msg => sprintf("[uid = %s] [name = %s] [namespace = %s] [node = %s] [status = %s] [ip = %s]", $self->{pods}->{$pod}->{uid}, $self->{pods}->{$pod}->{name}, $self->{pods}->{$pod}->{namespace}, $self->{pods}->{$pod}->{node}, $self->{pods}->{$pod}->{status}, $self->{pods}->{$pod}->{ip})); } $self->{output}->output_add(severity => 'OK', short_msg => 'List pods:'); $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 => ['uid', 'name', 'namespace', 'node', 'status', 'ip']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $pod (sort keys %{$self->{pods}}) { $self->{output}->add_disco_entry( uid => $self->{pods}->{$pod}->{uid}, name => $self->{pods}->{$pod}->{name}, namespace => $self->{pods}->{$pod}->{namespace}, namespace => $self->{pods}->{$pod}->{node}, namespace => $self->{pods}->{$pod}->{status}, namespace => $self->{pods}->{$pod}->{ip}, ); } } 1; __END__ =head1 MODE List pods. =over 8 =item B<--filter-name> Filter pod name (can be a regexp). =item B<--filter-namespace> Filter pod namespace (can be a regexp). =back =cut centreon-plugins-20220113/cloud/kubernetes/mode/listreplicasets.pm000066400000000000000000000100731417000230700252060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::kubernetes::mode::listreplicasets; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "filter-namespace:s" => { name => 'filter_namespace' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->kubernetes_list_replicasets(); foreach my $replicaset (@{$results}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $replicaset->{metadata}->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $replicaset->{metadata}->{name} . "': no matching filter name.", debug => 1); next; } if (defined($self->{option_results}->{filter_namespace}) && $self->{option_results}->{filter_namespace} ne '' && $replicaset->{metadata}->{namespace} !~ /$self->{option_results}->{filter_namespace}/) { $self->{output}->output_add(long_msg => "skipping '" . $replicaset->{metadata}->{namespace} . "': no matching filter namespace.", debug => 1); next; } $self->{replicasets}->{$replicaset->{metadata}->{uid}} = { uid => $replicaset->{metadata}->{uid}, name => $replicaset->{metadata}->{name}, namespace => $replicaset->{metadata}->{namespace}, } } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $replicaset (sort keys %{$self->{replicasets}}) { $self->{output}->output_add(long_msg => sprintf("[uid = %s] [name = %s] [namespace = %s]", $self->{replicasets}->{$replicaset}->{uid}, $self->{replicasets}->{$replicaset}->{name}, $self->{replicasets}->{$replicaset}->{namespace})); } $self->{output}->output_add(severity => 'OK', short_msg => 'List replicasets:'); $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 => ['uid', 'name', 'namespace']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $replicaset (sort keys %{$self->{replicasets}}) { $self->{output}->add_disco_entry( uid => $self->{replicasets}->{$replicaset}->{uid}, name => $self->{replicasets}->{$replicaset}->{name}, namespace => $self->{replicasets}->{$replicaset}->{namespace}, ); } } 1; __END__ =head1 MODE List replicasets. =over 8 =item B<--filter-name> Filter replicaset name (can be a regexp). =item B<--filter-namespace> Filter replicaset namespace (can be a regexp). =back =cut centreon-plugins-20220113/cloud/kubernetes/mode/listreplicationcontrollers.pm000066400000000000000000000074401417000230700274740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::kubernetes::mode::listreplicationcontrollers; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "filter-namespace:s" => { name => 'filter_namespace' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->kubernetes_list_rcs(); foreach my $rc (@{$results}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $rc->{metadata}->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $rc->{metadata}->{name} . "': no matching filter name.", debug => 1); next; } if (defined($self->{option_results}->{filter_namespace}) && $self->{option_results}->{filter_namespace} ne '' && $rc->{metadata}->{namespace} !~ /$self->{option_results}->{filter_namespace}/) { $self->{output}->output_add(long_msg => "skipping '" . $rc->{metadata}->{namespace} . "': no matching filter namespace.", debug => 1); next; } $self->{rcs}->{$rc->{metadata}->{uid}} = { uid => $rc->{metadata}->{uid}, name => $rc->{metadata}->{name}, namespace => $rc->{metadata}->{namespace}, } } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $rc (sort keys %{$self->{rcs}}) { $self->{output}->output_add(long_msg => sprintf("[uid = %s] [name = %s] [namespace = %s]", $self->{rcs}->{$rc}->{uid}, $self->{rcs}->{$rc}->{name}, $self->{rcs}->{$rc}->{namespace}) ); } $self->{output}->output_add(severity => 'OK', short_msg => 'List replication controllers:'); $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 => ['uid', 'name', 'namespace']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $rc (sort keys %{$self->{rcs}}) { $self->{output}->add_disco_entry( uid => $self->{rcs}->{$rc}->{uid}, name => $self->{rcs}->{$rc}->{name}, namespace => $self->{rcs}->{$rc}->{namespace}, ); } } 1; __END__ =head1 MODE List replication controllers. =over 8 =item B<--filter-name> Filter replication controller name (can be a regexp). =item B<--filter-namespace> Filter replication controller namespace (can be a regexp). =back =cut centreon-plugins-20220113/cloud/kubernetes/mode/listservices.pm000066400000000000000000000077331417000230700245240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::kubernetes::mode::listservices; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "filter-namespace:s" => { name => 'filter_namespace' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->kubernetes_list_services(); foreach my $service (@{$results}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $service->{metadata}->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $service->{metadata}->{name} . "': no matching filter name.", debug => 1); next; } if (defined($self->{option_results}->{filter_namespace}) && $self->{option_results}->{filter_namespace} ne '' && $service->{metadata}->{namespace} !~ /$self->{option_results}->{filter_namespace}/) { $self->{output}->output_add(long_msg => "skipping '" . $service->{metadata}->{namespace} . "': no matching filter namespace.", debug => 1); next; } $self->{services}->{$service->{metadata}->{uid}} = { uid => $service->{metadata}->{uid}, name => $service->{metadata}->{name}, namespace => $service->{metadata}->{namespace}, } } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $service (sort keys %{$self->{services}}) { $self->{output}->output_add(long_msg => sprintf("[uid = %s] [name = %s] [namespace = %s]", $self->{services}->{$service}->{uid}, $self->{services}->{$service}->{name}, $self->{services}->{$service}->{namespace})); } $self->{output}->output_add(severity => 'OK', short_msg => 'List services:'); $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 => ['uid', 'name', 'namespace']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $service (sort keys %{$self->{services}}) { $self->{output}->add_disco_entry( uid => $self->{services}->{$service}->{uid}, name => $self->{services}->{$service}->{name}, namespace => $self->{services}->{$service}->{namespace}, ); } } 1; __END__ =head1 MODE List services. =over 8 =item B<--filter-name> Filter service name (can be a regexp). =item B<--filter-namespace> Filter service namespace (can be a regexp). =back =cut centreon-plugins-20220113/cloud/kubernetes/mode/liststatefulsets.pm000066400000000000000000000101331417000230700254130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::kubernetes::mode::liststatefulsets; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "filter-namespace:s" => { name => 'filter_namespace' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->kubernetes_list_statefulsets(); foreach my $statefulset (@{$results}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $statefulset->{metadata}->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $statefulset->{metadata}->{name} . "': no matching filter name.", debug => 1); next; } if (defined($self->{option_results}->{filter_namespace}) && $self->{option_results}->{filter_namespace} ne '' && $statefulset->{metadata}->{namespace} !~ /$self->{option_results}->{filter_namespace}/) { $self->{output}->output_add(long_msg => "skipping '" . $statefulset->{metadata}->{namespace} . "': no matching filter namespace.", debug => 1); next; } $self->{statefulsets}->{$statefulset->{metadata}->{uid}} = { uid => $statefulset->{metadata}->{uid}, name => $statefulset->{metadata}->{name}, namespace => $statefulset->{metadata}->{namespace}, } } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $statefulset (sort keys %{$self->{statefulsets}}) { $self->{output}->output_add(long_msg => sprintf("[uid = %s] [name = %s] [namespace = %s]", $self->{statefulsets}->{$statefulset}->{uid}, $self->{statefulsets}->{$statefulset}->{name}, $self->{statefulsets}->{$statefulset}->{namespace})); } $self->{output}->output_add(severity => 'OK', short_msg => 'List statefulsets:'); $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 => ['uid', 'name', 'namespace']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $statefulset (sort keys %{$self->{statefulsets}}) { $self->{output}->add_disco_entry( uid => $self->{statefulsets}->{$statefulset}->{uid}, name => $self->{statefulsets}->{$statefulset}->{name}, namespace => $self->{statefulsets}->{$statefulset}->{namespace}, ); } } 1; __END__ =head1 MODE List statefulsets. =over 8 =item B<--filter-name> Filter statefulset name (can be a regexp). =item B<--filter-namespace> Filter statefulset namespace (can be a regexp). =back =cut centreon-plugins-20220113/cloud/kubernetes/mode/nodestatus.pm000066400000000000000000000131171417000230700241670ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::kubernetes::mode::nodestatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_condition_status_output { my ($self, %options) = @_; return sprintf("Status is '%s', Reason: '%s', Message: '%s'", $self->{result_values}->{status}, $self->{result_values}->{reason}, $self->{result_values}->{message}); } sub custom_condition_status_calc { my ($self, %options) = @_; $self->{result_values}->{type} = $options{new_datas}->{$self->{instance} . '_type'}; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; $self->{result_values}->{reason} = $options{new_datas}->{$self->{instance} . '_reason'}; $self->{result_values}->{message} = $options{new_datas}->{$self->{instance} . '_message'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'nodes', type => 3, cb_prefix_output => 'prefix_output', cb_long_output => 'long_output', message_multiple => 'All Nodes status are ok', indent_long_output => ' ', group => [ { name => 'conditions', display_long => 1, cb_prefix_output => 'prefix_condition_output', message_multiple => 'Conditions are ok', type => 1, skipped_code => { -10 => 1 } }, ] } ]; $self->{maps_counters}->{conditions} = [ { label => 'status', set => { key_values => [ { name => 'type' }, { name => 'status' }, { name => 'reason' }, { name => 'message' } ], closure_custom_calc => $self->can('custom_condition_status_calc'), closure_custom_output => $self->can('custom_condition_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold, } }, ]; } sub prefix_output { my ($self, %options) = @_; return "Node '" . $options{instance_value}->{display} . "' "; } sub prefix_condition_output { my ($self, %options) = @_; return "Condition '" . $options{instance_value}->{type} . "' "; } sub long_output { my ($self, %options) = @_; return "Checking node '" . $options{instance_value}->{display} . "'"; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "warning-status:s" => { name => 'warning_status', default => '' }, "critical-status:s" => { name => 'critical_status', default => '(%{type} =~ /Ready/i && %{status} !~ /True/i) || (%{type} =~ /.*Pressure/i && %{status} !~ /False/i)' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; $self->{nodes} = {}; my $results = $options{custom}->kubernetes_list_nodes(); foreach my $node (@{$results}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $node->{metadata}->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $node->{metadata}->{name} . "': no matching filter name.", debug => 1); next; } $self->{nodes}->{$node->{metadata}->{uid}}->{display} = $node->{metadata}->{name}; foreach my $condition (@{$node->{status}->{conditions}}) { $self->{nodes}->{$node->{metadata}->{uid}}->{conditions}->{$condition->{type}} = { type => $condition->{type}, status => $condition->{status}, reason => $condition->{reason}, message => $condition->{message} }; } } if (scalar(keys %{$self->{nodes}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No Nodes found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check node status. =over 8 =item B<--filter-name> Filter node name (can be a regexp). =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{type}, %{status}, %{reason}, %{message}. =item B<--critical-status> Set critical threshold for status (Default: '(%{type} =~ /Ready/i && %{status} !~ /True/i) || (%{type} =~ /.*Pressure/i && %{status} !~ /False/i)'). Can used special variables like: %{type}, %{status}, %{reason}, %{message}. =back =cut centreon-plugins-20220113/cloud/kubernetes/mode/nodeusage.pm000066400000000000000000000271751417000230700237610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::kubernetes::mode::nodeusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_cpu_output { my ($self, %options) = @_; return sprintf( 'CPU %s: %.2f%% (%s/%s)', $self->{result_values}->{flavor}, $self->{result_values}->{'cpu_' . $self->{result_values}->{flavor} . '_prct'}, $self->{result_values}->{'cpu_' . $self->{result_values}->{flavor}}, $self->{result_values}->{cpu_allocatable} ); } sub custom_cpu_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{flavor} = $options{extra_options}->{flavor}; $self->{result_values}->{cpu_allocatable} = $options{new_datas}->{$self->{instance} . '_cpu_allocatable'}; $self->{result_values}->{'cpu_' . $self->{result_values}->{flavor}} = $options{new_datas}->{$self->{instance} . '_cpu_' . $self->{result_values}->{flavor}}; $self->{result_values}->{'cpu_' . $self->{result_values}->{flavor} . '_prct'} = ($self->{result_values}->{cpu_allocatable} > 0) ? $self->{result_values}->{'cpu_' . $self->{result_values}->{flavor}} * 100 / $self->{result_values}->{cpu_allocatable} : 0; return 0; } sub custom_memory_output { my ($self, %options) = @_; return sprintf( 'Memory %s: %.2f%% (%s%s/%s%s)', $self->{result_values}->{flavor}, $self->{result_values}->{'memory_' . $self->{result_values}->{flavor} . '_prct'}, $self->{perfdata}->change_bytes(value => $self->{result_values}->{'memory_' . $self->{result_values}->{flavor}}), $self->{perfdata}->change_bytes(value => $self->{result_values}->{memory_allocatable}) ); } sub custom_memory_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{flavor} = $options{extra_options}->{flavor}; $self->{result_values}->{memory_allocatable} = $options{new_datas}->{$self->{instance} . '_memory_allocatable'}; $self->{result_values}->{'memory_' . $self->{result_values}->{flavor}} = $options{new_datas}->{$self->{instance} . '_memory_' . $self->{result_values}->{flavor}}; $self->{result_values}->{'memory_' . $self->{result_values}->{flavor} . '_prct'} = ($self->{result_values}->{memory_allocatable} > 0) ? $self->{result_values}->{'memory_' . $self->{result_values}->{flavor}} * 100 / $self->{result_values}->{memory_allocatable} : 0; return 0; } sub custom_pods_output { my ($self, %options) = @_; return sprintf( 'Pods allocation: %.2f%% (%s/%s)', $self->{result_values}->{pods_allocated_prct}, $self->{result_values}->{pods_allocated}, $self->{result_values}->{pods_allocatable} ); } sub custom_pods_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{pods_allocatable} = $options{new_datas}->{$self->{instance} . '_pods_allocatable'}; $self->{result_values}->{pods_allocated} = $options{new_datas}->{$self->{instance} . '_pods_allocated'}; $self->{result_values}->{pods_allocated_prct} = ($self->{result_values}->{pods_allocatable} > 0) ? $self->{result_values}->{pods_allocated} * 100 / $self->{result_values}->{pods_allocatable} : 0; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'nodes', type => 1, cb_prefix_output => 'prefix_node_output', message_multiple => 'All Nodes usage are ok', skipped_code => { -11 => 1 } }, ]; $self->{maps_counters}->{nodes} = [ { label => 'cpu-requests', nlabel => 'cpu.requests.percentage', set => { key_values => [ { name => 'cpu_allocatable' }, { name => 'cpu_requests' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_cpu_calc'), closure_custom_calc_extra_options => { flavor => 'requests' }, closure_custom_output => $self->can('custom_cpu_output'), perfdatas => [ { label => 'cpu_requests', value => 'cpu_requests_prct', template => '%.2f', min => 0, max => '100', unit => '%', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'cpu-limits', nlabel => 'cpu.limits.percentage', set => { key_values => [ { name => 'cpu_allocatable' }, { name => 'cpu_limits' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_cpu_calc'), closure_custom_calc_extra_options => { flavor => 'limits' }, closure_custom_output => $self->can('custom_cpu_output'), perfdatas => [ { label => 'cpu_limits', value => 'cpu_limits_prct', template => '%.2f', min => 0, max => '100', unit => '%', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'memory-requests', nlabel => 'memory.requests.percentage', set => { key_values => [ { name => 'memory_allocatable' }, { name => 'memory_requests' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_memory_calc'), closure_custom_calc_extra_options => { flavor => 'requests' }, closure_custom_output => $self->can('custom_memory_output'), perfdatas => [ { label => 'memory_requests', value => 'memory_requests_prct', template => '%.2f', min => 0, max => '100', unit => '%', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'memory-limits', nlabel => 'memory.limits.percentage', set => { key_values => [ { name => 'memory_allocatable' }, { name => 'memory_limits' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_memory_calc'), closure_custom_calc_extra_options => { flavor => 'limits' }, closure_custom_output => $self->can('custom_memory_output'), perfdatas => [ { label => 'memory_limits', value => 'memory_limits_prct', template => '%.2f', min => 0, max => '100', unit => '%', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'allocated-pods', nlabel => 'pods.allocation.percentage', set => { key_values => [ { name => 'pods_allocatable' }, { name => 'pods_allocated' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_pods_calc'), closure_custom_output => $self->can('custom_pods_output'), perfdatas => [ { label => 'allocated_pods', value => 'pods_allocated_prct', template => '%.2f', min => 0, max => '100', unit => '%', label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub prefix_node_output { my ($self, %options) = @_; return "Node '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "units:s" => { name => 'units', default => '%' }, # Keep compat }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; $self->{nodes} = {}; my $nodes = $options{custom}->kubernetes_list_nodes(); foreach my $node (@{$nodes}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $node->{metadata}->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $node->{metadata}->{name} . "': no matching filter name.", debug => 1); next; } $self->{nodes}->{$node->{metadata}->{name}} = { display => $node->{metadata}->{name}, pods_allocatable => $node->{status}->{allocatable}->{pods}, cpu_allocatable => $self->to_bytes(value => $node->{status}->{allocatable}->{cpu}), memory_allocatable => $self->to_bytes(value => $node->{status}->{capacity}->{memory}), } } if (scalar(keys %{$self->{nodes}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No Nodes found."); $self->{output}->option_exit(); } my $pods = $options{custom}->kubernetes_list_pods(); foreach my $pod (@{$pods}) { next if (defined($pod->{spec}->{nodeName}) && !defined($self->{nodes}->{$pod->{spec}->{nodeName}})); $self->{nodes}->{$pod->{spec}->{nodeName}}->{pods_allocated}++; foreach my $container (@{$pod->{spec}->{containers}}) { $self->{nodes}->{$pod->{spec}->{nodeName}}->{cpu_requests} += $self->to_core(value => $container->{resources}->{requests}->{cpu}) if (defined($container->{resources}->{requests}->{cpu})); $self->{nodes}->{$pod->{spec}->{nodeName}}->{cpu_limits} += $self->to_core(value => $container->{resources}->{limits}->{cpu}) if (defined($container->{resources}->{limits}->{cpu})); $self->{nodes}->{$pod->{spec}->{nodeName}}->{memory_requests} += $self->to_bytes(value => $container->{resources}->{requests}->{memory}) if (defined($container->{resources}->{requests}->{memory})); $self->{nodes}->{$pod->{spec}->{nodeName}}->{memory_limits} += $self->to_bytes(value => $container->{resources}->{limits}->{memory}) if (defined($container->{resources}->{limits}->{memory})); } } } sub to_bytes { my ($self, %options) = @_; my $value = $options{value}; if ($value =~ /(\d+)Ki$/) { $value = $1 * 1024; } elsif ($value =~ /(\d+)Mi$/) { $value = $1 * 1024 * 1024; } elsif ($value =~ /(\d+)Gi$/) { $value = $1 * 1024 * 1024 * 1024; } elsif ($value =~ /(\d+)Ti$/) { $value = $1 * 1024 * 1024 * 1024 * 1024; } return $value; } sub to_core { my ($self, %options) = @_; my $value = $options{value}; if ($value =~ /(\d+)m$/) { $value = $1 / 1000; } return $value; } 1; __END__ =head1 MODE Check node usage. =over 8 =item B<--filter-name> Filter node name (can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds (in percentage). Can be: 'cpu-requests', 'cpu-limits', 'memory-requests', 'memory-limits', 'allocated-pods'. =back =cut centreon-plugins-20220113/cloud/kubernetes/mode/persistentvolumestatus.pm000066400000000000000000000104021417000230700266640ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::kubernetes::mode::persistentvolumestatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; return sprintf("Phase is '%s'", $self->{result_values}->{phase}); } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_name'}; $self->{result_values}->{phase} = $options{new_datas}->{$self->{instance} . '_phase'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'pvs', type => 1, cb_prefix_output => 'prefix_pv_output', message_multiple => 'All PersistentVolumes status are ok', skipped_code => { -11 => 1 } }, ]; $self->{maps_counters}->{pvs} = [ { label => 'status', set => { key_values => [ { name => 'phase' }, { name => 'name' } ], 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 => \&catalog_status_threshold, } }, ]; } sub prefix_pv_output { my ($self, %options) = @_; return "Persistent Volume '" . $options{instance_value}->{name} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "filter-namespace:s" => { name => 'filter_namespace' }, "warning-status:s" => { name => 'warning_status', default => '' }, "critical-status:s" => { name => 'critical_status', default => '%{phase} !~ /Bound|Available|Released/i' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; $self->{pvs} = {}; my $results = $options{custom}->kubernetes_list_pvs(); foreach my $pv (@{$results}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $pv->{metadata}->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $pv->{metadata}->{name} . "': no matching filter name.", debug => 1); next; } $self->{pvs}->{$pv->{metadata}->{uid}} = { name => $pv->{metadata}->{name}, phase => $pv->{status}->{phase} } } if (scalar(keys %{$self->{pvs}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No PersistentVolumes found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check persistent volume status. =over 8 =item B<--filter-name> Filter persistent volume name (can be a regexp). =item B<--warning-status> Set warning threshold for status (Default: '') Can used special variables like: %{name}, %{phase}. =item B<--critical-status> Set critical threshold for status (Default: '%{phase} !~ /Bound|Available|Released/i'). Can used special variables like: %{name}, %{phase}. =back =cut centreon-plugins-20220113/cloud/kubernetes/mode/podstatus.pm000066400000000000000000000312301417000230700240200ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::kubernetes::mode::podstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_pod_status_output { my ($self, %options) = @_; return sprintf( "Status is '%s'", $self->{result_values}->{status} ); } sub custom_container_status_output { my ($self, %options) = @_; return sprintf( "Status is '%s', State is '%s'", $self->{result_values}->{status}, $self->{result_values}->{state} ); } sub custom_container_status_calc { my ($self, %options) = @_; $self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_name'}; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; $self->{result_values}->{state} = ($options{new_datas}->{$self->{instance} . '_state'} == 1) ? 'ready' : 'not ready'; return 0; } sub custom_ready_perfdata { my ($self, %options) = @_; my $value_perf = $self->{result_values}->{ready}; my %total_options = (); if ($self->{result_values}->{total} > 0 && $self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } $self->{output}->perfdata_add( label => 'containers_ready', nlabel => 'containers.ready.count', 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 => $total_options{total}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{name} : undef ); } sub custom_ready_threshold { my ($self, %options) = @_; my ($exit, $threshold_value); $threshold_value = $self->{result_values}->{ready}; if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_ready}; } $exit = $self->{perfdata}->threshold_check( value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_ready_output { my ($self, %options) = @_; return sprintf( "Containers Ready: %s/%s (%.2f%%)", $self->{result_values}->{ready}, $self->{result_values}->{total}, $self->{result_values}->{prct_ready} ); } sub custom_ready_calc { my ($self, %options) = @_; $self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_name'}; $self->{result_values}->{ready} = $options{new_datas}->{$self->{instance} . '_containers_ready'}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_containers_total'}; $self->{result_values}->{prct_ready} = 0; if ($self->{result_values}->{total} > 0) { $self->{result_values}->{prct_ready} = $self->{result_values}->{ready} * 100 / $self->{result_values}->{total}; } return 0; } sub prefix_pod_output { my ($self, %options) = @_; return "Pod '" . $options{instance_value}->{name} . "' "; } sub prefix_container_output { my ($self, %options) = @_; return "Container '" . $options{instance_value}->{name} . "' "; } sub long_output { my ($self, %options) = @_; return "Checking pod '" . $options{instance_value}->{name} . "'"; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'pods', type => 3, cb_prefix_output => 'prefix_pod_output', cb_long_output => 'long_output', message_multiple => 'All Pods status are ok', indent_long_output => ' ', group => [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'containers', display_long => 1, cb_prefix_output => 'prefix_container_output', message_multiple => 'All containers status are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'containers-ready', set => { key_values => [ { name => 'containers_total' }, { name => 'containers_ready' }, { name => 'name' } ], closure_custom_calc => $self->can('custom_ready_calc'), closure_custom_output => $self->can('custom_ready_output'), closure_custom_perfdata => $self->can('custom_ready_perfdata'), closure_custom_threshold_check => $self->can('custom_ready_threshold') } }, { label => 'pod-status', set => { key_values => [ { name => 'status' }, { name => 'name' }, { name => 'namespace' } ], closure_custom_output => $self->can('custom_pod_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } }, { label => 'total-restarts-count', nlabel => 'restarts.total.count', set => { key_values => [ { name => 'restarts_total' }, { name => 'name' } ], output_template => 'Restarts: %d', perfdatas => [ { label => 'restarts_count', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'name' } ] } } ]; $self->{maps_counters}->{containers} = [ { label => 'container-status', set => { key_values => [ { name => 'status' }, { name => 'state' } ], closure_custom_calc => $self->can('custom_container_status_calc'), closure_custom_output => $self->can('custom_container_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } }, { label => 'restarts-count', nlabel => 'containers.restarts.count', set => { key_values => [ { name => 'restarts' }, { name => 'perf' } ], output_template => 'Restarts: %d', perfdatas => [ { label => 'restarts_count', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'perf' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'filter-namespace:s' => { name => 'filter_namespace' }, 'extra-filter:s@' => { name => 'extra_filter' }, 'warning-pod-status:s' => { name => 'warning_pod_status', default => '' }, 'critical-pod-status:s' => { name => 'critical_pod_status', default => '%{status} !~ /running/i' }, 'warning-container-status:s' => { name => 'warning_container_status', default => '' }, 'critical-container-status:s' => { name => 'critical_container_status', default => '%{status} !~ /running/i || %{state} !~ /^ready$/' }, 'units:s' => { name => 'units', default => '%' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{extra_filter} = {}; foreach my $filter (@{$self->{option_results}->{extra_filter}}) { next if ($filter !~ /(.*)=(.*)/); $self->{extra_filter}->{$1} = $2; } $self->change_macros(macros => ['warning_pod_status', 'critical_pod_status', 'warning_container_status', 'critical_container_status']); } sub manage_selection { my ($self, %options) = @_; $self->{pods} = {}; my $results = $options{custom}->kubernetes_list_pods(); foreach my $pod (@{$results}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $pod->{metadata}->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $pod->{metadata}->{name} . "': no matching filter name.", debug => 1); next; } if (defined($self->{option_results}->{filter_namespace}) && $self->{option_results}->{filter_namespace} ne '' && $pod->{metadata}->{namespace} !~ /$self->{option_results}->{filter_namespace}/) { $self->{output}->output_add(long_msg => "skipping '" . $pod->{metadata}->{name} . "': no matching filter namespace.", debug => 1); next; } my $next = 0; foreach my $label (keys %{$self->{extra_filter}}) { if (!defined($pod->{metadata}->{labels}->{$label}) || $pod->{metadata}->{labels}->{$label} !~ /$self->{extra_filter}->{$label}/) { $self->{output}->output_add(long_msg => "skipping '" . $pod->{metadata}->{name} . "': no matching extra filter.", debug => 1); $next = 1; last; } } next if ($next == 1); $self->{pods}->{$pod->{metadata}->{uid}}->{name} = $pod->{metadata}->{name}; $self->{pods}->{$pod->{metadata}->{uid}}->{global} = { name => $pod->{metadata}->{name}, namespace => $pod->{metadata}->{namespace}, status => $pod->{status}->{phase}, containers_total => defined($pod->{status}->{containerStatuses}) ? scalar(@{$pod->{status}->{containerStatuses}}) : 0, containers_ready => 0, restarts_total => 0 }; foreach my $container (@{$pod->{status}->{containerStatuses}}) { $self->{pods}->{$pod->{metadata}->{uid}}->{containers}->{$container->{name}} = { name => $container->{name}, status => keys %{$container->{state}}, state => $container->{ready}, restarts => $container->{restartCount}, perf => $pod->{metadata}->{name} . '_' . $container->{name} }; $self->{pods}->{$pod->{metadata}->{uid}}->{global}->{containers_ready}++ if ($container->{ready}); $self->{pods}->{$pod->{metadata}->{uid}}->{global}->{restarts_total} += $container->{restartCount}; } } if (scalar(keys %{$self->{pods}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No Pods found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check pod status. =over 8 =item B<--filter-name> Filter pod name (can be a regexp). =item B<--filter-namespace> Filter pod namespace (can be a regexp). =item B<--extra-filter> Add an extra filter based on labels (Can be multiple) Example : --extra-filter='app=mynewapp' =item B<--warning-pod-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{name}, %{namespace}. =item B<--critical-pod-status> Set critical threshold for status (Default: '%{status} !~ /running/i'). Can used special variables like: %{status}, %{name}, %{namespace}. =item B<--warning-container-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{name}. =item B<--critical-container-status> Set critical threshold for status (Default: '%{status} !~ /running/i || %{state} !~ /^ready$/'). Can used special variables like: %{status}, %{state}, %{name}. =item B<--warning-*> Threshold warning. Can be: 'containers-ready', 'total-restarts-count' (count), 'restarts-count' (count). =item B<--critical-*> Threshold critical. Can be: 'containers-ready', 'total-restarts-count' (count), 'restarts-count' (count). =item B<--units> Units of thresholds (Default: '%') ('%', 'count'). =back =cut centreon-plugins-20220113/cloud/kubernetes/mode/replicasetstatus.pm000066400000000000000000000151541417000230700254000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::kubernetes::mode::replicasetstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => 'desired', nlabel => 'replicaset.replicas.desired.count', value => $self->{result_values}->{desired}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{name} : undef, ); $self->{output}->perfdata_add( label => 'current', nlabel => 'replicaset.replicas.current.count', value => $self->{result_values}->{current}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{name} : undef, ); $self->{output}->perfdata_add( label => 'ready', nlabel => 'replicaset.replicas.ready.count', value => $self->{result_values}->{ready}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{name} : undef, ); } sub custom_status_output { my ($self, %options) = @_; return sprintf("Replicas Desired: %s, Current: %s, Ready: %s", $self->{result_values}->{desired}, $self->{result_values}->{current}, $self->{result_values}->{ready}); } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_name'}; $self->{result_values}->{namespace} = $options{new_datas}->{$self->{instance} . '_namespace'}; $self->{result_values}->{desired} = $options{new_datas}->{$self->{instance} . '_desired'}; $self->{result_values}->{current} = $options{new_datas}->{$self->{instance} . '_current'}; $self->{result_values}->{ready} = $options{new_datas}->{$self->{instance} . '_ready'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'replicasets', type => 1, cb_prefix_output => 'prefix_replicaset_output', message_multiple => 'All ReplicaSets status are ok', skipped_code => { -11 => 1 } }, ]; $self->{maps_counters}->{replicasets} = [ { label => 'status', set => { key_values => [ { name => 'desired' }, { name => 'current' }, { name => 'ready' }, { name => 'name' }, { name => 'namespace' } ], closure_custom_calc => $self->can('custom_status_calc'), closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => $self->can('custom_status_perfdata'), closure_custom_threshold_check => \&catalog_status_threshold, } }, ]; } sub prefix_replicaset_output { my ($self, %options) = @_; return "ReplicaSet '" . $options{instance_value}->{name} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "filter-namespace:s" => { name => 'filter_namespace' }, "warning-status:s" => { name => 'warning_status', default => '' }, "critical-status:s" => { name => 'critical_status', default => '%{ready} < %{desired}' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; $self->{replicasets} = {}; my $results = $options{custom}->kubernetes_list_replicasets(); foreach my $replicaset (@{$results}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $replicaset->{metadata}->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $replicaset->{metadata}->{name} . "': no matching filter name.", debug => 1); next; } if (defined($self->{option_results}->{filter_namespace}) && $self->{option_results}->{filter_namespace} ne '' && $replicaset->{metadata}->{namespace} !~ /$self->{option_results}->{filter_namespace}/) { $self->{output}->output_add(long_msg => "skipping '" . $replicaset->{metadata}->{namespace} . "': no matching filter namespace.", debug => 1); next; } $self->{replicasets}->{$replicaset->{metadata}->{uid}} = { name => $replicaset->{metadata}->{name}, namespace => $replicaset->{metadata}->{namespace}, desired => $replicaset->{spec}->{replicas}, current => (defined($replicaset->{status}->{replicas})) && $replicaset->{status}->{replicas} =~ /(\d+)/ ? $1 : 0, ready => (defined($replicaset->{status}->{readyReplicas})) && $replicaset->{status}->{readyReplicas} =~ /(\d+)/ ? $1 : 0 } } if (scalar(keys %{$self->{replicasets}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No ReplicaSets found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check ReplicaSet status. =over 8 =item B<--filter-name> Filter ReplicaSet name (can be a regexp). =item B<--filter-namespace> Filter ReplicaSet namespace (can be a regexp). =item B<--warning-status> Set warning threshold for status (Default: '') Can used special variables like: %{name}, %{namespace}, %{desired}, %{current}, %{ready}. =item B<--critical-status> Set critical threshold for status (Default: '%{ready} < %{desired}'). Can used special variables like: %{name}, %{namespace}, %{desired}, %{current}, %{ready}. =back =cut centreon-plugins-20220113/cloud/kubernetes/mode/replicationcontrollerstatus.pm000066400000000000000000000150621417000230700276600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::kubernetes::mode::replicationcontrollerstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => 'desired', nlabel => 'replicationcontroller.replicas.desired.count', value => $self->{result_values}->{desired}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{name} : undef, ); $self->{output}->perfdata_add( label => 'current', nlabel => 'replicationcontroller.replicas.current.count', value => $self->{result_values}->{current}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{name} : undef, ); $self->{output}->perfdata_add( label => 'ready', nlabel => 'replicationcontroller.replicas.ready.count', value => $self->{result_values}->{ready}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{name} : undef, ); } sub custom_status_output { my ($self, %options) = @_; return sprintf("Replicas Desired: %s, Current: %s, Ready: %s", $self->{result_values}->{desired}, $self->{result_values}->{current}, $self->{result_values}->{ready}); } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_name'}; $self->{result_values}->{namespace} = $options{new_datas}->{$self->{instance} . '_namespace'}; $self->{result_values}->{desired} = $options{new_datas}->{$self->{instance} . '_desired'}; $self->{result_values}->{current} = $options{new_datas}->{$self->{instance} . '_current'}; $self->{result_values}->{ready} = $options{new_datas}->{$self->{instance} . '_ready'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'rcs', type => 1, cb_prefix_output => 'prefix_rc_output', message_multiple => 'All ReplicationControllers status are ok', skipped_code => { -11 => 1 } }, ]; $self->{maps_counters}->{rcs} = [ { label => 'status', set => { key_values => [ { name => 'desired' }, { name => 'current' }, { name => 'ready' }, { name => 'name' }, { name => 'namespace' } ], closure_custom_calc => $self->can('custom_status_calc'), closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => $self->can('custom_status_perfdata'), closure_custom_threshold_check => \&catalog_status_threshold, } }, ]; } sub prefix_rc_output { my ($self, %options) = @_; return "ReplicationController '" . $options{instance_value}->{name} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "filter-namespace:s" => { name => 'filter_namespace' }, "warning-status:s" => { name => 'warning_status', default => '' }, "critical-status:s" => { name => 'critical_status', default => '%{ready} < %{desired}' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; $self->{rcs} = {}; my $results = $options{custom}->kubernetes_list_rcs(); foreach my $rc (@{$results}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $rc->{metadata}->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $rc->{metadata}->{name} . "': no matching filter name.", debug => 1); next; } if (defined($self->{option_results}->{filter_namespace}) && $self->{option_results}->{filter_namespace} ne '' && $rc->{metadata}->{namespace} !~ /$self->{option_results}->{filter_namespace}/) { $self->{output}->output_add(long_msg => "skipping '" . $rc->{metadata}->{namespace} . "': no matching filter namespace.", debug => 1); next; } $self->{rcs}->{$rc->{metadata}->{uid}} = { name => $rc->{metadata}->{name}, namespace => $rc->{metadata}->{namespace}, desired => $rc->{spec}->{replicas}, current => (defined($rc->{status}->{replicas})) && $rc->{status}->{replicas} =~ /(\d+)/ ? $1 : 0, ready => (defined($rc->{status}->{readyReplicas})) && $rc->{status}->{readyReplicas} =~ /(\d+)/ ? $1 : 0 } } if (scalar(keys %{$self->{rcs}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No ReplicationControllers found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check ReplicationController status. =over 8 =item B<--filter-name> Filter ReplicationController name (can be a regexp). =item B<--filter-namespace> Filter ReplicationController namespace (can be a regexp). =item B<--warning-status> Set warning threshold for status (Default: '') Can used special variables like: %{name}, %{namespace}, %{desired}, %{current}, %{ready}. =item B<--critical-status> Set critical threshold for status (Default: '%{ready} < %{desired}'). Can used special variables like: %{name}, %{namespace}, %{desired}, %{current}, %{ready}. =back =cut centreon-plugins-20220113/cloud/kubernetes/mode/statefulsetstatus.pm000066400000000000000000000165311417000230700256100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::kubernetes::mode::statefulsetstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => 'desired', nlabel => 'statefulset.replicas.desired.count', value => $self->{result_values}->{desired}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{name} : undef, ); $self->{output}->perfdata_add( label => 'current', nlabel => 'statefulset.replicas.current.count', value => $self->{result_values}->{current}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{name} : undef, ); $self->{output}->perfdata_add( label => 'up_to_date', nlabel => 'statefulset.replicas.uptodate.count', value => $self->{result_values}->{up_to_date}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{name} : undef, ); $self->{output}->perfdata_add( label => 'ready', nlabel => 'statefulset.replicas.ready.count', value => $self->{result_values}->{ready}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{name} : undef, ); } sub custom_status_output { my ($self, %options) = @_; return sprintf("Replicas Desired: %s, Current: %s, Up-to-date: %s, Ready: %s", $self->{result_values}->{desired}, $self->{result_values}->{current}, $self->{result_values}->{up_to_date}, $self->{result_values}->{ready}); } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_name'}; $self->{result_values}->{namespace} = $options{new_datas}->{$self->{instance} . '_namespace'}; $self->{result_values}->{desired} = $options{new_datas}->{$self->{instance} . '_desired'}; $self->{result_values}->{current} = $options{new_datas}->{$self->{instance} . '_current'}; $self->{result_values}->{up_to_date} = $options{new_datas}->{$self->{instance} . '_up_to_date'}; $self->{result_values}->{ready} = $options{new_datas}->{$self->{instance} . '_ready'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'statefulsets', type => 1, cb_prefix_output => 'prefix_statefulset_output', message_multiple => 'All StatefulSets status are ok', skipped_code => { -11 => 1 } }, ]; $self->{maps_counters}->{statefulsets} = [ { label => 'status', set => { key_values => [ { name => 'desired' }, { name => 'current' }, { name => 'up_to_date' }, { name => 'ready' }, { name => 'name' } ], closure_custom_calc => $self->can('custom_status_calc'), closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => $self->can('custom_status_perfdata'), closure_custom_threshold_check => \&catalog_status_threshold, } }, ]; } sub prefix_statefulset_output { my ($self, %options) = @_; return "StatefulSet '" . $options{instance_value}->{name} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "filter-namespace:s" => { name => 'filter_namespace' }, "warning-status:s" => { name => 'warning_status', default => '%{up_to_date} < %{desired}' }, "critical-status:s" => { name => 'critical_status', default => '%{ready} < %{desired}' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; $self->{statefulsets} = {}; my $results = $options{custom}->kubernetes_list_statefulsets(); foreach my $statefulset (@{$results}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $statefulset->{metadata}->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $statefulset->{metadata}->{name} . "': no matching filter name.", debug => 1); next; } if (defined($self->{option_results}->{filter_namespace}) && $self->{option_results}->{filter_namespace} ne '' && $statefulset->{metadata}->{namespace} !~ /$self->{option_results}->{filter_namespace}/) { $self->{output}->output_add(long_msg => "skipping '" . $statefulset->{metadata}->{namespace} . "': no matching filter namespace.", debug => 1); next; } $self->{statefulsets}->{$statefulset->{metadata}->{uid}} = { name => $statefulset->{metadata}->{name}, namespace => $statefulset->{metadata}->{namespace}, desired => $statefulset->{spec}->{replicas}, current => (defined($statefulset->{status}->{currentReplicas})) && $statefulset->{status}->{currentReplicas} =~ /(\d+)/ ? $1 : 0, ready => (defined($statefulset->{status}->{readyReplicas})) && $statefulset->{status}->{readyReplicas} =~ /(\d+)/ ? $1 : 0, up_to_date => (defined($statefulset->{status}->{updatedReplicas})) && $statefulset->{status}->{updatedReplicas} =~ /(\d+)/ ? $1 : 0 } } if (scalar(keys %{$self->{statefulsets}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No StatefulSets found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check StatefulSet status. =over 8 =item B<--filter-name> Filter StatefulSet name (can be a regexp). =item B<--filter-namespace> Filter StatefulSet namespace (can be a regexp). =item B<--warning-status> Set warning threshold for status (Default: '%{up_to_date} < %{desired}') Can used special variables like: %{name}, %{namespace}, %{desired}, %{current}, %{up_to_date}, %{ready}. =item B<--critical-status> Set critical threshold for status (Default: '%{ready} < %{desired}'). Can used special variables like: %{name}, %{namespace}, %{desired}, %{current}, %{up_to_date}, %{ready}. =back =cut centreon-plugins-20220113/cloud/kubernetes/plugin.pm000066400000000000000000000065351417000230700223560ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::kubernetes::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} = '1.0'; %{$self->{modes}} = ( 'cluster-events' => 'cloud::kubernetes::mode::clusterevents', 'cronjob-status' => 'cloud::kubernetes::mode::cronjobstatus', 'daemonset-status' => 'cloud::kubernetes::mode::daemonsetstatus', 'deployment-status' => 'cloud::kubernetes::mode::deploymentstatus', 'discovery-nodes' => 'cloud::kubernetes::mode::discoverynodes', 'list-cronjobs' => 'cloud::kubernetes::mode::listcronjobs', 'list-daemonsets' => 'cloud::kubernetes::mode::listdaemonsets', 'list-deployments' => 'cloud::kubernetes::mode::listdeployments', 'list-ingresses' => 'cloud::kubernetes::mode::listingresses', 'list-namespaces' => 'cloud::kubernetes::mode::listnamespaces', 'list-nodes' => 'cloud::kubernetes::mode::listnodes', 'list-persistentvolumes' => 'cloud::kubernetes::mode::listpersistentvolumes', 'list-pods' => 'cloud::kubernetes::mode::listpods', 'list-replicasets' => 'cloud::kubernetes::mode::listreplicasets', 'list-replicationcontrollers' => 'cloud::kubernetes::mode::listreplicationcontrollers', 'list-services' => 'cloud::kubernetes::mode::listservices', 'list-statefulsets' => 'cloud::kubernetes::mode::liststatefulsets', 'node-status' => 'cloud::kubernetes::mode::nodestatus', 'node-usage' => 'cloud::kubernetes::mode::nodeusage', 'persistentvolume-status' => 'cloud::kubernetes::mode::persistentvolumestatus', 'pod-status' => 'cloud::kubernetes::mode::podstatus', 'replicaset-status' => 'cloud::kubernetes::mode::replicasetstatus', 'replicationcontroller-status' => 'cloud::kubernetes::mode::replicationcontrollerstatus', 'statefulset-status' => 'cloud::kubernetes::mode::statefulsetstatus', ); $self->{custom_modes}{api} = 'cloud::kubernetes::custom::api'; $self->{custom_modes}{kubectl} = 'cloud::kubernetes::custom::kubectl'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Kubernetes cluster using CLI (kubectl) or RestAPI. =cut centreon-plugins-20220113/cloud/microsoft/000077500000000000000000000000001417000230700203475ustar00rootroot00000000000000centreon-plugins-20220113/cloud/microsoft/office365/000077500000000000000000000000001417000230700220405ustar00rootroot00000000000000centreon-plugins-20220113/cloud/microsoft/office365/custom/000077500000000000000000000000001417000230700233525ustar00rootroot00000000000000centreon-plugins-20220113/cloud/microsoft/office365/custom/graphapi.pm000066400000000000000000000372721417000230700255160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::microsoft::office365::custom::graphapi; use strict; use warnings; use DateTime; use centreon::plugins::http; use centreon::plugins::statefile; use JSON::XS; use Text::CSV; use Encode; use URI::Encode; use Digest::MD5 qw(md5_hex); 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 => { 'tenant:s' => { name => 'tenant' }, 'client-id:s' => { name => 'client_id' }, 'client-secret:s' => { name => 'client_secret' }, 'login-endpoint:s' => { name => 'login_endpoint' }, 'graph-endpoint:s' => { name => 'graph_endpoint' }, 'timeout:s' => { name => 'timeout' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); $self->{cache} = centreon::plugins::statefile->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{tenant} = (defined($self->{option_results}->{tenant})) ? $self->{option_results}->{tenant} : undef; $self->{client_id} = (defined($self->{option_results}->{client_id})) ? $self->{option_results}->{client_id} : undef; $self->{client_secret} = (defined($self->{option_results}->{client_secret})) ? $self->{option_results}->{client_secret} : undef; $self->{login_endpoint} = (defined($self->{option_results}->{login_endpoint})) ? $self->{option_results}->{login_endpoint} : 'https://login.microsoftonline.com'; $self->{graph_endpoint} = (defined($self->{option_results}->{graph_endpoint})) ? $self->{option_results}->{graph_endpoint} : 'https://graph.microsoft.com'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; if (!defined($self->{tenant}) || $self->{tenant} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --tenant option."); $self->{output}->option_exit(); } if (!defined($self->{client_id}) || $self->{client_id} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --client-id option."); $self->{output}->option_exit(); } if (!defined($self->{client_secret}) || $self->{client_secret} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --client-secret option."); $self->{output}->option_exit(); } $self->{cache}->check_options(option_results => $self->{option_results}); return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{warning_status} = ''; $self->{option_results}->{critical_status} = ''; $self->{option_results}->{unknown_status} = ''; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->add_header(key => 'Content-Type', value => 'application/x-www-form-urlencoded'); if (defined($self->{access_token})) { $self->{http}->add_header(key => 'Authorization', value => 'Bearer ' . $self->{access_token}); } $self->{http}->set_options(%{$self->{option_results}}); } sub get_access_token { my ($self, %options) = @_; my $has_cache_file = $options{statefile}->read(statefile => 'office365_graphapi_' . md5_hex($self->{tenant}) . '_' . md5_hex($self->{client_id})); my $expires_on = $options{statefile}->get(name => 'expires_on'); my $access_token = $options{statefile}->get(name => 'access_token'); my $md5_secret_cache = $options{statefile}->get(name => 'md5_secret'); my $md5_secret = md5_hex($self->{client_secret}); if ($has_cache_file == 0 || !defined($access_token) || (($expires_on - time()) < 10) || (defined($md5_secret_cache) && $md5_secret_cache ne $md5_secret) ) { my $uri = URI::Encode->new({encode_reserved => 1}); my $encoded_client_secret = $uri->encode($self->{client_secret}); my $encoded_graph_endpoint = $uri->encode($self->{graph_endpoint} . '/.default'); my $post_data = 'grant_type=client_credentials' . '&client_id=' . $self->{client_id} . '&client_secret=' . $encoded_client_secret . '&scope=' . $encoded_graph_endpoint; $self->settings(); my $content = $self->{http}->request( method => 'POST', query_form_post => $post_data, full_url => $self->{login_endpoint} . '/' . $self->{tenant} . '/oauth2/v2.0/token', hostname => '' ); my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response"); $self->{output}->option_exit(); } if (defined($decoded->{error})) { $self->{output}->add_option_msg(short_msg => "Login endpoint API return error code '" . $decoded->{error} . "' (add --debug option for detailed message)"); $self->{output}->option_exit(); } $access_token = $decoded->{access_token}; my $datas = { last_timestamp => time(), access_token => $decoded->{access_token}, expires_on => time() + $decoded->{expires_in}, md5_secret => $md5_secret }; $options{statefile}->write(data => $datas); } return $access_token; } sub request_api_json { my ($self, %options) = @_; if (!defined($self->{access_token})) { $self->{access_token} = $self->get_access_token(statefile => $self->{cache}); } $self->settings(); my $results = []; my %local_options = %options; while (1) { my $content = $self->{http}->request(%local_options); if ($self->{http}->get_code() == 429) { last; } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } if (defined($decoded->{error})) { $self->{output}->add_option_msg(short_msg => "Graph endpoint API return error code '" . $decoded->{error}->{code} . "' (add --debug option for detailed message)"); $self->{output}->option_exit(); } push @$results, @{$decoded->{value}}; last if (!defined($decoded->{'@odata.nextLink'})); $local_options{full_url} = $decoded->{'@odata.nextLink'}; } return $results; } sub request_api_csv { my ($self, %options) = @_; if (!defined($self->{access_token})) { $self->{access_token} = $self->get_access_token(statefile => $self->{cache}); } $self->settings(); my $content = $self->{http}->request(%options); if ($self->{http}->get_code() != 200) { my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } if (defined($decoded->{error})) { $self->{output}->add_option_msg(short_msg => "Graph endpoint API return error code '" . $decoded->{error}->{code} . "' (add --debug option for detailed message)"); $self->{output}->option_exit(); } } $content =~ s/^(?:\x{feff}|\x{ef}\x{bb}\x{bf})//; my $decoded = encode('UTF-8', $content); my @rows; eval { open my $fh, '<', \$decoded; my $csv = Text::CSV->new({ binary => 1 }); $csv->column_names($csv->getline($fh)); while (my $row = $csv->getline_hr($fh)) { push @rows, $row; } }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot parse csv response: $@"); $self->{output}->option_exit(); } return \@rows; } sub office_get_sharepoint_site_usage_set_url { my ($self, %options) = @_; my $url = $self->{graph_endpoint} . "/v1.0/reports/getSharePointSiteUsageDetail(" . $options{param} . ")"; return $url; } sub office_get_sharepoint_site_usage { my ($self, %options) = @_; my $full_url = $self->office_get_sharepoint_site_usage_set_url(%options); my $response = $self->request_api_csv(method => 'GET', full_url => $full_url, hostname => ''); return $response; } sub office_get_sharepoint_activity_set_url { my ($self, %options) = @_; my $url = $self->{graph_endpoint} . "/v1.0/reports/getSharePointActivityUserDetail(" . $options{param} . ")"; return $url; } sub office_get_sharepoint_activity { my ($self, %options) = @_; my $full_url = $self->office_get_sharepoint_activity_set_url(%options); my $response = $self->request_api_csv(method => 'GET', full_url => $full_url, hostname => ''); return $response; } sub office_get_onedrive_usage_set_url { my ($self, %options) = @_; my $url = $self->{graph_endpoint} . "/v1.0/reports/getOneDriveUsageAccountDetail(" . $options{param} . ")"; return $url; } sub office_get_onedrive_usage { my ($self, %options) = @_; my $full_url = $self->office_get_onedrive_usage_set_url(%options); my $response = $self->request_api_csv(method => 'GET', full_url => $full_url, hostname => ''); return $response; } sub office_get_onedrive_activity_set_url { my ($self, %options) = @_; my $url = $self->{graph_endpoint} . "/v1.0/reports/getOneDriveActivityUserDetail(" . $options{param} . ")"; return $url; } sub office_get_onedrive_activity { my ($self, %options) = @_; my $full_url = $self->office_get_onedrive_activity_set_url(%options); my $response = $self->request_api_csv(method => 'GET', full_url => $full_url, hostname => ''); return $response; } sub office_get_exchange_activity_set_url { my ($self, %options) = @_; my $url = $self->{graph_endpoint} . "/v1.0/reports/getEmailActivityUserDetail(" . $options{param} . ")"; return $url; } sub office_get_exchange_activity { my ($self, %options) = @_; my $full_url = $self->office_get_exchange_activity_set_url(%options); my $response = $self->request_api_csv(method => 'GET', full_url => $full_url, hostname => ''); return $response; } sub office_get_exchange_mailbox_usage_set_url { my ($self, %options) = @_; my $url = $self->{graph_endpoint} . "/v1.0/reports/getMailboxUsageDetail(" . $options{param} . ")"; return $url; } sub office_get_exchange_mailbox_usage { my ($self, %options) = @_; my $full_url = $self->office_get_exchange_mailbox_usage_set_url(%options); my $response = $self->request_api_csv(method => 'GET', full_url => $full_url, hostname => ''); return $response; } sub office_get_teams_activity_set_url { my ($self, %options) = @_; my $url = $self->{graph_endpoint} . "/v1.0/reports/getTeamsUserActivityUserDetail(" . $options{param} . ")"; return $url; } sub office_get_teams_activity { my ($self, %options) = @_; my $full_url = $self->office_get_teams_activity_set_url(%options); my $response = $self->request_api_csv(method => 'GET', full_url => $full_url, hostname => ''); return $response; } sub office_get_teams_device_usage_set_url { my ($self, %options) = @_; my $url = $self->{graph_endpoint} . "/v1.0/reports/getTeamsDeviceUsageUserDetail(" . $options{param} . ")"; return $url; } sub office_get_teams_device_usage { my ($self, %options) = @_; my $full_url = $self->office_get_teams_device_usage_set_url(%options); my $response = $self->request_api_csv(method => 'GET', full_url => $full_url, hostname => ''); return $response; } sub office_get_skype_activity_set_url { my ($self, %options) = @_; my $url = $self->{graph_endpoint} . "/v1.0/reports/getSkypeForBusinessActivityUserDetail(" . $options{param} . ")"; return $url; } sub office_get_skype_activity { my ($self, %options) = @_; my $full_url = $self->office_get_skype_activity_set_url(%options); my $response = $self->request_api_csv(method => 'GET', full_url => $full_url, hostname => ''); return $response; } sub office_get_skype_device_usage_set_url { my ($self, %options) = @_; my $url = $self->{graph_endpoint} . "/v1.0/reports/getSkypeForBusinessDeviceUsageUserDetail(" . $options{param} . ")"; return $url; } sub office_get_skype_device_usage { my ($self, %options) = @_; my $full_url = $self->office_get_skype_device_usage_set_url(%options); my $response = $self->request_api_csv(method => 'GET', full_url => $full_url, hostname => ''); return $response; } sub teams_post_notification_set_url { my ($self, %options) = @_; my $url = $self->{graph_endpoint} . "/v1.0/teams/" . $options{team_id} . "/channels/" . $options{channel_id} . "/messages"; return $url; } sub teams_post_notification { my ($self, %options) = @_; my $encoded_data = JSON::XS->new->utf8->encode($options{json_request}); my $full_url = $self->teams_post_notification_set_url(%options); my $response = $self->request_api_json(method => 'POST', full_url => $full_url, hostname => '', query_form_post => $encoded_data); return $response; } sub get_services_health { my ($self, %options) = @_; my $full_url = $self->{graph_endpoint} . '/v1.0/admin/serviceAnnouncement/healthOverviews'; my $response = $self->request_api_json(method => 'GET', full_url => $full_url, hostname => '', get_param => ['$expand=issues']); return $response; } 1; __END__ =head1 NAME Microsoft Office 365 Graph API =head1 REST API OPTIONS Microsoft Office 365 Graph API To connect to the Office 365 Graph API, you must register an application. Follow the 'How-to guide' in https://docs.microsoft.com/en-us/graph/auth-register-app-v2?view=graph-rest-1.0 This custom mode is using the 'OAuth 2.0 Client Credentials Grant Flow'. =over 8 =item B<--tenant> Set Office 365 tenant ID. =item B<--client-id> Set Office 365 client ID. =item B<--client-secret> Set Office 365 client secret. =item B<--login-endpoint> Set Office 365 login endpoint URL (Default: 'https://login.microsoftonline.com') =item B<--graph-endpoint> Set Office 365 graph endpoint URL (Default: 'https://graph.microsoft.com') =item B<--timeout> Set timeout in seconds (Default: 10). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/cloud/microsoft/office365/custom/managementapi.pm000066400000000000000000000230621417000230700265210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::microsoft::office365::custom::managementapi; use strict; use warnings; use DateTime; use centreon::plugins::http; use centreon::plugins::statefile; use JSON::XS; use URI::Encode; use Digest::MD5 qw(md5_hex); 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 => { 'tenant:s' => { name => 'tenant' }, 'client-id:s' => { name => 'client_id' }, 'client-secret:s' => { name => 'client_secret' }, 'login-endpoint:s' => { name => 'login_endpoint' }, 'management-endpoint:s' => { name => 'management_endpoint' }, 'timeout:s' => { name => 'timeout' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); $self->{cache} = centreon::plugins::statefile->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{tenant} = (defined($self->{option_results}->{tenant})) ? $self->{option_results}->{tenant} : undef; $self->{client_id} = (defined($self->{option_results}->{client_id})) ? $self->{option_results}->{client_id} : undef; $self->{client_secret} = (defined($self->{option_results}->{client_secret})) ? $self->{option_results}->{client_secret} : undef; $self->{login_endpoint} = (defined($self->{option_results}->{login_endpoint})) ? $self->{option_results}->{login_endpoint} : 'https://login.windows.net'; $self->{management_endpoint} = (defined($self->{option_results}->{management_endpoint})) ? $self->{option_results}->{management_endpoint} : 'https://manage.office.com'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; if (!defined($self->{tenant}) || $self->{tenant} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --tenant option."); $self->{output}->option_exit(); } if (!defined($self->{client_id}) || $self->{client_id} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --client-id option."); $self->{output}->option_exit(); } if (!defined($self->{client_secret}) || $self->{client_secret} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --client-secret option."); $self->{output}->option_exit(); } $self->{cache}->check_options(option_results => $self->{option_results}); return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{warning_status} = ''; $self->{option_results}->{critical_status} = ''; $self->{option_results}->{unknown_status} = ''; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->add_header(key => 'Content-Type', value => 'application/x-www-form-urlencoded'); if (defined($self->{access_token})) { $self->{http}->add_header(key => 'Authorization', value => 'Bearer ' . $self->{access_token}); } $self->{http}->set_options(%{$self->{option_results}}); } sub get_access_token { my ($self, %options) = @_; my $has_cache_file = $options{statefile}->read(statefile => 'office365_managementapi_' . md5_hex($self->{tenant}) . '_' . md5_hex($self->{client_id})); my $expires_on = $options{statefile}->get(name => 'expires_on'); my $access_token = $options{statefile}->get(name => 'access_token'); my $md5_secret_cache = $options{statefile}->get(name => 'md5_secret'); my $md5_secret = md5_hex($self->{client_secret}); if ($has_cache_file == 0 || !defined($access_token) || (($expires_on - time()) < 10) || (defined($md5_secret_cache) && $md5_secret_cache ne $md5_secret) ) { my $uri = URI::Encode->new({encode_reserved => 1}); my $encoded_client_secret = $uri->encode($self->{client_secret}); my $encoded_management_endpoint = $uri->encode($self->{management_endpoint}); my $post_data = 'grant_type=client_credentials' . '&client_id=' . $self->{client_id} . '&client_secret=' . $encoded_client_secret . '&resource=' . $encoded_management_endpoint; $self->settings(); my $content = $self->{http}->request( method => 'POST', query_form_post => $post_data, full_url => $self->{login_endpoint} . '/' . $self->{tenant} . '/oauth2/token?api-version=1.0', hostname => '' ); my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->output_add(long_msg => $content, debug => 1); $self->{output}->add_option_msg(short_msg => "Cannot decode json response"); $self->{output}->option_exit(); } if (defined($decoded->{error})) { $self->{output}->output_add(long_msg => "Error message : " . $decoded->{error_description}, debug => 1); $self->{output}->add_option_msg(short_msg => "Login endpoint API return error code '" . $decoded->{error} . "' (add --debug option for detailed message)"); $self->{output}->option_exit(); } $access_token = $decoded->{access_token}; my $datas = { last_timestamp => time(), access_token => $decoded->{access_token}, expires_on => $decoded->{expires_on}, md5_secret => $md5_secret }; $options{statefile}->write(data => $datas); } return $access_token; } sub request_api { my ($self, %options) = @_; if (!defined($self->{access_token})) { $self->{access_token} = $self->get_access_token(statefile => $self->{cache}); } $self->settings(); my $content = $self->{http}->request(%options); my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } if (defined($decoded->{error})) { $self->{output}->add_option_msg(short_msg => "Management endpoint API return error code '" . $decoded->{error}->{code} . "' (add --debug option for detailed message)"); $self->{output}->option_exit(); } return $decoded; } sub office_get_services_status_set_url { my ($self, %options) = @_; my $url = $self->{management_endpoint} . "/api/v1.0/" . $self->{tenant} . "/ServiceComms/CurrentStatus"; return $url; } sub office_get_services_status { my ($self, %options) = @_; my $full_url = $self->office_get_services_status_set_url(%options); my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => ''); return $response; } sub office_list_services_set_url { my ($self, %options) = @_; my $url = $self->{management_endpoint} . "/api/v1.0/" . $self->{tenant} . "/ServiceComms/Services"; return $url; } sub office_list_services { my ($self, %options) = @_; my $full_url = $self->office_list_services_set_url(%options); my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => ''); return $response; } 1; __END__ =head1 NAME Microsoft Office 365 Management API =head1 REST API OPTIONS Microsoft Office 365 Management API To connect to the Office 365 Management API, you must register an application. Follow the 'How-to guide' in https://docs.microsoft.com/en-us/office/office-365-management-api/get-started-with-office-365-management-apis#register-your-application-in-azure-ad This custom mode is using the 'OAuth 2.0 Client Credentials Grant Flow'. =over 8 =item B<--tenant> Set Office 365 tenant ID. =item B<--client-id> Set Office 365 client ID. =item B<--client-secret> Set Office 365 client secret. =item B<--login-endpoint> Set Office 365 login endpoint URL (Default: 'https://login.windows.net') =item B<--management-endpoint> Set Office 365 management endpoint URL (Default: 'https://manage.office.com') =item B<--timeout> Set timeout in seconds (Default: 10). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/cloud/microsoft/office365/exchange/000077500000000000000000000000001417000230700236225ustar00rootroot00000000000000centreon-plugins-20220113/cloud/microsoft/office365/exchange/mode/000077500000000000000000000000001417000230700245465ustar00rootroot00000000000000centreon-plugins-20220113/cloud/microsoft/office365/exchange/mode/emailactivity.pm000066400000000000000000000244631417000230700277610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::microsoft::office365::exchange::mode::emailactivity; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Time::Local; sub custom_active_perfdata { my ($self, %options) = @_; my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } if ($self->{result_values}->{report_date} =~ /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/) { $self->{output}->perfdata_add(label => 'perfdate', value => timelocal(0,0,12,$3,$2-1,$1-1900)); } $self->{output}->perfdata_add( label => 'active_users', nlabel => 'exchange.users.active.count', value => $self->{result_values}->{active}, 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), unit => 'users', min => 0, max => $self->{result_values}->{total} ); } sub custom_active_threshold { my ($self, %options) = @_; my $threshold_value = $self->{result_values}->{active}; if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_active}; } my $exit = $self->{perfdata}->threshold_check( value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_active_output { my ($self, %options) = @_; return sprintf( "Active users on %s : %d/%d (%.2f%%)", $self->{result_values}->{report_date}, $self->{result_values}->{active}, $self->{result_values}->{total}, $self->{result_values}->{prct_active} ); } sub custom_active_calc { my ($self, %options) = @_; $self->{result_values}->{active} = $options{new_datas}->{$self->{instance} . '_active'}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_total'}; $self->{result_values}->{report_date} = $options{new_datas}->{$self->{instance} . '_report_date'}; $self->{result_values}->{prct_active} = ($self->{result_values}->{total} != 0) ? $self->{result_values}->{active} * 100 / $self->{result_values}->{total} : 0; return 0; } sub prefix_global_output { my ($self, %options) = @_; return "Total (active users) "; } sub prefix_mailbox_output { my ($self, %options) = @_; return "User '" . $options{instance_value}->{name} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'active', type => 0 }, { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }, { name => 'users', type => 1, cb_prefix_output => 'prefix_mailbox_output', message_multiple => 'All email activity are ok' } ]; $self->{maps_counters}->{active} = [ { label => 'active-users', set => { key_values => [ { name => 'active' }, { name => 'total' }, { name => 'report_date' } ], closure_custom_calc => $self->can('custom_active_calc'), closure_custom_output => $self->can('custom_active_output'), closure_custom_threshold_check => $self->can('custom_active_threshold'), closure_custom_perfdata => $self->can('custom_active_perfdata') } }, ]; $self->{maps_counters}->{global} = [ { label => 'total-send-count', nlabel => 'exchange.users.emails.sent.total.count', set => { key_values => [ { name => 'send_count' } ], output_template => 'Send Count: %d', perfdatas => [ { label => 'total_send_count', template => '%d', min => 0 } ] } }, { label => 'total-receive-count', nlabel => 'exchange.users.emails.received.total.count', set => { key_values => [ { name => 'receive_count' } ], output_template => 'Receive Count: %d', perfdatas => [ { label => 'total_receive_count', template => '%d', min => 0 } ] } }, { label => 'total-read-count', nlabel => 'exchange.users.emails.read.total.count', set => { key_values => [ { name => 'read_count' } ], output_template => 'Read Count: %d', perfdatas => [ { label => 'total_read_count', template => '%d', min => 0 } ] } } ]; $self->{maps_counters}->{users} = [ { label => 'send-count', nlabel => 'exchange.users.emails.sent.count', set => { key_values => [ { name => 'send_count' }, { name => 'name' } ], output_template => 'Send Count: %d', perfdatas => [ { label => 'send_count', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'name' } ] } }, { label => 'receive-count', nlabel => 'exchange.users.emails.received.count', set => { key_values => [ { name => 'receive_count' }, { name => 'name' } ], output_template => 'Receive Count: %d', perfdatas => [ { label => 'receive_count', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'name' } ] } }, { label => 'read-count', nlabel => 'exchange.users.emails.read.count', set => { key_values => [ { name => 'read_count' }, { name => 'name' } ], output_template => 'Read Count: %d', perfdatas => [ { label => 'read_count', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'name' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-user:s" => { name => 'filter_user' }, "units:s" => { name => 'units', default => '%' }, "filter-counters:s" => { name => 'filter_counters', default => 'active|total' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{active} = { active => 0, total => 0, report_date => '' }; $self->{global} = { send_count => 0, receive_count => 0 , read_count => 0 }; $self->{users} = {}; my $results = $options{custom}->office_get_exchange_activity(param => "period='D7'"); my $results_daily = []; if (scalar(@{$results})) { $self->{active}->{report_date} = @{$results}[0]->{'Report Refresh Date'}; $results_daily = $options{custom}->office_get_exchange_activity(param => "date=" . $self->{active}->{report_date}); } foreach my $user (@{$results}, @{$results_daily}) { if (defined($self->{option_results}->{filter_user}) && $self->{option_results}->{filter_user} ne '' && $user->{'User Principal Name'} !~ /$self->{option_results}->{filter_user}/) { $self->{output}->output_add(long_msg => "skipping '" . $user->{'User Principal Name'} . "': no matching filter name.", debug => 1); next; } if ($user->{'Report Period'} != 1) { if (!defined($user->{'Last Activity Date'}) || ($user->{'Last Activity Date'} ne $self->{active}->{report_date})) { $self->{output}->output_add(long_msg => "skipping '" . $user->{'User Principal Name'} . "': no activity.", debug => 1); } $self->{active}->{total}++; next; } $self->{active}->{active}++; $self->{global}->{send_count} += $user->{'Send Count'}; $self->{global}->{receive_count} += $user->{'Receive Count'}; $self->{global}->{read_count} += $user->{'Read Count'}; $self->{users}->{$user->{'User Principal Name'}}->{name} = $user->{'User Principal Name'}; $self->{users}->{$user->{'User Principal Name'}}->{send_count} = $user->{'Send Count'}; $self->{users}->{$user->{'User Principal Name'}}->{receive_count} = $user->{'Receive Count'}; $self->{users}->{$user->{'User Principal Name'}}->{read_count} = $user->{'Read Count'}; } } 1; __END__ =head1 MODE Check email activity (reporting period over the last refreshed day). (See link for details about metrics : https://docs.microsoft.com/en-us/office365/admin/activity-reports/email-activity?view=o365-worldwide) =over 8 =item B<--filter-user> Filter users. =item B<--warning-*> Threshold warning. Can be: 'active-users', 'total-send-count' (count), 'total-receive-count' (count), 'total-read-count' (count), 'send-count' (count), 'receive-count' (count), 'read-count' (count). =item B<--critical-*> Threshold critical. Can be: 'active-users', 'total-send-count' (count), 'total-receive-count' (count), 'total-read-count' (count), 'send-count' (count), 'receive-count' (count), 'read-count' (count). =item B<--filter-counters> Only display some counters (regexp can be used). Example to hide per user counters: --filter-counters='active|total' (Default: 'active|total') =item B<--units> Unit of thresholds (Default: '%') ('%', 'count'). =back =cut centreon-plugins-20220113/cloud/microsoft/office365/exchange/mode/mailboxusage.pm000066400000000000000000000317431417000230700275740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::microsoft::office365::exchange::mode::mailboxusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use Time::Local; sub custom_active_perfdata { my ($self, %options) = @_; my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } if ($self->{result_values}->{report_date} =~ /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/) { $self->{output}->perfdata_add(label => 'perfdate', value => timelocal(0,0,12,$3,$2-1,$1-1900)); } $self->{output}->perfdata_add( label => 'active_mailboxes', nlabel => 'exchange.mailboxes.active.count', value => $self->{result_values}->{active}, 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), unit => 'mailboxes', min => 0, max => $self->{result_values}->{total} ); } sub custom_active_threshold { my ($self, %options) = @_; my $threshold_value = $self->{result_values}->{active}; if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_active}; } my $exit = $self->{perfdata}->threshold_check( value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_active_output { my ($self, %options) = @_; return sprintf( 'Active mailboxes on %s : %d/%d (%.2f%%)', $self->{result_values}->{report_date}, $self->{result_values}->{active}, $self->{result_values}->{total}, $self->{result_values}->{prct_active} ); } sub custom_active_calc { my ($self, %options) = @_; $self->{result_values}->{active} = $options{new_datas}->{$self->{instance} . '_active'}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_total'}; $self->{result_values}->{report_date} = $options{new_datas}->{$self->{instance} . '_report_date'}; $self->{result_values}->{prct_active} = ($self->{result_values}->{total} != 0) ? $self->{result_values}->{active} * 100 / $self->{result_values}->{total} : 0; return 0; } sub custom_usage_perfdata { my ($self, %options) = @_; my $extra_label = ''; $extra_label = '_' . $self->{result_values}->{display} if (!defined($options{extra_instance}) || $options{extra_instance} != 0); $self->{output}->perfdata_add( label => 'used' . $extra_label, nlabel => $self->{result_values}->{display} . '#exchange.mailboxes.usage.bytes', unit => 'B', value => $self->{result_values}->{used}, min => 0 ); } sub custom_status_output { my ($self, %options) = @_; my ($used_value, $used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); my ($issue_warning_quota_value, $issue_warning_quota_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{issue_warning_quota}); my ($prohibit_send_quota_value, $prohibit_send_quota_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{prohibit_send_quota}); my ($prohibit_send_receive_quota_value, $prohibit_send_receive_quota_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{prohibit_send_receive_quota}); return sprintf( "Used: %s Issue Warning Quota: %s Prohibit Send Quota: %s Prohibit Send/Receive Quota: %s", $used_value . " " . $used_unit, $issue_warning_quota_value . " " . $issue_warning_quota_unit, $prohibit_send_quota_value . " " . $prohibit_send_quota_unit, $prohibit_send_receive_quota_value . " " . $prohibit_send_receive_quota_unit ); } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_name'}; $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_storage_used'}; $self->{result_values}->{issue_warning_quota} = $options{new_datas}->{$self->{instance} . '_issue_warning_quota'}; $self->{result_values}->{prohibit_send_quota} = $options{new_datas}->{$self->{instance} . '_prohibit_send_quota'}; $self->{result_values}->{prohibit_send_receive_quota} = $options{new_datas}->{$self->{instance} . '_prohibit_send_receive_quota'}; return 0; } sub prefix_global_output { my ($self, %options) = @_; return "Total "; } sub prefix_mailbox_output { my ($self, %options) = @_; return "Mailbox '" . $options{instance_value}->{name} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'active', type => 0 }, { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }, { name => 'mailboxes', type => 1, cb_prefix_output => 'prefix_mailbox_output', message_multiple => 'All mailboxes usage are ok' }, ]; $self->{maps_counters}->{active} = [ { label => 'active-mailboxes', set => { key_values => [ { name => 'active' }, { name => 'total' }, { name => 'report_date' } ], closure_custom_calc => $self->can('custom_active_calc'), closure_custom_output => $self->can('custom_active_output'), closure_custom_threshold_check => $self->can('custom_active_threshold'), closure_custom_perfdata => $self->can('custom_active_perfdata') } }, ]; $self->{maps_counters}->{global} = [ { label => 'total-usage-active', nlabel => 'exchange.mailboxes.active.usage.total.bytes', set => { key_values => [ { name => 'storage_used_active' } ], output_template => 'Usage (active mailboxes): %s %s', output_change_bytes => 1, perfdatas => [ { label => 'total_usage_active', value => 'storage_used_active', template => '%d', min => 0, unit => 'B' }, ], } }, { label => 'total-usage-inactive', nlabel => 'exchange.mailboxes.inactive.usage.total.bytes', set => { key_values => [ { name => 'storage_used_inactive' } ], output_template => 'Usage (inactive mailboxes): %s %s', output_change_bytes => 1, perfdatas => [ { label => 'total_usage_inactive', template => '%d', min => 0, unit => 'B' } ] } } ]; $self->{maps_counters}->{mailboxes} = [ { label => 'status', type => 2, warning_default => '%{used} > %{issue_warning_quota}', critical_default => '%{used} > %{prohibit_send_quota}', set => { key_values => [ { name => 'storage_used' }, { name => 'issue_warning_quota' }, { name => 'prohibit_send_quota' }, { name => 'prohibit_send_receive_quota' }, { name => 'name' } ], closure_custom_calc => $self->can('custom_status_calc'), closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => $self->can('custom_usage_perfdata'), closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'items', nlabel => 'exchange.mailboxes.items.count', set => { key_values => [ { name => 'items' }, { name => 'name' } ], output_template => 'Items: %d', perfdatas => [ { label => 'items', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'name' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-mailbox:s' => { name => 'filter_mailbox' }, 'units:s' => { name => 'units', default => '%' }, 'filter-counters:s' => { name => 'filter_counters', default => 'active|total' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{active} = { active => 0, total => 0, report_date => '' }; $self->{global} = { storage_used_active => 0, storage_used_inactive => 0 }; $self->{mailboxes} = {}; my $results = $options{custom}->office_get_exchange_mailbox_usage(param => "period='D7'"); my $results_daily = []; if (scalar(@{$results})) { $self->{active}->{report_date} = @{$results}[0]->{'Report Refresh Date'}; #$results_daily = $options{custom}->office_get_exchange_mailbox_usage(param => "date=" . $self->{active}->{report_date}); } foreach my $mailbox (@{$results}, @{$results_daily}) { if (defined($self->{option_results}->{filter_mailbox}) && $self->{option_results}->{filter_mailbox} ne '' && $mailbox->{'User Principal Name'} !~ /$self->{option_results}->{filter_mailbox}/) { $self->{output}->output_add(long_msg => "skipping '" . $mailbox->{'User Principal Name'} . "': no matching filter name.", debug => 1); next; } $self->{active}->{total}++; if (!defined($mailbox->{'Last Activity Date'}) || ($mailbox->{'Last Activity Date'} ne $self->{active}->{report_date})) { $self->{global}->{storage_used_inactive} += ($mailbox->{'Storage Used (Byte)'} ne '') ? $mailbox->{'Storage Used (Byte)'} : 0; $self->{output}->output_add(long_msg => "skipping '" . $mailbox->{'User Principal Name'} . "': no activity.", debug => 1); next; } $self->{active}->{active}++; $self->{global}->{storage_used_active} += ($mailbox->{'Storage Used (Byte)'} ne '') ? $mailbox->{'Storage Used (Byte)'} : 0; $self->{mailboxes}->{$mailbox->{'User Principal Name'}}->{name} = $mailbox->{'User Principal Name'}; $self->{mailboxes}->{$mailbox->{'User Principal Name'}}->{storage_used} = ($mailbox->{'Storage Used (Byte)'} ne '') ? $mailbox->{'Storage Used (Byte)'} : 0; $self->{mailboxes}->{$mailbox->{'User Principal Name'}}->{issue_warning_quota} = $mailbox->{'Issue Warning Quota (Byte)'}; $self->{mailboxes}->{$mailbox->{'User Principal Name'}}->{prohibit_send_quota} = $mailbox->{'Prohibit Send Quota (Byte)'}; $self->{mailboxes}->{$mailbox->{'User Principal Name'}}->{prohibit_send_receive_quota} = $mailbox->{'Prohibit Send/Receive Quota (Byte)'}; $self->{mailboxes}->{$mailbox->{'User Principal Name'}}->{items} = ($mailbox->{'Item Count'} ne '') ? $mailbox->{'Item Count'} : 0; } } 1; __END__ =head1 MODE Check mailbox usage (reporting period over the last refreshed day). (See link for details about metrics : https://docs.microsoft.com/en-us/office365/admin/activity-reports/mailbox-usage?view=o365-worldwide) =over 8 =item B<--filter-mailbox> Filter mailboxes. =item B<--warning-*> Threshold warning. Can be: 'active-mailboxes', 'total-usage-active' (count), 'total-usage-inactive' (count). =item B<--critical-*> Threshold critical. Can be: 'active-mailboxes', 'total-usage-active' (count), 'total-usage-inactive' (count). =item B<--warning-status> Set warning threshold for status (Default: '%{used} > %{issue_warning_quota}'). Can used special variables like: %{used}, %{issue_warning_quota}, %{prohibit_send_quota}, %{prohibit_send_receive_quota} =item B<--critical-status> Set critical threshold for status (Default: '%{used} > %{prohibit_send_quota}'). Can used special variables like: %{used}, %{issue_warning_quota}, %{prohibit_send_quota}, %{prohibit_send_receive_quota} =item B<--filter-counters> Only display some counters (regexp can be used). Example to hide per user counters: --filter-counters='active|total' (Default: 'active|total') =item B<--units> Unit of thresholds (Default: '%') ('%', 'count'). =back =cut centreon-plugins-20220113/cloud/microsoft/office365/exchange/plugin.pm000066400000000000000000000027211417000230700254600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::microsoft::office365::exchange::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} } = ( 'email-activity' => 'cloud::microsoft::office365::exchange::mode::emailactivity', 'mailbox-usage' => 'cloud::microsoft::office365::exchange::mode::mailboxusage', ); $self->{custom_modes}{graphapi} = 'cloud::microsoft::office365::custom::graphapi'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Office 365 Exchange. =cut centreon-plugins-20220113/cloud/microsoft/office365/management/000077500000000000000000000000001417000230700241545ustar00rootroot00000000000000centreon-plugins-20220113/cloud/microsoft/office365/management/mode/000077500000000000000000000000001417000230700251005ustar00rootroot00000000000000centreon-plugins-20220113/cloud/microsoft/office365/management/mode/listservices.pm000066400000000000000000000060571417000230700301650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::microsoft::office365::management::mode::listservices; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->get_services_health(); foreach my $service (@$results) { next if (defined($self->{option_results}->{filter_service_name}) && $self->{option_results}->{filter_service_name} ne '' && $service->{service} !~ /$self->{option_results}->{filter_service_name}/); $self->{services}->{ $service->{id} } = { service_id => $service->{id}, service_name => $service->{service} } } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $service (sort keys %{$self->{services}}) { $self->{output}->output_add( long_msg => sprintf( "[service_id: %s] [service_name: %s]", $self->{services}->{$service}->{service_id}, $self->{services}->{$service}->{service_name} ) ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List services:' ); $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 => ['service_id', 'service_name']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $service (sort keys %{$self->{services}}) { $self->{output}->add_disco_entry( service_id => $self->{services}->{$service}->{service_id}, service_name => $self->{services}->{$service}->{service_name} ); } } 1; __END__ =head1 MODE List services. =over 8 =item B<--filter-name> Filter service name (can be a regexp). =back =cut centreon-plugins-20220113/cloud/microsoft/office365/management/mode/servicestatus.pm000066400000000000000000000112341417000230700303430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::microsoft::office365::management::mode::servicestatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_threshold { my ($self, %options) = @_; my $status = catalog_status_threshold_ng($self, %options); $self->{instance_mode}->{last_status} = $status; return $status; } sub custom_status_output { my ($self, %options) = @_; my $msg = "status is '" . $self->{result_values}->{status} . "'"; if (!$self->{output}->is_status(value => $self->{instance_mode}->{last_status}, compare => 'ok', litteral => 1)) { $msg .= sprintf( ' [issue: %s %s]', $self->{result_values}->{issue_startDateTime}, $self->{result_values}->{issue_title} ); } return $msg; } sub prefix_service_output { my ($self, %options) = @_; return "Service '" . $options{instance_value}->{service_name} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'services', type => 1, cb_prefix_output => 'prefix_service_output', message_multiple => 'All services are ok' } ]; $self->{maps_counters}->{services} = [ { label => 'status', type => 2, critical_default => '%{status} !~ /serviceOperational|serviceRestored/i', set => { key_values => [ { name => 'status' }, { name => 'service_name' }, { name => 'issue_startDateTime' }, { name => 'issue_title' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => $self->can('custom_status_threshold'), } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-service-name:s' => { name => 'filter_service_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->get_services_health(); $self->{services} = {}; foreach my $service (@$results) { if (defined($self->{option_results}->{filter_service_name}) && $self->{option_results}->{filter_service_name} ne '' && $service->{service} !~ /$self->{option_results}->{filter_service_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $service->{service} . "': no matching filter name.", debug => 1); next; } $self->{services}->{ $service->{id} }->{service_name} = $service->{service}; $self->{services}->{ $service->{id} }->{status} = $service->{status}; $self->{services}->{ $service->{id} }->{issue_startDateTime} = '-'; $self->{services}->{ $service->{id} }->{issue_title} = '-'; if (defined($service->{issues}) && scalar(@{$service->{issues}}) > 0) { my $issue = pop @{$service->{issues}}; $self->{services}->{ $service->{id} }->{issue_startDateTime} = $issue->{startDateTime}; $self->{services}->{ $service->{id} }->{issue_title} = $issue->{title}; } } if (scalar(keys %{$self->{services}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No services found.'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check services status. =over 8 =item B<--filter-service-name> Filter services (can be a regexp). =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{service_name}, %{status} =item B<--critical-status> Set critical threshold for status (Default: '%{status} !~ /serviceOperational|serviceRestored/i'). Can used special variables like: %{service_name}, %{status} =back =cut centreon-plugins-20220113/cloud/microsoft/office365/management/plugin.pm000066400000000000000000000026221417000230700260120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::microsoft::office365::management::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->{modes} = { 'list-services' => 'cloud::microsoft::office365::management::mode::listservices', 'service-status' => 'cloud::microsoft::office365::management::mode::servicestatus' }; $self->{custom_modes}->{graphapi} = 'cloud::microsoft::office365::custom::graphapi'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Office 365. =cut centreon-plugins-20220113/cloud/microsoft/office365/onedrive/000077500000000000000000000000001417000230700236535ustar00rootroot00000000000000centreon-plugins-20220113/cloud/microsoft/office365/onedrive/mode/000077500000000000000000000000001417000230700245775ustar00rootroot00000000000000centreon-plugins-20220113/cloud/microsoft/office365/onedrive/mode/listsites.pm000066400000000000000000000072621417000230700271670ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::microsoft::office365::onedrive::mode::listsites; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-url:s" => { name => 'filter_url' }, "filter-owner:s" => { name => 'filter_owner' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->office_get_onedrive_usage(param => "period='D7'"); foreach my $site (@{$results}) { if (defined($self->{option_results}->{filter_url}) && $self->{option_results}->{filter_url} ne '' && $site->{'Site URL'} !~ /$self->{option_results}->{filter_url}/) { $self->{output}->output_add(long_msg => "skipping '" . $site->{'Site URL'} . "': no matching filter name.", debug => 1); next; } if (defined($self->{option_results}->{filter_owner}) && $self->{option_results}->{filter_owner} ne '' && $site->{'Owner Display Name'} !~ /$self->{option_results}->{filter_owner}/) { $self->{output}->output_add(long_msg => "skipping '" . $site->{'Owner Display Name'} . "': no matching filter name.", debug => 1); next; } $self->{sites}->{$site->{'Site URL'}} = { owner => $site->{'Owner Display Name'}, url => $site->{'Site URL'}, } } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $site (sort keys %{$self->{sites}}) { $self->{output}->output_add(long_msg => sprintf("[owner = %s] [url = %s]", $self->{sites}->{$site}->{owner}, $self->{sites}->{$site}->{url})); } $self->{output}->output_add(severity => 'OK', short_msg => 'List sites:'); $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 => ['owner', 'url']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $site (sort keys %{$self->{sites}}) { $self->{output}->add_disco_entry( owner => $self->{sites}->{$site}->{owner}, url => $self->{sites}->{$site}->{url}, ); } } 1; __END__ =head1 MODE List sites. =over 8 =item B<--filter-*> Filter sites. Can be: 'url', 'id' (can be a regexp). =back =cut centreon-plugins-20220113/cloud/microsoft/office365/onedrive/mode/siteusage.pm000066400000000000000000000377351417000230700271450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::microsoft::office365::onedrive::mode::siteusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Time::Local; sub custom_active_perfdata { my ($self, %options) = @_; my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } if ($self->{result_values}->{report_date} =~ /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/) { $self->{output}->perfdata_add(label => 'perfdate', value => timelocal(0,0,12,$3,$2-1,$1-1900)); } $self->{output}->perfdata_add( label => 'active_sites', nlabel => 'onedrive.sites.active.count', value => $self->{result_values}->{active}, 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), unit => 'sites', min => 0, max => $self->{result_values}->{total} ); } sub custom_active_threshold { my ($self, %options) = @_; my $threshold_value = $self->{result_values}->{active}; if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_active}; } my $exit = $self->{perfdata}->threshold_check( value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_active_output { my ($self, %options) = @_; return sprintf( "Active sites on %s : %d/%d (%.2f%%)", $self->{result_values}->{report_date}, $self->{result_values}->{active}, $self->{result_values}->{total}, $self->{result_values}->{prct_active} ); } sub custom_active_calc { my ($self, %options) = @_; $self->{result_values}->{active} = $options{new_datas}->{$self->{instance} . '_active'}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_total'}; $self->{result_values}->{report_date} = $options{new_datas}->{$self->{instance} . '_report_date'}; $self->{result_values}->{prct_active} = ($self->{result_values}->{total} != 0) ? $self->{result_values}->{active} * 100 / $self->{result_values}->{total} : 0; return 0; } sub custom_usage_perfdata { my ($self, %options) = @_; my $extra_label = ''; $extra_label = '_' . $self->{result_values}->{display} if (!defined($options{extra_instance}) || $options{extra_instance} != 0); $self->{output}->perfdata_add( label => 'used' . $extra_label, nlabel => $self->{result_values}->{display} . '#onedrive.sites.usage.bytes', unit => 'B', value => $self->{result_values}->{used}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), min => 0, max => $self->{result_values}->{total} ); } sub custom_usage_threshold { my ($self, %options) = @_; my ($exit, $threshold_value); $threshold_value = $self->{result_values}->{used}; $threshold_value = $self->{result_values}->{free} if (defined($self->{instance_mode}->{option_results}->{free})); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; $threshold_value = $self->{result_values}->{prct_free} if (defined($self->{instance_mode}->{option_results}->{free})); } $exit = $self->{perfdata}->threshold_check( value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_usage_output { my ($self, %options) = @_; my ($used_value, $used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); my ($free_value, $free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); my ($total_value, $total_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); return sprintf( "Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", $total_value . " " . $total_unit, $used_value . " " . $used_unit, $self->{result_values}->{prct_used}, $free_value . " " . $free_unit, $self->{result_values}->{prct_free} ); } sub custom_usage_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_url'}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_storage_allocated'}; $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_storage_used'}; if ($self->{result_values}->{total} != 0) { $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}; } else { $self->{result_values}->{free} = '0'; $self->{result_values}->{prct_used} = '0'; $self->{result_values}->{prct_free} = '0'; } return 0; } sub prefix_global_output { my ($self, %options) = @_; return "Total "; } sub prefix_site_output { my ($self, %options) = @_; return "Site '" . $options{instance_value}->{url} . "' [Owner: " . $options{instance_value}->{owner} . "] "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'active', type => 0 }, { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }, { name => 'sites', type => 1, cb_prefix_output => 'prefix_site_output', message_multiple => 'All sites usage are ok' } ]; $self->{maps_counters}->{active} = [ { label => 'active-sites', set => { key_values => [ { name => 'active' }, { name => 'total' }, { name => 'report_date' } ], closure_custom_calc => $self->can('custom_active_calc'), closure_custom_output => $self->can('custom_active_output'), closure_custom_threshold_check => $self->can('custom_active_threshold'), closure_custom_perfdata => $self->can('custom_active_perfdata') } } ]; $self->{maps_counters}->{global} = [ { label => 'total-usage-active', nlabel => 'onedrive.sites.active.usage.total.bytes', set => { key_values => [ { name => 'storage_used_active' } ], output_template => 'Usage (active sites): %s %s', output_change_bytes => 1, perfdatas => [ { label => 'total_usage_active', template => '%d', min => 0, unit => 'B' } ] } }, { label => 'total-usage-inactive', nlabel => 'onedrive.sites.inactive.usage.total.bytes', set => { key_values => [ { name => 'storage_used_inactive' } ], output_template => 'Usage (inactive sites): %s %s', output_change_bytes => 1, perfdatas => [ { label => 'total_usage_inactive', template => '%d', min => 0, unit => 'B' } ] } }, { label => 'total-file-count-active', nlabel => 'onedrive.sites.active.files.total.count', set => { key_values => [ { name => 'file_count_active' } ], output_template => 'File Count (active sites): %d', perfdatas => [ { label => 'total_file_count_active', template => '%d', min => 0 } ] } }, { label => 'total-file-count-inactive', nlabel => 'onedrive.sites.inactive.files.total.count', set => { key_values => [ { name => 'file_count_inactive' } ], output_template => 'File Count (inactive sites): %d', perfdatas => [ { label => 'total_file_count_inactive', template => '%d', min => 0 } ] } }, { label => 'total-active-file-count', nlabel => 'onedrive.sites.files.active.total.count', set => { key_values => [ { name => 'active_file_count' } ], output_template => 'Active File Count (active sites): %d', perfdatas => [ { label => 'total_active_file_count', template => '%d', min => 0 } ] } } ]; $self->{maps_counters}->{sites} = [ { label => 'usage', set => { key_values => [ { name => 'storage_used' }, { name => 'storage_allocated' }, { name => 'url' }, { name => 'owner' } ], 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 => 'file-count', nlabel => 'onedrive.sites.files.count', set => { key_values => [ { name => 'file_count' }, { name => 'url' }, { name => 'owner' } ], output_template => 'File Count: %d', perfdatas => [ { label => 'file_count', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'url' } ] } }, { label => 'active-file-count', nlabel => 'onedrive.sites.files.active.count', set => { key_values => [ { name => 'active_file_count' }, { name => 'url' }, { name => 'owner' } ], output_template => 'Active File Count: %d', perfdatas => [ { label => 'active_file_count', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'url' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-url:s" => { name => 'filter_url' }, "filter-owner:s" => { name => 'filter_owner' }, "units:s" => { name => 'units', default => '%' }, "free" => { name => 'free' }, "filter-counters:s" => { name => 'filter_counters', default => 'active-sites|total' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{active} = { active => 0, total => 0, report_date => '' }; $self->{global} = { storage_used_active => 0, storage_used_inactive => 0, file_count_active => 0, file_count_inactive => 0, active_file_count => 0 }; $self->{sites} = {}; my $results = $options{custom}->office_get_onedrive_usage(param => "period='D7'"); my $results_daily = []; if (scalar(@{$results})) { $self->{active}->{report_date} = @{$results}[0]->{'Report Refresh Date'}; $results_daily = $options{custom}->office_get_onedrive_usage(param => "date=" . $self->{active}->{report_date}); } foreach my $site (@{$results}, @{$results_daily}) { if (defined($self->{option_results}->{filter_url}) && $self->{option_results}->{filter_url} ne '' && $site->{'Site URL'} !~ /$self->{option_results}->{filter_url}/) { $self->{output}->output_add(long_msg => "skipping '" . $site->{'Site URL'} . "': no matching filter name.", debug => 1); next; } if (defined($self->{option_results}->{filter_owner}) && $self->{option_results}->{filter_owner} ne '' && $site->{'Owner Display Name'} !~ /$self->{option_results}->{filter_owner}/) { $self->{output}->output_add(long_msg => "skipping '" . $site->{'Owner Display Name'} . "': no matching filter name.", debug => 1); next; } if ($site->{'Report Period'} != 1) { if (!defined($site->{'Last Activity Date'}) || ($site->{'Last Activity Date'} ne $self->{active}->{report_date})) { $self->{global}->{storage_used_inactive} += ($site->{'Storage Used (Byte)'} ne '') ? $site->{'Storage Used (Byte)'} : 0; $self->{global}->{file_count_inactive} += ($site->{'File Count'} ne '') ? $site->{'File Count'} : 0; $self->{output}->output_add(long_msg => "skipping '" . $site->{'Site URL'} . "': no activity.", debug => 1); } $self->{active}->{total}++; next; } $self->{active}->{active}++; $self->{global}->{storage_used_active} += ($site->{'Storage Used (Byte)'} ne '') ? $site->{'Storage Used (Byte)'} : 0; $self->{global}->{file_count_active} += ($site->{'File Count'} ne '') ? $site->{'File Count'} : 0; $self->{global}->{active_file_count} += ($site->{'Active File Count'} ne '') ? $site->{'Active File Count'} : 0; $self->{sites}->{$site->{'Site URL'}}->{url} = $site->{'Site URL'}; $self->{sites}->{$site->{'Site URL'}}->{owner} = $site->{'Owner Display Name'}; $self->{sites}->{$site->{'Site URL'}}->{file_count} = $site->{'File Count'}; $self->{sites}->{$site->{'Site URL'}}->{active_file_count} = $site->{'Active File Count'}; $self->{sites}->{$site->{'Site URL'}}->{storage_used} = $site->{'Storage Used (Byte)'}; $self->{sites}->{$site->{'Site URL'}}->{storage_allocated} = $site->{'Storage Allocated (Byte)'}; } } 1; __END__ =head1 MODE Check sites usage (reporting period over the last refreshed day). (See link for details about metrics : https://docs.microsoft.com/en-us/microsoft-365/admin/activity-reports/onedrive-for-business-usage?view=o365-worldwide) =over 8 =item B<--filter-*> Filter sites. Can be: 'url', 'owner' (can be a regexp). =item B<--warning-*> Threshold warning. Can be: 'active-sites', 'total-usage-active' (count), 'total-usage-inactive' (count), 'total-file-count-active' (count), 'total-file-count-inactive' (count), 'total-active-file-count' (count), 'usage' (count), 'file-count' (count), 'active-file-count' (count). =item B<--critical-*> Threshold critical. Can be: 'active-sites', 'total-usage-active' (count), 'total-usage-inactive' (count), 'total-file-count-active' (count), 'total-file-count-inactive' (count), 'total-active-file-count' (count), 'usage' (count), 'file-count' (count), 'active-file-count' (count). =item B<--filter-counters> Only display some counters (regexp can be used). Example to hide per user counters: --filter-counters='active-sites|total' (Default: 'active-sites|total') =item B<--units> Unit of thresholds (Default: '%') ('%', 'count'). =back =cut centreon-plugins-20220113/cloud/microsoft/office365/onedrive/mode/usersactivity.pm000066400000000000000000000306061417000230700300600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::microsoft::office365::onedrive::mode::usersactivity; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Time::Local; sub custom_active_perfdata { my ($self, %options) = @_; my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } if ($self->{result_values}->{report_date} =~ /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/) { $self->{output}->perfdata_add(label => 'perfdate', value => timelocal(0,0,12,$3,$2-1,$1-1900)); } $self->{output}->perfdata_add( label => 'active_users', nlabel => 'onedrive.users.active.count', value => $self->{result_values}->{active}, 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), unit => 'users', min => 0, max => $self->{result_values}->{total} ); } sub custom_active_threshold { my ($self, %options) = @_; my $threshold_value = $self->{result_values}->{active}; if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_active}; } my $exit = $self->{perfdata}->threshold_check( value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_active_output { my ($self, %options) = @_; return sprintf( "Active users on %s : %d/%d (%.2f%%)", $self->{result_values}->{report_date}, $self->{result_values}->{active}, $self->{result_values}->{total}, $self->{result_values}->{prct_active} ); } sub custom_active_calc { my ($self, %options) = @_; $self->{result_values}->{active} = $options{new_datas}->{$self->{instance} . '_active'}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_total'}; $self->{result_values}->{report_date} = $options{new_datas}->{$self->{instance} . '_report_date'}; $self->{result_values}->{prct_active} = ($self->{result_values}->{total} != 0) ? $self->{result_values}->{active} * 100 / $self->{result_values}->{total} : 0; return 0; } sub prefix_global_output { my ($self, %options) = @_; return "Total (active sites) "; } sub prefix_user_output { my ($self, %options) = @_; return "User '" . $options{instance_value}->{name} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'active', type => 0 }, { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }, { name => 'users', type => 1, cb_prefix_output => 'prefix_user_output', message_multiple => 'All users activity are ok' } ]; $self->{maps_counters}->{active} = [ { label => 'active-users', set => { key_values => [ { name => 'active' }, { name => 'total' }, { name => 'report_date' } ], closure_custom_calc => $self->can('custom_active_calc'), closure_custom_output => $self->can('custom_active_output'), closure_custom_threshold_check => $self->can('custom_active_threshold'), closure_custom_perfdata => $self->can('custom_active_perfdata') } } ]; $self->{maps_counters}->{global} = [ { label => 'total-viewed-edited-file-count', nlabel => 'onedrive.users.files.viewed.total.count', set => { key_values => [ { name => 'viewed_edited_file_count' } ], output_template => 'Viewed or Edited File Count: %d', perfdatas => [ { label => 'total_viewed_edited_file_count', template => '%d', min => 0 } ] } }, { label => 'total-synced-file-count', nlabel => 'onedrive.users.files.synced.total.count', set => { key_values => [ { name => 'synced_file_count' } ], output_template => 'Synced File Count: %d', perfdatas => [ { label => 'total_synced_file_count', template => '%d', min => 0 } ] } }, { label => 'total-shared-int-file-count', nlabel => 'onedrive.users.files.shared.internally.total.count', set => { key_values => [ { name => 'shared_int_file_count' } ], output_template => 'Shared Internally File Count: %d', perfdatas => [ { label => 'total_shared_int_file_count', template => '%d', min => 0 } ] } }, { label => 'total-shared-ext-file-count', nlabel => 'onedrive.users.files.shared.externally.total.count', set => { key_values => [ { name => 'shared_ext_file_count' } ], output_template => 'Shared Externally File Count: %d', perfdatas => [ { label => 'total_shared_ext_file_count', template => '%d', min => 0 } ] } } ]; $self->{maps_counters}->{users} = [ { label => 'viewed-edited-file-count', nlabel => 'onedrive.users.files.viewed.count', set => { key_values => [ { name => 'viewed_edited_file_count' }, { name => 'name' } ], output_template => 'Viewed or Edited File Count: %d', perfdatas => [ { label => 'viewed_edited_file_count', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'name' } ] } }, { label => 'synced-file-count', nlabel => 'onedrive.users.files.synced.count', set => { key_values => [ { name => 'synced_file_count' }, { name => 'name' } ], output_template => 'Synced File Count: %d', perfdatas => [ { label => 'synced_file_count', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'name' } ] } }, { label => 'shared-int-file-count', nlabel => 'onedrive.users.files.shared.internally.count', set => { key_values => [ { name => 'shared_int_file_count' }, { name => 'name' } ], output_template => 'Shared Internally File Count: %d', perfdatas => [ { label => 'shared_int_file_count', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'name' } ] } }, { label => 'shared-ext-file-count', nlabel => 'onedrive.users.files.shared.externally.count', set => { key_values => [ { name => 'shared_ext_file_count' }, { name => 'name' } ], output_template => 'Shared Externally File Count: %d', perfdatas => [ { label => 'shared_ext_file_count', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'name' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-user:s" => { name => 'filter_user' }, "units:s" => { name => 'units', default => '%' }, "filter-counters:s" => { name => 'filter_counters', default => 'active|total' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{active} = { active => 0, total => 0, report_date => '' }; $self->{global} = { viewed_edited_file_count => 0, synced_file_count => 0, shared_int_file_count => 0, shared_ext_file_count => 0 }; $self->{users} = {}; my $results = $options{custom}->office_get_onedrive_activity(param => "period='D7'"); my $results_daily = []; if (scalar(@{$results})) { $self->{active}->{report_date} = @{$results}[0]->{'Report Refresh Date'}; $results_daily = $options{custom}->office_get_onedrive_activity(param => "date=" . $self->{active}->{report_date}); } foreach my $user (@{$results}, @{$results_daily}) { if (defined($self->{option_results}->{filter_user}) && $self->{option_results}->{filter_user} ne '' && $user->{'User Principal Name'} !~ /$self->{option_results}->{filter_user}/) { $self->{output}->output_add(long_msg => "skipping '" . $user->{'User Principal Name'} . "': no matching filter name.", debug => 1); next; } if ($user->{'Report Period'} != 1) { if (!defined($user->{'Last Activity Date'}) || ($user->{'Last Activity Date'} ne $self->{active}->{report_date})) { $self->{output}->output_add(long_msg => "skipping '" . $user->{'User Principal Name'} . "': no activity.", debug => 1); } $self->{active}->{total}++; next; } $self->{active}->{active}++; $self->{global}->{viewed_edited_file_count} += ($user->{'Viewed Or Edited File Count'} ne '') ? $user->{'Viewed Or Edited File Count'} : 0; $self->{global}->{synced_file_count} += ($user->{'Synced File Count'} ne '') ? $user->{'Synced File Count'} : 0; $self->{global}->{shared_int_file_count} += ($user->{'Shared Internally File Count'} ne '') ? $user->{'Shared Internally File Count'} : 0; $self->{global}->{shared_ext_file_count} += ($user->{'Shared Externally File Count'} ne '') ? $user->{'Shared Externally File Count'} : 0; $self->{users}->{$user->{'User Principal Name'}}->{name} = $user->{'User Principal Name'}; $self->{users}->{$user->{'User Principal Name'}}->{viewed_edited_file_count} = $user->{'Viewed Or Edited File Count'}; $self->{users}->{$user->{'User Principal Name'}}->{synced_file_count} = $user->{'Synced File Count'}; $self->{users}->{$user->{'User Principal Name'}}->{shared_int_file_count} = $user->{'Shared Internally File Count'}; $self->{users}->{$user->{'User Principal Name'}}->{shared_ext_file_count} = $user->{'Shared Externally File Count'}; } } 1; __END__ =head1 MODE Check users activity (reporting period over the last refreshed day). (See link for details about metrics : https://docs.microsoft.com/en-us/microsoft-365/admin/activity-reports/onedrive-for-business-activity?view=o365-worldwide) =over 8 =item B<--filter-user> Filter users. =item B<--warning-*> Threshold warning. Can be: 'active-users', 'total-viewed-edited-file-count' (count), 'total-synced-file-count' (count), 'total-shared-int-file-count' (count), 'total-shared-ext-file-count' (count), 'viewed-edited-file-count' (count), 'synced-file-count' (count), 'shared-int-file-count' (count), 'shared-ext-file-count' (count). =item B<--critical-*> Threshold critical. Can be: 'active-users', 'total-viewed-edited-file-count' (count), 'total-synced-file-count' (count), 'total-shared-int-file-count' (count), 'total-shared-ext-file-count' (count), 'viewed-edited-file-count' (count), 'synced-file-count' (count), 'shared-int-file-count' (count), 'shared-ext-file-count' (count). =item B<--filter-counters> Only display some counters (regexp can be used). Example to hide per user counters: --filter-counters='active|total' (Default: 'active|total') =item B<--units> Unit of thresholds (Default: '%') ('%', 'count'). =back =cut centreon-plugins-20220113/cloud/microsoft/office365/onedrive/plugin.pm000066400000000000000000000030431417000230700255070ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::microsoft::office365::onedrive::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} } = ( 'list-sites' => 'cloud::microsoft::office365::onedrive::mode::listsites', 'site-usage' => 'cloud::microsoft::office365::onedrive::mode::siteusage', 'users-activity' => 'cloud::microsoft::office365::onedrive::mode::usersactivity', ); $self->{custom_modes}{graphapi} = 'cloud::microsoft::office365::custom::graphapi'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Office 365 OneDrive. =cut centreon-plugins-20220113/cloud/microsoft/office365/sharepoint/000077500000000000000000000000001417000230700242145ustar00rootroot00000000000000centreon-plugins-20220113/cloud/microsoft/office365/sharepoint/mode/000077500000000000000000000000001417000230700251405ustar00rootroot00000000000000centreon-plugins-20220113/cloud/microsoft/office365/sharepoint/mode/listsites.pm000066400000000000000000000076501417000230700275310ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::microsoft::office365::sharepoint::mode::listsites; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-url:s' => { name => 'filter_url' }, 'filter-id:s' => { name => 'filter_id' }, 'use-pseudonymize:s' => { name => 'use_pseudonymize' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->office_get_sharepoint_site_usage(param => "period='D7'"); foreach my $site (@$results) { if ($site->{'Site URL'} !~ /^(https|http):/ && !defined($self->{option_results}->{use_pseudonymize})) { $self->{output}->add_option_msg(short_msg => "reports pseudonymize user-level information is enabled. use option --use-pseudonymize or disable it"); $self->{output}->option_exit(); } if (defined($self->{option_results}->{filter_url}) && $self->{option_results}->{filter_url} ne '' && $site->{'Site URL'} !~ /$self->{option_results}->{filter_url}/) { $self->{output}->output_add(long_msg => "skipping '" . $site->{'Site URL'} . "': no matching filter name.", debug => 1); next; } if (defined($self->{option_results}->{filter_id}) && $self->{option_results}->{filter_id} ne '' && $site->{'Site Id'} !~ /$self->{option_results}->{filter_id}/) { $self->{output}->output_add(long_msg => "skipping '" . $site->{'Site Id'} . "': no matching filter name.", debug => 1); next; } $self->{sites}->{ $site->{'Site Id'} } = { id => $site->{'Site Id'}, url => $site->{'Site URL'} } } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $site (sort keys %{$self->{sites}}) { $self->{output}->output_add( long_msg => sprintf( "[id: %s] [url: %s]", $self->{sites}->{$site}->{id}, $self->{sites}->{$site}->{url} ) ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List sites:' ); $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 => ['id', 'url']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $site (sort keys %{$self->{sites}}) { $self->{output}->add_disco_entry( id => $self->{sites}->{$site}->{id}, url => $self->{sites}->{$site}->{url} ); } } 1; __END__ =head1 MODE List sites. =over 8 =item B<--filter-*> Filter sites. Can be: 'url', 'id' (can be a regexp). =item B<--use-pseudonymize> Use pseudonymize user-level information. =back =cut centreon-plugins-20220113/cloud/microsoft/office365/sharepoint/mode/siteusage.pm000066400000000000000000000446461417000230700275050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::microsoft::office365::sharepoint::mode::siteusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Time::Local; sub custom_active_perfdata { my ($self, %options) = @_; my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } if ($self->{result_values}->{report_date} =~ /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/) { $self->{output}->perfdata_add(label => 'perfdate', value => timelocal(0,0,12,$3,$2-1,$1-1900)); } $self->{output}->perfdata_add( label => 'active_sites', nlabel => 'sharepoint.sites.active.count', value => $self->{result_values}->{active}, 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), unit => 'sites', min => 0, max => $self->{result_values}->{total} ); } sub custom_active_threshold { my ($self, %options) = @_; my $threshold_value = $self->{result_values}->{active}; if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_active}; } my $exit = $self->{perfdata}->threshold_check( value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_active_output { my ($self, %options) = @_; return sprintf( 'Active sites on %s : %d/%d (%.2f%%)', $self->{result_values}->{report_date}, $self->{result_values}->{active}, $self->{result_values}->{total}, $self->{result_values}->{prct_active} ); } sub custom_active_calc { my ($self, %options) = @_; $self->{result_values}->{active} = $options{new_datas}->{$self->{instance} . '_active'}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_total'}; $self->{result_values}->{report_date} = $options{new_datas}->{$self->{instance} . '_report_date'}; $self->{result_values}->{prct_active} = ($self->{result_values}->{total} != 0) ? $self->{result_values}->{active} * 100 / $self->{result_values}->{total} : 0; return 0; } sub custom_usage_perfdata { my ($self, %options) = @_; my $extra_label = ''; $extra_label = '_' . $self->{result_values}->{display} if (!defined($options{extra_instance}) || $options{extra_instance} != 0); $self->{output}->perfdata_add( label => 'used' . $extra_label, nlabel => $self->{result_values}->{display} . '#sharepoint.sites.usage.bytes', unit => 'B', value => $self->{result_values}->{used}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), min => 0, max => $self->{result_values}->{total} ); } sub custom_usage_threshold { my ($self, %options) = @_; my ($exit, $threshold_value); $threshold_value = $self->{result_values}->{used}; $threshold_value = $self->{result_values}->{free} if (defined($self->{instance_mode}->{option_results}->{free})); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; $threshold_value = $self->{result_values}->{prct_free} if (defined($self->{instance_mode}->{option_results}->{free})); } $exit = $self->{perfdata}->threshold_check( value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_usage_output { my ($self, %options) = @_; my ($used_value, $used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); my ($free_value, $free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); my ($total_value, $total_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); return sprintf( 'Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)', $total_value . " " . $total_unit, $used_value . " " . $used_unit, $self->{result_values}->{prct_used}, $free_value . " " . $free_unit, $self->{result_values}->{prct_free} ); } sub custom_usage_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_url'}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_storage_allocated'}; $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_storage_used'}; if ($self->{result_values}->{total} != 0) { $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}; } else { $self->{result_values}->{free} = '0'; $self->{result_values}->{prct_used} = '0'; $self->{result_values}->{prct_free} = '0'; } return 0; } sub prefix_global_output { my ($self, %options) = @_; return "Total "; } sub prefix_site_output { my ($self, %options) = @_; return "Site '" . $options{instance_value}->{url} . "' [ID: " . $options{instance_value}->{id} . "] "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'active', type => 0 }, { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }, { name => 'sites', type => 1, cb_prefix_output => 'prefix_site_output', message_multiple => 'All sites usage are ok' }, ]; $self->{maps_counters}->{active} = [ { label => 'active-sites', set => { key_values => [ { name => 'active' }, { name => 'total' }, { name => 'report_date' } ], closure_custom_calc => $self->can('custom_active_calc'), closure_custom_output => $self->can('custom_active_output'), closure_custom_threshold_check => $self->can('custom_active_threshold'), closure_custom_perfdata => $self->can('custom_active_perfdata') } } ]; $self->{maps_counters}->{global} = [ { label => 'total-usage-active', nlabel => 'sharepoint.sites.active.usage.total.bytes', set => { key_values => [ { name => 'storage_used_active' } ], output_template => 'Usage (active sites): %s %s', output_change_bytes => 1, perfdatas => [ { label => 'total_usage_active', template => '%d', min => 0, unit => 'B' } ] } }, { label => 'total-usage-inactive', nlabel => 'sharepoint.sites.inactive.usage.total.bytes', set => { key_values => [ { name => 'storage_used_inactive' } ], output_template => 'Usage (inactive sites): %s %s', output_change_bytes => 1, perfdatas => [ { label => 'total_usage_inactive', template => '%d', min => 0, unit => 'B' } ] } }, { label => 'total-file-count-active', nlabel => 'sharepoint.sites.active.files.total.count', set => { key_values => [ { name => 'file_count_active' } ], output_template => 'File Count (active sites): %d', perfdatas => [ { label => 'total_file_count_active', template => '%d', min => 0 } ] } }, { label => 'total-file-count-inactive', nlabel => 'sharepoint.sites.inactive.files.total.count', set => { key_values => [ { name => 'file_count_inactive' } ], output_template => 'File Count (inactive sites): %d', perfdatas => [ { label => 'total_file_count_inactive', template => '%d', min => 0 } ] } }, { label => 'total-active-file-count', nlabel => 'sharepoint.sites.files.active.total.count', set => { key_values => [ { name => 'active_file_count' } ], output_template => 'Active File Count (active sites): %d', perfdatas => [ { label => 'total_active_file_count', template => '%d', min => 0 } ] } }, { label => 'total-visited-page-count', nlabel => 'sharepoint.sites.pages.visited.total.count', set => { key_values => [ { name => 'visited_page_count' } ], output_template => 'Visited Page Count (active sites): %d', perfdatas => [ { label => 'total_visited_page_count', template => '%d', min => 0 } ] } }, { label => 'total-page-view-count', nlabel => 'sharepoint.sites.pages.viewed.total.count', set => { key_values => [ { name => 'page_view_count' } ], output_template => 'Page View Count (active sites): %d', perfdatas => [ { label => 'total_page_view_count', template => '%d', min => 0 } ] } } ]; $self->{maps_counters}->{sites} = [ { label => 'usage', set => { key_values => [ { name => 'storage_used' }, { name => 'storage_allocated' }, { name => 'url' }, { name => 'id' } ], 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 => 'file-count', nlabel => 'sharepoint.sites.files.count', set => { key_values => [ { name => 'file_count' }, { name => 'url' }, { name => 'id' } ], output_template => 'File Count: %d', perfdatas => [ { label => 'file_count', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'url' } ] } }, { label => 'active-file-count', nlabel => 'sharepoint.sites.files.active.count', set => { key_values => [ { name => 'active_file_count' }, { name => 'url' }, { name => 'id' } ], output_template => 'Active File Count: %d', perfdatas => [ { label => 'active_file_count', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'url' } ] } }, { label => 'visited-page-count', nlabel => 'sharepoint.sites.pages.visited.count', set => { key_values => [ { name => 'visited_page_count' }, { name => 'url' }, { name => 'id' } ], output_template => 'Visited Page Count: %d', perfdatas => [ { label => 'visited_page_count', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'url' } ] } }, { label => 'page-view-count', nlabel => 'sharepoint.sites.pages.viewed.count', set => { key_values => [ { name => 'page_view_count' }, { name => 'url' }, { name => 'id' } ], output_template => 'Page View Count: %d', perfdatas => [ { label => 'page_view_count', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'url' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-url:s' => { name => 'filter_url' }, 'filter-id:s' => { name => 'filter_id' }, 'use-pseudonymize:s' => { name => 'use_pseudonymize' }, 'units:s' => { name => 'units', default => '%' }, 'free' => { name => 'free' }, 'filter-counters:s' => { name => 'filter_counters', default => 'active-sites|total' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{active} = { active => 0, total => 0, report_date => '' }; $self->{global} = { storage_used_active => 0, storage_used_inactive => 0, file_count_active => 0, file_count_inactive => 0, active_file_count => 0 , visited_page_count => 0 , page_view_count => 0 }; $self->{sites} = {}; my $results = $options{custom}->office_get_sharepoint_site_usage(param => "period='D7'"); my $results_daily = []; if (scalar(@{$results})) { $self->{active}->{report_date} = $results->[0]->{'Report Refresh Date'}; $results_daily = $options{custom}->office_get_sharepoint_site_usage(param => "date=" . $self->{active}->{report_date}); } foreach my $site (@{$results}, @{$results_daily}) { if ($site->{'Site URL'} !~ /^(https|http):/ && !defined($self->{option_results}->{use_pseudonymize})) { $self->{output}->add_option_msg(short_msg => "reports pseudonymize user-level information is enabled. use option --use-pseudonymize or disable it"); $self->{output}->option_exit(); } if (defined($self->{option_results}->{filter_url}) && $self->{option_results}->{filter_url} ne '' && $site->{'Site URL'} !~ /$self->{option_results}->{filter_url}/) { $self->{output}->output_add(long_msg => "skipping '" . $site->{'Site URL'} . "': no matching filter name.", debug => 1); next; } if (defined($self->{option_results}->{filter_id}) && $self->{option_results}->{filter_id} ne '' && $site->{'Site Id'} !~ /$self->{option_results}->{filter_id}/) { $self->{output}->output_add(long_msg => "skipping '" . $site->{'Site Id'} . "': no matching filter name.", debug => 1); next; } if ($site->{'Report Period'} != 1) { if (!defined($site->{'Last Activity Date'}) || ($site->{'Last Activity Date'} ne $self->{active}->{report_date})) { $self->{global}->{storage_used_inactive} += ($site->{'Storage Used (Byte)'} ne '') ? $site->{'Storage Used (Byte)'} : 0; $self->{global}->{file_count_inactive} += ($site->{'File Count'} ne '') ? $site->{'File Count'} : 0; $self->{output}->output_add(long_msg => "skipping '" . $site->{'Site URL'} . "': no activity.", debug => 1); } $self->{active}->{total}++; next; } $self->{active}->{active}++; $self->{global}->{storage_used_active} += ($site->{'Storage Used (Byte)'} ne '') ? $site->{'Storage Used (Byte)'} : 0; $self->{global}->{file_count_active} += ($site->{'File Count'} ne '') ? $site->{'File Count'} : 0; $self->{global}->{active_file_count} += ($site->{'Active File Count'} ne '') ? $site->{'Active File Count'} : 0; $self->{global}->{visited_page_count} += ($site->{'Visited Page Count'} ne '') ? $site->{'Visited Page Count'} : 0; $self->{global}->{page_view_count} += ($site->{'Page View Count'} ne '') ? $site->{'Page View Count'} : 0; $self->{sites}->{$site->{'Site URL'}}->{url} = $site->{'Site URL'}; $self->{sites}->{$site->{'Site URL'}}->{id} = $site->{'Site Id'}; $self->{sites}->{$site->{'Site URL'}}->{file_count} = $site->{'File Count'}; $self->{sites}->{$site->{'Site URL'}}->{active_file_count} = $site->{'Active File Count'}; $self->{sites}->{$site->{'Site URL'}}->{visited_page_count} = $site->{'Visited Page Count'}; $self->{sites}->{$site->{'Site URL'}}->{page_view_count} = $site->{'Page View Count'}; $self->{sites}->{$site->{'Site URL'}}->{storage_used} = $site->{'Storage Used (Byte)'}; $self->{sites}->{$site->{'Site URL'}}->{storage_allocated} = $site->{'Storage Allocated (Byte)'}; $self->{sites}->{$site->{'Site URL'}}->{last_activity_date} = $site->{'Last Activity Date'}; } } 1; __END__ =head1 MODE Check sites usage (reporting period over the last refreshed day). (See link for details about metrics : https://docs.microsoft.com/en-us/microsoft-365/admin/activity-reports/sharepoint-site-usage?view=o365-worldwide) =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example to hide per user counters: --filter-counters='active-sites|total' (Default: 'active-sites|total') =item B<--filter-*> Filter sites. Can be: 'url', 'id' (can be a regexp). =item B<--use-pseudonymize> Use pseudonymize user-level information. =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'active-sites', 'total-usage-active' (count), 'total-usage-inactive' (count), 'total-file-count-active' (count), 'total-file-count-inactive' (count), 'total-active-file-count' (count), 'total-visited-page-count' (count), 'total-page-view-count' (count), 'usage' (count), 'file-count' (count), 'active-file-count' (count), 'visited-page-count' (count), 'page-view-count' (count). =item B<--units> Unit of thresholds (Default: '%') ('%', 'count'). =back =cut centreon-plugins-20220113/cloud/microsoft/office365/sharepoint/mode/usersactivity.pm000066400000000000000000000332611417000230700304210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::microsoft::office365::sharepoint::mode::usersactivity; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Time::Local; sub custom_active_perfdata { my ($self, %options) = @_; my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } if ($self->{result_values}->{report_date} =~ /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/) { $self->{output}->perfdata_add(label => 'perfdate', value => timelocal(0,0,12,$3,$2-1,$1-1900)); } $self->{output}->perfdata_add( label => 'active_users', nlabel => 'sharepoint.users.active.count', value => $self->{result_values}->{active}, 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), unit => 'users', min => 0, max => $self->{result_values}->{total} ); } sub custom_active_threshold { my ($self, %options) = @_; my $threshold_value = $self->{result_values}->{active}; if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_active}; } my $exit = $self->{perfdata}->threshold_check( value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_active_output { my ($self, %options) = @_; return sprintf( "Active users on %s : %d/%d (%.2f%%)", $self->{result_values}->{report_date}, $self->{result_values}->{active}, $self->{result_values}->{total}, $self->{result_values}->{prct_active} ); } sub custom_active_calc { my ($self, %options) = @_; $self->{result_values}->{active} = $options{new_datas}->{$self->{instance} . '_active'}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_total'}; $self->{result_values}->{report_date} = $options{new_datas}->{$self->{instance} . '_report_date'}; $self->{result_values}->{prct_active} = ($self->{result_values}->{total} != 0) ? $self->{result_values}->{active} * 100 / $self->{result_values}->{total} : 0; return 0; } sub prefix_global_output { my ($self, %options) = @_; return "Total (active sites) "; } sub prefix_user_output { my ($self, %options) = @_; return "User '" . $options{instance_value}->{name} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'active', type => 0 }, { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }, { name => 'users', type => 1, cb_prefix_output => 'prefix_user_output', message_multiple => 'All users activity are ok' } ]; $self->{maps_counters}->{active} = [ { label => 'active-users', set => { key_values => [ { name => 'active' }, { name => 'total' }, { name => 'report_date' } ], closure_custom_calc => $self->can('custom_active_calc'), closure_custom_output => $self->can('custom_active_output'), closure_custom_threshold_check => $self->can('custom_active_threshold'), closure_custom_perfdata => $self->can('custom_active_perfdata') } } ]; $self->{maps_counters}->{global} = [ { label => 'total-viewed-edited-file-count', nlabel => 'sharepoint.users.files.viewed.total.count', set => { key_values => [ { name => 'viewed_edited_file_count' } ], output_template => 'Viewed or Edited File Count: %d', perfdatas => [ { label => 'total_viewed_edited_file_count', template => '%d', min => 0 } ] } }, { label => 'total-synced-file-count', nlabel => 'sharepoint.users.files.synced.total.count', set => { key_values => [ { name => 'synced_file_count' } ], output_template => 'Synced File Count: %d', perfdatas => [ { label => 'total_synced_file_count', template => '%d', min => 0 } ] } }, { label => 'total-shared-int-file-count', nlabel => 'sharepoint.users.files.shared.internally.total.count', set => { key_values => [ { name => 'shared_int_file_count' } ], output_template => 'Shared Internally File Count: %d', perfdatas => [ { label => 'total_shared_int_file_count', template => '%d', min => 0 } ] } }, { label => 'total-shared-ext-file-count', nlabel => 'sharepoint.users.files.shared.externally.total.count', set => { key_values => [ { name => 'shared_ext_file_count' } ], output_template => 'Shared Externally File Count: %d', perfdatas => [ { label => 'total_shared_ext_file_count', template => '%d', min => 0 } ] } }, { label => 'total-visited-page-count', nlabel => 'sharepoint.users.pages.visited.total.count', set => { key_values => [ { name => 'visited_page_count' } ], output_template => 'Visited Page Count (active sites): %d', perfdatas => [ { label => 'total_visited_page_count', template => '%d', min => 0 } ] } } ]; $self->{maps_counters}->{users} = [ { label => 'viewed-edited-file-count', nlabel => 'sharepoint.users.files.viewed.count', set => { key_values => [ { name => 'viewed_edited_file_count' }, { name => 'name' } ], output_template => 'Viewed or Edited File Count: %d', perfdatas => [ { label => 'viewed_edited_file_count', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'name' } ] } }, { label => 'synced-file-count', nlabel => 'sharepoint.users.files.synced.count', set => { key_values => [ { name => 'synced_file_count' }, { name => 'name' } ], output_template => 'Synced File Count: %d', perfdatas => [ { label => 'synced_file_count', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'name' } ] } }, { label => 'shared-int-file-count', nlabel => 'sharepoint.users.files.shared.internally.count', set => { key_values => [ { name => 'shared_int_file_count' }, { name => 'name' } ], output_template => 'Shared Internally File Count: %d', perfdatas => [ { label => 'shared_int_file_count', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'name' } ] } }, { label => 'shared-ext-file-count', nlabel => 'sharepoint.users.files.shared.externally.count', set => { key_values => [ { name => 'shared_ext_file_count' }, { name => 'name' } ], output_template => 'Shared Externally File Count: %d', perfdatas => [ { label => 'shared_ext_file_count', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'name' } ] } }, { label => 'visited-page-count', nlabel => 'sharepoint.users.pages.visited.count', set => { key_values => [ { name => 'visited_page_count' }, { name => 'name' } ], output_template => 'Visited Page Count: %d', perfdatas => [ { label => 'visited_page_count', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'name' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-user:s" => { name => 'filter_user' }, "units:s" => { name => 'units', default => '%' }, "filter-counters:s" => { name => 'filter_counters', default => 'active|total' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{active} = { active => 0, total => 0, report_date => '' }; $self->{global} = { viewed_edited_file_count => 0, synced_file_count => 0, shared_int_file_count => 0, shared_ext_file_count => 0, visited_page_count => 0 }; $self->{users} = {}; my $results = $options{custom}->office_get_sharepoint_activity(param => "period='D7'"); my $results_daily = []; if (scalar(@{$results})) { $self->{active}->{report_date} = @{$results}[0]->{'Report Refresh Date'}; $results_daily = $options{custom}->office_get_sharepoint_activity(param => "date=" . $self->{active}->{report_date}); } foreach my $user (@{$results}, @{$results_daily}) { if (defined($self->{option_results}->{filter_user}) && $self->{option_results}->{filter_user} ne '' && $user->{'User Principal Name'} !~ /$self->{option_results}->{filter_user}/) { $self->{output}->output_add(long_msg => "skipping '" . $user->{'User Principal Name'} . "': no matching filter name.", debug => 1); next; } if ($user->{'Report Period'} != 1) { if (!defined($user->{'Last Activity Date'}) || ($user->{'Last Activity Date'} ne $self->{active}->{report_date})) { $self->{output}->output_add(long_msg => "skipping '" . $user->{'User Principal Name'} . "': no activity.", debug => 1); } $self->{active}->{total}++; next; } $self->{active}->{active}++; $self->{global}->{viewed_edited_file_count} += ($user->{'Viewed Or Edited File Count'} ne '') ? $user->{'Viewed Or Edited File Count'} : 0; $self->{global}->{synced_file_count} += ($user->{'Synced File Count'} ne '') ? $user->{'Synced File Count'} : 0; $self->{global}->{shared_int_file_count} += ($user->{'Shared Internally File Count'} ne '') ? $user->{'Shared Internally File Count'} : 0; $self->{global}->{shared_ext_file_count} += ($user->{'Shared Externally File Count'} ne '') ? $user->{'Shared Externally File Count'} : 0; $self->{global}->{visited_page_count} += ($user->{'Visited Page Count'} ne '') ? $user->{'Visited Page Count'} : 0; $self->{users}->{$user->{'User Principal Name'}}->{name} = $user->{'User Principal Name'}; $self->{users}->{$user->{'User Principal Name'}}->{viewed_edited_file_count} = $user->{'Viewed Or Edited File Count'}; $self->{users}->{$user->{'User Principal Name'}}->{synced_file_count} = $user->{'Synced File Count'}; $self->{users}->{$user->{'User Principal Name'}}->{shared_int_file_count} = $user->{'Shared Internally File Count'}; $self->{users}->{$user->{'User Principal Name'}}->{shared_ext_file_count} = $user->{'Shared Externally File Count'}; $self->{users}->{$user->{'User Principal Name'}}->{visited_page_count} = $user->{'Visited Page Count'}; } } 1; __END__ =head1 MODE Check users activity (reporting period over the last refreshed day). (See link for details about metrics : https://docs.microsoft.com/en-us/microsoft-365/admin/activity-reports/sharepoint-activity?view=o365-worldwide) =over 8 =item B<--filter-user> Filter users. =item B<--warning-*> Threshold warning. Can be: 'active-users', 'total-viewed-edited-file-count' (count), 'total-synced-file-count' (count), 'total-shared-int-file-count' (count), 'total-shared-ext-file-count' (count), 'total-visited-page-count' (count), 'viewed-edited-file-count' (count), 'synced-file-count' (count), 'shared-int-file-count' (count), 'shared-ext-file-count' (count), 'visited-page-count' (count). =item B<--critical-*> Threshold critical. Can be: 'active-users', 'total-viewed-edited-file-count' (count), 'total-synced-file-count' (count), 'total-shared-int-file-count' (count), 'total-shared-ext-file-count' (count), 'total-visited-page-count' (count), 'viewed-edited-file-count' (count), 'synced-file-count' (count), 'shared-int-file-count' (count), 'shared-ext-file-count' (count), 'visited-page-count' (count). =item B<--filter-counters> Only display some counters (regexp can be used). Example to hide per user counters: --filter-counters='active|total' (Default: 'active|total') =item B<--units> Unit of thresholds (Default: '%') ('%', 'count'). =back =cut centreon-plugins-20220113/cloud/microsoft/office365/sharepoint/plugin.pm000066400000000000000000000030551417000230700260530ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::microsoft::office365::sharepoint::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} } = ( 'list-sites' => 'cloud::microsoft::office365::sharepoint::mode::listsites', 'site-usage' => 'cloud::microsoft::office365::sharepoint::mode::siteusage', 'users-activity' => 'cloud::microsoft::office365::sharepoint::mode::usersactivity', ); $self->{custom_modes}{graphapi} = 'cloud::microsoft::office365::custom::graphapi'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Office 365 SharePoint. =cut centreon-plugins-20220113/cloud/microsoft/office365/skype/000077500000000000000000000000001417000230700231735ustar00rootroot00000000000000centreon-plugins-20220113/cloud/microsoft/office365/skype/mode/000077500000000000000000000000001417000230700241175ustar00rootroot00000000000000centreon-plugins-20220113/cloud/microsoft/office365/skype/mode/devicesusage.pm000066400000000000000000000223771417000230700271370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::microsoft::office365::skype::mode::devicesusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Time::Local; sub custom_active_perfdata { my ($self, %options) = @_; my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } if ($self->{result_values}->{report_date} =~ /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/) { $self->{output}->perfdata_add(label => 'perfdate', value => timelocal(0,0,12,$3,$2-1,$1-1900)); } $self->{output}->perfdata_add( label => 'active_devices', nlabel => 'skype.devices.active.count', value => $self->{result_values}->{active}, 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), unit => 'devices', min => 0, max => $self->{result_values}->{total} ); } sub custom_active_threshold { my ($self, %options) = @_; my $threshold_value = $self->{result_values}->{active}; if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_active}; } my $exit = $self->{perfdata}->threshold_check( value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_active_output { my ($self, %options) = @_; return sprintf( "Active devices on %s : %d/%d (%.2f%%)", $self->{result_values}->{report_date}, $self->{result_values}->{active}, $self->{result_values}->{total}, $self->{result_values}->{prct_active} ); } sub custom_active_calc { my ($self, %options) = @_; $self->{result_values}->{active} = $options{new_datas}->{$self->{instance} . '_active'}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_total'}; $self->{result_values}->{report_date} = $options{new_datas}->{$self->{instance} . '_report_date'}; $self->{result_values}->{prct_active} = ($self->{result_values}->{total} != 0) ? $self->{result_values}->{active} * 100 / $self->{result_values}->{total} : 0; return 0; } sub prefix_global_output { my ($self, %options) = @_; return "Users count by device type : "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'active', type => 0 }, { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }, ]; $self->{maps_counters}->{active} = [ { label => 'active-devices', set => { key_values => [ { name => 'active' }, { name => 'total' }, { name => 'report_date' } ], closure_custom_calc => $self->can('custom_active_calc'), closure_custom_output => $self->can('custom_active_output'), closure_custom_threshold_check => $self->can('custom_active_threshold'), closure_custom_perfdata => $self->can('custom_active_perfdata') } }, ]; $self->{maps_counters}->{global} = [ { label => 'windows', nlabel => 'skype.devices.windows.count', set => { key_values => [ { name => 'windows' } ], output_template => 'Windows: %d', perfdatas => [ { label => 'windows', template => '%d', min => 0 } ] } }, { label => 'ipad', nlabel => 'skype.devices.ipad.count', set => { key_values => [ { name => 'ipad' } ], output_template => 'iPad: %d', perfdatas => [ { label => 'ipad', template => '%d', min => 0 } ] } }, { label => 'iphone', nlabel => 'skype.devices.iphone.count', set => { key_values => [ { name => 'iphone' } ], output_template => 'iPhone: %d', perfdatas => [ { label => 'iphone', template => '%d', min => 0 } ] } }, { label => 'android-phone', nlabel => 'skype.devices.android.count', set => { key_values => [ { name => 'android_phone' } ], output_template => 'Android Phone: %d', perfdatas => [ { label => 'android_phone', template => '%d', min => 0 } ] } }, { label => 'windows-phone', nlabel => 'skype.devices.windowsphone.count', set => { key_values => [ { name => 'windows_phone' } ], output_template => 'Windows Phone: %d', perfdatas => [ { label => 'windows_phone', template => '%d', min => 0 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-user:s' => { name => 'filter_user' }, 'units:s' => { name => 'units', default => '%' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{active} = { active => 0, total => 0, report_date => '' }; $self->{global} = { windows => 0, ipad => 0, iphone => 0, android_phone => 0, windows_phone => 0 }; my $results = $options{custom}->office_get_skype_device_usage(param => "period='D7'"); my $results_daily = []; if (scalar(@{$results})) { $self->{active}->{report_date} = @{$results}[0]->{'Report Refresh Date'}; $results_daily = $options{custom}->office_get_skype_device_usage(param => "date=" . $self->{active}->{report_date}); } foreach my $user (@{$results}, @{$results_daily}) { if (defined($self->{option_results}->{filter_user}) && $self->{option_results}->{filter_user} ne '' && $user->{'User Principal Name'} !~ /$self->{option_results}->{filter_user}/) { $self->{output}->output_add(long_msg => "skipping '" . $user->{'User Principal Name'} . "': no matching filter name.", debug => 1); next; } my $used_devices = 0; $used_devices++ if ($user->{'Used Windows'} =~ /Yes/); $used_devices++ if ($user->{'Used iPad'} =~ /Yes/); $used_devices++ if ($user->{'Used iPhone'} =~ /Yes/); $used_devices++ if ($user->{'Used Android Phone'} =~ /Yes/); $used_devices++ if ($user->{'Used Windows Phone'} =~ /Yes/); if ($user->{'Report Period'} != 1) { if (!defined($user->{'Last Activity Date'}) || ($user->{'Last Activity Date'} ne $self->{active}->{report_date})) { $self->{output}->output_add(long_msg => "skipping '" . $user->{'User Principal Name'} . "': no activity.", debug => 1); } $self->{active}->{total} += $used_devices; next; } $self->{active}->{active} += $used_devices; $self->{global}->{windows}++ if ($user->{'Used Windows'} =~ /Yes/); $self->{global}->{ipad}++ if ($user->{'Used iPad'} =~ /Yes/); $self->{global}->{iphone}++ if ($user->{'Used iPhone'} =~ /Yes/); $self->{global}->{android_phone}++ if ($user->{'Used Android Phone'} =~ /Yes/); $self->{global}->{windows_phone}++ if ($user->{'Used Windows Phone'} =~ /Yes/); } } 1; __END__ =head1 MODE Check devices usage (reporting period over the last refreshed day). (See link for details about metrics : https://docs.microsoft.com/en-us/SkypeForBusiness/skype-for-business-online-reporting/device-usage-report) =over 8 =item B<--filter-user> Filter users. =item B<--warning-*> Threshold warning. Can be: 'active-devices', 'windows' (count), 'ipad' (count), 'iphone' (count), 'android-phone' (count), 'windows-phone' (count). =item B<--critical-*> Threshold critical. Can be: 'active-devices', 'windows' (count), 'ipad' (count), 'iphone' (count), 'android-phone' (count), 'windows-phone' (count). =item B<--filter-counters> Only display some counters (regexp can be used). Example to hide per user counters: --filter-counters='windows' =item B<--units> Unit of thresholds (Default: '%') ('%', 'count'). =back =cut centreon-plugins-20220113/cloud/microsoft/office365/skype/mode/usersactivity.pm000066400000000000000000000256141417000230700274030ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::microsoft::office365::skype::mode::usersactivity; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Time::Local; sub custom_active_perfdata { my ($self, %options) = @_; my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } if ($self->{result_values}->{report_date} =~ /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/) { $self->{output}->perfdata_add(label => 'perfdate', value => timelocal(0,0,12,$3,$2-1,$1-1900)); } $self->{output}->perfdata_add( label => 'active_users', nlabel => 'skype.users.active.count', value => $self->{result_values}->{active}, 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), unit => 'users', min => 0, max => $self->{result_values}->{total} ); } sub custom_active_threshold { my ($self, %options) = @_; my $threshold_value = $self->{result_values}->{active}; if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_active}; } my $exit = $self->{perfdata}->threshold_check( value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_active_output { my ($self, %options) = @_; return sprintf( "Active users on %s : %d/%d (%.2f%%)", $self->{result_values}->{report_date}, $self->{result_values}->{active}, $self->{result_values}->{total}, $self->{result_values}->{prct_active} ); } sub custom_active_calc { my ($self, %options) = @_; $self->{result_values}->{active} = $options{new_datas}->{$self->{instance} . '_active'}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_total'}; $self->{result_values}->{report_date} = $options{new_datas}->{$self->{instance} . '_report_date'}; $self->{result_values}->{prct_active} = ($self->{result_values}->{total} != 0) ? $self->{result_values}->{active} * 100 / $self->{result_values}->{total} : 0; return 0; } sub prefix_global_output { my ($self, %options) = @_; return "Total "; } sub prefix_user_output { my ($self, %options) = @_; return "User '" . $options{instance_value}->{name} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'active', type => 0 }, { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }, { name => 'users', type => 1, cb_prefix_output => 'prefix_user_output', message_multiple => 'All users activity are ok' } ]; $self->{maps_counters}->{active} = [ { label => 'active-users', set => { key_values => [ { name => 'active' }, { name => 'total' }, { name => 'report_date' } ], closure_custom_calc => $self->can('custom_active_calc'), closure_custom_output => $self->can('custom_active_output'), closure_custom_threshold_check => $self->can('custom_active_threshold'), closure_custom_perfdata => $self->can('custom_active_perfdata') } }, ]; $self->{maps_counters}->{global} = [ { label => 'total-peer-to-peer-sessions', nlabel => 'skype.users.sessions.p2p.total.count', set => { key_values => [ { name => 'peer_to_peer_sessions' } ], output_template => 'Peer-to-peer Sessions Count: %d', perfdatas => [ { label => 'total_peer_to_peer_sessions', template => '%d', min => 0 } ] } }, { label => 'total-organized-conference', nlabel => 'skype.users.conferences.organized.total.count', set => { key_values => [ { name => 'organized_conference' } ], output_template => 'Organized Conference Count: %d', perfdatas => [ { label => 'total_organized_conference', template => '%d', min => 0 } ] } }, { label => 'total-participated-conference', nlabel => 'skype.users.conferences.participated.total.count', set => { key_values => [ { name => 'participated_conference' } ], output_template => 'Participated Conference Count: %d', perfdatas => [ { label => 'total_participated_conference', template => '%d', min => 0 } ] } } ]; $self->{maps_counters}->{users} = [ { label => 'peer-to-peer-sessions', nlabel => 'skype.users.sessions.p2p.count', set => { key_values => [ { name => 'peer_to_peer_sessions' }, { name => 'name' } ], output_template => 'Peer-to-peer Sessions Count: %d', perfdatas => [ { label => 'peer_to_peer_sessions', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'name' } ] } }, { label => 'organized-conference', nlabel => 'skype.users.conferences.organized.count', set => { key_values => [ { name => 'organized_conference' }, { name => 'name' } ], output_template => 'Organized Conference Count: %d', perfdatas => [ { label => 'organized_conference', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'name' } ] } }, { label => 'participated-conference', nlabel => 'skype.users.conferences.participated.count', set => { key_values => [ { name => 'participated_conference' }, { name => 'name' } ], output_template => 'Participated Conference Count: %d', perfdatas => [ { label => 'participated_conference', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'name' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-user:s" => { name => 'filter_user' }, "units:s" => { name => 'units', default => '%' }, "filter-counters:s" => { name => 'filter_counters', default => 'active|total' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{active} = { active => 0, total => 0, report_date => '' }; $self->{global} = { peer_to_peer_sessions => 0, organized_conference => 0, participated_conference => 0 }; $self->{users} = {}; my $results = $options{custom}->office_get_skype_activity(param => "period='D7'"); my $results_daily = []; if (scalar(@{$results})) { $self->{active}->{report_date} = @{$results}[0]->{'Report Refresh Date'}; $results_daily = $options{custom}->office_get_skype_activity(param => "date=" . $self->{active}->{report_date}); } foreach my $user (@{$results}, @{$results_daily}) { if (defined($self->{option_results}->{filter_user}) && $self->{option_results}->{filter_user} ne '' && $user->{'User Principal Name'} !~ /$self->{option_results}->{filter_user}/) { $self->{output}->output_add(long_msg => "skipping '" . $user->{'User Principal Name'} . "': no matching filter name.", debug => 1); next; } if ($user->{'Report Period'} != 1) { if (!defined($user->{'Last Activity Date'}) || ($user->{'Last Activity Date'} ne $self->{active}->{report_date})) { $self->{output}->output_add(long_msg => "skipping '" . $user->{'User Principal Name'} . "': no activity.", debug => 1); } $self->{active}->{total}++; next; } $self->{active}->{active}++; $self->{global}->{peer_to_peer_sessions} += $user->{'Total Peer-to-peer Session Count'}; $self->{global}->{organized_conference} += $user->{'Total Organized Conference Count'}; $self->{global}->{participated_conference} += $user->{'Total Participated Conference Count'}; $self->{users}->{$user->{'User Principal Name'}}->{name} = $user->{'User Principal Name'}; $self->{users}->{$user->{'User Principal Name'}}->{peer_to_peer_sessions} = $user->{'Total Peer-to-peer Session Count'}; $self->{users}->{$user->{'User Principal Name'}}->{organized_conference} = $user->{'Total Organized Conference Count'}; $self->{users}->{$user->{'User Principal Name'}}->{participated_conference} = $user->{'Total Participated Conference Count'}; } } 1; __END__ =head1 MODE Check users activity (reporting period over the last refreshed day). (See link for details about metrics : https://docs.microsoft.com/en-us/SkypeForBusiness/skype-for-business-online-reporting/activity-report) =over 8 =item B<--filter-user> Filter users. =item B<--warning-*> Threshold warning. Can be: 'active-users', 'total-peer-to-peer-sessions' (count), 'total-organized-conference' (count), 'total-participated-conference' (count), 'peer-to-peer-sessions' (count), 'organized-conference' (count), 'participated-conference' (count). =item B<--critical-*> Threshold critical. Can be: 'active-users', 'total-peer-to-peer-sessions' (count), 'total-organized-conference' (count), 'total-participated-conference' (count), 'peer-to-peer-sessions' (count), 'organized-conference' (count), 'participated-conference' (count). =item B<--filter-counters> Only display some counters (regexp can be used). Example to hide per user counters: --filter-counters='total' (Default: 'active|total') =item B<--units> Unit of thresholds (Default: '%') ('%', 'count'). =back =cut centreon-plugins-20220113/cloud/microsoft/office365/skype/plugin.pm000066400000000000000000000027321417000230700250330ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::microsoft::office365::skype::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} } = ( 'devices-usage' => 'cloud::microsoft::office365::skype::mode::devicesusage', 'users-activity' => 'cloud::microsoft::office365::skype::mode::usersactivity', ); $self->{custom_modes}{graphapi} = 'cloud::microsoft::office365::custom::graphapi'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Office 365 Skype for Business. =cut centreon-plugins-20220113/cloud/microsoft/office365/teams/000077500000000000000000000000001417000230700231515ustar00rootroot00000000000000centreon-plugins-20220113/cloud/microsoft/office365/teams/mode/000077500000000000000000000000001417000230700240755ustar00rootroot00000000000000centreon-plugins-20220113/cloud/microsoft/office365/teams/mode/devicesusage.pm000066400000000000000000000231341417000230700271050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::microsoft::office365::teams::mode::devicesusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Time::Local; sub custom_active_perfdata { my ($self, %options) = @_; my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } if ($self->{result_values}->{report_date} =~ /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/) { $self->{output}->perfdata_add(label => 'perfdate', value => timelocal(0,0,12,$3,$2-1,$1-1900)); } $self->{output}->perfdata_add( label => 'active_devices', nlabel => 'teams.devices.active.count', value => $self->{result_values}->{active}, 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), unit => 'devices', min => 0, max => $self->{result_values}->{total} ); } sub custom_active_threshold { my ($self, %options) = @_; my $threshold_value = $self->{result_values}->{active}; if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_active}; } my $exit = $self->{perfdata}->threshold_check( value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_active_output { my ($self, %options) = @_; my $msg = sprintf( "Active devices on %s : %d/%d (%.2f%%)", $self->{result_values}->{report_date}, $self->{result_values}->{active}, $self->{result_values}->{total}, $self->{result_values}->{prct_active} ); return $msg; } sub custom_active_calc { my ($self, %options) = @_; $self->{result_values}->{active} = $options{new_datas}->{$self->{instance} . '_active'}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_total'}; $self->{result_values}->{report_date} = $options{new_datas}->{$self->{instance} . '_report_date'}; $self->{result_values}->{prct_active} = ($self->{result_values}->{total} != 0) ? $self->{result_values}->{active} * 100 / $self->{result_values}->{total} : 0; return 0; } sub prefix_global_output { my ($self, %options) = @_; return "Users count by device type : "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'active', type => 0 }, { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }, ]; $self->{maps_counters}->{active} = [ { label => 'active-devices', set => { key_values => [ { name => 'active' }, { name => 'total' }, { name => 'report_date' } ], closure_custom_calc => $self->can('custom_active_calc'), closure_custom_output => $self->can('custom_active_output'), closure_custom_threshold_check => $self->can('custom_active_threshold'), closure_custom_perfdata => $self->can('custom_active_perfdata') } } ]; $self->{maps_counters}->{global} = [ { label => 'windows', nlabel => 'teams.devices.windows.count', set => { key_values => [ { name => 'windows' } ], output_template => 'Windows: %d', perfdatas => [ { label => 'windows', template => '%d', min => 0 } ] } }, { label => 'mac', nlabel => 'teams.devices.mac.count', set => { key_values => [ { name => 'mac' } ], output_template => 'Mac: %d', perfdatas => [ { label => 'mac', template => '%d', min => 0 } ] } }, { label => 'web', nlabel => 'teams.devices.web.count', set => { key_values => [ { name => 'web' } ], output_template => 'Web: %d', perfdatas => [ { label => 'web', template => '%d', min => 0 } ] } }, { label => 'ios', nlabel => 'teams.devices.ios.count', set => { key_values => [ { name => 'ios' } ], output_template => 'iOS: %d', perfdatas => [ { label => 'ios', template => '%d', min => 0 } ] } }, { label => 'android-phone', nlabel => 'teams.devices.android.count', set => { key_values => [ { name => 'android_phone' } ], output_template => 'Android Phone: %d', perfdatas => [ { label => 'android_phone', template => '%d', min => 0 } ] } }, { label => 'windows-phone', nlabel => 'teams.devices.windowsphone.count', set => { key_values => [ { name => 'windows_phone' } ], output_template => 'Windows Phone: %d', perfdatas => [ { label => 'windows_phone', template => '%d', min => 0 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-user:s" => { name => 'filter_user' }, "units:s" => { name => 'units', default => '%' }, }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{active} = { active => 0, total => 0, report_date => '' }; $self->{global} = { windows => 0, mac => 0, web => 0, ios => 0, android_phone => 0, windows_phone => 0 }; my $results = $options{custom}->office_get_teams_device_usage(param => "period='D7'"); my $results_daily = []; if (scalar(@{$results})) { $self->{active}->{report_date} = @{$results}[0]->{'Report Refresh Date'}; $results_daily = $options{custom}->office_get_teams_device_usage(param => "date=" . $self->{active}->{report_date}); } foreach my $user (@{$results}, @{$results_daily}) { if (defined($self->{option_results}->{filter_user}) && $self->{option_results}->{filter_user} ne '' && $user->{'User Principal Name'} !~ /$self->{option_results}->{filter_user}/) { $self->{output}->output_add(long_msg => "skipping '" . $user->{'User Principal Name'} . "': no matching filter name.", debug => 1); next; } my $used_devices = 0; $used_devices++ if ($user->{'Used Windows'} =~ /Yes/); $used_devices++ if ($user->{'Used Mac'} =~ /Yes/); $used_devices++ if ($user->{'Used Web'} =~ /Yes/); $used_devices++ if ($user->{'Used iOS'} =~ /Yes/); $used_devices++ if ($user->{'Used Android Phone'} =~ /Yes/); $used_devices++ if ($user->{'Used Windows Phone'} =~ /Yes/); if ($user->{'Report Period'} != 1) { if (!defined($user->{'Last Activity Date'}) || ($user->{'Last Activity Date'} ne $self->{active}->{report_date})) { $self->{output}->output_add(long_msg => "skipping '" . $user->{'User Principal Name'} . "': no activity.", debug => 1); } $self->{active}->{total} += $used_devices; next; } $self->{active}->{active} += $used_devices; $self->{global}->{windows}++ if ($user->{'Used Windows'} =~ /Yes/); $self->{global}->{mac}++ if ($user->{'Used Mac'} =~ /Yes/); $self->{global}->{web}++ if ($user->{'Used Web'} =~ /Yes/); $self->{global}->{ios}++ if ($user->{'Used iOS'} =~ /Yes/); $self->{global}->{android_phone}++ if ($user->{'Used Android Phone'} =~ /Yes/); $self->{global}->{windows_phone}++ if ($user->{'Used Windows Phone'} =~ /Yes/); } } 1; __END__ =head1 MODE Check devices usage (reporting period over the last refreshed day). (See link for details about metrics : https://docs.microsoft.com/en-us/office365/admin/activity-reports/microsoft-teams-device-usage?view=o365-worldwide) =over 8 =item B<--filter-user> Filter users. =item B<--warning-*> Threshold warning. Can be: 'active-devices', 'windows' (count), 'mac' (count), 'web' (count), 'ios' (count), 'android-phone' (count), 'windows-phone' (count). =item B<--critical-*> Threshold critical. Can be: 'active-devices', 'windows' (count), 'mac' (count), 'web' (count), 'ios' (count), 'android-phone' (count), 'windows-phone' (count). =item B<--filter-counters> Only display some counters (regexp can be used). Example to hide per user counters: --filter-counters='windows' =item B<--units> Unit of thresholds (Default: '%') ('%', 'count'). =back =cut centreon-plugins-20220113/cloud/microsoft/office365/teams/mode/usersactivity.pm000066400000000000000000000264331417000230700273610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::microsoft::office365::teams::mode::usersactivity; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Time::Local; sub custom_active_perfdata { my ($self, %options) = @_; my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } if ($self->{result_values}->{report_date} =~ /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/) { $self->{output}->perfdata_add(label => 'perfdate', value => timelocal(0,0,12,$3,$2-1,$1-1900)); } $self->{output}->perfdata_add( label => 'active_users', nlabel => 'teams.users.active.count', value => $self->{result_values}->{active}, 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), unit => 'users', min => 0, max => $self->{result_values}->{total} ); } sub custom_active_threshold { my ($self, %options) = @_; my $threshold_value = $self->{result_values}->{active}; if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_active}; } my $exit = $self->{perfdata}->threshold_check( value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_active_output { my ($self, %options) = @_; return sprintf( "Active users on %s : %d/%d (%.2f%%)", $self->{result_values}->{report_date}, $self->{result_values}->{active}, $self->{result_values}->{total}, $self->{result_values}->{prct_active} ); } sub custom_active_calc { my ($self, %options) = @_; $self->{result_values}->{active} = $options{new_datas}->{$self->{instance} . '_active'}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_total'}; $self->{result_values}->{report_date} = $options{new_datas}->{$self->{instance} . '_report_date'}; $self->{result_values}->{prct_active} = ($self->{result_values}->{total} != 0) ? $self->{result_values}->{active} * 100 / $self->{result_values}->{total} : 0; return 0; } sub prefix_global_output { my ($self, %options) = @_; return "Total "; } sub prefix_user_output { my ($self, %options) = @_; return "User '" . $options{instance_value}->{name} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'active', type => 0 }, { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }, { name => 'users', type => 1, cb_prefix_output => 'prefix_user_output', message_multiple => 'All users activity are ok' } ]; $self->{maps_counters}->{active} = [ { label => 'active-users', set => { key_values => [ { name => 'active' }, { name => 'total' }, { name => 'report_date' } ], closure_custom_calc => $self->can('custom_active_calc'), closure_custom_output => $self->can('custom_active_output'), closure_custom_threshold_check => $self->can('custom_active_threshold'), closure_custom_perfdata => $self->can('custom_active_perfdata') } } ]; $self->{maps_counters}->{global} = [ { label => 'total-team-chat', nlabel => 'teams.users.messages.team.total.count', set => { key_values => [ { name => 'team_chat' } ], output_template => 'Team Chat Message Count: %d', perfdatas => [ { label => 'total_team_chat', template => '%d', min => 0 } ] } }, { label => 'total-private-chat', nlabel => 'teams.users.messages.private.total.count', set => { key_values => [ { name => 'private_chat' } ], output_template => 'Private Chat Message Count: %d', perfdatas => [ { label => 'total_private_chat', template => '%d', min => 0 } ] } }, { label => 'total-call', nlabel => 'teams.users.call.total.count', set => { key_values => [ { name => 'call' } ], output_template => 'Call Count: %d', perfdatas => [ { label => 'total_call', template => '%d', min => 0 } ] } }, { label => 'total-meeting', nlabel => 'teams.users.meeting.total.count', set => { key_values => [ { name => 'meeting' } ], output_template => 'Meeting Count: %d', perfdatas => [ { label => 'total_meeting', template => '%d', min => 0 } ] } } ]; $self->{maps_counters}->{users} = [ { label => 'team-chat', nlabel => 'teams.users.messages.team.count', set => { key_values => [ { name => 'team_chat' }, { name => 'name' } ], output_template => 'Team Chat Message Count: %d', perfdatas => [ { label => 'team_chat', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'name' } ] } }, { label => 'private-chat', nlabel => 'teams.users.messages.private.count', set => { key_values => [ { name => 'private_chat' }, { name => 'name' } ], output_template => 'Private Chat Message Count: %d', perfdatas => [ { label => 'private_chat', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'name' } ] } }, { label => 'call', nlabel => 'teams.users.call.count', set => { key_values => [ { name => 'call' }, { name => 'name' } ], output_template => 'Call Count: %d', perfdatas => [ { label => 'call', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'name' } ] } }, { label => 'meeting', nlabel => 'teams.users.meeting.count', set => { key_values => [ { name => 'meeting' }, { name => 'name' } ], output_template => 'Meeting Count: %d', perfdatas => [ { label => 'meeting', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'name' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-user:s" => { name => 'filter_user' }, "units:s" => { name => 'units', default => '%' }, "filter-counters:s" => { name => 'filter_counters', default => 'active|total' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{active} = { active => 0, total => 0, report_date => '' }; $self->{global} = { team_chat => 0, private_chat => 0, call => 0, meeting => 0 }; $self->{users} = {}; my $results = $options{custom}->office_get_teams_activity(param => "period='D7'"); my $results_daily = []; if (scalar(@{$results})) { $self->{active}->{report_date} = @{$results}[0]->{'Report Refresh Date'}; $results_daily = $options{custom}->office_get_teams_activity(param => "date=" . $self->{active}->{report_date}); } foreach my $user (@{$results}, @{$results_daily}) { if (defined($self->{option_results}->{filter_user}) && $self->{option_results}->{filter_user} ne '' && $user->{'User Principal Name'} !~ /$self->{option_results}->{filter_user}/) { $self->{output}->output_add(long_msg => "skipping '" . $user->{'User Principal Name'} . "': no matching filter name.", debug => 1); next; } if ($user->{'Report Period'} != 1) { if (!defined($user->{'Last Activity Date'}) || ($user->{'Last Activity Date'} ne $self->{active}->{report_date})) { $self->{output}->output_add(long_msg => "skipping '" . $user->{'User Principal Name'} . "': no activity.", debug => 1); } $self->{active}->{total}++; next; } $self->{active}->{active}++; $self->{global}->{team_chat} += $user->{'Team Chat Message Count'}; $self->{global}->{private_chat} += $user->{'Private Chat Message Count'}; $self->{global}->{call} += $user->{'Call Count'}; $self->{global}->{meeting} += $user->{'Meeting Count'}; $self->{users}->{$user->{'User Principal Name'}}->{name} = $user->{'User Principal Name'}; $self->{users}->{$user->{'User Principal Name'}}->{team_chat} = $user->{'Team Chat Message Count'}; $self->{users}->{$user->{'User Principal Name'}}->{private_chat} = $user->{'Private Chat Message Count'}; $self->{users}->{$user->{'User Principal Name'}}->{call} = $user->{'Call Count'}; $self->{users}->{$user->{'User Principal Name'}}->{meeting} = $user->{'Meeting Count'}; } } 1; __END__ =head1 MODE Check users activity (reporting period over the last refreshed day). (See link for details about metrics : https://docs.microsoft.com/en-us/office365/admin/activity-reports/microsoft-teams-user-activity?view=o365-worldwide) =over 8 =item B<--filter-user> Filter users. =item B<--warning-*> Threshold warning. Can be: 'active-users', 'total-team-chat' (count), 'total-private-chat' (count), 'total-call' (count), 'total-meeting' (count), 'team-chat' (count), 'private-chat' (count), 'call' (count), 'meeting' (count). =item B<--critical-*> Threshold critical. Can be: 'active-users', 'total-team-chat' (count), 'total-private-chat' (count), 'total-call' (count), 'total-meeting' (count), 'team-chat' (count), 'private-chat' (count), 'call' (count), 'meeting' (count). =item B<--filter-counters> Only display some counters (regexp can be used). Example to hide per user counters: --filter-counters='total' (Default: 'active|total') =item B<--units> Unit of thresholds (Default: '%') ('%', 'count'). =back =cut centreon-plugins-20220113/cloud/microsoft/office365/teams/plugin.pm000066400000000000000000000027151417000230700250120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::microsoft::office365::teams::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} } = ( 'devices-usage' => 'cloud::microsoft::office365::teams::mode::devicesusage', 'users-activity' => 'cloud::microsoft::office365::teams::mode::usersactivity', ); $self->{custom_modes}{graphapi} = 'cloud::microsoft::office365::custom::graphapi'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Microsoft Office 365 Teams. =cut centreon-plugins-20220113/cloud/nutanix/000077500000000000000000000000001417000230700200305ustar00rootroot00000000000000centreon-plugins-20220113/cloud/nutanix/snmp/000077500000000000000000000000001417000230700210055ustar00rootroot00000000000000centreon-plugins-20220113/cloud/nutanix/snmp/mode/000077500000000000000000000000001417000230700217315ustar00rootroot00000000000000centreon-plugins-20220113/cloud/nutanix/snmp/mode/clusterusage.pm000066400000000000000000000216111417000230700247760ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::nutanix::snmp::mode::clusterusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); my $cluster_name = ''; sub custom_status_output { my ($self, %options) = @_; return 'status : ' . $self->{result_values}->{status}; } 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($self->{instance_mode}->{option_results}->{free})) { $label = 'free'; $value_perf = $self->{result_values}->{free}; } my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } $self->{output}->perfdata_add( label => $label, 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($self->{instance_mode}->{option_results}->{free})); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; $threshold_value = $self->{result_values}->{prct_free} if (defined($self->{instance_mode}->{option_results}->{free})); } $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{label}, exit_litteral => 'warning' } ]); return $exit; } sub custom_usage_output { my ($self, %options) = @_; my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); return sprintf( 'Usage Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)', $total_size_value . " " . $total_size_unit, $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}, $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free} ); } sub 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 => \&catalog_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', template => '%s', unit => 'µs', min => 0 }, ], } }, { label => 'iops', set => { key_values => [ { name => 'clusterIops' } ], output_template => 'IOPs : %s', perfdatas => [ { label => 'iops', value => 'clusterIops', template => '%s', unit => 'iops', min => 0 }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $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); $self->change_macros(macros => ['warning_status', 'critical_status']); } 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 centreon-plugins-20220113/cloud/nutanix/snmp/mode/containerusage.pm000066400000000000000000000211001417000230700252700ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::nutanix::snmp::mode::containerusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; sub custom_usage_perfdata { my ($self, %options) = @_; my $label = 'used'; my $value_perf = $self->{result_values}->{used}; if (defined($self->{instance_mode}->{option_results}->{free})) { $label = 'free'; $value_perf = $self->{result_values}->{free}; } my $extra_label = ''; $extra_label = '_' . $self->{result_values}->{display} if (!defined($options{extra_instance}) || $options{extra_instance} != 0); my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } $self->{output}->perfdata_add( label => $label . $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($self->{instance_mode}->{option_results}->{free})); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; $threshold_value = $self->{result_values}->{prct_free} if (defined($self->{instance_mode}->{option_results}->{free})); } $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{label}, exit_litteral => 'warning' } ]); return $exit; } sub custom_usage_output { my ($self, %options) = @_; my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); return sprintf( 'Usage Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)', $total_size_value . " " . $total_size_unit, $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}, $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free} ); } sub 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', template => '%s', unit => 'µs', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'iops', set => { key_values => [ { name => 'citIOPerSecond' }, { name => 'display' } ], output_template => 'IOPs : %s', perfdatas => [ { label => 'iops', value => 'citIOPerSecond', template => '%s', unit => 'iops', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'units:s' => { name => 'units', default => '%' }, 'free' => { name => 'free' }, }); return $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 centreon-plugins-20220113/cloud/nutanix/snmp/mode/diskusage.pm000066400000000000000000000255651417000230700242630ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::nutanix::snmp::mode::diskusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; return 'state : ' . $self->{result_values}->{state}; } 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($self->{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 ($self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } $self->{output}->perfdata_add( label => $label . $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($self->{instance_mode}->{option_results}->{free})); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; $threshold_value = $self->{result_values}->{prct_free} if (defined($self->{instance_mode}->{option_results}->{free})); } $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{label}, exit_litteral => 'warning' } ]); return $exit; } sub custom_usage_output { my ($self, %options) = @_; my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); return sprintf( 'Usage Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)', $total_size_value . " " . $total_size_unit, $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}, $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free} ); } sub 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 => \&catalog_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', template => '%s', unit => '%', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'avg-latency', set => { key_values => [ { name => 'dstAverageLatency' }, { name => 'display' } ], output_template => 'Average Latency : %s µs', perfdatas => [ { label => 'avg_latency', value => 'dstAverageLatency', template => '%s', unit => 'µs', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'iops', set => { key_values => [ { name => 'dstNumberIops' }, { name => 'display' } ], output_template => 'IOPs : %s', perfdatas => [ { label => 'iops', value => 'dstNumberIops', template => '%s', unit => 'iops', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $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); $self->change_macros(macros => ['warning_status', 'critical_status']); } 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 centreon-plugins-20220113/cloud/nutanix/snmp/mode/hypervisorusage.pm000066400000000000000000000221731417000230700255330ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::nutanix::snmp::mode::hypervisorusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; 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}); return sprintf( 'Memory Usage Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)', $total_size_value . " " . $total_size_unit, $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}, $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free} ); } sub 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', template => '%s', unit => '%', min => 0, max => 100, label_extra_instance => 1, instance_use => 'display' }, ], } }, { 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', template => '%s', unit => 'µs', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'read-iops', set => { key_values => [ { name => 'hypervisorReadIOPerSecond' }, { name => 'display' } ], output_template => 'Read IOPs : %s', perfdatas => [ { label => 'read_iops', value => 'hypervisorReadIOPerSecond', template => '%s', unit => 'iops', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'write-iops', set => { key_values => [ { name => 'hypervisorWriteIOPerSecond' }, { name => 'display' } ], output_template => 'Write IOPs : %s', perfdatas => [ { label => 'write_iops', value => 'hypervisorWriteIOPerSecond', template => '%s', unit => 'iops', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'vm-count', set => { key_values => [ { name => 'hypervisorVmCount' }, { name => 'display' } ], output_template => 'VM Count : %s', perfdatas => [ { label => 'vm_count', value => 'hypervisorVmCount', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, }); return $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 centreon-plugins-20220113/cloud/nutanix/snmp/mode/listcontainers.pm000066400000000000000000000057231417000230700253370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package 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; $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 centreon-plugins-20220113/cloud/nutanix/snmp/mode/listdisks.pm000066400000000000000000000071261417000230700243060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package 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; $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 centreon-plugins-20220113/cloud/nutanix/snmp/mode/listhypervisors.pm000066400000000000000000000057571417000230700255760ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package 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; $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 centreon-plugins-20220113/cloud/nutanix/snmp/mode/liststoragepools.pm000066400000000000000000000057421417000230700257140ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package 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; $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 centreon-plugins-20220113/cloud/nutanix/snmp/mode/listvms.pm000066400000000000000000000070251417000230700237740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package 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; $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 centreon-plugins-20220113/cloud/nutanix/snmp/mode/storagepoolusage.pm000066400000000000000000000211531417000230700256540ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::nutanix::snmp::mode::storagepoolusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; sub custom_usage_perfdata { my ($self, %options) = @_; my $label = 'used'; my $value_perf = $self->{result_values}->{used}; if (defined($self->{instance_mode}->{option_results}->{free})) { $label = 'free'; $value_perf = $self->{result_values}->{free}; } my $extra_label = ''; $extra_label = '_' . $self->{result_values}->{display} if (!defined($options{extra_instance}) || $options{extra_instance} != 0); my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } $self->{output}->perfdata_add( label => $label . $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($self->{instance_mode}->{option_results}->{free})); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; $threshold_value = $self->{result_values}->{prct_free} if (defined($self->{instance_mode}->{option_results}->{free})); } $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{label}, exit_litteral => 'warning' } ]); return $exit; } sub custom_usage_output { my ($self, %options) = @_; my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); return sprintf( 'Usage Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)', $total_size_value . " " . $total_size_unit, $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}, $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free} ); } sub 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', template => '%s', unit => 'µs', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'iops', set => { key_values => [ { name => 'spitIOPerSecond' }, { name => 'display' } ], output_template => 'IOPs : %s', perfdatas => [ { label => 'iops', value => 'spitIOPerSecond', template => '%s', unit => 'iops', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'units:s' => { name => 'units', default => '%' }, 'free' => { name => 'free' }, }); return $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 centreon-plugins-20220113/cloud/nutanix/snmp/mode/vmusage.pm000066400000000000000000000163731417000230700237500ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package 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); 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', template => '%s', unit => '%', min => 0, max => 100, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'avg-latency', set => { key_values => [ { name => 'vmAverageLatency' }, { name => 'display' } ], output_template => 'Average Latency : %s µs', perfdatas => [ { label => 'avg_latency', template => '%s', unit => 'µs', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'read-iops', set => { key_values => [ { name => 'vmReadIOPerSecond' }, { name => 'display' } ], output_template => 'Read IOPs : %s', perfdatas => [ { label => 'read_iops', template => '%s', unit => 'iops', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'write-iops', set => { key_values => [ { name => 'vmWriteIOPerSecond' }, { name => 'display' } ], output_template => 'Write IOPs : %s', perfdatas => [ { label => 'write_iops', template => '%s', unit => 'iops', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'traffic-in', set => { key_values => [ { name => 'vmRxBytes', per_second => 1 }, { name => 'display' } ], output_template => 'Traffic In : %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'traffic_in', template => '%.2f', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'traffic-out', set => { key_values => [ { name => 'vmTxBytes', per_second => 1 }, { name => 'display' } ], output_template => 'Traffic Out : %s %s/s', output_change_bytes => 2, perfdatas => [ { label => 'traffic_out', template => '%.2f', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, }); return $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 centreon-plugins-20220113/cloud/nutanix/snmp/plugin.pm000066400000000000000000000037461417000230700226530ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package 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 centreon-plugins-20220113/cloud/ovh/000077500000000000000000000000001417000230700171365ustar00rootroot00000000000000centreon-plugins-20220113/cloud/ovh/restapi/000077500000000000000000000000001417000230700206055ustar00rootroot00000000000000centreon-plugins-20220113/cloud/ovh/restapi/custom/000077500000000000000000000000001417000230700221175ustar00rootroot00000000000000centreon-plugins-20220113/cloud/ovh/restapi/custom/api.pm000066400000000000000000000164701417000230700232360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::ovh::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use JSON::XS; use Digest::SHA 'sha1_hex'; my %map_ovh_type = ( OVH_API_EU => 'https://eu.api.ovh.com/1.0', OVH_API_CA => 'https://ca.api.ovh.com/1.0' ); 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 => { 'ovh-type:s@' => { name => 'ovh_type' }, 'ovh-application-key:s@' => { name => 'ovh_application_key' }, 'ovh-application-secret:s@' => { name => 'ovh_application_secret' }, 'ovh-consumer-key:s@' => { name => 'ovh_consumer_key' }, 'timeout:s@' => { name => 'timeout' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{ovh_type} = (defined($self->{option_results}->{ovh_type})) ? shift(@{$self->{option_results}->{ovh_type}}) : 'OVH_API_EU'; $self->{ovh_application_key} = (defined($self->{option_results}->{ovh_application_key})) ? shift(@{$self->{option_results}->{ovh_application_key}}) : undef; $self->{ovh_application_secret} = (defined($self->{option_results}->{ovh_application_secret})) ? shift(@{$self->{option_results}->{ovh_application_secret}}) : undef; $self->{ovh_consumer_key} = (defined($self->{option_results}->{ovh_consumer_key})) ? shift(@{$self->{option_results}->{ovh_consumer_key}}) : undef; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? shift(@{$self->{option_results}->{timeout}}) : 10; if (!defined($self->{ovh_application_key})) { $self->{output}->add_option_msg(short_msg => "Need to specify --ovh-application-key option."); $self->{output}->option_exit(); } if (!defined($self->{ovh_application_secret})) { $self->{output}->add_option_msg(short_msg => "Need to specify --ovh-application-secret option."); $self->{output}->option_exit(); } if (!defined($self->{ovh_consumer_key})) { $self->{output}->add_option_msg(short_msg => "Need to specify --ovh-consumer-key option."); $self->{output}->option_exit(); } if (!defined($self->{ovh_application_key}) || scalar(@{$self->{option_results}->{ovh_application_key}}) == 0) { return 0; } return 1; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{timeout} = $self->{timeout}; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'X-Ovh-Application', value => $self->{ovh_application_key}); if (!defined($options{no_signature}) || $options{no_signature} == 0) { my $now = $self->time_delta() + time; my $method = defined($options{method}) ? uc($options{method}) : 'GET'; my $body = ''; if ($method !~ /GET|DELETE/) { my $content; eval { $content = JSON::XS->new->utf8->encode($options{body}); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot encode json: $@"); $self->{output}->option_exit(); } $self->{http}->add_header(key => 'Content-type', value => 'application/json'); $self->{option_results}->{query_form_post} = $content; } $self->{http}->add_header(key => 'X-Ovh-Consumer', value => $self->{ovh_consumer_key}); $self->{http}->add_header(key => 'X-Ovh-Timestamp', value => $now); $self->{http}->add_header(key => 'X-Ovh-Signature', value => '$1$' . sha1_hex(join('+', ( # Full signature is '$1$' followed by the hex digest of the SHA1 of all these data joined by a + sign $self->{ovh_application_secret}, # Application secret $self->{ovh_consumer_key}, # Consumer key $method, # HTTP method (uppercased) $map_ovh_type{uc($self->{ovh_type})} . $options{path}, # Full URL $body, # Full body $now, # Curent OVH server time )))); } $self->{http}->set_options(%{$self->{option_results}}); } sub time_delta { my ($self, %options) = @_; if (!defined($self->{time_delta})) { my $response = $self->get(path => '/auth/time', no_signature => 1, no_decode => 1); $self->{time_delta} = $response - time(); } return $self->{time_delta}; } sub get { my ($self, %options) = @_; $self->settings(%options); my $response = $self->{http}->request( full_url => $map_ovh_type{uc($self->{ovh_type})} . $options{path}, hostname => '', critical_status => '', warning_status => '' ); my ($client_warning) = $self->{http}->get_header(name => 'Client-Warning'); if (defined($client_warning) && $client_warning eq 'Internal response') { $self->{output}->add_option_msg(short_msg => "Internal LWP::UserAgent error: $response"); $self->{output}->option_exit(); } if (defined($options{no_decode}) && $options{no_decode} == 1) { return $response; } my $content; eval { $content = JSON::XS->new->utf8->decode($response); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } return $content; } 1; __END__ =head1 NAME OVH REST API =head1 SYNOPSIS OVH Rest API custom mode =head1 REST API OPTIONS =over 8 =item B<--ovh-type> Can be: OVH_API_EU or OVH_API_CA (default: OVH_API_EU). =item B<--ovh-application-key> OVH API applicationKey =item B<--ovh-application-secret> OVH API applicationSecret =item B<--ovh-consumer-key> OVH API consumerKey =item B<--timeout> Set HTTP timeout =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/cloud/ovh/restapi/mode/000077500000000000000000000000001417000230700215315ustar00rootroot00000000000000centreon-plugins-20220113/cloud/ovh/restapi/mode/quotausage.pm000066400000000000000000000160451417000230700242530ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::ovh::restapi::mode::quotausage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; sub custom_usage_perfdata { my ($self, %options) = @_; my $label = 'used'; my $value_perf = $self->{result_values}->{used}; if (defined($self->{instance_mode}->{option_results}->{free})) { $label = 'free'; $value_perf = $self->{result_values}->{free}; } my $extra_label = ''; $extra_label = '_' . $self->{result_values}->{display} if (!defined($options{extra_instance}) || $options{extra_instance} != 0); my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } $self->{output}->perfdata_add(label => $label . $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($self->{instance_mode}->{option_results}->{free})); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; $threshold_value = $self->{result_values}->{prct_free} if (defined($self->{instance_mode}->{option_results}->{free})); } $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{label}, exit_litteral => 'warning' } ]); return $exit; } sub custom_usage_output { my ($self, %options) = @_; my ($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 => 'service', type => 1, cb_prefix_output => 'prefix_services_output', message_multiple => 'All services are ok' } ]; $self->{maps_counters}->{service} = [ { 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; $options{options}->add_options(arguments => { "filter-service:s" => { name => 'filter_service' }, "units:s" => { name => 'units', default => '%' }, "free" => { name => 'free' }, }); return $self; } sub prefix_services_output { my ($self, %options) = @_; return "Service '" . $options{instance_value}->{display} . "' "; } sub manage_selection { my ($self, %options) = @_; $self->{service} = {}; my $result = $options{custom}->get(path => '/hosting/web'); foreach my $service (@$result) { if (defined($self->{option_results}->{filter_service}) && $self->{option_results}->{filter_service} ne '' && $service !~ /$self->{option_results}->{filter_service}/) { $self->{output}->output_add(long_msg => "skipping '" . $service . "': no matching filter.", debug => 1); next; } my $result2 = $options{custom}->get(path => '/hosting/web/' . $service); my $used = centreon::plugins::misc::convert_bytes(value => $result2->{quotaUsed}->{value}, unit => $result2->{quotaUsed}->{unit}); my $total = centreon::plugins::misc::convert_bytes(value => $result2->{quotaSize}->{value}, unit => $result2->{quotaSize}->{unit}); $self->{service}->{$service} = { display => $service, used => $used, total => $total }; } if (scalar(keys %{$self->{service}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No service found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check web hosting space. =over 8 =item B<--filter-service> Filter service name (can be a regexp). =item B<--warning-*> Threshold warning. Can be: 'usage'. =item B<--critical-*> Threshold critical. Can be: 'usage'. =item B<--units> Units of thresholds (Default: '%') ('%', 'B'). =item B<--free> Thresholds are on free space left. =back =cut centreon-plugins-20220113/cloud/ovh/restapi/mode/sms.pm000066400000000000000000000062301417000230700226720ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::ovh::restapi::mode::sms; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'sms', type => 1, cb_prefix_output => 'prefix_sms_output', message_multiple => 'All sms services are ok' } ]; $self->{maps_counters}->{sms} = [ { label => 'left', set => { key_values => [ { name => 'left' }, { name => 'display' } ], output_template => 'SMS left : %s', perfdatas => [ { label => 'left', value => 'left', template => '%s', unit => 'sms', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-service:s" => { name => 'filter_service' }, }); return $self; } sub prefix_sms_output { my ($self, %options) = @_; return "Service '" . $options{instance_value}->{display} . "' "; } sub manage_selection { my ($self, %options) = @_; $self->{sms} = {}; my $result = $options{custom}->get(path => '/sms'); foreach my $service (@$result) { if (defined($self->{option_results}->{filter_service}) && $self->{option_results}->{filter_service} ne '' && $service !~ /$self->{option_results}->{filter_service}/) { $self->{output}->output_add(long_msg => "skipping '" . $service . "': no matching filter.", debug => 1); next; } my $result2 = $options{custom}->get(path => '/sms/' . $service); $self->{sms}->{$service} = { display => $service, left => $result2->{creditsLeft} }; } if (scalar(keys %{$self->{sms}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No sms service found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check sms left. =over 8 =item B<--filter-service> Filter service name (can be a regexp). =item B<--warning-*> Threshold warning. Can be: 'left'. =item B<--critical-*> Threshold critical. Can be: 'left'. =back =cut centreon-plugins-20220113/cloud/ovh/restapi/plugin.pm000066400000000000000000000025311417000230700224420ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::ovh::restapi::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} = '1.0'; %{$self->{modes}} = ( 'quota-usage' => 'cloud::ovh::restapi::mode::quotausage', 'sms' => 'cloud::ovh::restapi::mode::sms', ); $self->{custom_modes}{api} = 'cloud::ovh::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check OVH through HTTP/REST API. =cut centreon-plugins-20220113/cloud/prometheus/000077500000000000000000000000001417000230700205355ustar00rootroot00000000000000centreon-plugins-20220113/cloud/prometheus/direct/000077500000000000000000000000001417000230700220075ustar00rootroot00000000000000centreon-plugins-20220113/cloud/prometheus/direct/kubernetes/000077500000000000000000000000001417000230700241565ustar00rootroot00000000000000centreon-plugins-20220113/cloud/prometheus/direct/kubernetes/mode/000077500000000000000000000000001417000230700251025ustar00rootroot00000000000000centreon-plugins-20220113/cloud/prometheus/direct/kubernetes/mode/containerstatus.pm000066400000000000000000000264471417000230700307030ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::prometheus::direct::kubernetes::mode::containerstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("state is '%s', status is '%s'", $self->{result_values}->{state}, $self->{result_values}->{status}); $msg .= " [reason: " . $self->{result_values}->{reason} . "]" if (defined($self->{result_values}->{reason}) && $self->{result_values}->{reason} ne ""); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_container'}; $self->{result_values}->{pod} = $options{new_datas}->{$self->{instance} . '_pod'}; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; $self->{result_values}->{state} = ($options{new_datas}->{$self->{instance} . '_state'} == 1) ? "ready" : "not ready"; $self->{result_values}->{reason} = $options{new_datas}->{$self->{instance} . '_reason'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'containers', type => 1, cb_prefix_output => 'prefix_container_output', message_multiple => 'All containers status are ok', message_separator => ' - ', skipped_code => { -11 => 1 } }, ]; $self->{maps_counters}->{containers} = [ { label => 'status', set => { key_values => [ { name => 'status' }, { name => 'state' }, { name => 'reason' }, { name => 'pod' }, { name => 'container' } ], 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 => \&catalog_status_threshold, } }, { label => 'restarts-count', nlabel => 'containers.restarts.count', set => { key_values => [ { name => 'restarts' }, { name => 'perf' } ], output_template => 'Restarts count : %d', perfdatas => [ { label => 'restarts_count', value => 'restarts', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'perf' }, ], } }, ]; } sub prefix_container_output { my ($self, %options) = @_; return "Container '" . $options{instance_value}->{container} . "' [pod: " . $options{instance_value}->{pod} . ", namespace: " . $options{instance_value}->{namespace} . "] "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "container:s" => { name => 'container', default => 'container=~".*"' }, "pod:s" => { name => 'pod', default => 'pod=~".*"' }, "warning-status:s" => { name => 'warning_status', default => '' }, "critical-status:s" => { name => 'critical_status', default => '%{status} !~ /running/ || %{state} !~ /ready/' }, "extra-filter:s@" => { name => 'extra_filter' }, "metric-overload:s@" => { name => 'metric_overload' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{metrics} = { 'ready' => '^kube_pod_container_status_ready$', 'running' => '^kube_pod_container_status_running$', 'terminated' => '^kube_pod_container_status_terminated$', 'terminated_reason' => '^kube_pod_container_status_terminated_reason$', 'waiting' => '^kube_pod_container_status_waiting$', 'waiting_reason' => '^kube_pod_container_status_waiting_reason$', 'restarts' => '^kube_pod_container_status_restarts_total$', }; foreach my $metric (@{$self->{option_results}->{metric_overload}}) { next if ($metric !~ /(.*),(.*)/); $self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1})); } $self->{labels} = {}; foreach my $label (('container', 'pod')) { if ($self->{option_results}->{$label} !~ /^(\w+)[!~=]+\".*\"$/) { $self->{output}->add_option_msg(short_msg => "Need to specify --" . $label . " option as a PromQL filter."); $self->{output}->option_exit(); } $self->{labels}->{$label} = $1; } $self->{extra_filter} = ''; foreach my $filter (@{$self->{option_results}->{extra_filter}}) { $self->{extra_filter} .= ',' . $filter; } $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; $self->{containers} = {}; my $results = $options{custom}->query( queries => [ 'label_replace({__name__=~"' . $self->{metrics}->{ready} . '",' . $self->{option_results}->{container} . ',' . $self->{option_results}->{pod} . $self->{extra_filter} . '}, "__name__", "ready", "", "")', 'label_replace({__name__=~"' . $self->{metrics}->{running} . '",' . $self->{option_results}->{container} . ',' . $self->{option_results}->{pod} . $self->{extra_filter} . '}, "__name__", "running", "", "")', 'label_replace({__name__=~"' . $self->{metrics}->{terminated} . '",' . $self->{option_results}->{container} . ',' . $self->{option_results}->{pod} . $self->{extra_filter} . '}, "__name__", "terminated", "", "")', 'label_replace({__name__=~"' . $self->{metrics}->{terminated_reason} . '",' . $self->{option_results}->{container} . ',' . $self->{option_results}->{pod} . $self->{extra_filter} . '}, "__name__", "terminated_reason", "", "")', 'label_replace({__name__=~"' . $self->{metrics}->{waiting} . '",' . $self->{option_results}->{container} . ',' . $self->{option_results}->{pod} . $self->{extra_filter} . '}, "__name__", "waiting", "", "")', 'label_replace({__name__=~"' . $self->{metrics}->{waiting_reason} . '",' . $self->{option_results}->{container} . ',' . $self->{option_results}->{pod} . $self->{extra_filter} . '}, "__name__", "waiting_reason", "", "")', 'label_replace({__name__=~"' . $self->{metrics}->{restarts} . '",' . $self->{option_results}->{container} . ',' . $self->{option_results}->{pod} . $self->{extra_filter} . '}, "__name__", "restarts", "", "")' ] ); foreach my $result (@{$results}) { next if (!defined($result->{metric}->{$self->{labels}->{pod}}) || !defined($result->{metric}->{$self->{labels}->{container}})); $self->{containers}->{$result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}}->{container} = $result->{metric}->{$self->{labels}->{container}}; $self->{containers}->{$result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}}->{pod} = $result->{metric}->{$self->{labels}->{pod}}; $self->{containers}->{$result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}}->{perf} = $result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}; $self->{containers}->{$result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}}->{restarts} = ${$result->{value}}[1] if ($result->{metric}->{__name__} =~ /restarts/); $self->{containers}->{$result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}}->{state} = ${$result->{value}}[1] if ($result->{metric}->{__name__} =~ /ready/); $self->{containers}->{$result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}}->{status} = $result->{metric}->{__name__} if ($result->{metric}->{__name__} =~ /ready|running|terminated|waiting/ && ${$result->{value}}[1] == 1); $self->{containers}->{$result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}}->{reason} = ""; $self->{containers}->{$result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}}->{reason} = $result->{metric}->{reason} if ($result->{metric}->{__name__} =~ /reason/ && ${$result->{value}}[1] == 1); $self->{containers}->{$result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}}->{namespace} = $result->{metric}->{namespace}; } if (scalar(keys %{$self->{containers}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No containers found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check container status. =over 8 =item B<--container> Filter on a specific container (Must be a PromQL filter, Default: 'container=~".*"') =item B<--pod> Filter on a specific pod (Must be a PromQL filter, Default: 'pod=~".*"') =item B<--warning-status> Set warning threshold for status (Default: '') Can used special variables like: %{status}, %{state}, %{reason} =item B<--critical-status> Set critical threshold for status (Default: '%{status} !~ /running/ || %{state} !~ /ready/'). Can used special variables like: %{status}, %{state}, %{reason} =item B<--warning-restarts-count> Threshold warning for container restarts count. =item B<--critical-restarts-count> Threshold critical for container restarts count. =item B<--extra-filter> Add a PromQL filter (Can be multiple) Example : --extra-filter='name=~".*pretty.*"' =item B<--metric-overload> Overload default metrics name (Can be multiple) Example : --metric-overload='metric,^my_metric_name$' Default : - ready: ^kube_pod_container_status_ready$ - running: ^kube_pod_container_status_running$ - terminated: ^kube_pod_container_status_terminated$ - terminated_reason: ^kube_pod_container_status_terminated_reason$ - waiting: ^kube_pod_container_status_waiting$ - waiting_reason: ^kube_pod_container_status_waiting_reason$ - restarts: ^kube_pod_container_status_restarts_total$ =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='status' =back =cut centreon-plugins-20220113/cloud/prometheus/direct/kubernetes/mode/daemonsetstatus.pm000066400000000000000000000263411417000230700306710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::prometheus::direct::kubernetes::mode::daemonsetstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => 'desired', nlabel => 'daemonset.nodes.desired.count', value => $self->{result_values}->{desired}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, ); $self->{output}->perfdata_add( label => 'current', nlabel => 'daemonset.nodes.current.count', value => $self->{result_values}->{current}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, ); $self->{output}->perfdata_add( label => 'available', nlabel => 'daemonset.nodes.available.count', value => $self->{result_values}->{available}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, ); $self->{output}->perfdata_add( label => 'unavailable', nlabel => 'daemonset.nodes.unavailable.count', value => $self->{result_values}->{unavailable}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, ); $self->{output}->perfdata_add( label => 'up_to_date', nlabel => 'daemonset.nodes.uptodate.count', value => $self->{result_values}->{up_to_date}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, ); $self->{output}->perfdata_add( label => 'ready', nlabel => 'daemonset.nodes.ready.count', value => $self->{result_values}->{ready}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, ); $self->{output}->perfdata_add( label => 'misscheduled', nlabel => 'daemonset.nodes.misscheduled.count', value => $self->{result_values}->{misscheduled}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, ); } sub custom_status_output { my ($self, %options) = @_; return sprintf("Nodes Desired : %s, Current : %s, Available : %s, Unavailable : %s, Up-to-date : %s, Ready : %s, Misscheduled : %s", $self->{result_values}->{desired}, $self->{result_values}->{current}, $self->{result_values}->{available}, $self->{result_values}->{unavailable}, $self->{result_values}->{up_to_date}, $self->{result_values}->{ready}, $self->{result_values}->{misscheduled}); } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{desired} = $options{new_datas}->{$self->{instance} . '_desired'}; $self->{result_values}->{current} = $options{new_datas}->{$self->{instance} . '_current'}; $self->{result_values}->{available} = $options{new_datas}->{$self->{instance} . '_available'}; $self->{result_values}->{unavailable} = $options{new_datas}->{$self->{instance} . '_unavailable'}; $self->{result_values}->{up_to_date} = $options{new_datas}->{$self->{instance} . '_up_to_date'}; $self->{result_values}->{ready} = $options{new_datas}->{$self->{instance} . '_ready'}; $self->{result_values}->{misscheduled} = $options{new_datas}->{$self->{instance} . '_misscheduled'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'daemonsets', type => 1, cb_prefix_output => 'prefix_daemonset_output', message_multiple => 'All daemonsets status are ok', skipped_code => { -11 => 1 } }, ]; $self->{maps_counters}->{daemonsets} = [ { label => 'status', set => { key_values => [ { name => 'desired' }, { name => 'current' }, { name => 'up_to_date' }, { name => 'available' }, { name => 'unavailable' }, { name => 'ready' }, { name => 'misscheduled' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_status_calc'), closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => $self->can('custom_status_perfdata'), closure_custom_threshold_check => \&catalog_status_threshold, } }, ]; } sub prefix_daemonset_output { my ($self, %options) = @_; return "Daemonset '" . $options{instance_value}->{display} . " [namespace: ". $options{instance_value}->{namespace} . "]' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "daemonset:s" => { name => 'daemonset', default => 'daemonset=~".*"' }, "warning-status:s" => { name => 'warning_status', default => '%{up_to_date} < %{desired}' }, "critical-status:s" => { name => 'critical_status', default => '%{available} < %{desired}' }, "extra-filter:s@" => { name => 'extra_filter' }, "metric-overload:s@" => { name => 'metric_overload' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{metrics} = { 'desired' => '^kube_daemonset_status_desired_number_scheduled$', 'current' => '^kube_daemonset_status_current_number_scheduled$', 'available' => '^kube_daemonset_status_number_available$', 'unavailable' => '^kube_daemonset_status_number_unavailable$', 'up_to_date' => '^kube_daemonset_updated_number_scheduled$', 'ready' => '^kube_daemonset_status_number_ready$', 'misscheduled' => '^kube_daemonset_status_number_misscheduled$', }; foreach my $metric (@{$self->{option_results}->{metric_overload}}) { next if ($metric !~ /(.*),(.*)/); $self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1})); } $self->{labels} = {}; foreach my $label (('daemonset')) { if ($self->{option_results}->{$label} !~ /^(\w+)[!~=]+\".*\"$/) { $self->{output}->add_option_msg(short_msg => "Need to specify --" . $label . " option as a PromQL filter."); $self->{output}->option_exit(); } $self->{labels}->{$label} = $1; } $self->{extra_filter} = ''; foreach my $filter (@{$self->{option_results}->{extra_filter}}) { $self->{extra_filter} .= ',' . $filter; } $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; $self->{daemonsets} = {}; my $results = $options{custom}->query( queries => [ 'label_replace({__name__=~"' . $self->{metrics}->{desired} . '",' . $self->{option_results}->{daemonset} . $self->{extra_filter} . '}, "__name__", "desired", "", "")', 'label_replace({__name__=~"' . $self->{metrics}->{current} . '",' . $self->{option_results}->{daemonset} . $self->{extra_filter} . '}, "__name__", "current", "", "")', 'label_replace({__name__=~"' . $self->{metrics}->{available} . '",' . $self->{option_results}->{daemonset} . $self->{extra_filter} . '}, "__name__", "available", "", "")', 'label_replace({__name__=~"' . $self->{metrics}->{unavailable} . '",' . $self->{option_results}->{daemonset} . $self->{extra_filter} . '}, "__name__", "unavailable", "", "")', 'label_replace({__name__=~"' . $self->{metrics}->{up_to_date} . '",' . $self->{option_results}->{daemonset} . $self->{extra_filter} . '}, "__name__", "up_to_date", "", "")', 'label_replace({__name__=~"' . $self->{metrics}->{ready} . '",' . $self->{option_results}->{daemonset} . $self->{extra_filter} . '}, "__name__", "ready", "", "")', 'label_replace({__name__=~"' . $self->{metrics}->{misscheduled} . '",' . $self->{option_results}->{daemonset} . $self->{extra_filter} . '}, "__name__", "misscheduled", "", "")' ] ); foreach my $result (@{$results}) { $self->{daemonsets}->{$result->{metric}->{$self->{labels}->{daemonset}}}->{display} = $result->{metric}->{$self->{labels}->{daemonset}}; $self->{daemonsets}->{$result->{metric}->{$self->{labels}->{daemonset}}}->{$result->{metric}->{__name__}} = ${$result->{value}}[1]; $self->{daemonsets}->{$result->{metric}->{$self->{labels}->{daemonset}}}->{namespace} = $result->{metric}->{namespace}; } if (scalar(keys %{$self->{daemonsets}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No daemonsets found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check daemonset status. =over 8 =item B<--daemonset> Filter on a specific daemonset (Must be a PromQL filter, Default: 'daemonset=~".*"') =item B<--warning-status> Set warning threshold for status (Default: '%{up_to_date} < %{desired}') Can used special variables like: %{display}, %{desired}, %{current}, %{available}, %{unavailable}, %{up_to_date}, %{ready}, %{misscheduled} =item B<--critical-status> Set critical threshold for status (Default: '%{available} < %{desired}'). Can used special variables like: %{display}, %{desired}, %{current}, %{available}, %{unavailable}, %{up_to_date}, %{ready}, %{misscheduled} =item B<--extra-filter> Add a PromQL filter (Can be multiple) Example : --extra-filter='name=~".*pretty.*"' =item B<--metric-overload> Overload default metrics name (Can be multiple) Example : --metric-overload='metric,^my_metric_name$' Default : - desired: ^kube_daemonset_status_desired_number_scheduled$ - current: ^kube_daemonset_status_current_number_scheduled$ - available: ^kube_daemonset_status_number_available$ - unavailable: ^kube_daemonset_status_number_unavailable$ - up_to_date: ^kube_daemonset_updated_number_scheduled$ - ready: ^kube_daemonset_status_number_ready$ - misscheduled: ^kube_daemonset_status_number_misscheduled$ =back =cut centreon-plugins-20220113/cloud/prometheus/direct/kubernetes/mode/deploymentstatus.pm000066400000000000000000000230401417000230700310630ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::prometheus::direct::kubernetes::mode::deploymentstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => 'desired', nlabel => 'deployment.replicas.desired.count', value => $self->{result_values}->{desired}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, ); $self->{output}->perfdata_add( label => 'current', nlabel => 'deployment.replicas.current.count', value => $self->{result_values}->{current}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, ); $self->{output}->perfdata_add( label => 'available', nlabel => 'deployment.replicas.available.count', value => $self->{result_values}->{available}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, ); $self->{output}->perfdata_add( label => 'unavailable', nlabel => 'deployment.replicas.unavailable.count', value => $self->{result_values}->{unavailable}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, ); $self->{output}->perfdata_add( label => 'up_to_date', nlabel => 'deployment.replicas.uptodate.count', value => $self->{result_values}->{up_to_date}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, ); } sub custom_status_output { my ($self, %options) = @_; return sprintf("Replicas Desired : %s, Current : %s, Available : %s, Unavailable : %s, Up-to-date : %s", $self->{result_values}->{desired}, $self->{result_values}->{current}, $self->{result_values}->{available}, $self->{result_values}->{unavailable}, $self->{result_values}->{up_to_date}); } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{desired} = $options{new_datas}->{$self->{instance} . '_desired'}; $self->{result_values}->{current} = $options{new_datas}->{$self->{instance} . '_current'}; $self->{result_values}->{available} = $options{new_datas}->{$self->{instance} . '_available'}; $self->{result_values}->{unavailable} = $options{new_datas}->{$self->{instance} . '_unavailable'}; $self->{result_values}->{up_to_date} = $options{new_datas}->{$self->{instance} . '_up_to_date'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'deployments', type => 1, cb_prefix_output => 'prefix_deployment_output', message_multiple => 'All deployments status are ok', skipped_code => { -11 => 1 } }, ]; $self->{maps_counters}->{deployments} = [ { label => 'status', set => { key_values => [ { name => 'desired' }, { name => 'current' }, { name => 'up_to_date' }, { name => 'available' }, { name => 'unavailable' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_status_calc'), closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => $self->can('custom_status_perfdata'), closure_custom_threshold_check => \&catalog_status_threshold, } }, ]; } sub prefix_deployment_output { my ($self, %options) = @_; return "Deployment '" . $options{instance_value}->{display} . " [namespace: ". $options{instance_value}->{namespace} ."]' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "deployment:s" => { name => 'deployment', default => 'deployment=~".*"' }, "warning-status:s" => { name => 'warning_status', default => '%{up_to_date} < %{desired}' }, "critical-status:s" => { name => 'critical_status', default => '%{available} < %{desired}' }, "extra-filter:s@" => { name => 'extra_filter' }, "metric-overload:s@" => { name => 'metric_overload' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{metrics} = { 'desired' => '^kube_deployment_spec_replicas$', 'current' => '^kube_deployment_status_replicas$', 'available' => '^kube_deployment_status_replicas_available$', 'unavailable' => '^kube_deployment_status_replicas_unavailable$', 'up_to_date' => '^kube_deployment_status_replicas_updated$', }; foreach my $metric (@{$self->{option_results}->{metric_overload}}) { next if ($metric !~ /(.*),(.*)/); $self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1})); } $self->{labels} = {}; foreach my $label (('deployment')) { if ($self->{option_results}->{$label} !~ /^(\w+)[!~=]+\".*\"$/) { $self->{output}->add_option_msg(short_msg => "Need to specify --" . $label . " option as a PromQL filter."); $self->{output}->option_exit(); } $self->{labels}->{$label} = $1; } $self->{extra_filter} = ''; foreach my $filter (@{$self->{option_results}->{extra_filter}}) { $self->{extra_filter} .= ',' . $filter; } $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; $self->{deployments} = {}; my $results = $options{custom}->query( queries => [ 'label_replace({__name__=~"' . $self->{metrics}->{desired} . '",' . $self->{option_results}->{deployment} . $self->{extra_filter} . '}, "__name__", "desired", "", "")', 'label_replace({__name__=~"' . $self->{metrics}->{current} . '",' . $self->{option_results}->{deployment} . $self->{extra_filter} . '}, "__name__", "current", "", "")', 'label_replace({__name__=~"' . $self->{metrics}->{available} . '",' . $self->{option_results}->{deployment} . $self->{extra_filter} . '}, "__name__", "available", "", "")', 'label_replace({__name__=~"' . $self->{metrics}->{unavailable} . '",' . $self->{option_results}->{deployment} . $self->{extra_filter} . '}, "__name__", "unavailable", "", "")', 'label_replace({__name__=~"' . $self->{metrics}->{up_to_date} . '",' . $self->{option_results}->{deployment} . $self->{extra_filter} . '}, "__name__", "up_to_date", "", "")' ] ); foreach my $result (@{$results}) { $self->{deployments}->{$result->{metric}->{$self->{labels}->{deployment}}}->{display} = $result->{metric}->{$self->{labels}->{deployment}}; $self->{deployments}->{$result->{metric}->{$self->{labels}->{deployment}}}->{$result->{metric}->{__name__}} = ${$result->{value}}[1]; $self->{deployments}->{$result->{metric}->{$self->{labels}->{deployment}}}->{namespace} = $result->{metric}->{namespace}; } if (scalar(keys %{$self->{deployments}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No deployments found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check deployment status. =over 8 =item B<--deployment> Filter on a specific deployment (Must be a PromQL filter, Default: 'deployment=~".*"') =item B<--warning-status> Set warning threshold for status (Default: '%{up_to_date} < %{desired}') Can used special variables like: %{display}, %{desired}, %{current}, %{available}, %{unavailable}, %{up_to_date} =item B<--critical-status> Set critical threshold for status (Default: '%{available} < %{desired}'). Can used special variables like: %{display}, %{desired}, %{current}, %{available}, %{unavailable}, %{up_to_date} =item B<--extra-filter> Add a PromQL filter (Can be multiple) Example : --extra-filter='name=~".*pretty.*"' =item B<--metric-overload> Overload default metrics name (Can be multiple) Example : --metric-overload='metric,^my_metric_name$' Default : - desired: ^kube_deployment_spec_replicas$ - current: ^kube_deployment_status_replicas$ - available: ^kube_deployment_status_replicas_available$ - unavailable: ^kube_deployment_status_replicas_unavailable$ - up_to_date: ^kube_deployment_status_replicas_updated$ =back =cut centreon-plugins-20220113/cloud/prometheus/direct/kubernetes/mode/listcontainers.pm000066400000000000000000000124561417000230700305110ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::prometheus::direct::kubernetes::mode::listcontainers; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "container:s" => { name => 'container', default => 'container=~".*"' }, "pod:s" => { name => 'pod', default => 'pod=~".*"' }, "namespace:s" => { name => 'namespace', default => 'namespace=~".*"' }, "image:s" => { name => 'image', default => 'image=~".*"' }, "extra-filter:s@" => { name => 'extra_filter' }, "metric-overload:s@" => { name => 'metric_overload' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); $self->{metrics} = { 'info' => '^kube_pod_container_info$', }; foreach my $metric (@{$self->{option_results}->{metric_overload}}) { next if ($metric !~ /(.*),(.*)/); $self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1})); } $self->{labels} = {}; foreach my $label (('container', 'pod', 'namespace', 'image')) { if ($self->{option_results}->{$label} !~ /^(\w+)[!~=]+\".*\"$/) { $self->{output}->add_option_msg(short_msg => "Need to specify --" . $label . " option as a PromQL filter."); $self->{output}->option_exit(); } $self->{labels}->{$label} = $1; } $self->{extra_filter} = ''; foreach my $filter (@{$self->{option_results}->{extra_filter}}) { $self->{extra_filter} .= ',' . $filter; } } sub manage_selection { my ($self, %options) = @_; $self->{containers} = $options{custom}->query(queries => [ '{__name__=~"' . $self->{metrics}->{info} . '",' . $self->{option_results}->{container} . ',' . $self->{option_results}->{pod} . ',' . $self->{option_results}->{namespace} . $self->{extra_filter} . '}' ]); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $container (@{$self->{containers}}) { $self->{output}->output_add(long_msg => sprintf("[container = %s][pod = %s][namespace = %s][image = %s]", $container->{metric}->{$self->{labels}->{container}}, $container->{metric}->{$self->{labels}->{pod}}, $container->{metric}->{$self->{labels}->{namespace}}, $container->{metric}->{$self->{labels}->{image}})); } $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 => ['container', 'pod', 'namespace', 'image']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $container (@{$self->{containers}}) { $self->{output}->add_disco_entry( container => $container->{metric}->{$self->{labels}->{container}}, pod => $container->{metric}->{$self->{labels}->{pod}}, namespace => $container->{metric}->{$self->{labels}->{namespace}}, image => $container->{metric}->{$self->{labels}->{image}}, ); } } 1; __END__ =head1 MODE List containers. =over 8 =item B<--container> Filter on a specific container (Must be a PromQL filter, Default: 'container_name=~".*"') =item B<--pod> Filter on a specific pod (Must be a PromQL filter, Default: 'pod_name=~".*"') =item B<--namespace> Filter on a specific namespace (Must be a PromQL filter, Default: 'namespace=~".*"') =item B<--image> Filter on a specific image (Must be a PromQL filter, Default: 'image=~".*"') =item B<--extra-filter> Add a PromQL filter (Can be multiple) Example : --extra-filter='name=~".*pretty.*"' =item B<--metric-overload> Overload default metrics name (Can be multiple, metric can be 'info') Example : --metric-overload='metric,^my_metric_name$' =back =cut centreon-plugins-20220113/cloud/prometheus/direct/kubernetes/mode/listdaemonsets.pm000066400000000000000000000110151417000230700304740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::prometheus::direct::kubernetes::mode::listdaemonsets; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "daemonset:s" => { name => 'daemonset', default => 'daemonset=~".*"' }, "namespace:s" => { name => 'namespace', default => 'namespace=~".*"' }, "extra-filter:s@" => { name => 'extra_filter' }, "metric-overload:s@" => { name => 'metric_overload' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); $self->{metrics} = { 'created' => '^kube_daemonset_created$', }; foreach my $metric (@{$self->{option_results}->{metric_overload}}) { next if ($metric !~ /(.*),(.*)/); $self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1})); } $self->{labels} = {}; foreach my $label (('daemonset', 'namespace')) { if ($self->{option_results}->{$label} !~ /^(\w+)[!~=]+\".*\"$/) { $self->{output}->add_option_msg(short_msg => "Need to specify --" . $label . " option as a PromQL filter."); $self->{output}->option_exit(); } $self->{labels}->{$label} = $1; } $self->{extra_filter} = ''; foreach my $filter (@{$self->{option_results}->{extra_filter}}) { $self->{extra_filter} .= ',' . $filter; } } sub manage_selection { my ($self, %options) = @_; $self->{daemonsets} = $options{custom}->query(queries => [ '{__name__=~"' . $self->{metrics}->{created} . '",' . $self->{option_results}->{daemonset} . ',' . $self->{option_results}->{namespace} . $self->{extra_filter} . '}' ]); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $daemonset (@{$self->{daemonsets}}) { $self->{output}->output_add(long_msg => sprintf("[daemonset = %s][namespace = %s]", $daemonset->{metric}->{$self->{labels}->{daemonset}}, $daemonset->{metric}->{$self->{labels}->{namespace}})); } $self->{output}->output_add(severity => 'OK', short_msg => 'List daemonsets:'); $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 => ['daemonset', 'namespace']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $daemonset (@{$self->{daemonsets}}) { $self->{output}->add_disco_entry( daemonset => $daemonset->{metric}->{$self->{labels}->{daemonset}}, namespace => $daemonset->{metric}->{$self->{labels}->{namespace}}, ); } } 1; __END__ =head1 MODE List daemonsets. =over 8 =item B<--daemonset> Filter on a specific daemonset (Must be a PromQL filter, Default: 'daemonset=~".*"') =item B<--namespace> Filter on a specific namespace (Must be a PromQL filter, Default: 'namespace=~".*"') =item B<--extra-filter> Add a PromQL filter (Can be multiple) Example : --extra-filter='name=~".*pretty.*"' =item B<--metric-overload> Overload default metrics name (Can be multiple, metric can be 'created') Example : --metric-overload='metric,^my_metric_name$' =back =cut centreon-plugins-20220113/cloud/prometheus/direct/kubernetes/mode/listdeployments.pm000066400000000000000000000100451417000230700306770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::prometheus::direct::kubernetes::mode::listdeployments; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "deployment:s" => { name => 'deployment', default => 'deployment=~".*"' }, "extra-filter:s@" => { name => 'extra_filter' }, "metric-overload:s@" => { name => 'metric_overload' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); $self->{metrics} = { 'labels' => '^kube_deployment_labels$', }; foreach my $metric (@{$self->{option_results}->{metric_overload}}) { next if ($metric !~ /(.*),(.*)/); $self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1})); } $self->{labels} = {}; foreach my $label (('deployment')) { if ($self->{option_results}->{$label} !~ /^(\w+)[!~=]+\".*\"$/) { $self->{output}->add_option_msg(short_msg => "Need to specify --" . $label . " option as a PromQL filter."); $self->{output}->option_exit(); } $self->{labels}->{$label} = $1; } $self->{extra_filter} = ''; foreach my $filter (@{$self->{option_results}->{extra_filter}}) { $self->{extra_filter} .= ',' . $filter; } } sub manage_selection { my ($self, %options) = @_; $self->{deployments} = $options{custom}->query(queries => [ '{__name__=~"' . $self->{metrics}->{labels} . '",' . $self->{option_results}->{deployment} . $self->{extra_filter} . '}' ]); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $deployment (@{$self->{deployments}}) { $self->{output}->output_add(long_msg => sprintf("[deployment = %s]", $deployment->{metric}->{$self->{labels}->{deployment}})); } $self->{output}->output_add(severity => 'OK', short_msg => 'List deployments:'); $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 => ['deployment']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $deployment (@{$self->{deployments}}) { $self->{output}->add_disco_entry( deployment => $deployment->{metric}->{$self->{labels}->{deployment}}, ); } } 1; __END__ =head1 MODE List deployments. =over 8 =item B<--deployment> Filter on a specific deployment (Must be a PromQL filter, Default: 'deployment=~".*"') =item B<--extra-filter> Add a PromQL filter (Can be multiple) Example : --extra-filter='name=~".*pretty.*"' =item B<--metric-overload> Overload default metrics name (Can be multiple, metric can be 'labels') Example : --metric-overload='metric,^my_metric_name$' =back =cut centreon-plugins-20220113/cloud/prometheus/direct/kubernetes/mode/listnamespaces.pm000066400000000000000000000100161417000230700304510ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::prometheus::direct::kubernetes::mode::listnamespaces; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "namespace:s" => { name => 'namespace', default => 'namespace=~".*"' }, "extra-filter:s@" => { name => 'extra_filter' }, "metric-overload:s@" => { name => 'metric_overload' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); $self->{metrics} = { 'labels' => '^kube_namespace_labels$', }; foreach my $metric (@{$self->{option_results}->{metric_overload}}) { next if ($metric !~ /(.*),(.*)/); $self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1})); } $self->{labels} = {}; foreach my $label (('namespace')) { if ($self->{option_results}->{$label} !~ /^(\w+)[!~=]+\".*\"$/) { $self->{output}->add_option_msg(short_msg => "Need to specify --" . $label . " option as a PromQL filter."); $self->{output}->option_exit(); } $self->{labels}->{$label} = $1; } $self->{extra_filter} = ''; foreach my $filter (@{$self->{option_results}->{extra_filter}}) { $self->{extra_filter} .= ',' . $filter; } } sub manage_selection { my ($self, %options) = @_; $self->{namespaces} = $options{custom}->query(queries => [ '{__name__=~"' . $self->{metrics}->{labels} . '",' . $self->{option_results}->{namespace} . $self->{extra_filter} . '}' ]); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $namespace (@{$self->{namespaces}}) { $self->{output}->output_add(long_msg => sprintf("[namespace = %s]", $namespace->{metric}->{$self->{labels}->{namespace}})); } $self->{output}->output_add(severity => 'OK', short_msg => 'List namespaces:'); $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 => ['namespace']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $namespace (@{$self->{namespaces}}) { $self->{output}->add_disco_entry( namespace => $namespace->{metric}->{$self->{labels}->{namespace}}, ); } } 1; __END__ =head1 MODE List namespaces. =over 8 =item B<--namespace> Filter on a specific namespace (Must be a PromQL filter, Default: 'namespace=~".*"') =item B<--extra-filter> Add a PromQL filter (Can be multiple) Example : --extra-filter='name=~".*pretty.*"' =item B<--metric-overload> Overload default metrics name (Can be multiple, metric can be 'labels') Example : --metric-overload='metric,^my_metric_name$' =back =cut centreon-plugins-20220113/cloud/prometheus/direct/kubernetes/mode/listnodes.pm000066400000000000000000000154541417000230700274550ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::prometheus::direct::kubernetes::mode::listnodes; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "node:s" => { name => 'node', default => 'node=~".*"' }, "os-image:s" => { name => 'os_image', default => 'os_image=~".*"' }, "kubelet-version:s" => { name => 'kubelet_version', default => 'kubelet_version=~".*"' }, "kubeproxy-version:s" => { name => 'kubeproxy_version', default => 'kubeproxy_version=~".*"' }, "kernel-version:s" => { name => 'kernel_version', default => 'kernel_version=~".*"' }, "container-runtime-version:s" => { name => 'container_runtime_version', default => 'container_runtime_version=~".*"' }, "extra-filter:s@" => { name => 'extra_filter' }, "metric-overload:s@" => { name => 'metric_overload' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); $self->{metrics} = { 'info' => '^kube_node_info$', }; foreach my $metric (@{$self->{option_results}->{metric_overload}}) { next if ($metric !~ /(.*),(.*)/); $self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1})); } $self->{labels} = {}; foreach my $label (('node', 'os_image', 'kubelet_version', 'kubeproxy_version', 'kernel_version', 'container_runtime_version')) { if ($self->{option_results}->{$label} !~ /^(\w+)[!~=]+\".*\"$/) { $self->{output}->add_option_msg(short_msg => "Need to specify --" . $label . " option as a PromQL filter."); $self->{output}->option_exit(); } $self->{labels}->{$label} = $1; } $self->{extra_filter} = ''; foreach my $filter (@{$self->{option_results}->{extra_filter}}) { $self->{extra_filter} .= ',' . $filter; } } sub manage_selection { my ($self, %options) = @_; $self->{nodes} = $options{custom}->query(queries => [ '{__name__=~"' . $self->{metrics}->{info} . '",' . $self->{option_results}->{node} . ',' . $self->{option_results}->{os_image} . ',' . $self->{option_results}->{kubelet_version} . ',' . $self->{option_results}->{kubeproxy_version} . ',' . $self->{option_results}->{kernel_version} . ',' . $self->{option_results}->{container_runtime_version} . $self->{extra_filter} . '}' ]); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $node (@{$self->{nodes}}) { $self->{output}->output_add(long_msg => sprintf("[node = %s][os_image = %s][kubelet_version = %s][kubeproxy_version = %s]" . "[kernel_version = %s][container_runtime_version = %s]", $node->{metric}->{$self->{labels}->{node}}, $node->{metric}->{$self->{labels}->{os_image}}, $node->{metric}->{$self->{labels}->{kubelet_version}}, $node->{metric}->{$self->{labels}->{kubeproxy_version}}, $node->{metric}->{$self->{labels}->{kernel_version}}, $node->{metric}->{$self->{labels}->{container_runtime_version}})); } $self->{output}->output_add(severity => 'OK', short_msg => 'List nodes:'); $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 => ['node', 'os_image', 'kubelet_version', 'kubeproxy_version', 'kernel_version', 'container_runtime_version']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $node (@{$self->{nodes}}) { $self->{output}->add_disco_entry( node => $node->{metric}->{$self->{labels}->{node}}, os_image => $node->{metric}->{$self->{labels}->{os_image}}, kubelet_version => $node->{metric}->{$self->{labels}->{kubelet_version}}, kubeproxy_version => $node->{metric}->{$self->{labels}->{kubeproxy_version}}, kernel_version => $node->{metric}->{$self->{labels}->{kernel_version}}, container_runtime_version => $node->{metric}->{$self->{labels}->{container_runtime_version}}, ); } } 1; __END__ =head1 MODE List nodes. =over 8 =item B<--node> Filter on a specific node (Must be a PromQL filter, Default: 'node=~".*"') =item B<--os-image> Filter on a specific os image (Must be a PromQL filter, Default: 'os_image=~".*"') =item B<--kubelet-version> Filter on a specific kubelet version (Must be a PromQL filter, Default: 'kubelet_version=~".*"') =item B<--kubeproxy-version> Filter on a specific kubeproxy version (Must be a PromQL filter, Default: 'kubeproxy_version=~".*"') =item B<--kernel-version> Filter on a specific kernel version (Must be a PromQL filter, Default: 'kernel_version=~".*"') =item B<--container-runtime-version> Filter on a specific container runtime version (Must be a PromQL filter, Default: 'container_runtime_version=~".*"') =item B<--extra-filter> Add a PromQL filter (Can be multiple) Example : --extra-filter='name=~".*pretty.*"' =item B<--metric-overload> Overload default metrics name (Can be multiple, metric can be 'info') Example : --metric-overload='metric,^my_metric_name$' =back =cut centreon-plugins-20220113/cloud/prometheus/direct/kubernetes/mode/listservices.pm000066400000000000000000000107321417000230700301620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::prometheus::direct::kubernetes::mode::listservices; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "service:s" => { name => 'service', default => 'service=~".*"' }, "cluster-ip:s" => { name => 'cluster_ip', default => 'cluster_ip=~".*"' }, "extra-filter:s@" => { name => 'extra_filter' }, "metric-overload:s@" => { name => 'metric_overload' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); $self->{metrics} = { 'info' => '^kube_service_info$', }; foreach my $metric (@{$self->{option_results}->{metric_overload}}) { next if ($metric !~ /(.*),(.*)/); $self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1})); } $self->{labels} = {}; foreach my $label (('service', 'cluster_ip')) { if ($self->{option_results}->{$label} !~ /^(\w+)[!~=]+\".*\"$/) { $self->{output}->add_option_msg(short_msg => "Need to specify --" . $label . " option as a PromQL filter."); $self->{output}->option_exit(); } $self->{labels}->{$label} = $1; } $self->{extra_filter} = ''; foreach my $filter (@{$self->{option_results}->{extra_filter}}) { $self->{extra_filter} .= ',' . $filter; } } sub manage_selection { my ($self, %options) = @_; $self->{services} = $options{custom}->query(queries => [ '{__name__=~"' . $self->{metrics}->{info} . '",' . $self->{option_results}->{service} . ',' . $self->{option_results}->{cluster_ip} . $self->{extra_filter} . '}' ]); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $service (@{$self->{services}}) { $self->{output}->output_add(long_msg => sprintf("[service = %s][cluster_ip = %s]", $service->{metric}->{$self->{labels}->{service}}, $service->{metric}->{$self->{labels}->{cluster_ip}})); } $self->{output}->output_add(severity => 'OK', short_msg => 'List services:'); $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 => ['service', 'cluster_ip']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $service (@{$self->{services}}) { $self->{output}->add_disco_entry( service => $service->{metric}->{$self->{labels}->{service}}, cluster_ip => $service->{metric}->{$self->{labels}->{cluster_ip}}, ); } } 1; __END__ =head1 MODE List services. =over 8 =item B<--service> Filter on a specific service (Must be a PromQL filter, Default: 'service=~".*"') =item B<--cluster-ip> Filter on a specific cluster ip (Must be a PromQL filter, Default: 'cluster_ip=~".*"') =item B<--extra-filter> Add a PromQL filter (Can be multiple) Example : --extra-filter='name=~".*pretty.*"' =item B<--metric-overload> Overload default metrics name (Can be multiple, metric can be 'info') Example : --metric-overload='metric,^my_metric_name$' =back =cut centreon-plugins-20220113/cloud/prometheus/direct/kubernetes/mode/namespacestatus.pm000066400000000000000000000157661417000230700306570ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::prometheus::direct::kubernetes::mode::namespacestatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; return sprintf("status phase is '%s'", $self->{result_values}->{phase}); } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{phase} = $options{new_datas}->{$self->{instance} . '_phase'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_init => 'skip_global', cb_prefix_output => 'prefix_global_output' }, { name => 'namespaces', type => 1, cb_prefix_output => 'prefix_namespace_output', message_multiple => 'All namespaces status are ok', skipped_code => { -11 => 1 } }, ]; $self->{maps_counters}->{global} = [ { label => 'active', nlabel => 'namespaces.active.count', set => { key_values => [ { name => 'active' } ], output_template => 'Active : %d', perfdatas => [ { label => 'active', value => 'active', template => '%d', min => 0 }, ], } }, { label => 'terminating', nlabel => 'namespaces.terminating.count', set => { key_values => [ { name => 'terminating' } ], output_template => 'Terminating : %d', perfdatas => [ { label => 'terminating', value => 'terminating', template => '%d', min => 0 }, ], } }, ]; $self->{maps_counters}->{namespaces} = [ { label => 'status', set => { key_values => [ { name => 'phase' }, { 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 => \&catalog_status_threshold, } }, ]; } sub skip_global { my ($self, %options) = @_; scalar(keys %{$self->{namespaces}}) > 1 ? return(0) : return(1); } sub prefix_global_output { my ($self, %options) = @_; return "Namespaces "; } sub prefix_namespace_output { my ($self, %options) = @_; return "Namespace '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "namespace:s" => { name => 'namespace', default => 'namespace=~".*"' }, "phase:s" => { name => 'phase', default => 'phase=~".*"' }, "warning-status:s" => { name => 'warning_status' }, "critical-status:s" => { name => 'critical_status', default => '%{phase} !~ /Active/' }, "extra-filter:s@" => { name => 'extra_filter' }, "metric-overload:s@" => { name => 'metric_overload' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{metrics} = { 'status' => '^kube_namespace_status_phase$', }; foreach my $metric (@{$self->{option_results}->{metric_overload}}) { next if ($metric !~ /(.*),(.*)/); $self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1})); } $self->{labels} = {}; foreach my $label (('namespace', 'phase')) { if ($self->{option_results}->{$label} !~ /^(\w+)[!~=]+\".*\"$/) { $self->{output}->add_option_msg(short_msg => "Need to specify --" . $label . " option as a PromQL filter."); $self->{output}->option_exit(); } $self->{labels}->{$label} = $1; } $self->{extra_filter} = ''; foreach my $filter (@{$self->{option_results}->{extra_filter}}) { $self->{extra_filter} .= ',' . $filter; } $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; $self->{global} = { active => 0, terminating => 0 }; $self->{namespaces} = {}; my $results = $options{custom}->query( queries => [ '{__name__=~"' . $self->{metrics}->{status} . '",' . $self->{option_results}->{namespace} . $self->{extra_filter} . '}' ] ); foreach my $result (@{$results}) { $self->{namespaces}->{$result->{metric}->{$self->{labels}->{namespace}}}->{display} = $result->{metric}->{$self->{labels}->{namespace}}; $self->{namespaces}->{$result->{metric}->{$self->{labels}->{namespace}}}->{$self->{labels}->{phase}} = $result->{metric}->{$self->{labels}->{phase}} if (${$result->{value}}[1] == 1); $self->{global}->{lc($result->{metric}->{$self->{labels}->{phase}})}++ if (${$result->{value}}[1] == 1); } if (scalar(keys %{$self->{namespaces}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No namespaces found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check namespace status phase. =over 8 =item B<--namespace> Filter on a specific namespace (Must be a PromQL filter, Default: 'namespace=~".*"') =item B<--phase> Filter on a specific phase (Must be a PromQL filter, Default: 'phase=~".*"') =item B<--warning-status> Set warning threshold for status (Default: '') Can used special variables like: %{display}, %{phase}. =item B<--critical-status> Set critical threshold for status (Default: '%{phase} !~ /Active/'). Can used special variables like: %{display}, %{phase} =item B<--extra-filter> Add a PromQL filter (Can be multiple) Example : --extra-filter='name=~".*pretty.*"' =item B<--metric-overload> Overload default metrics name (Can be multiple) Example : --metric-overload='metric,^my_metric_name$' Default : - status: ^kube_namespace_status_phase$ =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='status' =back =cut centreon-plugins-20220113/cloud/prometheus/direct/kubernetes/mode/nodestatus.pm000066400000000000000000000250771417000230700276440ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::prometheus::direct::kubernetes::mode::nodestatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; return sprintf("Status is '%s', New Pods Schedulable : %s", $self->{result_values}->{status}, $self->{result_values}->{schedulable}); } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; $self->{result_values}->{schedulable} = ($options{new_datas}->{$self->{instance} . '_unschedulable'} == 1) ? "false" : "true"; return 0; } sub custom_usage_perfdata { my ($self, %options) = @_; my $label = 'allocated_pods'; my $value_perf = $self->{result_values}->{allocated}; my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{allocatable}; $total_options{cast_int} = 1; } $self->{output}->perfdata_add( label => $label, nlabel => 'pods.allocated.count', 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}->{allocatable}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, ); } sub custom_usage_threshold { my ($self, %options) = @_; my ($exit, $threshold_value); $threshold_value = $self->{result_values}->{allocated}; if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_allocated}; } $exit = $self->{perfdata}->threshold_check( value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_usage_output { my ($self, %options) = @_; my $msg = sprintf("Pods Capacity: %s, Allocatable: %s, Allocated: %s (%.2f%%)", $self->{result_values}->{capacity}, $self->{result_values}->{allocatable}, $self->{result_values}->{allocated}, $self->{result_values}->{prct_allocated}); return $msg; } sub custom_usage_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{capacity} = $options{new_datas}->{$self->{instance} . '_capacity'}; $self->{result_values}->{allocatable} = $options{new_datas}->{$self->{instance} . '_allocatable'}; $self->{result_values}->{allocated} = $options{new_datas}->{$self->{instance} . '_allocated'}; $self->{result_values}->{prct_allocated} = ($self->{result_values}->{allocatable} > 0) ? $self->{result_values}->{allocated} * 100 / $self->{result_values}->{allocatable} : 0; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'nodes', type => 1, cb_prefix_output => 'prefix_node_output', message_multiple => 'All nodes status are ok', message_separator => ' - ', skipped_code => { -11 => 1 } }, ]; $self->{maps_counters}->{nodes} = [ { label => 'status', set => { key_values => [ { name => 'status' }, { name => 'unschedulable' }, { 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 => \&catalog_status_threshold, } }, { label => 'allocated-pods', set => { key_values => [ { name => 'capacity' }, { name => 'allocatable' }, { name => 'allocated' }, { name => 'display' } ], 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 prefix_node_output { my ($self, %options) = @_; return "Node '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "node:s" => { name => 'node', default => 'node=~".*"' }, "warning-status:s" => { name => 'warning_status' }, "critical-status:s" => { name => 'critical_status', default => '%{status} !~ /Ready/ || %{schedulable} =~ /false/' }, "extra-filter:s@" => { name => 'extra_filter' }, "metric-overload:s@" => { name => 'metric_overload' }, "units:s" => { name => 'units', default => '' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{metrics} = { 'status' => '^kube_node_status_condition$', 'unschedulable' => '^kube_node_spec_unschedulable$', 'capacity' => '^kube_node_status_capacity_pods$', 'allocatable' => '^kube_node_status_allocatable_pods$', 'allocated' => '^kubelet_running_pod_count$', }; foreach my $metric (@{$self->{option_results}->{metric_overload}}) { next if ($metric !~ /(.*),(.*)/); $self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1})); } $self->{labels} = {}; foreach my $label (('node')) { if ($self->{option_results}->{$label} !~ /^(\w+)[!~=]+\".*\"$/) { $self->{output}->add_option_msg(short_msg => "Need to specify --" . $label . " option as a PromQL filter."); $self->{output}->option_exit(); } $self->{labels}->{$label} = $1; } $self->{extra_filter} = ''; foreach my $filter (@{$self->{option_results}->{extra_filter}}) { $self->{extra_filter} .= ',' . $filter; } $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; $self->{nodes} = {}; my $results = $options{custom}->query( queries => [ 'label_replace({__name__=~"' . $self->{metrics}->{status} . '",' . $self->{option_results}->{node} . ',' . 'status="true"' . $self->{extra_filter} . '}, "__name__", "status", "", "")', 'label_replace({__name__=~"' . $self->{metrics}->{unschedulable} . '",' . $self->{option_results}->{node} . $self->{extra_filter} . '}, "__name__", "unschedulable", "", "")', 'label_replace({__name__=~"' . $self->{metrics}->{capacity} . '",' . $self->{option_results}->{node} . $self->{extra_filter} . '}, "__name__", "capacity", "", "")', 'label_replace({__name__=~"' . $self->{metrics}->{allocatable} . '",' . $self->{option_results}->{node} . $self->{extra_filter} . '}, "__name__", "allocatable", "", "")', 'label_replace({__name__=~"' . $self->{metrics}->{allocated} . '",' . $self->{option_results}->{node} . $self->{extra_filter} . '}, "__name__", "allocated", "", "")' ] ); foreach my $result (@{$results}) { $self->{nodes}->{$result->{metric}->{$self->{labels}->{node}}}->{display} = $result->{metric}->{$self->{labels}->{node}}; $self->{nodes}->{$result->{metric}->{$self->{labels}->{node}}}->{$result->{metric}->{__name__}} = ${$result->{value}}[1]; $self->{nodes}->{$result->{metric}->{$self->{labels}->{node}}}->{$result->{metric}->{__name__}} = $result->{metric}->{condition} if ($result->{metric}->{__name__} =~ /status/); } if (scalar(keys %{$self->{nodes}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No nodes found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check node status. =over 8 =item B<--node> Filter on a specific node (Must be a PromQL filter, Default: 'node=~".*"') =item B<--warning-status> Set warning threshold for status (Default: '') Can used special variables like: %{display}, %{status}, %{schedulable} =item B<--critical-status> Set critical threshold for status (Default: '%{status} !~ /Ready/ || %{schedulable} != /false/'). Can used special variables like: %{display}, %{status}, %{schedulable} =item B<--warning-allocated-pods> Threshold warning for pods allocation. =item B<--critical-allocated-pods> Threshold critical for pods allocation. =item B<--units> Units of thresholds (Default: '') (Can be '%'). =item B<--extra-filter> Add a PromQL filter (Can be multiple) Example : --extra-filter='name=~".*pretty.*"' =item B<--metric-overload> Overload default metrics name (Can be multiple) Example : --metric-overload='metric,^my_metric_name$' Default : - status: ^kube_node_status_condition$ - unschedulable: ^kube_node_spec_unschedulable$ - capacity: ^kube_node_status_capacity_pods$ - allocatable: ^kube_node_status_allocatable_pods$ - allocated: ^kubelet_running_pod_count$ =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='status' =back =cut centreon-plugins-20220113/cloud/prometheus/direct/kubernetes/plugin.pm000066400000000000000000000046301417000230700260150ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::prometheus::direct::kubernetes::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}} = ( 'container-status' => 'cloud::prometheus::direct::kubernetes::mode::containerstatus', 'daemonset-status' => 'cloud::prometheus::direct::kubernetes::mode::daemonsetstatus', 'deployment-status' => 'cloud::prometheus::direct::kubernetes::mode::deploymentstatus', 'list-containers' => 'cloud::prometheus::direct::kubernetes::mode::listcontainers', 'list-daemonsets' => 'cloud::prometheus::direct::kubernetes::mode::listdaemonsets', 'list-deployments' => 'cloud::prometheus::direct::kubernetes::mode::listdeployments', 'list-namespaces' => 'cloud::prometheus::direct::kubernetes::mode::listnamespaces', 'list-nodes' => 'cloud::prometheus::direct::kubernetes::mode::listnodes', 'list-services' => 'cloud::prometheus::direct::kubernetes::mode::listservices', 'namespace-status' => 'cloud::prometheus::direct::kubernetes::mode::namespacestatus', 'node-status' => 'cloud::prometheus::direct::kubernetes::mode::nodestatus', ); $self->{custom_modes}{api} = 'cloud::prometheus::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Kubernetes metrics through Prometheus server using the Kubernetes kube-state-metrics add-on agent. =cut centreon-plugins-20220113/cloud/prometheus/direct/nginxingresscontroller/000077500000000000000000000000001417000230700266315ustar00rootroot00000000000000centreon-plugins-20220113/cloud/prometheus/direct/nginxingresscontroller/mode/000077500000000000000000000000001417000230700275555ustar00rootroot00000000000000centreon-plugins-20220113/cloud/prometheus/direct/nginxingresscontroller/mode/connections.pm000066400000000000000000000137451417000230700324470ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::prometheus::direct::nginxingresscontroller::mode::connections; 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 => 'global', type => 0, cb_prefix_output => 'prefix_containers_output' }, ]; $self->{maps_counters}->{global} = [ { label => 'reading', nlabel => 'connections.reading.count', set => { key_values => [ { name => 'reading' } ], output_template => 'Reading: %d', perfdatas => [ { label => 'reading',template => '%d', min => 0, unit => 'connections' }, ], } }, { label => 'waiting', nlabel => 'connections.waiting.count', set => { key_values => [ { name => 'waiting' } ], output_template => 'Waiting: %d', perfdatas => [ { label => 'waiting', template => '%d', min => 0, unit => 'connections' }, ], } }, { label => 'writing', nlabel => 'connections.writing.count', set => { key_values => [ { name => 'writing' } ], output_template => 'Writing: %d', perfdatas => [ { label => 'writing', template => '%d', min => 0, unit => 'connections' }, ], } }, { label => 'active', nlabel => 'connections.active.count', set => { key_values => [ { name => 'active' } ], output_template => 'Active: %d', perfdatas => [ { label => 'active', template => '%d', min => 0, unit => 'connections' }, ], } }, { label => 'accepted', nlabel => 'connections.accepted.persecond', set => { key_values => [ { name => 'accepted', per_second => 1 } ], output_template => 'Accepted: %.2f/s', perfdatas => [ { label => 'accepted', template => '%.2f', min => 0, unit => 'connections/s' }, ], } }, { label => 'handled', nlabel => 'connections.handled.persecond', set => { key_values => [ { name => 'handled', per_second => 1 } ], output_template => 'Handled: %.2f/s', perfdatas => [ { label => 'handled', template => '%.2f', min => 0, unit => 'connections/s' }, ], } }, ]; } sub prefix_containers_output { my ($self, %options) = @_; return "Connections "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'extra-filter:s@' => { name => 'extra_filter' }, 'metric-overload:s@' => { name => 'metric_overload' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{metrics} = { 'connections' => '^nginx_ingress_controller_nginx_process_connections$', 'connections_total' => '^nginx_ingress_controller_nginx_process_connections_total$', }; foreach my $metric (@{$self->{option_results}->{metric_overload}}) { next if ($metric !~ /(.*),(.*)/); $self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1})); } $self->{extra_filter} = ''; foreach my $filter (@{$self->{option_results}->{extra_filter}}) { $self->{extra_filter} .= ',' . $filter; } } sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = "prometheus_nginxingresscontroller_" . md5_hex($options{custom}->get_connection_info()) . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); $self->{global} = {}; my $results = $options{custom}->query( queries => [ 'label_replace({__name__=~"' . $self->{metrics}->{connections} . '",' . $self->{extra_filter} . '}, "__name__", "connections", "", "")', 'label_replace({__name__=~"' . $self->{metrics}->{connections_total} . '",' . $self->{extra_filter} . '}, "__name__", "connections_total", "", "")' ] ); foreach my $result (@{$results}) { $self->{global}->{$result->{metric}->{state}} = ${$result->{value}}[1]; } } 1; __END__ =head1 MODE Check connections number. =over 8 =item B<--warning-*> Threshold warning. Can be: 'reading', 'waiting', 'writing', 'active', 'accepted', 'handled'. =item B<--critical-*> Threshold critical. Can be: 'reading', 'waiting', 'writing', 'active', 'accepted', 'handled'. =item B<--extra-filter> Add a PromQL filter (Can be multiple) Example : --extra-filter='name=~".*pretty.*"' =item B<--metric-overload> Overload default metrics name (Can be multiple) Example : --metric-overload='metric,^my_metric_name$' Default : - connections: ^nginx_ingress_controller_nginx_process_connections$ - connections_total: ^nginx_ingress_controller_nginx_process_connections_total$ =back =cut centreon-plugins-20220113/cloud/prometheus/direct/nginxingresscontroller/mode/requests.pm000066400000000000000000000157231417000230700317760ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::prometheus::direct::nginxingresscontroller::mode::requests; 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 => 'global', type => 0 }, { name => 'namespaces', type => 1, cb_prefix_output => 'prefix_namespaces_output', message_multiple => 'All namespaces request metrics are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ { label => 'requests', nlabel => 'requests.total.persecond', set => { key_values => [ { name => 'requests', per_second => 1 } ], output_template => 'Requests: %.2f/s', perfdatas => [ { label => 'requests', template => '%.2f', min => 0, unit => 'requests/s' }, ], } }, ]; $self->{maps_counters}->{namespaces} = [ { label => 'requests-2xx', nlabel => 'namespace.requests.2xx.persecond', set => { key_values => [ { name => 'requests_2xx', per_second => 1 } ], output_template => 'Requests 2xx: %.2f/s', perfdatas => [ { label => 'requests_2xx', template => '%.2f', unit => 'requests/s', min => 0, label_extra_instance => 1 }, ], } }, { label => 'requests-3xx', nlabel => 'namespace.requests.2xx.persecond', set => { key_values => [ { name => 'requests_3xx', per_second => 1 } ], output_template => 'Requests 3xx: %.2f/s', perfdatas => [ { label => 'requests_3xx', template => '%.2f', unit => 'requests/s', min => 0, label_extra_instance => 1 }, ], } }, { label => 'requests-4xx', nlabel => 'namespace.requests.4xx.persecond', set => { key_values => [ { name => 'requests_4xx', per_second => 1 } ], output_template => 'Requests 4xx: %.2f/s', perfdatas => [ { label => 'requests_4xx', template => '%.2f', unit => 'requests/s', min => 0, label_extra_instance => 1 }, ], } }, { label => 'requests-5xx', nlabel => 'namespace.requests.5xx.persecond', set => { key_values => [ { name => 'requests_5xx', per_second => 1 } ], output_template => 'Requests 5xx: %.2f/s', perfdatas => [ { label => 'requests_5xx', template => '%.2f', unit => 'requests/s', min => 0, label_extra_instance => 1 }, ], } }, ]; } sub prefix_namespaces_output { my ($self, %options) = @_; return "Namespace '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'extra-filter:s@' => { name => 'extra_filter' }, 'metric-overload:s@' => { name => 'metric_overload' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{metrics} = { 'requests_total' => '^nginx_ingress_controller_nginx_process_requests_total$', 'requests' => '^nginx_ingress_controller_requests$', }; foreach my $metric (@{$self->{option_results}->{metric_overload}}) { next if ($metric !~ /(.*),(.*)/); $self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1})); } $self->{extra_filter} = ''; foreach my $filter (@{$self->{option_results}->{extra_filter}}) { $self->{extra_filter} .= ',' . $filter; } } sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = "prometheus_nginxingresscontroller_" . md5_hex($options{custom}->get_connection_info()) . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); $self->{global} = {}; my $results = $options{custom}->query( queries => [ 'label_replace({__name__=~"' . $self->{metrics}->{requests_total} . '",' . $self->{extra_filter} . '}, "__name__", "requests_total", "", "")' ] ); foreach my $result (@{$results}) { $self->{global}->{requests} = ${$result->{value}}[1]; } $self->{namespaces} = {}; $results = $options{custom}->query(queries => [ 'label_replace({__name__=~"' . $self->{metrics}->{requests} . '",' . $self->{extra_filter} . '}, "__name__", "requests", "", "")' ]); foreach my $result (@{$results}) { $self->{namespaces}->{$result->{metric}->{exported_namespace}}->{display} = $result->{metric}->{exported_namespace}; $self->{namespaces}->{$result->{metric}->{exported_namespace}}->{requests_2xx} += ${$result->{value}}[1] if ($result->{metric}->{status} =~ /^2/); $self->{namespaces}->{$result->{metric}->{exported_namespace}}->{requests_3xx} += ${$result->{value}}[1] if ($result->{metric}->{status} =~ /^3/); $self->{namespaces}->{$result->{metric}->{exported_namespace}}->{requests_4xx} += ${$result->{value}}[1] if ($result->{metric}->{status} =~ /^4/); $self->{namespaces}->{$result->{metric}->{exported_namespace}}->{requests_5xx} += ${$result->{value}}[1] if ($result->{metric}->{status} =~ /^5/); } } 1; __END__ =head1 MODE Check requests number. =over 8 =item B<--warning-*> Threshold warning. Can be: 'requests', 'requests-2xx', 'requests-3xx', 'requests-4xx', 'requests-5xx'. =item B<--critical-*> Threshold critical. Can be: 'requests', 'requests-2xx', 'requests-3xx', 'requests-4xx', 'requests-5xx'. =item B<--extra-filter> Add a PromQL filter (Can be multiple) Example : --extra-filter='name=~".*pretty.*"' =item B<--metric-overload> Overload default metrics name (Can be multiple) Example : --metric-overload='metric,^my_metric_name$' Default : - requests_total: ^nginx_ingress_controller_nginx_process_requests_total$ - requests: ^nginx_ingress_controller_requests$ =back =cut centreon-plugins-20220113/cloud/prometheus/direct/nginxingresscontroller/plugin.pm000066400000000000000000000027431417000230700304730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::prometheus::direct::nginxingresscontroller::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}} = ( 'connections' => 'cloud::prometheus::direct::nginxingresscontroller::mode::connections', 'requests' => 'cloud::prometheus::direct::nginxingresscontroller::mode::requests', ); $self->{custom_modes}{api} = 'cloud::prometheus::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Nginx Ingress Controller metrics through Prometheus server. =cut centreon-plugins-20220113/cloud/prometheus/exporters/000077500000000000000000000000001417000230700225705ustar00rootroot00000000000000centreon-plugins-20220113/cloud/prometheus/exporters/cadvisor/000077500000000000000000000000001417000230700244025ustar00rootroot00000000000000centreon-plugins-20220113/cloud/prometheus/exporters/cadvisor/mode/000077500000000000000000000000001417000230700253265ustar00rootroot00000000000000centreon-plugins-20220113/cloud/prometheus/exporters/cadvisor/mode/cpu.pm000066400000000000000000000167361417000230700264700ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::prometheus::exporters::cadvisor::mode::cpu; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'containers', type => 1, cb_prefix_output => 'prefix_containers_output', message_multiple => 'All containers CPU usage are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{containers} = [ { label => 'usage', nlabel => 'container.cpu.utilization.percentage', set => { key_values => [ { name => 'usage' }, { name => 'container' }, { name => 'pod' }, { name => 'perf' } ], output_template => 'Usage: %.2f %%', perfdatas => [ { label => 'usage', value => 'usage', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'perf' }, ], } }, { label => 'throttled', nlabel => 'container.cpu.throttled.percentage', set => { key_values => [ { name => 'throttled' }, { name => 'container' }, { name => 'pod' }, { name => 'perf' } ], output_template => 'Throttled: %.2f %%', perfdatas => [ { label => 'throttled', value => 'throttled', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'perf' }, ], } }, ]; } sub prefix_containers_output { my ($self, %options) = @_; return "Container '" . $options{instance_value}->{container} . "' [pod: " . $options{instance_value}->{pod} . "] CPU "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "cpu-attribute:s" => { name => 'cpu_attribute', default => 'cpu="total"' }, "container:s" => { name => 'container', default => 'container_name!~".*POD.*"' }, "pod:s" => { name => 'pod', default => 'pod_name=~".*"' }, "extra-filter:s@" => { name => 'extra_filter' }, "metric-overload:s@" => { name => 'metric_overload' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{metrics} = { 'throttled' => "^container_cpu_cfs_throttled_seconds_total.*", 'usage' => "^container_cpu_usage_seconds_total.*", }; foreach my $metric (@{$self->{option_results}->{metric_overload}}) { next if ($metric !~ /(.*),(.*)/); $self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1})); } $self->{labels} = {}; foreach my $label (('container', 'pod')) { if ($self->{option_results}->{$label} !~ /^(\w+)[!~=]+\".*\"$/) { $self->{output}->add_option_msg(short_msg => "Need to specify --" . $label . " option as a PromQL filter."); $self->{output}->option_exit(); } $self->{labels}->{$label} = $1; } $self->{extra_filter} = ''; foreach my $filter (@{$self->{option_results}->{extra_filter}}) { $self->{extra_filter} .= ',' . $filter; } $self->{prom_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{prom_step} = defined($self->{option_results}->{step}) ? $self->{option_results}->{step} : "5m"; } sub manage_selection { my ($self, %options) = @_; $self->{containers} = {}; my $results = $options{custom}->query_range( queries => [ 'label_replace((irate({__name__=~"' . $self->{metrics}->{usage} . '",' . $self->{option_results}->{cpu_attribute} . ',' . $self->{option_results}->{container} . ',' . $self->{option_results}->{pod} . $self->{extra_filter} . '}[' . $self->{prom_step} . '])) * 100, "__name__", "usage", "", "")', 'label_replace((irate({__name__=~"' . $self->{metrics}->{throttled} . '",' . $self->{option_results}->{container} . ',' . $self->{option_results}->{pod} . $self->{extra_filter} . '}[' . $self->{prom_step} . '])) * 100, "__name__", "throttled", "", "")' ], timeframe => $self->{prom_timeframe}, step => $self->{prom_step} ); foreach my $result (@{$results}) { next if (!defined($result->{metric}->{$self->{labels}->{pod}}) || !defined($result->{metric}->{$self->{labels}->{container}})); my $average = $options{custom}->compute(aggregation => 'average', values => $result->{values}); $self->{containers}->{$result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}}->{container} = $result->{metric}->{$self->{labels}->{container}}; $self->{containers}->{$result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}}->{pod} = $result->{metric}->{$self->{labels}->{pod}}; $self->{containers}->{$result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}}->{perf} = $result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}; $self->{containers}->{$result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}}->{$result->{metric}->{__name__}} = $average; } if (scalar(keys %{$self->{containers}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No containers found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check containers CPU usage and throttled. =over 8 =item B<--cpu-attribute> Set the cpu attribute to match element (Must be a PromQL filter, Default: 'cpu="total"') =item B<--container> Filter on a specific container (Must be a PromQL filter, Default: 'container_name!~".*POD.*"') =item B<--pod> Filter on a specific pod (Must be a PromQL filter, Default: 'pod_name=~".*"') =item B<--warning-*> Threshold warning. Can be: 'usage', 'throttled'. =item B<--critical-*> Threshold critical. Can be: 'usage', 'throttled'. =item B<--extra-filter> Add a PromQL filter (Can be multiple) Example : --extra-filter='name=~".*pretty.*"' =item B<--metric-overload> Overload default metrics name (Can be multiple) Example : --metric-overload='metric,^my_metric_name$' Default : - throttled: ^container_cpu_cfs_throttled_seconds_total.* - usage: ^container_cpu_usage_seconds_total.* =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='throttled' =back =cut centreon-plugins-20220113/cloud/prometheus/exporters/cadvisor/mode/listcontainers.pm000066400000000000000000000121051417000230700307240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::prometheus::exporters::cadvisor::mode::listcontainers; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "container:s" => { name => 'container', default => 'container_name!~".*POD.*"' }, "pod:s" => { name => 'pod', default => 'pod_name=~".*"' }, "namespace:s" => { name => 'namespace', default => 'namespace=~".*"' }, "extra-filter:s@" => { name => 'extra_filter' }, "metric-overload:s@" => { name => 'metric_overload' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); $self->{metrics} = { 'last_seen' => '^container_last_seen$', }; foreach my $metric (@{$self->{option_results}->{metric_overload}}) { next if ($metric !~ /(.*),(.*)/); $self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1})); } $self->{labels} = {}; foreach my $label (('container', 'pod', 'namespace')) { if ($self->{option_results}->{$label} !~ /^(\w+)[!~=]+\".*\"$/) { $self->{output}->add_option_msg(short_msg => "Need to specify --" . $label . " option as a PromQL filter."); $self->{output}->option_exit(); } $self->{labels}->{$label} = $1; } $self->{extra_filter} = ''; foreach my $filter (@{$self->{option_results}->{extra_filter}}) { $self->{extra_filter} .= ',' . $filter; } } sub manage_selection { my ($self, %options) = @_; $self->{containers} = $options{custom}->query(queries => [ '{__name__=~"' . $self->{metrics}->{last_seen} . '",' . $self->{option_results}->{container} . ',' . $self->{option_results}->{pod} . ',' . $self->{option_results}->{namespace} . $self->{extra_filter} . '}' ]); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $container (@{$self->{containers}}) { next if (!defined($container->{metric}->{name})); $self->{output}->output_add(long_msg => sprintf("[container_name = %s][pod_name = %s][namespace = %s]", $container->{metric}->{$self->{labels}->{container}}, $container->{metric}->{$self->{labels}->{pod}}, $container->{metric}->{$self->{labels}->{namespace}})); } $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 => ['container_name', 'pod_name', 'namespace']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $container (@{$self->{containers}}) { $self->{output}->add_disco_entry( container_name => $container->{metric}->{$self->{labels}->{container}}, pod_name => $container->{metric}->{$self->{labels}->{pod}}, namespace => $container->{metric}->{$self->{labels}->{namespace}}, ); } } 1; __END__ =head1 MODE List containers. =over 8 =item B<--container> Filter on a specific container (Must be a PromQL filter, Default: 'container_name!~".*POD.*"') =item B<--pod> Filter on a specific pod (Must be a PromQL filter, Default: 'pod_name=~".*"') =item B<--namespace> Filter on a specific namespace (Must be a PromQL filter, Default: 'namespace=~".*"') =item B<--extra-filter> Add a PromQL filter (Can be multiple) Example : --extra-filter='name=~".*pretty.*"' =item B<--metric-overload> Overload default metrics name (Can be multiple, metric can be 'last_seen') Example : --metric-overload='metric,^my_metric_name$' =back =cut centreon-plugins-20220113/cloud/prometheus/exporters/cadvisor/mode/load.pm000066400000000000000000000136441417000230700266130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::prometheus::exporters::cadvisor::mode::load; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'containers', type => 1, cb_prefix_output => 'prefix_containers_output', message_multiple => 'All containers load are ok' }, ]; $self->{maps_counters}->{containers} = [ { label => 'load', nlabel => 'container.load.count', set => { key_values => [ { name => 'load' }, { name => 'container' }, { name => 'pod' }, { name => 'perf' } ], output_template => 'Load: %.2f', output_change_bytes => 1, perfdatas => [ { label => 'load', value => 'load', template => '%.2f', min => 0, label_extra_instance => 1, instance_use => 'perf' }, ], } }, ]; } sub prefix_containers_output { my ($self, %options) = @_; return "Container '" . $options{instance_value}->{container} . "' [pod: " . $options{instance_value}->{pod} . "] "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "container:s" => { name => 'container', default => 'container_name!~".*POD.*"' }, "pod:s" => { name => 'pod', default => 'pod_name=~".*"' }, "extra-filter:s@" => { name => 'extra_filter' }, "metric-overload:s@" => { name => 'metric_overload' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{metrics} = { 'load' => '^container_cpu_load_average_10s$', }; foreach my $metric (@{$self->{option_results}->{metric_overload}}) { next if ($metric !~ /(.*),(.*)/); $self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1})); } $self->{labels} = {}; foreach my $label (('container', 'pod')) { if ($self->{option_results}->{$label} !~ /^(\w+)[!~=]+\".*\"$/) { $self->{output}->add_option_msg(short_msg => "Need to specify --" . $label . " option as a PromQL filter."); $self->{output}->option_exit(); } $self->{labels}->{$label} = $1; } $self->{extra_filter} = ''; foreach my $filter (@{$self->{option_results}->{extra_filter}}) { $self->{extra_filter} .= ',' . $filter; } $self->{prom_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{prom_step} = defined($self->{option_results}->{step}) ? $self->{option_results}->{step} : "1m"; } sub manage_selection { my ($self, %options) = @_; $self->{containers} = {}; my $results = $options{custom}->query_range( queries => [ 'label_replace({__name__=~"' . $self->{metrics}->{load} . '",' . $self->{option_results}->{container} . ',' . $self->{option_results}->{pod} . $self->{extra_filter} . '}, "__name__", "load", "", "")' ], timeframe => $self->{prom_timeframe}, step => $self->{prom_step} ); foreach my $result (@{$results}) { next if (!defined($result->{metric}->{$self->{labels}->{pod}}) || !defined($result->{metric}->{$self->{labels}->{container}})); my $average = $options{custom}->compute(aggregation => 'average', values => $result->{values}); $self->{containers}->{$result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}}->{container} = $result->{metric}->{$self->{labels}->{container}}; $self->{containers}->{$result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}}->{pod} = $result->{metric}->{$self->{labels}->{pod}}; $self->{containers}->{$result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}}->{perf} = $result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}; $self->{containers}->{$result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}}->{$result->{metric}->{__name__}} = $average; } if (scalar(keys %{$self->{containers}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No containers found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check containers load. =over 8 =item B<--container> Filter on a specific container (Must be a PromQL filter, Default: 'container_name!~".*POD.*"') =item B<--pod> Filter on a specific pod (Must be a PromQL filter, Default: 'pod_name=~".*"') =item B<--warning-load> Threshold warning. =item B<--critical-load> Threshold critical. =item B<--extra-filter> Add a PromQL filter (Can be multiple) Example : --extra-filter='name=~".*pretty.*"' =item B<--metric-overload> Overload default metrics name (Can be multiple) Example : --metric-overload='metric,^my_metric_name$' Default : - load: ^container_cpu_load_average_10s$ =back =cut centreon-plugins-20220113/cloud/prometheus/exporters/cadvisor/mode/memory.pm000066400000000000000000000325611417000230700272030ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::prometheus::exporters::cadvisor::mode::memory; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_usage_perfdata { my ($self, %options) = @_; my $label = $self->{result_values}->{perfdata}; my $value_perf = $self->{result_values}->{used}; my %total_options = (); if ($self->{result_values}->{total} > 0 && $self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } $self->{output}->perfdata_add( label => $label, unit => 'B', nlabel => 'memory.' . $label . '.bytes', 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}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, ); } sub custom_usage_threshold { my ($self, %options) = @_; return 'ok' if ($self->{result_values}->{total} <= 0 && $self->{instance_mode}->{option_results}->{units} eq '%'); my ($exit, $threshold_value); $threshold_value = $self->{result_values}->{used}; if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; } $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{result_values}->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{result_values}->{thlabel}, exit_litteral => 'warning' } ]); return $exit; } sub custom_usage_output { my ($self, %options) = @_; my $msg; my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); if ($self->{result_values}->{total} <= 0) { $msg = sprintf("%s: %s (unlimited)", ucfirst($self->{result_values}->{label}), $total_used_value . " " . $total_used_unit); } else { my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); $msg = sprintf("%s: %s (%.2f%% of %s)", ucfirst($self->{result_values}->{label}), $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}, $total_size_value . " " . $total_size_unit); } return $msg; } sub custom_usage_calc { my ($self, %options) = @_; $self->{result_values}->{label} = $options{extra_options}->{label_ref}; $self->{result_values}->{perfdata} = $options{extra_options}->{perfdata_ref}; $self->{result_values}->{container} = $options{new_datas}->{$self->{instance} . '_container'}; $self->{result_values}->{pod} = $options{new_datas}->{$self->{instance} . '_pod'}; $self->{result_values}->{perf} = $options{new_datas}->{$self->{instance} . '_perf'}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_limits'}; $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_' . $self->{result_values}->{label}}; return 0 if ($self->{result_values}->{total} == 0); $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'containers', type => 1, cb_prefix_output => 'prefix_containers_output', message_multiple => 'All containers memory usage are ok' }, ]; $self->{maps_counters}->{containers} = [ { label => 'usage', set => { key_values => [ { name => 'limits' }, { name => 'usage' }, { name => 'container' }, { name => 'pod' }, { name => 'perf' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { label_ref => 'usage', perfdata_ref => 'used' }, 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 => 'working', set => { key_values => [ { name => 'limits' }, { name => 'working' }, { name => 'container' }, { name => 'pod' }, { name => 'perf' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { label_ref => 'working', perfdata_ref => 'working' }, 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 => 'cache', nlabel => 'cache.usage.bytes', set => { key_values => [ { name => 'cache' }, { name => 'container' }, { name => 'pod' }, { name => 'perf' } ], output_template => 'Cache: %.2f %s', output_change_bytes => 1, perfdatas => [ { label => 'cache', value => 'cache', template => '%s', min => 0, unit => 'B', label_extra_instance => 1, instance_use => 'perf' }, ], } }, { label => 'rss', nlabel => 'rss.usage.bytes', set => { key_values => [ { name => 'rss' }, { name => 'container' }, { name => 'pod' }, { name => 'perf' } ], output_template => 'Rss: %.2f %s', output_change_bytes => 1, perfdatas => [ { label => 'rss', value => 'rss', template => '%s', min => 0, unit => 'B', label_extra_instance => 1, instance_use => 'perf' }, ], } }, { label => 'swap', nlabel => 'swap.usage.bytes', set => { key_values => [ { name => 'swap' }, { name => 'container' }, { name => 'pod' }, { name => 'perf' } ], output_template => 'Swap: %.2f %s', output_change_bytes => 1, perfdatas => [ { label => 'swap', value => 'swap', template => '%s', min => 0, unit => 'B', label_extra_instance => 1, instance_use => 'perf' }, ], } }, ]; } sub prefix_containers_output { my ($self, %options) = @_; return "Container '" . $options{instance_value}->{container} . "' [pod: " . $options{instance_value}->{pod} . "] Memory "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "container:s" => { name => 'container', default => 'container_name!~".*POD.*"' }, "pod:s" => { name => 'pod', default => 'pod_name=~".*"' }, "extra-filter:s@" => { name => 'extra_filter' }, "units:s" => { name => 'units', default => '%' }, "metric-overload:s@" => { name => 'metric_overload' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{metrics} = { 'limits' => "^container_spec_memory_limit_bytes.*", 'usage' => "^container_memory_usage_bytes.*", 'working' => "^container_memory_working_set_bytes.*", 'cache' => "^container_memory_cache.*", 'rss' => "^container_memory_rss.*", 'swap' => "^container_memory_swap.*", }; foreach my $metric (@{$self->{option_results}->{metric_overload}}) { next if ($metric !~ /(.*),(.*)/); $self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1})); } $self->{labels} = {}; foreach my $label (('container', 'pod')) { if ($self->{option_results}->{$label} !~ /^(\w+)[!~=]+\".*\"$/) { $self->{output}->add_option_msg(short_msg => "Need to specify --" . $label . " option as a PromQL filter."); $self->{output}->option_exit(); } $self->{labels}->{$label} = $1; } $self->{extra_filter} = ''; foreach my $filter (@{$self->{option_results}->{extra_filter}}) { $self->{extra_filter} .= ',' . $filter; } } sub manage_selection { my ($self, %options) = @_; $self->{containers} = {}; my $results = $options{custom}->query( queries => [ 'label_replace({__name__=~"' . $self->{metrics}->{usage} . '",' . $self->{option_results}->{container} . ',' . $self->{option_results}->{pod} . $self->{extra_filter} . '}, "__name__", "usage", "", "")', 'label_replace({__name__=~"' . $self->{metrics}->{limits} . '",' . $self->{option_results}->{container} . ',' . $self->{option_results}->{pod} . $self->{extra_filter} . '}, "__name__", "limits", "", "")', 'label_replace({__name__=~"' . $self->{metrics}->{working} . '",' . $self->{option_results}->{container} . ',' . $self->{option_results}->{pod} . $self->{extra_filter} . '}, "__name__", "working", "", "")', 'label_replace({__name__=~"' . $self->{metrics}->{cache} . '",' . $self->{option_results}->{container} . ',' . $self->{option_results}->{pod} . $self->{extra_filter} . '}, "__name__", "cache", "", "")', 'label_replace({__name__=~"' . $self->{metrics}->{rss} . '",' . $self->{option_results}->{container} . ',' . $self->{option_results}->{pod} . $self->{extra_filter} . '}, "__name__", "rss", "", "")', 'label_replace({__name__=~"' . $self->{metrics}->{swap} . '",' . $self->{option_results}->{container} . ',' . $self->{option_results}->{pod} . $self->{extra_filter} . '}, "__name__", "swap", "", "")' ] ); foreach my $result (@{$results}) { next if (!defined($result->{metric}->{$self->{labels}->{pod}}) || !defined($result->{metric}->{$self->{labels}->{container}})); $self->{containers}->{$result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}}->{container} = $result->{metric}->{$self->{labels}->{container}}; $self->{containers}->{$result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}}->{pod} = $result->{metric}->{$self->{labels}->{pod}}; $self->{containers}->{$result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}}->{perf} = $result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}; $self->{containers}->{$result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}}->{$result->{metric}->{__name__}} = ${$result->{value}}[1]; } if (scalar(keys %{$self->{containers}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No containers found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check containers memory usage. =over 8 =item B<--container> Filter on a specific container (Must be a PromQL filter, Default: 'container_name!~".*POD.*"') =item B<--pod> Filter on a specific pod (Must be a PromQL filter, Default: 'pod_name=~".*"') =item B<--warning-*> Threshold warning. Can be: 'usage', 'working', 'cache' (B), 'rss' (B), 'swap' (B). =item B<--critical-*> Threshold critical. Can be: 'usage', 'working', 'cache' (B), 'rss' (B), 'swap' (B). =item B<--units> Units of thresholds (Default: '%') ('%', 'B'). =item B<--extra-filter> Add a PromQL filter (Can be multiple) Example : --extra-filter='name=~".*pretty.*"' =item B<--metric-overload> Overload default metrics name (Can be multiple) Example : --metric-overload='metric,^my_metric_name$' Default : - limits: ^container_spec_memory_limit_bytes.* - usage: ^container_memory_usage_bytes.* - working: ^container_memory_working_set_bytes.* - cache: ^container_memory_cache.* - rss: ^container_memory_rss.* - swap: ^container_memory_swap.* =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='usage' =back =cut centreon-plugins-20220113/cloud/prometheus/exporters/cadvisor/mode/storage.pm000066400000000000000000000260611417000230700273350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::prometheus::exporters::cadvisor::mode::storage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_usage_perfdata { my ($self, %options) = @_; my $label = 'used'; my $value_perf = $self->{result_values}->{used}; if (defined($self->{instance_mode}->{option_results}->{free})) { $label = 'free'; $value_perf = $self->{result_values}->{free}; } my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } $self->{output}->perfdata_add( label => $label, unit => 'B', nlabel => 'storage.space.usage.bytes', 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}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, ); } sub custom_usage_threshold { my ($self, %options) = @_; my ($exit, $threshold_value); $threshold_value = $self->{result_values}->{used}; $threshold_value = $self->{result_values}->{free} if (defined($self->{instance_mode}->{option_results}->{free})); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; $threshold_value = $self->{result_values}->{prct_free} if (defined($self->{instance_mode}->{option_results}->{free})); } $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel}, exit_litteral => 'warning' } ]); return $exit; } sub custom_usage_output { my ($self, %options) = @_; my ($total_limit_value, $total_limit_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 Limit: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", $total_limit_value . " " . $total_limit_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}->{label} = $self->{instance}; $self->{result_values}->{container} = $options{new_datas}->{$self->{instance} . '_container'}; $self->{result_values}->{pod} = $options{new_datas}->{$self->{instance} . '_pod'}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_limit'}; $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}->{total} > 0) ? $self->{result_values}->{used} * 100 / $self->{result_values}->{total} : 0; $self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used}; # limit to 100. Better output. if ($self->{result_values}->{prct_used} > 100) { $self->{result_values}->{free} = 0; $self->{result_values}->{prct_used} = 100; $self->{result_values}->{prct_free} = 0; } return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'containers', type => 3, cb_prefix_output => 'prefix_containers_output', cb_long_output => 'long_output', message_multiple => 'All containers storages usage are ok', indent_long_output => ' ', group => [ { name => 'storage', display_long => 1, cb_prefix_output => 'prefix_storage_output', message_multiple => 'All storages usage are ok', type => 1, skipped_code => { -10 => 1 } }, ] } ]; $self->{maps_counters}->{storage} = [ { label => 'usage', set => { key_values => [ { name => 'used' }, { name => 'limit' } ], 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 prefix_container_output { my ($self, %options) = @_; return "Container '" . $options{instance_value}->{container} . "' [pod: " . $options{instance_value}->{pod} . "] "; } sub long_output { my ($self, %options) = @_; return "Checking container '" . $options{instance_value}->{container} . "' [pod: " . $options{instance_value}->{pod} . "]"; } sub prefix_storage_output { my ($self, %options) = @_; return "Storage '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "container:s" => { name => 'container', default => 'container_name!~".*POD.*"' }, "pod:s" => { name => 'pod', default => 'pod_name=~".*"' }, "device:s" => { name => 'device', default => 'device=~".*"' }, "extra-filter:s@" => { name => 'extra_filter' }, "units:s" => { name => 'units', default => '%' }, "free" => { name => 'free' }, "metric-overload:s@" => { name => 'metric_overload' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{metrics} = { 'used' => "^container_fs_usage_bytes.*", 'limit' => "^container_fs_limit_bytes.*", }; foreach my $metric (@{$self->{option_results}->{metric_overload}}) { next if ($metric !~ /(.*),(.*)/); $self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1})); } $self->{labels} = {}; foreach my $label (('container', 'pod', 'device')) { if ($self->{option_results}->{$label} !~ /^(\w+)[!~=]+\".*\"$/) { $self->{output}->add_option_msg(short_msg => "Need to specify --" . $label . " option as a PromQL filter."); $self->{output}->option_exit(); } $self->{labels}->{$label} = $1; } $self->{extra_filter} = ''; foreach my $filter (@{$self->{option_results}->{extra_filter}}) { $self->{extra_filter} .= ',' . $filter; } } sub manage_selection { my ($self, %options) = @_; $self->{containers} = {}; my $results = $options{custom}->query( queries => [ 'label_replace({__name__=~"' . $self->{metrics}->{used} . '",' . $self->{option_results}->{container} . ',' . $self->{option_results}->{pod} . ',' . $self->{option_results}->{device} . $self->{extra_filter} . '}, "__name__", "used", "", "")', 'label_replace({__name__=~"' . $self->{metrics}->{limit} . '",' . $self->{option_results}->{container} . ',' . $self->{option_results}->{pod} . ',' . $self->{option_results}->{device} . $self->{extra_filter} . '}, "__name__", "limit", "", "")' ] ); foreach my $result (@{$results}) { next if (!defined($result->{metric}->{$self->{labels}->{pod}}) || !defined($result->{metric}->{$self->{labels}->{container}})); $self->{containers}->{$result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}}->{display} = $result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}; $self->{containers}->{$result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}}->{container} = $result->{metric}->{$self->{labels}->{container}}; $self->{containers}->{$result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}}->{pod} = $result->{metric}->{$self->{labels}->{pod}}; $self->{containers}->{$result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}}->{storage}->{$result->{metric}->{$self->{labels}->{device}}}->{display} = $result->{metric}->{$self->{labels}->{device}}; $self->{containers}->{$result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}}->{storage}->{$result->{metric}->{$self->{labels}->{device}}}->{$result->{metric}->{__name__}} = ${$result->{value}}[1]; } if (scalar(keys %{$self->{containers}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No containers found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check containers storages usage. =over 8 =item B<--container> Filter on a specific container (Must be a PromQL filter, Default: 'container_name!~".*POD.*"') =item B<--pod> Filter on a specific pod (Must be a PromQL filter, Default: 'pod_name=~".*"') =item B<--device> Filter on a specific device (Must be a PromQL filter, Default: 'device=~".*"') =item B<--units> Units of thresholds (Default: '%') ('%', 'B'). =item B<--free> Thresholds are on free space left. =item B<--warning-usage> Threshold warning. =item B<--critical-usage> Threshold critical. =item B<--extra-filter> Add a PromQL filter (Can be multiple) Example : --extra-filter='name=~".*pretty.*"' =item B<--metric-overload> Overload default metrics name (Can be multiple) Example : --metric-overload='metric,^my_metric_name$' Default : - used: ^container_fs_usage_bytes.* - limit: ^container_fs_limit_bytes.* =back =cut centreon-plugins-20220113/cloud/prometheus/exporters/cadvisor/mode/taskstate.pm000066400000000000000000000202141417000230700276660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::prometheus::exporters::cadvisor::mode::taskstate; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'containers', type => 1, cb_prefix_output => 'prefix_containers_output', message_multiple => 'All containers tasks states are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{containers} = [ { label => 'sleeping', nlabel => 'tasks.sleeping.count', set => { key_values => [ { name => 'sleeping' }, { name => 'container' }, { name => 'pod' }, { name => 'perf' } ], output_template => 'Sleeping: %d', output_change_bytes => 1, perfdatas => [ { label => 'tasks_sleeping', value => 'sleeping', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'perf' }, ], } }, { label => 'running', nlabel => 'tasks.running.count', set => { key_values => [ { name => 'running' }, { name => 'container' }, { name => 'pod' }, { name => 'perf' } ], output_template => 'Running: %d', output_change_bytes => 1, perfdatas => [ { label => 'tasks_running', value => 'running', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'perf' }, ], } }, { label => 'stopped', nlabel => 'tasks.stopped.count', set => { key_values => [ { name => 'stopped' }, { name => 'container' }, { name => 'pod' }, { name => 'perf' } ], output_template => 'Stopped: %d', output_change_bytes => 1, perfdatas => [ { label => 'tasks_stopped', value => 'stopped', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'perf' }, ], } }, { label => 'uninterruptible', nlabel => 'tasks.uninterruptible.count', set => { key_values => [ { name => 'uninterruptible' }, { name => 'container' }, { name => 'pod' }, { name => 'perf' } ], output_template => 'Uninterruptible: %d', output_change_bytes => 1, perfdatas => [ { label => 'tasks_uninterruptible', value => 'uninterruptible', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'perf' }, ], } }, { label => 'iowaiting', nlabel => 'tasks.iowaiting.count', set => { key_values => [ { name => 'iowaiting' }, { name => 'container' }, { name => 'pod' }, { name => 'perf' } ], output_template => 'Iowaiting: %d', output_change_bytes => 1, perfdatas => [ { label => 'tasks_iowaiting', value => 'iowaiting', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'perf' }, ], } }, ]; } sub prefix_containers_output { my ($self, %options) = @_; return "Container '" . $options{instance_value}->{container} . "' [pod: " . $options{instance_value}->{pod} . "] Tasks "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "container:s" => { name => 'container', default => 'container_name!~".*POD.*"' }, "pod:s" => { name => 'pod', default => 'pod_name=~".*"' }, "state:s" => { name => 'state', default => 'state=~".*"' }, "extra-filter:s@" => { name => 'extra_filter' }, "metric-overload:s@" => { name => 'metric_overload' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{metrics} = { 'tasks_state' => '^container_tasks_state$', }; foreach my $metric (@{$self->{option_results}->{metric_overload}}) { next if ($metric !~ /(.*),(.*)/); $self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1})); } $self->{labels} = {}; foreach my $label (('container', 'pod', 'state')) { if ($self->{option_results}->{$label} !~ /^(\w+)[!~=]+\".*\"$/) { $self->{output}->add_option_msg(short_msg => "Need to specify --" . $label . " option as a PromQL filter."); $self->{output}->option_exit(); } $self->{labels}->{$label} = $1; } $self->{extra_filter} = ''; foreach my $filter (@{$self->{option_results}->{extra_filter}}) { $self->{extra_filter} .= ',' . $filter; } } sub manage_selection { my ($self, %options) = @_; $self->{containers} = {}; my $results = $options{custom}->query( queries => [ 'label_replace({__name__=~"' . $self->{metrics}->{tasks_state} . '",' . $self->{option_results}->{container} . ',' . $self->{option_results}->{pod} . ',' . $self->{option_results}->{state} . $self->{extra_filter} . '}, "__name__", "tasks_state", "", "")' ] ); foreach my $result (@{$results}) { next if (!defined($result->{metric}->{$self->{labels}->{pod}}) || !defined($result->{metric}->{$self->{labels}->{container}})); $self->{containers}->{$result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}}->{container} = $result->{metric}->{$self->{labels}->{container}}; $self->{containers}->{$result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}}->{pod} = $result->{metric}->{$self->{labels}->{pod}}; $self->{containers}->{$result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}}->{perf} = $result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}; $self->{containers}->{$result->{metric}->{$self->{labels}->{pod}} . "_" . $result->{metric}->{$self->{labels}->{container}}}->{$result->{metric}->{$self->{labels}->{state}}} = ${$result->{value}}[1]; } if (scalar(keys %{$self->{containers}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No containers found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check containers number of tasks in given state. =over 8 =item B<--container> Filter on a specific container (Must be a PromQL filter, Default: 'container_name!~".*POD.*"') =item B<--pod> Filter on a specific pod (Must be a PromQL filter, Default: 'pod_name=~".*"') =item B<--state> Filter on a specific state (Must be a PromQL filter, Default: 'state=~".*"') =item B<--warning-*> Threshold warning. Can be: 'sleeping', 'running', 'stopped', 'uninterruptible', 'iowaiting'. =item B<--critical-*> Threshold critical. Can be: 'sleeping', 'running', 'stopped', 'uninterruptible', 'iowaiting'. =item B<--extra-filter> Add a PromQL filter (Can be multiple) Example : --extra-filter='name=~".*pretty.*"' =item B<--metric-overload> Overload default metrics name (Can be multiple) Example : --metric-overload='metric,^my_metric_name$' Default : - tasks_state: ^container_tasks_state$ =back =cut centreon-plugins-20220113/cloud/prometheus/exporters/cadvisor/plugin.pm000066400000000000000000000034261417000230700262430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::prometheus::exporters::cadvisor::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}} = ( 'cpu' => 'cloud::prometheus::exporters::cadvisor::mode::cpu', 'list-containers' => 'cloud::prometheus::exporters::cadvisor::mode::listcontainers', 'load' => 'cloud::prometheus::exporters::cadvisor::mode::load', 'memory' => 'cloud::prometheus::exporters::cadvisor::mode::memory', 'storage' => 'cloud::prometheus::exporters::cadvisor::mode::storage', 'task-state' => 'cloud::prometheus::exporters::cadvisor::mode::taskstate', ); $self->{custom_modes}{api} = 'cloud::prometheus::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check cAdvisor metrics through Prometheus server. =cut centreon-plugins-20220113/cloud/prometheus/exporters/nodeexporter/000077500000000000000000000000001417000230700253065ustar00rootroot00000000000000centreon-plugins-20220113/cloud/prometheus/exporters/nodeexporter/mode/000077500000000000000000000000001417000230700262325ustar00rootroot00000000000000centreon-plugins-20220113/cloud/prometheus/exporters/nodeexporter/mode/cpu.pm000066400000000000000000000160051417000230700273610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::prometheus::exporters::nodeexporter::mode::cpu; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'nodes', type => 3, cb_prefix_output => 'prefix_node_output', cb_long_output => 'node_long_output', message_multiple => 'All nodes usage are ok', indent_long_output => ' ', group => [ { name => 'global_cpu', cb_prefix_output => 'prefix_global_cpu_output', type => 0, skipped_code => { -10 => 1 } }, { name => 'cpu', display_long => 1, cb_prefix_output => 'prefix_cpu_output', message_multiple => 'All CPUs usage are ok', type => 1, skipped_code => { -10 => 1 } }, ] } ]; $self->{maps_counters}->{global_cpu} = [ { label => 'node-usage', nlabel => 'node.cpu.utilization.percentage', set => { key_values => [ { name => 'node_average' } ], output_template => '%.2f %%', perfdatas => [ { label => 'node', value => 'node_average', template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1 }, ], } }, ]; $self->{maps_counters}->{cpu} = [ { label => 'cpu-usage', nlabel => 'core.cpu.utilization.percentage', set => { key_values => [ { name => 'cpu_usage' }, { name => 'display' } ], output_template => 'Usage: %.2f %%', perfdatas => [ { label => 'cpu', value => 'cpu_usage', template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1 }, ], } }, ]; } sub prefix_node_output { my ($self, %options) = @_; return "Node '" . $options{instance_value}->{display} . "' "; } sub node_long_output { my ($self, %options) = @_; return "Checking node '" . $options{instance_value}->{display} . "'"; } sub prefix_global_cpu_output { my ($self, %options) = @_; return "CPU Average Usage: "; } 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; $options{options}->add_options(arguments => { "instance:s" => { name => 'instance', default => 'instance=~".*"' }, "cpu:s" => { name => 'cpu', default => 'cpu=~".*"' }, "extra-filter:s@" => { name => 'extra_filter' }, "metric-overload:s@" => { name => 'metric_overload' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{metrics} = { 'cpu' => "^node_cpu.*", }; foreach my $metric (@{$self->{option_results}->{metric_overload}}) { next if ($metric !~ /(.*),(.*)/); $self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1})); } $self->{labels} = {}; foreach my $label (('instance', 'cpu')) { if ($self->{option_results}->{$label} !~ /^(\w+)[!~=]+\".*\"$/) { $self->{output}->add_option_msg(short_msg => "Need to specify --" . $label . " option as a PromQL filter."); $self->{output}->option_exit(); } $self->{labels}->{$label} = $1; } $self->{extra_filter} = ''; foreach my $filter (@{$self->{option_results}->{extra_filter}}) { $self->{extra_filter} .= ',' . $filter; } $self->{prom_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{prom_step} = defined($self->{option_results}->{step}) ? $self->{option_results}->{step} : "5m"; } sub manage_selection { my ($self, %options) = @_; $self->{nodes} = {}; my $results = $options{custom}->query_range( queries => [ '(1 - irate({__name__=~"' . $self->{metrics}->{cpu} . '",' . 'mode="idle",' . $self->{option_results}->{instance} . ',' . $self->{option_results}->{cpu} . $self->{extra_filter} . '}[' . $self->{prom_step} . '])) * 100' ], timeframe => $self->{prom_timeframe}, step => $self->{prom_step} ); foreach my $result (@{$results}) { my $average = $options{custom}->compute(aggregation => 'average', values => $result->{values}); $self->{nodes}->{$result->{metric}->{$self->{labels}->{instance}}}->{display} = $result->{metric}->{$self->{labels}->{instance}}, $self->{nodes}->{$result->{metric}->{$self->{labels}->{instance}}}->{global_cpu}->{node_average} += $average; $self->{nodes}->{$result->{metric}->{$self->{labels}->{instance}}}->{cpu}->{$result->{metric}->{$self->{labels}->{cpu}}}->{display} = $result->{metric}->{$self->{labels}->{cpu}}; $self->{nodes}->{$result->{metric}->{$self->{labels}->{instance}}}->{cpu}->{$result->{metric}->{$self->{labels}->{cpu}}}->{cpu_usage} = $average; } foreach my $node (keys %{$self->{nodes}}) { $self->{nodes}->{$node}->{global_cpu}->{node_average} /= scalar(keys %{$self->{nodes}->{$node}->{cpu}}); } if (scalar(keys %{$self->{nodes}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No nodes found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check CPU usage for nodes and each of their cores. =over 8 =item B<--instance> Filter on a specific instance (Must be a PromQL filter, Default: 'instance=~".*"') =item B<--cpu> Filter on a specific cpu (Must be a PromQL filter, Default: 'cpu=~".*"') =item B<--warning-*> Threshold warning. Can be: 'node-usage', 'cpu-usage'. =item B<--critical-*> Threshold critical. Can be: 'node-usage', 'cpu-usage'. =item B<--extra-filter> Add a PromQL filter (Can be multiple) Example : --extra-filter='name=~".*pretty.*"' =item B<--metric-overload> Overload default metrics name (Can be multiple) Example : --metric-overload='metric,^my_metric_name$' Default : - cpu: ^node_cpu.* =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='node' =back =cut centreon-plugins-20220113/cloud/prometheus/exporters/nodeexporter/mode/cpudetailed.pm000066400000000000000000000337731417000230700310700ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::prometheus::exporters::nodeexporter::mode::cpudetailed; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'nodes', type => 3, cb_prefix_output => 'prefix_node_output', cb_long_output => 'node_long_output', message_multiple => 'All nodes usage are ok', indent_long_output => ' ', group => [ { name => 'global_cpu', cb_prefix_output => 'prefix_global_cpu_output', type => 0, skipped_code => { -10 => 1 } }, { name => 'cpu', display_long => 1, cb_prefix_output => 'prefix_cpu_output', message_multiple => 'All CPUs usage are ok', type => 1, skipped_code => { -10 => 1 } }, ] } ]; $self->{maps_counters}->{global_cpu} = [ { label => 'node-wait', nlabel => 'node.cpu.wait.utilization.percentage', set => { key_values => [ { name => 'iowait' } ], output_template => 'Wait: %.2f %%', perfdatas => [ { label => 'wait', value => 'iowait', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 }, ], } }, { label => 'node-user', nlabel => 'node.cpu.user.utilization.percentage', set => { key_values => [ { name => 'user' } ], output_template => 'User: %.2f %%', perfdatas => [ { label => 'user', value => 'user', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 }, ], } }, { label => 'node-softirq', nlabel => 'node.cpu.softirq.utilization.percentage', set => { key_values => [ { name => 'softirq' } ], output_template => 'Soft Irq: %.2f %%', perfdatas => [ { label => 'softirq', value => 'softirq', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 }, ], } }, { label => 'node-interrupt', nlabel => 'node.cpu.interrupt.utilization.percentage', set => { key_values => [ { name => 'irq' } ], output_template => 'Interrupt: %.2f %%', perfdatas => [ { label => 'interrupt', value => 'irq', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 }, ], } }, { label => 'node-idle', nlabel => 'node.cpu.idle.utilization.percentage', set => { key_values => [ { name => 'idle' } ], output_template => 'Idle: %.2f %%', perfdatas => [ { label => 'idle', value => 'idle', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 }, ], } }, { label => 'node-steal', nlabel => 'node.cpu.steal.utilization.percentage', set => { key_values => [ { name => 'steal' } ], output_template => 'Steal: %.2f %%', perfdatas => [ { label => 'steal', value => 'steal', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 }, ], } }, { label => 'node-system', nlabel => 'node.cpu.system.utilization.percentage', set => { key_values => [ { name => 'system' } ], output_template => 'System: %.2f %%', perfdatas => [ { label => 'system', value => 'system', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 }, ], } }, { label => 'node-nice', nlabel => 'node.cpu.nice.utilization.percentage', set => { key_values => [ { name => 'nice' } ], output_template => 'Nice: %.2f %%', perfdatas => [ { label => 'nice', value => 'nice', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 }, ], } }, ]; $self->{maps_counters}->{cpu} = [ { label => 'cpu-wait', nlabel => 'core.cpu.wait.utilization.percentage', set => { key_values => [ { name => 'iowait' }, { name => 'display' } ], output_template => 'Wait: %.2f %%', perfdatas => [ { label => 'wait', value => 'iowait', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 }, ], } }, { label => 'cpu-user', nlabel => 'core.cpu.user.utilization.percentage', set => { key_values => [ { name => 'user' }, { name => 'display' } ], output_template => 'User: %.2f %%', perfdatas => [ { label => 'user', value => 'user', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 }, ], } }, { label => 'cpu-softirq', nlabel => 'core.cpu.softirq.utilization.percentage', set => { key_values => [ { name => 'softirq' }, { name => 'display' } ], output_template => 'Soft Irq: %.2f %%', perfdatas => [ { label => 'softirq', value => 'softirq', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 }, ], } }, { label => 'cpu-interrupt', nlabel => 'core.cpu.interrupt.utilization.percentage', set => { key_values => [ { name => 'irq' }, { name => 'display' } ], output_template => 'Interrupt: %.2f %%', perfdatas => [ { label => 'interrupt', value => 'irq', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 }, ], } }, { label => 'cpu-idle', nlabel => 'core.cpu.idle.utilization.percentage', set => { key_values => [ { name => 'idle' }, { name => 'display' } ], output_template => 'Idle: %.2f %%', perfdatas => [ { label => 'idle', value => 'idle', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 }, ], } }, { label => 'cpu-steal', nlabel => 'core.cpu.steal.utilization.percentage', set => { key_values => [ { name => 'steal' }, { name => 'display' } ], output_template => 'Steal: %.2f %%', perfdatas => [ { label => 'steal', value => 'steal', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 }, ], } }, { label => 'cpu-system', nlabel => 'core.cpu.system.utilization.percentage', set => { key_values => [ { name => 'system' }, { name => 'display' } ], output_template => 'System: %.2f %%', perfdatas => [ { label => 'system', value => 'system', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 }, ], } }, { label => 'cpu-nice', nlabel => 'core.cpu.nice.utilization.percentage', set => { key_values => [ { name => 'nice' }, { name => 'display' } ], output_template => 'Nice: %.2f %%', perfdatas => [ { label => 'nice', value => 'nice', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 }, ], } }, ]; } sub prefix_node_output { my ($self, %options) = @_; return "Node '" . $options{instance_value}->{display} . "' "; } sub node_long_output { my ($self, %options) = @_; return "Checking node '" . $options{instance_value}->{display} . "'"; } sub prefix_global_cpu_output { my ($self, %options) = @_; return "CPU Average "; } 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; $options{options}->add_options(arguments => { "instance:s" => { name => 'instance', default => 'instance=~".*"' }, "cpu:s" => { name => 'cpu', default => 'cpu=~".*"' }, "type:s" => { name => 'type', default => 'mode=~".*"' }, "extra-filter:s@" => { name => 'extra_filter' }, "metric-overload:s@" => { name => 'metric_overload' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{metrics} = { 'cpu' => "^node_cpu_seconds_total.*", }; foreach my $metric (@{$self->{option_results}->{metric_overload}}) { next if ($metric !~ /(.*),(.*)/); $self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1})); } $self->{labels} = {}; foreach my $label (('instance', 'cpu', 'type')) { if ($self->{option_results}->{$label} !~ /^(\w+)[!~=]+\".*\"$/) { $self->{output}->add_option_msg(short_msg => "Need to specify --" . $label . " option as a PromQL filter."); $self->{output}->option_exit(); } $self->{labels}->{$label} = $1; } $self->{extra_filter} = ''; foreach my $filter (@{$self->{option_results}->{extra_filter}}) { $self->{extra_filter} .= ',' . $filter; } $self->{prom_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{prom_step} = defined($self->{option_results}->{step}) ? $self->{option_results}->{step} : "5m"; } sub manage_selection { my ($self, %options) = @_; $self->{nodes} = {}; my $results = $options{custom}->query_range( queries => [ '(irate({__name__=~"' . $self->{metrics}->{cpu} . '",' . $self->{option_results}->{instance} . ',' . $self->{option_results}->{cpu} . ',' . $self->{option_results}->{type} . $self->{extra_filter} . '}[' . $self->{prom_step} . '])) * 100' ], timeframe => $self->{prom_timeframe}, step => $self->{prom_step} ); foreach my $result (@{$results}) { my $average = $options{custom}->compute(aggregation => 'average', values => $result->{values}); $self->{nodes}->{$result->{metric}->{$self->{labels}->{instance}}}->{display} = $result->{metric}->{$self->{labels}->{instance}}; $self->{nodes}->{$result->{metric}->{$self->{labels}->{instance}}}->{global_cpu}->{$result->{metric}->{$self->{labels}->{type}}} += $average; $self->{nodes}->{$result->{metric}->{$self->{labels}->{instance}}}->{cpu}->{$result->{metric}->{$self->{labels}->{cpu}}}->{display} = $result->{metric}->{$self->{labels}->{cpu}}; $self->{nodes}->{$result->{metric}->{$self->{labels}->{instance}}}->{cpu}->{$result->{metric}->{$self->{labels}->{cpu}}}->{$result->{metric}->{$self->{labels}->{type}}} = $average; } foreach my $node (keys %{$self->{nodes}}) { foreach my $metric (keys %{$self->{nodes}->{$node}->{global_cpu}}) { next if ($metric =~ /cpu|display/); $self->{nodes}->{$node}->{global_cpu}->{$metric} /= scalar(keys %{$self->{nodes}->{$node}->{cpu}}); } } if (scalar(keys %{$self->{nodes}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No nodes found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check CPU detailed usage for nodes and each of their cores. =over 8 =item B<--instance> Filter on a specific instance (Must be a PromQL filter, Default: 'instance=~".*"') =item B<--cpu> Filter on a specific cpu (Must be a PromQL filter, Default: 'cpu=~".*"') =item B<--type> Filter on a specific type (Must be a PromQL filter, Default: 'mode=~".*"') =item B<--warning-*> Threshold warning. Can be: 'node-idle', 'node-wait', 'node-interrupt', 'node-nice', 'node-softirq', 'node-steal', 'node-system', 'node-user', 'cpu-idle', 'cpu-wait', 'cpu-interrupt', 'cpu-nice', 'cpu-softirq', 'cpu-steal', 'cpu-system', 'cpu-user'. =item B<--critical-*> Threshold critical. Can be: 'node-idle', 'node-wait', 'node-interrupt', 'node-nice', 'node-softirq', 'node-steal', 'node-system', 'node-user', 'cpu-idle', 'cpu-wait', 'cpu-interrupt', 'cpu-nice', 'cpu-softirq', 'cpu-steal', 'cpu-system', 'cpu-user'. =item B<--extra-filter> Add a PromQL filter (Can be multiple) Example : --extra-filter='name=~".*pretty.*"' =item B<--metric-overload> Overload default metrics name (Can be multiple) Example : --metric-overload='metric,^my_metric_name$' Default : - cpu: ^node_cpu_seconds_total.* =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='wait' =back =cut centreon-plugins-20220113/cloud/prometheus/exporters/nodeexporter/mode/load.pm000066400000000000000000000141451417000230700275140ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::prometheus::exporters::nodeexporter::mode::load; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'nodes', type => 1, cb_prefix_output => 'prefix_nodes_output', message_multiple => 'All nodes load are ok' }, ]; $self->{maps_counters}->{nodes} = [ { label => 'load1', nlabel => 'load.1minute.count', set => { key_values => [ { name => 'load1' }, { name => 'display' } ], output_template => 'Load 1 minute: %.2f', output_change_bytes => 1, perfdatas => [ { label => 'load1', value => 'load1', template => '%.2f', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'load5', nlabel => 'load.5minutes.count', set => { key_values => [ { name => 'load5' }, { name => 'display' } ], output_template => 'Load 5 minutes: %.2f', output_change_bytes => 1, perfdatas => [ { label => 'load5', value => 'load5', template => '%.2f', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'load15', nlabel => 'load.15minutes.count', set => { key_values => [ { name => 'load15' }, { name => 'display' } ], output_template => 'Load 15 minutes: %.2f', output_change_bytes => 1, perfdatas => [ { label => 'load15', value => 'load15', template => '%.2f', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub prefix_nodes_output { my ($self, %options) = @_; return "Node '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "instance:s" => { name => 'instance', default => 'instance=~".*"' }, "extra-filter:s@" => { name => 'extra_filter' }, "metric-overload:s@" => { name => 'metric_overload' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{metrics} = { 'load1' => '^node_load1$', 'load5' => '^node_load5$', 'load15' => '^node_load15$', }; foreach my $metric (@{$self->{option_results}->{metric_overload}}) { next if ($metric !~ /(.*),(.*)/); $self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1})); } $self->{labels} = {}; foreach my $label (('instance')) { if ($self->{option_results}->{$label} !~ /^(\w+)[!~=]+\".*\"$/) { $self->{output}->add_option_msg(short_msg => "Need to specify --" . $label . " option as a PromQL filter."); $self->{output}->option_exit(); } $self->{labels}->{$label} = $1; } $self->{extra_filter} = ''; foreach my $filter (@{$self->{option_results}->{extra_filter}}) { $self->{extra_filter} .= ',' . $filter; } } sub manage_selection { my ($self, %options) = @_; $self->{nodes} = {}; my $results = $options{custom}->query( queries => [ 'label_replace({__name__=~"' . $self->{metrics}->{load1} . '",' . $self->{option_results}->{instance} . $self->{extra_filter} . '}, "__name__", "load1", "", "")', 'label_replace({__name__=~"' . $self->{metrics}->{load5} . '",' . $self->{option_results}->{instance} . $self->{extra_filter} . '}, "__name__", "load5", "", "")', 'label_replace({__name__=~"' . $self->{metrics}->{load15} . '",' . $self->{option_results}->{instance} . $self->{extra_filter} . '}, "__name__", "load15", "", "")' ] ); foreach my $result (@{$results}) { $self->{nodes}->{$result->{metric}->{$self->{labels}->{instance}}}->{display} = $result->{metric}->{$self->{labels}->{instance}}; $self->{nodes}->{$result->{metric}->{$self->{labels}->{instance}}}->{$result->{metric}->{__name__}} = ${$result->{value}}[1]; } if (scalar(keys %{$self->{nodes}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No nodes found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check nodes load. =over 8 =item B<--instance> Filter on a specific instance (Must be a PromQL filter, Default: 'instance=~".*"') =item B<--warning-*> Threshold warning. Can be: 'load1', 'load5', 'load15'. =item B<--critical-*> Threshold critical. Can be: 'load1', 'load5', 'load15'. =item B<--extra-filter> Add a PromQL filter (Can be multiple) Example : --extra-filter='name=~".*pretty.*"' =item B<--metric-overload> Overload default metrics name (Can be multiple) Example : --metric-overload='metric,^my_metric_name$' Default : - load1: ^node_load1$ - load5: ^node_load5$ - load15: ^node_load15$ =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='load15' =back =cut centreon-plugins-20220113/cloud/prometheus/exporters/nodeexporter/mode/memory.pm000066400000000000000000000234751417000230700301130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::prometheus::exporters::nodeexporter::mode::memory; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_usage_perfdata { my ($self, %options) = @_; my $label = 'used'; my $value_perf = $self->{result_values}->{used}; my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } $self->{output}->perfdata_add( label => $label, unit => 'B', nlabel => 'memory.usage.bytes', 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}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, ); } sub custom_usage_threshold { my ($self, %options) = @_; my ($exit, $threshold_value); $threshold_value = $self->{result_values}->{used}; if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; } $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel}, 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 $msg = sprintf("Ram Total: %s, Used (-buffers/cache): %s (%.2f%%)", $total_size_value . " " . $total_size_unit, $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}); 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}->{available} = $options{new_datas}->{$self->{instance} . '_available'}; $self->{result_values}->{buffer} = $options{new_datas}->{$self->{instance} . '_buffer'}; $self->{result_values}->{cached} = $options{new_datas}->{$self->{instance} . '_cached'}; $self->{result_values}->{used} = $self->{result_values}->{total} - $self->{result_values}->{available} - $self->{result_values}->{buffer} - $self->{result_values}->{cached}; $self->{result_values}->{prct_used} = ($self->{result_values}->{total} > 0) ? $self->{result_values}->{used} * 100 / $self->{result_values}->{total} : 0; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'nodes', type => 1, cb_prefix_output => 'prefix_nodes_output', message_multiple => 'All nodes memory usage are ok' }, ]; $self->{maps_counters}->{nodes} = [ { label => 'usage', set => { key_values => [ { name => 'total' }, { name => 'available' }, { name => 'buffer' }, { name => 'cached' }, { name => 'display' } ], 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 => 'buffer', nlabel => 'buffer.usage.bytes', set => { key_values => [ { name => 'buffer' }, { name => 'display' } ], output_template => 'Buffer: %.2f %s', output_change_bytes => 1, perfdatas => [ { label => 'buffer', value => 'buffer', template => '%s', min => 0, unit => 'B', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'cached', nlabel => 'cache.usage.bytes', set => { key_values => [ { name => 'cached' }, { name => 'display' } ], output_template => 'Cached: %.2f %s', output_change_bytes => 1, perfdatas => [ { label => 'cached', value => 'cached', template => '%s', min => 0, unit => 'B', label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub prefix_nodes_output { my ($self, %options) = @_; return "Node '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "instance:s" => { name => 'instance', default => 'instance=~".*"' }, "units:s" => { name => 'units', default => '%' }, "extra-filter:s@" => { name => 'extra_filter' }, "metric-overload:s@" => { name => 'metric_overload' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{metrics} = { 'total' => "^node_memory_MemTotal.*", 'available' => "^node_memory_MemFree.*", 'cached' => "^node_memory_Cached.*", 'buffer' => "^node_memory_Buffers.*", }; foreach my $metric (@{$self->{option_results}->{metric_overload}}) { next if ($metric !~ /(.*),(.*)/); $self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1})); } $self->{labels} = {}; foreach my $label (('instance')) { if ($self->{option_results}->{$label} !~ /^(\w+)[!~=]+\".*\"$/) { $self->{output}->add_option_msg(short_msg => "Need to specify --" . $label . " option as a PromQL filter."); $self->{output}->option_exit(); } $self->{labels}->{$label} = $1; } $self->{extra_filter} = ''; foreach my $filter (@{$self->{option_results}->{extra_filter}}) { $self->{extra_filter} .= ',' . $filter; } } sub manage_selection { my ($self, %options) = @_; $self->{nodes} = {}; my $results = $options{custom}->query( queries => [ 'label_replace({__name__=~"' . $self->{metrics}->{total} . '",' . $self->{option_results}->{instance} . $self->{extra_filter} . '}, "__name__", "total", "", "")', 'label_replace({__name__=~"' . $self->{metrics}->{available} . '",' . $self->{option_results}->{instance} . $self->{extra_filter} . '}, "__name__", "available", "", "")', 'label_replace({__name__=~"' . $self->{metrics}->{cached} . '",' . $self->{option_results}->{instance} . $self->{extra_filter} . '}, "__name__", "cached", "", "")', 'label_replace({__name__=~"' . $self->{metrics}->{buffer} . '",' . $self->{option_results}->{instance} . $self->{extra_filter} . '}, "__name__", "buffer", "", "")' ] ); foreach my $result (@{$results}) { $self->{nodes}->{$result->{metric}->{$self->{labels}->{instance}}}->{display} = $result->{metric}->{$self->{labels}->{instance}}; $self->{nodes}->{$result->{metric}->{$self->{labels}->{instance}}}->{$result->{metric}->{__name__}} = ${$result->{value}}[1]; } if (scalar(keys %{$self->{nodes}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No nodes found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check memory usage. =over 8 =item B<--instance> Filter on a specific instance (Must be a PromQL filter, Default: 'instance=~".*"') =item B<--warning-*> Threshold warning. Can be: 'usage', 'buffer', 'cached'. =item B<--critical-*> Threshold critical. Can be: 'usage', 'buffer', 'cached'. =item B<--units> Units of thresholds (Default: '%') ('%', 'B'). =item B<--extra-filter> Add a PromQL filter (Can be multiple) Example : --extra-filter='name=~".*pretty.*"' =item B<--metric-overload> Overload default metrics name (Can be multiple) Example : --metric-overload='metric,^my_metric_name$' By default, 'node_memory_MemFree' node's metric will be used for 'available' metric as it is more commonly used for now. The best being to use 'node_memory_MemAvailable' in the future. Default : - total: ^node_memory_MemTotal.* - available: ^node_memory_MemFree.* - cached: ^node_memory_Cached.* - buffer: ^node_memory_Buffers.* =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='usage' =back =cut centreon-plugins-20220113/cloud/prometheus/exporters/nodeexporter/mode/storage.pm000066400000000000000000000243231417000230700302400ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::prometheus::exporters::nodeexporter::mode::storage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_usage_perfdata { my ($self, %options) = @_; my $label = 'used'; my $value_perf = $self->{result_values}->{used}; if (defined($self->{instance_mode}->{option_results}->{free})) { $label = 'free'; $value_perf = $self->{result_values}->{free}; } my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } $self->{output}->perfdata_add( label => $label, unit => 'B', nlabel => 'storage.space.usage.bytes', 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}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, ); } sub custom_usage_threshold { my ($self, %options) = @_; my ($exit, $threshold_value); $threshold_value = $self->{result_values}->{used}; $threshold_value = $self->{result_values}->{free} if (defined($self->{instance_mode}->{option_results}->{free})); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; $threshold_value = $self->{result_values}->{prct_free} if (defined($self->{instance_mode}->{option_results}->{free})); } $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel}, 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}->{label} = $self->{instance}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_size'}; $self->{result_values}->{free} = $options{new_datas}->{$self->{instance} . '_free'}; $self->{result_values}->{used} = $self->{result_values}->{total} - $self->{result_values}->{free}; $self->{result_values}->{prct_used} = ($self->{result_values}->{total} > 0) ? $self->{result_values}->{used} * 100 / $self->{result_values}->{total} : 0; $self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used}; # limit to 100. Better output. if ($self->{result_values}->{prct_used} > 100) { $self->{result_values}->{free} = 0; $self->{result_values}->{prct_used} = 100; $self->{result_values}->{prct_free} = 0; } return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'nodes', type => 3, cb_prefix_output => 'prefix_node_output', cb_long_output => 'node_long_output', message_multiple => 'All nodes storages usage are ok', indent_long_output => ' ', group => [ { name => 'storage', display_long => 1, cb_prefix_output => 'prefix_storage_output', message_multiple => 'All storages usage are ok', type => 1, skipped_code => { -10 => 1 } }, ] } ]; $self->{maps_counters}->{storage} = [ { label => 'usage', set => { key_values => [ { name => 'free' }, { name => 'size' }, { name => 'display' } ], 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_extra_instance => 1, instance_use => 'display' } }, ]; } sub prefix_node_output { my ($self, %options) = @_; return "Node '" . $options{instance_value}->{display} . "' "; } sub node_long_output { my ($self, %options) = @_; return "Checking node '" . $options{instance_value}->{display} . "'"; } sub prefix_storage_output { my ($self, %options) = @_; return "Storage '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "instance:s" => { name => 'instance', default => 'instance=~".*"' }, "mountpoint:s" => { name => 'mountpoint', default => 'mountpoint=~".*"' }, "fstype:s" => { name => 'fstype', default => 'fstype!~"linuxfs|rootfs|tmpfs"' }, "units:s" => { name => 'units', default => '%' }, "free" => { name => 'free' }, "extra-filter:s@" => { name => 'extra_filter' }, "metric-overload:s@" => { name => 'metric_overload' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{metrics} = { 'free' => "^node_filesystem_free.*", 'size' => "^node_filesystem_size.*", }; foreach my $metric (@{$self->{option_results}->{metric_overload}}) { next if ($metric !~ /(.*),(.*)/); $self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1})); } $self->{labels} = {}; foreach my $label (('instance', 'mountpoint', 'fstype')) { if ($self->{option_results}->{$label} !~ /^(\w+)[!~=]+\".*\"$/) { $self->{output}->add_option_msg(short_msg => "Need to specify --" . $label . " option as a PromQL filter."); $self->{output}->option_exit(); } $self->{labels}->{$label} = $1; } $self->{extra_filter} = ''; foreach my $filter (@{$self->{option_results}->{extra_filter}}) { $self->{extra_filter} .= ',' . $filter; } } sub manage_selection { my ($self, %options) = @_; $self->{nodes} = {}; my $results = $options{custom}->query( queries => [ 'label_replace({__name__=~"' . $self->{metrics}->{free} . '",' . $self->{option_results}->{instance} . ',' . $self->{option_results}->{mountpoint} . ',' . $self->{option_results}->{fstype} . $self->{extra_filter} . '}, "__name__", "free", "", "")', 'label_replace({__name__=~"' . $self->{metrics}->{size} . '",' . $self->{option_results}->{instance} . ',' . $self->{option_results}->{mountpoint} . ',' . $self->{option_results}->{fstype} . $self->{extra_filter} . '}, "__name__", "size", "", "")' ] ); foreach my $result (@{$results}) { $self->{nodes}->{$result->{metric}->{$self->{labels}->{instance}}}->{display} = $result->{metric}->{$self->{labels}->{instance}}; $self->{nodes}->{$result->{metric}->{$self->{labels}->{instance}}}->{storage}->{$result->{metric}->{mountpoint}}->{display} = $result->{metric}->{$self->{labels}->{mountpoint}}; $self->{nodes}->{$result->{metric}->{$self->{labels}->{instance}}}->{storage}->{$result->{metric}->{mountpoint}}->{$result->{metric}->{__name__}} = ${$result->{value}}[1]; } if (scalar(keys %{$self->{nodes}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No nodes found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check storages usage. =over 8 =item B<--instance> Filter on a specific instance (Must be a PromQL filter, Default: 'instance=~".*"') =item B<--mountpoint> Filter on a specific mountpoint (Must be a PromQL filter, Default: 'mountpoint=~".*"') =item B<--fstype> Filter on a specific fstype (Must be a PromQL filter, Default: 'fstype!~"linuxfs|rootfs|tmpfs"') =item B<--units> Units of thresholds (Default: '%') ('%', 'B'). =item B<--free> Thresholds are on free space left. =item B<--warning-usage> Threshold warning. =item B<--critical-usage> Threshold critical. =item B<--extra-filter> Add a PromQL filter (Can be multiple) Example : --extra-filter='name=~".*pretty.*"' =item B<--metric-overload> Overload default metrics name (Can be multiple) Example : --metric-overload='metric,^my_metric_name$' Default : - free: ^node_filesystem_free.* - size: ^node_filesystem_size.* =back =cut centreon-plugins-20220113/cloud/prometheus/exporters/nodeexporter/plugin.pm000066400000000000000000000033261417000230700271460ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::prometheus::exporters::nodeexporter::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}} = ( 'cpu' => 'cloud::prometheus::exporters::nodeexporter::mode::cpu', 'cpu-detailed' => 'cloud::prometheus::exporters::nodeexporter::mode::cpudetailed', 'load' => 'cloud::prometheus::exporters::nodeexporter::mode::load', 'memory' => 'cloud::prometheus::exporters::nodeexporter::mode::memory', 'storage' => 'cloud::prometheus::exporters::nodeexporter::mode::storage', ); $self->{custom_modes}{api} = 'cloud::prometheus::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check node_exporter metrics through Prometheus server. =cut centreon-plugins-20220113/cloud/prometheus/restapi/000077500000000000000000000000001417000230700222045ustar00rootroot00000000000000centreon-plugins-20220113/cloud/prometheus/restapi/custom/000077500000000000000000000000001417000230700235165ustar00rootroot00000000000000centreon-plugins-20220113/cloud/prometheus/restapi/custom/api.pm000066400000000000000000000207471417000230700246370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::prometheus::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use DateTime; use JSON::XS; use URI::Encode; 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 => { 'hostname:s' => { name => 'hostname' }, 'url-path:s' => { name => 'url_path' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'credentials' => { name => 'credentials' }, 'basic' => { name => 'basic' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'timeout:s' => { name => 'timeout' }, 'header:s@' => { name => 'header' }, 'timeframe:s' => { name => 'timeframe' }, 'step:s' => { name => 'step' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : undef; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 9090; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'http'; $self->{url_path} = (defined($self->{option_results}->{url_path})) ? $self->{option_results}->{url_path} : '/api/v1'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{credentials} = (defined($self->{option_results}->{credentials})) ? 1 : undef; $self->{basic} = (defined($self->{option_results}->{basic})) ? 1 : undef; $self->{timeframe} = (defined($self->{option_results}->{timeframe})) ? $self->{option_results}->{timeframe} : undef; $self->{step} = (defined($self->{option_results}->{step})) ? $self->{option_results}->{step} : undef; if (!defined($self->{hostname}) || $self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify hostname option."); $self->{output}->option_exit(); } return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{url_path} = $self->{url_path}; $self->{option_results}->{credentials} = $self->{credentials}; $self->{option_results}->{basic} = $self->{basic}; $self->{option_results}->{warning_status} = ''; $self->{option_results}->{critical_status} = ''; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->set_options(%{$self->{option_results}}); } sub get_connection_info { my ($self, %options) = @_; return $self->{hostname} . ":" . $self->{port}; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub get_port { my ($self, %options) = @_; return $self->{port}; } sub query_range { my ($self, %options) = @_; my $data; my $start_time = DateTime->now->subtract(seconds => $options{timeframe})->iso8601.'Z'; my $end_time = DateTime->now->iso8601.'Z'; my $uri = URI::Encode->new({encode_reserved => 1}); foreach my $query (@{$options{queries}}) { my $result = $self->get_endpoint(url_path => '/query_range?query=' . $uri->encode($query) . '&start=' . $start_time . '&end=' . $end_time . '&step=' . $options{step}); push @{$data}, @{$result->{result}}; } return $data; } sub query { my ($self, %options) = @_; my $data; my $uri = URI::Encode->new({encode_reserved => 1}); foreach my $query (@{$options{queries}}) { my $result = $self->get_endpoint(url_path => '/query?query=' . $uri->encode($query)); push @{$data}, @{$result->{result}}; } return $data; } sub get_endpoint { my ($self, %options) = @_; $self->settings; $self->{output}->output_add(long_msg => "Query URL: '" . $self->{proto} . "://" . $self->{hostname} . $self->{url_path} . $options{url_path} . "'", debug => 1); my $response = $self->{http}->request(url_path => $self->{url_path} . $options{url_path}); my $content; eval { $content = JSON::XS->new->utf8->decode($response); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } if ($content->{status} ne 'success') { $self->{output}->add_option_msg(short_msg => "Cannot get data: " . $content->{status}); $self->{output}->option_exit(); } return $content->{data}; } sub compute { my ($self, %options) = @_; my $result; if ($options{aggregation} eq 'average') { my $points = 0; foreach my $value (@{$options{values}}) { $result = 0 if (!defined($result)); $result += $$value[1]; $points++; } $result /= $points; } elsif ($options{aggregation} eq 'minimum') { foreach my $value (@{$options{values}}) { $result = $$value[1] if (!defined($result) || $$value[1] < $result); } } elsif ($options{aggregation} eq 'maximum') { foreach my $value (@{$options{values}}) { $result = $$value[1] if (!defined($result) || $$value[1] > $result); } } elsif ($options{aggregation} eq 'sum') { foreach my $value (@{$options{values}}) { $result = 0 if (!defined($result)); $result += $$value[1]; } } return $result; } 1; __END__ =head1 NAME Prometheus Rest API =head1 SYNOPSIS Prometheus Rest API custom mode =head1 REST API OPTIONS Prometheus Rest API =over 8 =item B<--timeframe> Set timeframe in seconds (i.e. 3600 to check last hour). =item B<--step> Set the step of the metric query (Examples: '30s', '1m', '15m', '1h'). =item B<--hostname> Prometheus hostname. =item B<--url-path> API url path (Default: '/api/v1') =item B<--port> API port (Default: 9090) =item B<--proto> Specify https if needed (Default: 'http') =item B<--credentials> Specify this option if you access the API with authentication =item B<--username> Specify username for authentication (Mandatory if --credentials is specified) =item B<--password> Specify password for authentication (Mandatory if --credentials is specified) =item B<--basic> Specify this option if you access the API over basic authentication and don't want a '401 UNAUTHORIZED' error to be logged on your webserver. Specify this option if you access the API over hidden basic authentication or you'll get a '404 NOT FOUND' error. (Use with --credentials) =item B<--timeout> Set HTTP timeout =item B<--header> Set HTTP header (Can be multiple, example: --header='Authorization:Bearer ABCD') Useful to access Prometheus API hosted in a specific environment. =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/cloud/prometheus/restapi/mode/000077500000000000000000000000001417000230700231305ustar00rootroot00000000000000centreon-plugins-20220113/cloud/prometheus/restapi/mode/expression.pm000066400000000000000000000243411417000230700256710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::prometheus::restapi::mode::expression; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_perfdata { my ($self, %options) = @_; foreach my $key (@{$self->{instance_mode}->{custom_keys}}) { $self->{output}->perfdata_add( label => $key, nlabel => $key, value => $self->{result_values}->{$key}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{instance} : undef ); } } sub custom_status_output { my ($self, %options) = @_; my $msg = $self->{instance_mode}->{option_results}->{output}; while ($msg =~ /%\{(.*?)\}/g) { my $key = $1; if (defined($self->{result_values}->{$key})) { $msg =~ s/%\{$key\}/$self->{result_values}->{$key}/g; } } return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{instance} = $options{new_datas}->{$self->{instance} . '_instance'}; foreach my $key (@{$self->{instance_mode}->{custom_keys}}) { $self->{result_values}->{$key} = $options{new_datas}->{$self->{instance} . '_' . $key}; } return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'expressions', type => 1, message_multiple => 'All expressions results are ok', skipped_code => { -11 => 1 } }, ]; $self->{maps_counters}->{expressions} = [ { label => 'status', set => { key_values => [ { name => 'instance' } ], closure_custom_calc => $self->can('custom_status_calc'), closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => $self->can('custom_status_perfdata'), closure_custom_threshold_check => \&catalog_status_threshold, } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "query:s@" => { name => 'query' }, "query-range:s@" => { name => 'query_range' }, "instance:s" => { name => 'instance' }, "aggregation:s" => { name => 'aggregation', default => 'average' }, "output:s" => { name => 'output' }, "multiple-output:s" => { name => 'multiple_output' }, "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); if (!defined($self->{option_results}->{output}) || $self->{option_results}->{output} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify output option."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{instance}) || $self->{option_results}->{instance} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify instance option."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{query}) && !defined($self->{option_results}->{query_range})) { $self->{output}->add_option_msg(short_msg => "Need to specify query or query-range option."); $self->{output}->option_exit(); } $self->{custom_keys} = []; $self->{queries} = {}; foreach my $query (@{$self->{option_results}->{query}}) { next if ($query !~ /^(\w+),(.*)/); $self->{queries}->{$1} = $2; push @{$self->{maps_counters}->{expressions}[0]->{set}->{key_values}}, { name => $1 }; push @{$self->{custom_keys}}, $1; } $self->{query_ranges} = {}; foreach my $query (@{$self->{option_results}->{query_range}}) { next if ($query !~ /^(\w+),(.*)/); $self->{query_ranges}->{$1} = $2; push @{$self->{maps_counters}->{expressions}[0]->{set}->{key_values}}, { name => $1 }; push @{$self->{custom_keys}}, $1; } $self->{maps_counters_type}[0]->{message_multiple} = $self->{option_results}->{multiple_output} if (defined($self->{option_results}->{multiple_output})); $self->{prom_timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; $self->{prom_step} = defined($self->{option_results}->{step}) ? $self->{option_results}->{step} : "1m"; $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; $self->{expressions} = {}; my (@results, @queries, @query_ranges); foreach my $label (keys %{$self->{queries}}) { my $prom_query = sprintf('label_replace(%s,"__name__","%s","","")', $self->{queries}->{$label}, $label); push @queries, $prom_query; } foreach my $label (keys %{$self->{query_ranges}}) { my $prom_query = sprintf('label_replace(%s,"__name__","%s","","")', $self->{query_ranges}->{$label}, $label); push @query_ranges, $prom_query; } my $queries_results = $options{custom}->query(queries => \@queries) if (scalar(@queries) > 0); my $query_ranges_results = $options{custom}->query_range(queries => \@query_ranges, timeframe => $self->{prom_timeframe}, step => $self->{prom_step}) if (scalar(@query_ranges) > 0); push @results, @{$queries_results} if (defined($queries_results)); push @results, @{$query_ranges_results} if (defined($query_ranges_results)); foreach my $result (@results) { next if (!defined($result->{metric}->{$self->{option_results}->{instance}})); my $value; $value = $options{custom}->compute(aggregation => $self->{option_results}->{aggregation}, values => $result->{values}) if (defined($result->{values})); $value = ${$result->{value}}[1] if (defined($result->{value})); $self->{expressions}->{$result->{metric}->{$self->{option_results}->{instance}}}->{instance} = $result->{metric}->{$self->{option_results}->{instance}}; $self->{expressions}->{$result->{metric}->{$self->{option_results}->{instance}}}->{$result->{metric}->{__name__}} = $value; } if (scalar(keys %{$self->{expressions}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No expressions found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check expression. Examples: # perl centreon_plugins.pl --plugin=cloud::prometheus::restapi::plugin --mode=expression --hostname=localhost --port=9090 --query='desired,kube_deployment_spec_replicas' --query='available,kube_deployment_status_replicas_available' --instance='deployment' --critical-status='%{available} < %{desired}' --output='Deployment %{instance} Replicas Desired: %{desired}, Available: %{available}' --multiple-output='All deployments replicas are ok' # perl centreon_plugins.pl --plugin=cloud::prometheus::restapi::plugin --mode=expression --hostname=localhost --port=9090 --query='last,container_cpu_usage_seconds_total{container_name!~".*POD.*"}' --query-range='average,irate(container_cpu_usage_seconds_total{container_name!~".*POD.*"}[1m])*100' --timeframe='900' --step='1m' --aggregation='average' --instance='name' --critical-status='%{last} > 50 || %{average} > 10' --output='Container %{instance} CPU Average: %{average}%, Last: %{last}%' --multiple-output='All containers CPU usage are ok' # perl centreon_plugins.pl --plugin=cloud::prometheus::restapi::plugin --mode=expression --hostname=localhost --port=9090 --query='usage_prct,container_memory_usage_bytes/container_spec_memory_limit_bytes*100' --query='usage_bytes,container_memory_usage_bytes' --query='limits_bytes,container_spec_memory_limit_bytes' --instance='name' --critical-status='%{limits_bytes} > 0 && %{usage_prct} > 10' --output='Container %{instance} Memory usage: %{average}% [usage = %{usage_bytes}B][limits = %{limits_bytes}B]' =over 8 =item B<--query> Set a PromQL query. Query option must be like --query='label,query'. =item B<--query-range> Set a PromQL query. Query option must be like --query-range='label,query'. This query type uses --step, --timeframe and --aggregation options to compute the values. =item B<--instance> Set the instance label on which the results should be calculate for (Example: --instance='name'). =item B<--output> Set the output for each instances (Example: --output='Container %{instance} value is %{label}'). =item B<--multiple-output> Set the global output in case everything is fine for multiple instances (Example: --multiple-output='Containers are OK'). =item B<--warning-status> Set warning threshold for status (Default: ''). Can use special variables like %{instance} and any other labels you set through --query and --query-range options. =item B<--critical-status> Set critical threshold for status (Default: ''). Can use special variables like %{instance} and any other labels you set through --query and --query-range options. =item B<--timeframe> Set timeframe in seconds (i.e. 3600 to check last hour) (Required for --query-range queries, Default: '900'). =item B<--step> Set the step of the metric query (Examples: '30s', '1m', '15m', '1h') (Required for --query-range queries, Default: '1m'). =item B<--aggregation> Set the aggregation on metric values (Can be: 'average', 'min', 'max', 'sum') (Required for --query-range queries, Default: 'average'). =back =cut centreon-plugins-20220113/cloud/prometheus/restapi/mode/targetstatus.pm000066400000000000000000000166611417000230700262320ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::prometheus::restapi::mode::targetstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = "health is '" . $self->{result_values}->{health} . "'"; $msg .= " [last error: " . $self->{result_values}->{last_error} . "]" if ($self->{result_values}->{last_error} ne ''); $msg .= " " . $self->{result_values}->{labels} if ($self->{result_values}->{labels} ne ''); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{health} = $options{new_datas}->{$self->{instance} . '_health'}; $self->{result_values}->{last_error} = $options{new_datas}->{$self->{instance} . '_last_error'}; $self->{result_values}->{labels} = $options{new_datas}->{$self->{instance} . '_labels'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub prefix_targets_output { my ($self, %options) = @_; return "Target '" . $options{instance_value}->{display} . "' "; } sub prefix_global_output { my ($self, %options) = @_; return "Targets "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }, { name => 'targets', type => 1, cb_prefix_output => 'prefix_targets_output', message_multiple => 'All targets status are ok', skipped_code => { -11 => 1 } }, ]; $self->{maps_counters}->{global} = [ { label => 'active', nlabel => 'targets.active.count', set => { key_values => [ { name => 'active' } ], output_template => 'Active: %s', perfdatas => [ { label => 'active_targets', value => 'active', template => '%s', min => 0 }, ], } }, { label => 'dropped', nlabel => 'targets.dropped.count', set => { key_values => [ { name => 'dropped' } ], output_template => 'Dropped: %s', perfdatas => [ { label => 'dropped_targets', value => 'dropped', template => '%s', min => 0 }, ], } }, { label => 'up', nlabel => 'targets.up.count', set => { key_values => [ { name => 'up' } ], output_template => 'Up: %s', perfdatas => [ { label => 'up_targets', value => 'up', template => '%s', min => 0 }, ], } }, { label => 'down', nlabel => 'targets.down.count', set => { key_values => [ { name => 'down' } ], output_template => 'Down: %s', perfdatas => [ { label => 'down_targets', value => 'down', template => '%s', min => 0 }, ], } }, { label => 'unknown', nlabel => 'targets.unknown.count', set => { key_values => [ { name => 'unknown' } ], output_template => 'Unknown: %s', perfdatas => [ { label => 'unknown_targets', value => 'unknown', template => '%s', min => 0 }, ], } }, ]; $self->{maps_counters}->{targets} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'health' }, { name => 'last_error' }, { name => 'display' }, { name => 'labels' } ], 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 => \&catalog_status_threshold, } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-label:s@" => { name => 'filter_label' }, "warning-status:s" => { name => 'warning_status', default => '' }, "critical-status:s" => { name => 'critical_status', default => '%{health} !~ /up/' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); foreach my $filter (@{$self->{option_results}->{filter_label}}) { next if ($filter !~ /^(\w+),(.*)/); $self->{filters}->{$1} = $2; } $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; $self->{global} = { active => 0, dropped => 0, up => 0, down => 0, unknown => 0 }; $self->{targets} = {}; my $result = $options{custom}->get_endpoint(url_path => '/targets'); foreach my $active (@{$result->{activeTargets}}) { my $next; foreach my $filter (keys %{$self->{filters}}) { $next = 1 if (defined($active->{labels}->{$filter}) && $active->{labels}->{$filter} !~ /$self->{filters}->{$filter}/); } next if ($next); $self->{global}->{active}++; $self->{targets}->{$active->{scrapeUrl}} = { display => $active->{scrapeUrl}, health => $active->{health}, last_error => $active->{lastError}, }; foreach my $label (keys %{$active->{labels}}) { $self->{targets}->{$active->{scrapeUrl}}->{labels} .= "[" . $label . " = " . $active->{labels}->{$label} . "]"; } $self->{global}->{$active->{health}}++; } foreach my $dropped (@{$result->{droppedTargets}}) { $self->{global}->{dropped}++; } if (scalar(keys %{$self->{targets}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No targets found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check targets status. =over 8 =item B<--filter-label> Set filter on label (Regexp, Can be multiple) (Example: --filter-label='job,kube.*'). =item B<--warning-status> Set warning threshold for status (Default: '') Can used special variables like: %{display}, %{health}. =item B<--critical-status> Set critical threshold for status (Default: '%{health} !~ /up/'). Can used special variables like: %{display}, %{health} =item B<--warning-*> Threshold warning. Can be: 'active', 'dropped', 'up', 'down', 'unknown'. =item B<--critical-*> Threshold critical. Can be: 'active', 'dropped', 'up', 'down', 'unknown'. =back =cut centreon-plugins-20220113/cloud/prometheus/restapi/plugin.pm000066400000000000000000000025761417000230700240520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::prometheus::restapi::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}} = ( 'expression' => 'cloud::prometheus::restapi::mode::expression', 'target-status' => 'cloud::prometheus::restapi::mode::targetstatus', ); $self->{custom_modes}{api} = 'cloud::prometheus::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Prometheus server. =cut centreon-plugins-20220113/cloud/vmware/000077500000000000000000000000001417000230700176435ustar00rootroot00000000000000centreon-plugins-20220113/cloud/vmware/velocloud/000077500000000000000000000000001417000230700216375ustar00rootroot00000000000000centreon-plugins-20220113/cloud/vmware/velocloud/restapi/000077500000000000000000000000001417000230700233065ustar00rootroot00000000000000centreon-plugins-20220113/cloud/vmware/velocloud/restapi/custom/000077500000000000000000000000001417000230700246205ustar00rootroot00000000000000centreon-plugins-20220113/cloud/vmware/velocloud/restapi/custom/api.pm000066400000000000000000000403221417000230700257300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::vmware::velocloud::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use JSON::XS; use Digest::MD5 qw(md5_hex); use centreon::plugins::statefile; use DateTime; 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'operator-user' => { name => 'operator_user' }, 'api-path:s' => { name => 'api_path' }, 'timeframe:s' => { name => 'timeframe' }, 'timeout:s' => { name => 'timeout' }, 'cache-expires-in:s' => { name => 'cache_expires_in' }, 'unknown-http-status:s' => { name => 'unknown_http_status' }, 'warning-http-status:s' => { name => 'warning_http_status' }, 'critical-http-status:s' => { name => 'critical_http_status' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); $self->{cache_cookie} = centreon::plugins::statefile->new(%options); $self->{cache_app} = centreon::plugins::statefile->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{username} = (defined($self->{option_results}->{username})) ? $self->{option_results}->{username} : ''; $self->{password} = (defined($self->{option_results}->{password})) ? $self->{option_results}->{password} : ''; $self->{api_path} = (defined($self->{option_results}->{api_path})) ? $self->{option_results}->{api_path} : '/portal/rest'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{cache_expires_in} = (defined($self->{option_results}->{cache_expires_in})) && $self->{option_results}->{cache_expires_in} =~ /(\d+)/ ? $1 : 7200; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300'; $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } if ($self->{username} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --username option."); $self->{output}->option_exit(); } if ($self->{password} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --password option."); $self->{output}->option_exit(); } $self->{cache_cookie}->check_options(option_results => $self->{option_results}); $self->{cache_app}->check_options(option_results => $self->{option_results}); return 0; } sub json_decode { my ($self, %options) = @_; my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($options{content}); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } return $decoded; } sub get_connection_infos { my ($self, %options) = @_; return $self->{hostname} . '_' . $self->{http}->get_port(); } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->add_header(key => 'Content-Type', value => 'application/json'); $self->{http}->set_options(%{$self->{option_results}}); } sub clean_session { my ($self, %options) = @_; my $datas = {}; $options{statefile}->write(data => $datas); $self->{session_cookie} = undef; $self->{http}->add_header(key => 'Cookie', value => undef); } sub get_session_cookie { my ($self, %options) = @_; my $has_cache_file = $options{statefile}->read(statefile => 'vmware_velocloud_' . md5_hex($self->{option_results}->{hostname}) . '_' . md5_hex($self->{option_results}->{username})); my $session_cookie = $options{statefile}->get(name => 'session_cookie'); if ($has_cache_file == 0 || !defined($session_cookie)) { my $form_post = { username => $self->{username}, password => $self->{password} }; my $encoded; eval { $encoded = JSON::XS->new->utf8->encode($form_post); }; if ($@) { $self->{output}->add_option_msg(short_msg => 'Cannot encode json request'); $self->{output}->option_exit(); } my $login_url = (defined($self->{option_results}->{operator_user})) ? '/login/operatorLogin' : '/login/enterpriseLogin'; $self->{http}->request( method => 'POST', url_path => $self->{api_path} . $login_url, query_form_post => $encoded, warning_status => '', unknown_status => '', critical_status => '' ); if ($self->{http}->get_code() != 200) { $self->{output}->add_option_msg(short_msg => "Authentication error [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my (@cookies) = $self->{http}->get_header(name => 'Set-Cookie'); my $message = ''; foreach my $cookie (@cookies) { $message = $1 if ($cookie =~ /^velocloud\.message=(.+?);/); $session_cookie = $1 if ($cookie =~ /^velocloud\.session=(.+?);/); } if (!defined($session_cookie) || $session_cookie eq '') { $self->{output}->add_option_msg(short_msg => "Cannot get session cookie: " . $message); $self->{output}->option_exit(); } $options{statefile}->write(data => { session_cookie => $session_cookie }); } $self->{session_cookie} = $session_cookie; $self->{http}->add_header(key => 'Cookie', value => 'velocloud.session=' . $self->{session_cookie}); } sub request_api { my ($self, %options) = @_; $self->settings(); my $encoded_form_post; if (defined($options{query_form_post})) { eval { $encoded_form_post = JSON::XS->new->utf8->encode($options{query_form_post}); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot encode json request"); $self->{output}->option_exit(); } } my $loop = 0; while (1) { if (!defined($self->{session_cookie})) { $self->get_session_cookie(statefile => $self->{cache_cookie}); } my ($content) = $self->{http}->request( method => $options{method}, url_path => $self->{api_path} . $options{endpoint}, query_form_post => $encoded_form_post, unknown_status => $loop > 0 ? $self->{unknown_http_status} : '', warning_status => $loop > 0 ? $self->{warning_http_status} : '', critical_status => $loop > 0 ? $self->{critical_http_status} : '' ); $loop++; if ($loop == 5) { $self->{output}->add_option_msg(short_msg => 'cannot get valid data'); $self->{output}->option_exit(); } if ($self->{http}->get_code() < 200 || $self->{http}->get_code() >= 300) { $self->clean_session(statefile => $self->{cache_cookie}); next; } my $decoded = $self->json_decode(content => $content); if (!defined($decoded)) { $self->{output}->add_option_msg(short_msg => 'error while retrieving data (add --debug option for detailed message)'); $self->{output}->option_exit(); } if (ref($decoded) ne 'ARRAY' && defined($decoded->{error})) { if ($decoded->{error}->{code} == -32000) { $self->clean_session(statefile => $self->{cache_cookie}); next; } $self->{output}->add_option_msg( short_msg => sprintf( "API returned error code '%s', message '%s'", $decoded->{error}->{code}, $decoded->{error}->{message} ) ); $self->{output}->option_exit(); } return $decoded; } } sub get_entreprise_id { my ($self, %options) = @_; return if (defined($self->{entreprise_id})); my $response = $self->request_api( method => 'POST', endpoint => '/enterprise/getEnterprise' ); $self->{entreprise_id} = $response->{id}; } sub list_edges { my ($self, %options) = @_; $self->get_entreprise_id(); my $response = $self->request_api( method => 'POST', endpoint => '/enterprise/getEnterpriseEdges', query_form_post => { enterpriseId => int($self->{entreprise_id}) } ); return $response; } sub list_links { my ($self, %options) = @_; $self->get_entreprise_id(); my $start_time = DateTime->now->subtract(seconds => $options{timeframe})->iso8601.'Z'; my $response = $self->request_api( method => 'POST', endpoint => '/metrics/getEdgeLinkMetrics', query_form_post => { enterpriseId => int($self->{entreprise_id}), edgeId => $options{edge_id}, metrics => [ 'bytesRx' ], interval => { start => $start_time } } ); return $response; } sub get_links_metrics { my ($self, %options) = @_; $self->get_entreprise_id(); my $start_time = DateTime->now->subtract(seconds => $options{timeframe})->iso8601.'Z'; my $response = $self->request_api( method => 'POST', endpoint => '/metrics/getEdgeLinkMetrics', query_form_post => { enterpriseId => int($self->{entreprise_id}), edgeId => $options{edge_id}, metrics => [ 'bytesRx', 'bytesTx', 'bestJitterMsRx', 'bestJitterMsTx', 'bestLatencyMsRx', 'bestLatencyMsTx', 'bestLossPctRx', 'bestLossPctTx' ], interval => { start => $start_time } } ); return $response; } sub get_application_name { my ($self, %options) = @_; $self->get_entreprise_id(); my $has_cache_file = $self->{cache_app}->read(statefile => 'vmware_velocloud_app_' . md5_hex($self->{option_results}->{hostname}) . '_' . md5_hex($self->{entreprise_id})); my $updated = $self->{cache_app}->get(name => 'updated'); my $applications = $self->{cache_app}->get(name => 'applications'); if ($has_cache_file == 0 || !defined($updated) || (time() > ($updated + $self->{cache_expires_in}))) { my $response = $self->request_api( method => 'POST', endpoint => '/configuration/getIdentifiableApplications', query_form_post => { enterpriseId => int($self->{entreprise_id}) } ); $applications = {}; foreach (@{$response->{applications}}) { $applications->{ $_->{id} } = $_->{name}; } $self->{cache_app}->write(data => { applications => $applications, updated => time() }); } return defined($applications->{ $options{app_id} }) ? $applications->{ $options{app_id} } : undef; } sub get_apps_metrics { my ($self, %options) = @_; $self->get_entreprise_id(); my $start_time = DateTime->now->subtract(seconds => $options{timeframe})->iso8601.'Z'; my $response = $self->request_api( method => 'POST', endpoint => '/metrics/getEdgeAppMetrics', query_form_post => { enterpriseId => int($self->{entreprise_id}), edgeId => $options{edge_id}, metrics => [ 'bytesRx', 'bytesTx', 'packetsRx', 'packetsTx' ], interval => { start => $start_time } } ); return $response; } sub get_links_qoe { my ($self, %options) = @_; $self->get_entreprise_id(); my $start_time = DateTime->now->subtract(seconds => $options{timeframe})->iso8601.'Z'; my $response = $self->request_api( method => 'POST', endpoint => '/linkQualityEvent/getLinkQualityEvents', query_form_post => { enterpriseId => int($self->{entreprise_id}), edgeId => $options{edge_id}, debug => \0, individualScores => \0, maxSamples => 15, interval => { start => $start_time } } ); return $response; } sub get_categories_metrics { my ($self, %options) = @_; $self->get_entreprise_id(); my $start_time = DateTime->now->subtract(seconds => $options{timeframe})->iso8601.'Z'; my $response = $self->request_api( method => 'POST', endpoint => '/metrics/getEdgeCategoryMetrics', query_form_post => { id => $options{edge_id}, metrics => [ 'bytesRx', 'bytesTx', 'packetsRx', 'packetsTx' ], interval => { start => $start_time } } ); return $response; } 1; __END__ =head1 NAME VMware VeloCloud Orchestrator REST API =head1 SYNOPSIS VMware VeloCloud Orchestrator Rest API custom mode =head1 REST API OPTIONS =over 8 =item B<--hostname> VMware VeloCloud Orchestrator hostname. =item B<--port> Port used (Default: 443) =item B<--proto> Specify https if needed (Default: 'https') =item B<--cache-expires-in> Cache (application) expires each X secondes (Default: 7200) =item B<--username> VMware VeloCloud Orchestrator username. =item B<--password> VMware VeloCloud Orchestrator password. =item B<--operator-user> Set if the user is an operator. =item B<--api-path> API base url path (Default: '/portal/rest'). =item B<--timeframe> Set timeframe in seconds (Default: 900). =item B<--timeout> Set HTTP timeout in seconds (Default: '10'). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/cloud/vmware/velocloud/restapi/mode/000077500000000000000000000000001417000230700242325ustar00rootroot00000000000000centreon-plugins-20220113/cloud/vmware/velocloud/restapi/mode/applicationusage.pm000066400000000000000000000161631417000230700301270ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::vmware::velocloud::restapi::mode::applicationusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'edges', type => 3, cb_prefix_output => 'prefix_edge_output', cb_long_output => 'long_output', message_multiple => 'All edges applications usage are ok', indent_long_output => ' ', group => [ { name => 'global', type => 0 }, { name => 'apps', display_long => 1, cb_prefix_output => 'prefix_app_output', message_multiple => 'All applications usage are ok', type => 1 } ] } ]; $self->{maps_counters}->{global} = [ { label => 'edge-applications-count', nlabel => 'edge.applications.total.count', set => { key_values => [ { name => 'app_count' } ], output_template => '%s application(s)', perfdatas => [ { template => '%d', unit => '', min => 0, label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{apps} = [ { label => 'traffic-in', nlabel => 'application.traffic.in.bitspersecond', set => { key_values => [ { name => 'traffic_in' }, { name => 'display' }, { name => 'id' } ], output_change_bytes => 2, output_template => 'Traffic In: %s %s/s', perfdatas => [ { template => '%s', min => 0, unit => 'b/s', label_extra_instance => 1 } ] } }, { label => 'traffic-out', nlabel => 'application.traffic.out.bitspersecond', set => { key_values => [ { name => 'traffic_out' }, { name => 'display' }, { name => 'id' } ], output_change_bytes => 2, output_template => 'Traffic Out: %s %s/s', perfdatas => [ { template => '%s', min => 0, unit => 'b/s', label_extra_instance => 1 } ] } }, { label => 'packets-in', nlabel => 'application.packets.in.persecond', set => { key_values => [ { name => 'packets_in' }, { name => 'display' }, { name => 'id' } ], output_template => 'Packets In: %.2f packets/s', perfdatas => [ { template => '%.2f', min => 0, unit => 'packets/s', label_extra_instance => 1 } ] } }, { label => 'packets-out', nlabel => 'application.packets.out.persecond', set => { key_values => [ { name => 'packets_out' }, { name => 'display' }, { name => 'id' } ], output_template => 'Packets Out: %.2f packets/s', perfdatas => [ { template => '%.2f', min => 0, unit => 'packets/s', label_extra_instance => 1 } ] } } ]; } sub prefix_edge_output { my ($self, %options) = @_; return "Edge '" . $options{instance_value}->{display} . "' "; } sub prefix_app_output { my ($self, %options) = @_; return "Application '" . $options{instance_value}->{display} . "' [Id: " . $options{instance_value}->{id} . "] "; } sub long_output { my ($self, %options) = @_; return "Checking edge '" . $options{instance_value}->{display} . "' [Id: " . $options{instance_value}->{id} . "] "; } 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-edge-name:s' => { name => 'filter_edge_name' }, 'filter-application-name:s' => { name => 'filter_application_name' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->list_edges(); $self->{edges} = {}; foreach my $edge (@{$results}) { if (defined($self->{option_results}->{filter_edge_name}) && $self->{option_results}->{filter_edge_name} ne '' && $edge->{name} !~ /$self->{option_results}->{filter_edge_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $edge->{name} . "'.", debug => 1); next; } $self->{edges}->{ $edge->{name} }->{id} = $edge->{id}; $self->{edges}->{ $edge->{name} }->{display} = $edge->{name}; my $apps = $options{custom}->get_apps_metrics( edge_id => $edge->{id}, timeframe => $self->{timeframe} ); foreach my $app (@{$apps}) { my $app_name = $options{custom}->get_application_name( app_id => $app->{application} ); $app_name = $app->{application} if (!defined($app_name)); if (defined($self->{option_results}->{filter_application_name}) && $self->{option_results}->{filter_application_name} ne '' && $app_name !~ /$self->{option_results}->{filter_application_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $app_name . "'.", debug => 1); next; } $self->{edges}->{$edge->{name}}->{global}->{app_count}++; $self->{edges}->{$edge->{name}}->{apps}->{ $app_name } = { id => $app->{application}, display => $app_name, traffic_out => int($app->{bytesTx} * 8 / $self->{timeframe}), traffic_in => int($app->{bytesRx} * 8 / $self->{timeframe}), packets_out => $app->{packetsTx} / $self->{timeframe}, packets_in => $app->{packetsRx} / $self->{timeframe} }; } } if (scalar(keys %{$self->{edges}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No edge found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check applications usage per edges. =over 8 =item B<--filter-edge-name> Filter edge by name (Can be a regexp). =item B<--filter-application-name> Filter application by name (Can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'edge-applications-count', 'traffic-in', 'traffic-out', 'packets-in', 'packets-out'. =back =cut centreon-plugins-20220113/cloud/vmware/velocloud/restapi/mode/categoryusage.pm000066400000000000000000000157421417000230700274430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::vmware::velocloud::restapi::mode::categoryusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'edges', type => 3, cb_prefix_output => 'prefix_edge_output', cb_long_output => 'long_output', message_multiple => 'All edges categories usage are ok', indent_long_output => ' ', group => [ { name => 'global', type => 0 }, { name => 'categories', display_long => 1, cb_prefix_output => 'prefix_category_output', message_multiple => 'All categories usage are ok', type => 1 } ] } ]; $self->{maps_counters}->{global} = [ { label => 'edge-categories-count', nlabel => 'edge.categories.total.count', set => { key_values => [ { name => 'category_count' } ], output_template => '%s categorie(s)', perfdatas => [ { template => '%d', unit => '', min => 0, label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{categories} = [ { label => 'traffic-in', nlabel => 'category.traffic.in.bitspersecond', set => { key_values => [ { name => 'traffic_in' }, { name => 'display' }, { name => 'id' } ], output_change_bytes => 2, output_template => 'Traffic In: %s %s/s', perfdatas => [ { template => '%s', min => 0, unit => 'b/s', label_extra_instance => 1 } ] } }, { label => 'traffic-out', nlabel => 'category.traffic.out.bitspersecond', set => { key_values => [ { name => 'traffic_out' }, { name => 'display' }, { name => 'id' } ], output_change_bytes => 2, output_template => 'Traffic Out: %s %s/s', perfdatas => [ { template => '%s', min => 0, unit => 'b/s', label_extra_instance => 1 } ] } }, { label => 'packets-in', nlabel => 'category.packets.in.persecond', set => { key_values => [ { name => 'packets_in' }, { name => 'display' }, { name => 'id' } ], output_template => 'Packets In: %.2f packets/s', perfdatas => [ { template => '%.2f', min => 0, unit => 'packets/s', label_extra_instance => 1 } ] } }, { label => 'packets-out', nlabel => 'category.packets.out.persecond', set => { key_values => [ { name => 'packets_out' }, { name => 'display' }, { name => 'id' } ], output_template => 'Packets Out: %.2f packets/s', perfdatas => [ { template => '%.2f', min => 0, unit => 'packets/s', label_extra_instance => 1 } ] } } ]; } sub prefix_edge_output { my ($self, %options) = @_; return "Edge '" . $options{instance_value}->{display} . "' "; } sub prefix_category_output { my ($self, %options) = @_; return "Category '" . $options{instance_value}->{display} . "' [Id: " . $options{instance_value}->{id} . "] "; } sub long_output { my ($self, %options) = @_; return "Checking edge '" . $options{instance_value}->{display} . "' [Id: " . $options{instance_value}->{id} . "] "; } 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-edge-name:s' => { name => 'filter_edge_name' }, 'filter-category-name:s' => { name => 'filter_category_name' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->list_edges(); $self->{edges} = {}; foreach my $edge (@{$results}) { if (defined($self->{option_results}->{filter_edge_name}) && $self->{option_results}->{filter_edge_name} ne '' && $edge->{name} !~ /$self->{option_results}->{filter_edge_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $edge->{name} . "'.", debug => 1); next; } $self->{edges}->{$edge->{name}}->{id} = $edge->{id}; $self->{edges}->{$edge->{name}}->{display} = $edge->{name}; my $categories = $options{custom}->get_categories_metrics( edge_id => $edge->{id}, timeframe => $self->{timeframe} ); foreach my $category (@{$categories}) { if (defined($self->{option_results}->{filter_category_name}) && $self->{option_results}->{filter_category_name} ne '' && $category->{name} !~ /$self->{option_results}->{filter_category_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $category->{name} . "'.", debug => 1); next; } $self->{edges}->{$edge->{name}}->{global}->{category_count}++; $self->{edges}->{$edge->{name}}->{categories}->{$category->{name}} = { id => $category->{category}, display => $category->{name}, traffic_out => int($category->{bytesTx} * 8 / $self->{timeframe}), traffic_in => int($category->{bytesRx} * 8 / $self->{timeframe}), packets_out => $category->{packetsTx} / $self->{timeframe}, packets_in => $category->{packetsRx} / $self->{timeframe}, }; } } if (scalar(keys %{$self->{edges}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No edge found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check categories usage per edges. =over 8 =item B<--filter-edge-name> Filter edge by name (Can be a regexp). =item B<--filter-category-name> Filter category by name (Can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'edge-categories-count', 'traffic-in', 'traffic-out', 'packets-in', 'packets-out'. =back =cut centreon-plugins-20220113/cloud/vmware/velocloud/restapi/mode/discovery.pm000066400000000000000000000057371417000230700266130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::vmware::velocloud::restapi::mode::discovery; use base qw(centreon::plugins::mode); use strict; use warnings; use JSON::XS; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "prettify" => { name => 'prettify' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my @disco_data; my $disco_stats; $disco_stats->{start_time} = time(); my $results = $options{custom}->list_edges; foreach my $edge (@{$results}) { my %edge; $edge{id} = $edge->{id}; $edge{site_id} = $edge->{siteId}; $edge{enterprise_id} = $edge->{enterpriseId}; $edge{activation_state} = $edge->{activationState}; $edge{model_number} = $edge->{modelNumber}; $edge{device_family} = $edge->{deviceFamily}; $edge{name} = $edge->{name}; $edge{description} = $edge->{description}; $edge{description} =~ s/\n//g if (defined($edge{description})); $edge{edge_state} = $edge->{edgeState}; $edge{service_state} = $edge->{serviceState}; $edge{ha_state} = $edge->{haState}; $edge{type} = 'edge'; push @disco_data, \%edge; } $disco_stats->{end_time} = time(); $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; $disco_stats->{discovered_items} = @disco_data; $disco_stats->{results} = \@disco_data; my $encoded_data; eval { if (defined($self->{option_results}->{prettify})) { $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); } else { $encoded_data = JSON::XS->new->utf8->encode($disco_stats); } }; if ($@) { $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; } $self->{output}->output_add(short_msg => $encoded_data); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); $self->{output}->exit(); } 1; __END__ =head1 MODE Resources discovery. =over 8 =back =cut centreon-plugins-20220113/cloud/vmware/velocloud/restapi/mode/edgeqoe.pm000066400000000000000000000177341417000230700262150ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::vmware::velocloud::restapi::mode::edgeqoe; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'edges', type => 3, cb_prefix_output => 'prefix_edge_output', cb_long_output => 'long_output', message_multiple => 'All edges links QOE are ok', indent_long_output => ' ', group => [ { name => 'global', type => 0 }, { name => 'links', display_long => 1, cb_prefix_output => 'prefix_link_output', message_multiple => 'All links QOE are ok', type => 1 } ] } ]; $self->{maps_counters}->{global} = [ { label => 'qoe-voice-global', nlabel => 'global.qoe.voice.count', set => { key_values => [ { name => 'voice' } ], output_template => 'Global voice QOE: %s', perfdatas => [ { template => '%s', min => 0, max => 10, label_extra_instance => 1 } ] } }, { label => 'qoe-video-global', nlabel => 'global.qoe.video.count', set => { key_values => [ { name => 'video' } ], output_template => 'Global video QOE: %s', perfdatas => [ { template => '%s', min => 0, max => 10, label_extra_instance => 1 } ] } }, { label => 'qoe-transactional-global', nlabel => 'global.qoe.transactional.count', set => { key_values => [ { name => 'transactional' } ], output_template => 'Global transactional QOE: %s', perfdatas => [ { template => '%s', min => 0, max => 10, label_extra_instance => 1 } ] } }, { label => 'edge-links-count', nlabel => 'global.links.total.count', set => { key_values => [ { name => 'link_count' } ], output_template => '%s link(s)', perfdatas => [ { template => '%d', unit => '', min => 0, label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{links} = [ { label => 'qoe-voice', nlabel => 'link.qoe.voice.count', set => { key_values => [ { name => 'voice' }, { name => 'display' }, { name => 'id' } ], output_template => 'Voice QOE: %s', perfdatas => [ { template => '%s', min => 0, max => 10, label_extra_instance => 1 } ] } }, { label => 'qoe-video', nlabel => 'link.qoe.video.count', set => { key_values => [ { name => 'video' }, { name => 'display' }, { name => 'id' } ], output_template => 'Video QOE: %s', perfdatas => [ { template => '%s', min => 0, max => 10, label_extra_instance => 1 } ] } }, { label => 'qoe-transactional', nlabel => 'link.qoe.transactional.count', set => { key_values => [ { name => 'transactional' }, { name => 'display' }, { name => 'id' } ], output_template => 'Transactional QOE: %s', perfdatas => [ { template => '%s', min => 0, max => 10, label_extra_instance => 1 } ] } }, ]; } sub prefix_edge_output { my ($self, %options) = @_; return "Edge '" . $options{instance_value}->{display} . "' "; } sub prefix_link_output { my ($self, %options) = @_; return "Link '" . $options{instance_value}->{display} . "' [Id: " . $options{instance_value}->{id} . "] "; } sub long_output { my ($self, %options) = @_; return "Checking edge '" . $options{instance_value}->{display} . "' [Id: " . $options{instance_value}->{id} . "] "; } 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-edge-name:s' => { name => 'filter_edge_name' }, 'filter-link-name:s' => { name => 'filter_link_name' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->list_edges(); $self->{edges} = {}; foreach my $edge (@{$results}) { if (defined($self->{option_results}->{filter_edge_name}) && $self->{option_results}->{filter_edge_name} ne '' && $edge->{name} !~ /$self->{option_results}->{filter_edge_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $edge->{name} . "'.", debug => 1); next; } $self->{edges}->{$edge->{name}}->{id} = $edge->{id}; $self->{edges}->{$edge->{name}}->{display} = $edge->{name}; my $links = $options{custom}->list_links( edge_id => $edge->{id}, timeframe => $self->{timeframe} ); my $qoes = $options{custom}->get_links_qoe( edge_id => $edge->{id}, timeframe => $self->{timeframe} ); next if (ref($qoes) ne 'HASH'); $self->{edges}->{$edge->{name}}->{global} = { voice => $qoes->{overallLinkQuality}->{score}->{0}, video => $qoes->{overallLinkQuality}->{score}->{1}, transactional => $qoes->{overallLinkQuality}->{score}->{2} }; foreach my $link (@{$links}) { next if (!defined($qoes->{$link->{link}->{internalId}})); if (defined($self->{option_results}->{filter_link_name}) && $self->{option_results}->{filter_link_name} ne '' && $link->{link}->{displayName} !~ /$self->{option_results}->{filter_link_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $edge->{id} . "'.", debug => 1); next; } $self->{edges}->{$edge->{name}}->{global}->{link_count}++; $self->{edges}->{$edge->{name}}->{links}->{$link->{link}->{displayName}} = { id => $link->{linkId}, display => $link->{link}->{displayName}, voice => $qoes->{$link->{link}->{internalId}}->{score}->{0}, video => $qoes->{$link->{link}->{internalId}}->{score}->{1}, transactional => $qoes->{$link->{link}->{internalId}}->{score}->{2} }; } } if (scalar(keys %{$self->{edges}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No edge found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check links QOE before and global QOE after VeloCloud Enhancements. =over 8 =item B<--filter-edge-name> Filter edge by name (Can be a regexp). =item B<--filter-link-name> Filter link by name (Can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'edge-links-count', 'qoe-voice-global', 'qoe-video-global', 'qoe-transactional-global' (global values) and/or 'qoe-voice', 'qoe-video', 'qoe-transactional' (per link values). =back =cutcentreon-plugins-20220113/cloud/vmware/velocloud/restapi/mode/edgestatus.pm000066400000000000000000000105531417000230700267440ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::vmware::velocloud::restapi::mode::edgestatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf( "State is '%s', Service State is '%s', HA State is '%s', Activation State is '%s'", $self->{result_values}->{edge_state}, $self->{result_values}->{service_state}, $self->{result_values}->{ha_state}, $self->{result_values}->{activation_state} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'edges', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All edges status are ok' }, ]; $self->{maps_counters}->{edges} = [ { label => 'status', type => 2, unknown_default => '%{edge_state} =~ /NEVER_ACTIVATED/', critical_default => '%{edge_state} !~ /CONNECTED/ && %{edge_state} !~ /NEVER_ACTIVATED/', set => { key_values => [ { name => 'edge_state' }, { name => 'service_state' }, { name => 'ha_state' }, { name => 'activation_state' }, { name => 'display' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub prefix_output { my ($self, %options) = @_; return "Edge '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->list_edges(); $self->{edges} = {}; foreach my $edge (@{$results}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $edge->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $edge->{name} . "'.", debug => 1); next; } $self->{edges}->{$edge->{id}} = { display => $edge->{name}, edge_state => $edge->{edgeState}, service_state => $edge->{serviceState}, ha_state => $edge->{haState}, activation_state => $edge->{activationState} } } if (scalar(keys %{$self->{edges}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No edge found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check edge status. =over 8 =item B<--filter-name> Filter edge by name (Can be a regexp). =item B<--unknown-status> Set unknown threshold for status (Default: '%{edge_state} =~ /NEVER_ACTIVATED/'). Can used special variables like: %{edge_state}, %{service_state}, %{ha_state}, %{activation_state}. =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{edge_state}, %{service_state}, %{ha_state}, %{activation_state}. =item B<--critical-status> Set critical threshold for status (Default: '%{edge_state} !~ /CONNECTED/ && %{edge_state} !~ /NEVER_ACTIVATED/'). Can used special variables like: %{edge_state}, %{service_state}, %{ha_state}, %{activation_state}. =back =cut centreon-plugins-20220113/cloud/vmware/velocloud/restapi/mode/linkstatus.pm000066400000000000000000000144041417000230700267740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::vmware::velocloud::restapi::mode::linkstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf( "status is '%s' [vpn state: '%s'] [backup state: '%s']", $self->{result_values}->{state}, $self->{result_values}->{vpn_state}, $self->{result_values}->{backup_state} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'edges', type => 3, cb_prefix_output => 'prefix_edge_output', cb_long_output => 'long_output', message_multiple => 'All edges links status are ok', indent_long_output => ' ', group => [ { name => 'global', type => 0 }, { name => 'links', display_long => 1, cb_prefix_output => 'prefix_link_output', message_multiple => 'All links status are ok', type => 1 } ] } ]; $self->{maps_counters}->{global} = [ { label => 'edge-links-count', nlabel => 'edge.links.total.count', set => { key_values => [ { name => 'link_count' } ], output_template => '%s link(s)', perfdatas => [ { template => '%d', unit => '', min => 0 } ] } } ]; $self->{maps_counters}->{links} = [ { label => 'status', type => 2, critical_default => '%{state} !~ /STABLE/ || %{vpn_state} !~ /STABLE/', set => { key_values => [ { name => 'state' }, { name => 'vpn_state' }, { name => 'backup_state' }, { name => 'display' }, { name => 'id' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub prefix_edge_output { my ($self, %options) = @_; return "Edge '" . $options{instance_value}->{display} . "' "; } sub prefix_link_output { my ($self, %options) = @_; return "Link '" . $options{instance_value}->{display} . "' [Id: " . $options{instance_value}->{id} . "] "; } sub long_output { my ($self, %options) = @_; return "Checking edge '" . $options{instance_value}->{display} . "' [Id: " . $options{instance_value}->{id} . "] "; } 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-edge-name:s' => { name => 'filter_edge_name' }, 'filter-link-name:s' => { name => 'filter_link_name' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->list_edges(); $self->{edges} = {}; foreach my $edge (@{$results}) { if (defined($self->{option_results}->{filter_edge_name}) && $self->{option_results}->{filter_edge_name} ne '' && $edge->{name} !~ /$self->{option_results}->{filter_edge_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $edge->{name} . "'.", debug => 1); next; } $self->{edges}->{$edge->{name}}->{id} = $edge->{id}; $self->{edges}->{$edge->{name}}->{display} = $edge->{name}; my $links = $options{custom}->get_links_metrics( edge_id => $edge->{id}, timeframe => $self->{timeframe} ); foreach my $link (@{$links}) { if (defined($self->{option_results}->{filter_link_name}) && $self->{option_results}->{filter_link_name} ne '' && $link->{link}->{displayName} !~ /$self->{option_results}->{filter_link_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $edge->{id} . "'.", debug => 1); next; } $self->{edges}->{$edge->{name}}->{global}->{link_count}++; $self->{edges}->{$edge->{name}}->{links}->{$link->{link}->{displayName}} = { id => $link->{linkId}, display => $link->{link}->{displayName}, state => $link->{link}->{state}, vpn_state => $link->{link}->{vpnState}, backup_state => defined($link->{link}->{backupState}) ? $link->{link}->{backupState} : '-' }; } } if (scalar(keys %{$self->{edges}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No edge found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check edge links status. =over 8 =item B<--filter-edge-name> Filter edge by name (Can be a regexp). =item B<--filter-link-name> Filter link by name (Can be a regexp). =item B<--unknown-status> Set unknown threshold for status (Default: ''). Can used special variables like: %{state}, %{vpn_state}, %{backup_state}. =item B<--warning-*> B<--critical-*> Warning & Critical thresholds Can be 'status', 'edge-links-count'. For 'status', special variables can be used: %{state}, %{vpn_state}, %{backup_state} (Critical threshold default: '%{state} !~ /STABLE/ || %{vpn_state} !~ /STABLE/'). =back =cut centreon-plugins-20220113/cloud/vmware/velocloud/restapi/mode/linkusage.pm000066400000000000000000000243521417000230700265600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::vmware::velocloud::restapi::mode::linkusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'edges', type => 3, cb_prefix_output => 'prefix_edge_output', cb_long_output => 'long_output', message_multiple => 'All edges links usage are ok', indent_long_output => ' ', group => [ { name => 'global', cb_prefix_output => 'prefix_global_output', type => 0, skipped_code => { -10 => 1 } }, { name => 'links', display_long => 1, cb_prefix_output => 'prefix_link_output', message_multiple => 'All links status are ok', type => 1 } ] } ]; $self->{maps_counters}->{global} = [ { label => 'links-traffic-in', nlabel => 'links.traffic.in.bitspersecond', set => { key_values => [ { name => 'traffic_in' } ], output_template => 'Total Traffic In: %s %s/s', output_change_bytes => 2, perfdatas => [ { template => '%s', min => 0, unit => 'b/s', label_extra_instance => 1 } ] } }, { label => 'links-traffic-out', nlabel => 'links.traffic.out.bitspersecond', set => { key_values => [ { name => 'traffic_out' } ], output_template => 'Total Traffic Out: %s %s/s', output_change_bytes => 2, perfdatas => [ { template => '%s', min => 0, unit => 'b/s', label_extra_instance => 1 } ] } }, { label => 'edge-links-count', nlabel => 'links.total.count', set => { key_values => [ { name => 'link_count' } ], output_template => '%s link(s)', perfdatas => [ { template => '%d', unit => '', min => 0, label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{links} = [ { label => 'traffic-in', nlabel => 'link.traffic.in.bitspersecond', set => { key_values => [ { name => 'traffic_in' }, { name => 'display' }, { name => 'id' } ], output_change_bytes => 2, output_template => 'Traffic In: %s %s/s', perfdatas => [ { template => '%s', min => 0, unit => 'b/s', label_extra_instance => 1 } ] } }, { label => 'traffic-out', nlabel => 'link.traffic.out.bitspersecond', set => { key_values => [ { name => 'traffic_out' }, { name => 'display' }, { name => 'id' } ], output_change_bytes => 2, output_template => 'Traffic Out: %s %s/s', perfdatas => [ { template => '%s', min => 0, unit => 'b/s', label_extra_instance => 1 } ] } }, { label => 'latency-in', nlabel => 'link.latency.in.milliseconds', set => { key_values => [ { name => 'latency_in' }, { name => 'display' }, { name => 'id' } ], output_template => 'Latency In: %.2f ms', perfdatas => [ { template => '%.2f', min => 0, unit => 'ms', label_extra_instance => 1 } ] } }, { label => 'latency-out', nlabel => 'link.latency.out.milliseconds', set => { key_values => [ { name => 'latency_out' }, { name => 'display' }, { name => 'id' } ], output_template => 'Latency Out: %.2f ms', perfdatas => [ { template => '%.2f', min => 0, unit => 'ms', label_extra_instance => 1 } ] } }, { label => 'jitter-in', nlabel => 'link.jitter.in.milliseconds', set => { key_values => [ { name => 'jitter_in' }, { name => 'display' }, { name => 'id' } ], output_template => 'Jitter In: %.2f ms', perfdatas => [ { template => '%.2f', min => 0, unit => 'ms', label_extra_instance => 1 } ] } }, { label => 'jitter-out', nlabel => 'link.jitter.out.milliseconds', set => { key_values => [ { name => 'jitter_out' }, { name => 'display' }, { name => 'id' } ], output_template => 'Jitter Out: %.2f ms', perfdatas => [ { template => '%.2f', min => 0, unit => 'ms', label_extra_instance => 1 } ] } }, { label => 'packet-loss-in', nlabel => 'link.packet.loss.in.percentage', set => { key_values => [ { name => 'packet_loss_in' }, { name => 'display' }, { name => 'id' } ], output_template => 'Packet Loss In: %.2f%%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 } ] } }, { label => 'packet-loss-out', nlabel => 'link.packet.loss.out.percentage', set => { key_values => [ { name => 'packet_loss_out' }, { name => 'display' }, { name => 'id' } ], output_template => 'Packet Loss Out: %.2f%%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 } ] } } ]; } sub prefix_edge_output { my ($self, %options) = @_; return "Edge '" . $options{instance_value}->{display} . "' "; } sub prefix_link_output { my ($self, %options) = @_; return "Link '" . $options{instance_value}->{display} . "' [Id: " . $options{instance_value}->{id} . "] "; } sub long_output { my ($self, %options) = @_; return "Checking edge '" . $options{instance_value}->{display} . "' [Id: " . $options{instance_value}->{id} . "] "; } 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-edge-name:s' => { name => 'filter_edge_name' }, 'filter-link-name:s' => { name => 'filter_link_name' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->list_edges(); $self->{edges} = {}; foreach my $edge (@{$results}) { if (defined($self->{option_results}->{filter_edge_name}) && $self->{option_results}->{filter_edge_name} ne '' && $edge->{name} !~ /$self->{option_results}->{filter_edge_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $edge->{name} . "'.", debug => 1); next; } $self->{edges}->{$edge->{name}} = { id => $edge->{id}, display => $edge->{name}, global => {}, links => {} }; my $links = $options{custom}->get_links_metrics( edge_id => $edge->{id}, timeframe => $self->{timeframe} ); foreach my $link (@{$links}) { if (defined($self->{option_results}->{filter_link_name}) && $self->{option_results}->{filter_link_name} ne '' && $link->{link}->{displayName} !~ /$self->{option_results}->{filter_link_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $edge->{id} . "'.", debug => 1); next; } $self->{edges}->{$edge->{name}}->{global}->{link_count}++; $self->{edges}->{$edge->{name}}->{links}->{$link->{link}->{displayName}} = { id => $link->{linkId}, display => $link->{link}->{displayName}, traffic_out => int($link->{bytesTx} * 8 / $self->{timeframe}), traffic_in => int($link->{bytesRx} * 8 / $self->{timeframe}), latency_out => $link->{bestLatencyMsTx}, latency_in => $link->{bestLatencyMsRx}, jitter_out => $link->{bestJitterMsTx}, jitter_in => $link->{bestJitterMsRx}, packet_loss_out => $link->{bestLossPctTx}, packet_loss_in => $link->{bestLossPctRx} }; if (!defined($self->{edges}->{$edge->{name}}->{global}->{traffic_in})) { $self->{edges}->{$edge->{name}}->{global}->{traffic_in} = 0; $self->{edges}->{$edge->{name}}->{global}->{traffic_out} = 0; } $self->{edges}->{$edge->{name}}->{global}->{traffic_in} += (int($link->{bytesRx} * 8 / $self->{timeframe})); $self->{edges}->{$edge->{name}}->{global}->{traffic_out} += (int($link->{bytesTx} * 8 / $self->{timeframe})); } } if (scalar(keys %{$self->{edges}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'no edge found.'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check links usage per edges. =over 8 =item B<--filter-edge-name> Filter edge by name (Can be a regexp). =item B<--filter-link-name> Filter link by name (Can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'edge-links-count', 'links-traffic-in', 'links-traffic-out', 'traffic-in', 'traffic-out', 'latency-in', 'latency-out', 'jitter-in', 'jitter-out', 'packet-loss-in', 'packet-loss-out'. =back =cut centreon-plugins-20220113/cloud/vmware/velocloud/restapi/mode/listedges.pm000066400000000000000000000057501417000230700265620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::vmware::velocloud::restapi::mode::listedges; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{edges} = $options{custom}->list_edges; } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $edge (@{$self->{edges}}) { $self->{output}->output_add( long_msg => sprintf( "[id = %s][name = %s][description = %s][edge_state = %s]" . "[service_state = %s][ha_state = %s][activation_state = %s]", $edge->{id}, $edge->{name}, defined($edge->{description}) ? $edge->{description} : '', $edge->{edgeState}, $edge->{serviceState}, $edge->{haState}, $edge->{activationState} ) ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List edges:' ); $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 => [ 'id', 'name', 'description', 'edge_state', 'service_state', 'ha_state', 'activation_state' ] ); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $edge (@{$self->{edges}}) { $self->{output}->add_disco_entry( id => $edge->{id}, name => $edge->{name}, description => defined($edge->{description}) ? $edge->{description} : '', edge_state => $edge->{edgeState}, service_state => $edge->{serviceState}, ha_state => $edge->{haState}, activation_state => $edge->{activationState} ); } } 1; __END__ =head1 MODE List edges. =over 8 =back =cut centreon-plugins-20220113/cloud/vmware/velocloud/restapi/mode/listlinks.pm000066400000000000000000000072141417000230700266100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::vmware::velocloud::restapi::mode::listlinks; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-edge-name:s' => { name => 'filter_edge_name' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); $self->{timeframe} = defined($self->{option_results}->{timeframe}) ? $self->{option_results}->{timeframe} : 900; } sub manage_selection { my ($self, %options) = @_; my $edges = $options{custom}->list_edges(); foreach my $edge (@{$edges}) { if (defined($self->{option_results}->{filter_edge_name}) && $self->{option_results}->{filter_edge_name} ne '' && $edge->{name} !~ /$self->{option_results}->{filter_edge_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $edge->{name} . "'.", debug => 1); next; } my $links = $options{custom}->list_links(edge_id => $edge->{id}, timeframe => $self->{timeframe}); foreach my $link (@{$links}) { push @{$self->{links}}, { %{$link}, edgeName => $edge->{name} }; } } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $link (@{$self->{links}}) { $self->{output}->output_add( long_msg => sprintf( "[id = %s][display_name = %s][name = %s][edge_id = %s]" . "[edge_name = %s][state = %s][vpn_state = %s]", $link->{linkId}, $link->{link}->{displayName}, $link->{name}, $link->{link}->{edgeId}, $link->{edgeName}, $link->{link}->{state}, $link->{link}->{vpnState} ) ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List links:' ); $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 => [ 'id', 'display_name', 'name', 'edge_id', 'edge_name', 'state', 'vpn_state' ] ); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $link (@{$self->{links}}) { $self->{output}->add_disco_entry( id => $link->{linkId}, display_name => $link->{link}->{displayName}, name => $link->{name}, edge_id => $link->{link}->{edgeId}, edge_name => $link->{edgeName}, state => $link->{link}->{state}, vpn_state => $link->{link}->{vpnState} ); } } 1; __END__ =head1 MODE List links. =over 8 =item B<--filter-edge-name> Filter edge by name (Can be a regexp). =back =cut centreon-plugins-20220113/cloud/vmware/velocloud/restapi/plugin.pm000066400000000000000000000040361417000230700251450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package cloud::vmware::velocloud::restapi::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} = { 'application-usage' => 'cloud::vmware::velocloud::restapi::mode::applicationusage', 'category-usage' => 'cloud::vmware::velocloud::restapi::mode::categoryusage', 'discovery' => 'cloud::vmware::velocloud::restapi::mode::discovery', 'edge-qoe' => 'cloud::vmware::velocloud::restapi::mode::edgeqoe', 'edge-status' => 'cloud::vmware::velocloud::restapi::mode::edgestatus', 'link-status' => 'cloud::vmware::velocloud::restapi::mode::linkstatus', 'link-usage' => 'cloud::vmware::velocloud::restapi::mode::linkusage', 'list-edges' => 'cloud::vmware::velocloud::restapi::mode::listedges', 'list-links' => 'cloud::vmware::velocloud::restapi::mode::listlinks' }; $self->{custom_modes}->{api} = 'cloud::vmware::velocloud::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check VMware VeloCloud through VeloCloud Orchestrator RestAPI. =cut centreon-plugins-20220113/contrib/000077500000000000000000000000001417000230700166745ustar00rootroot00000000000000centreon-plugins-20220113/contrib/README.md000066400000000000000000000017231417000230700201560ustar00rootroot00000000000000# HOWTO Centos > :warning: **cwrapper_perl is deprecated** because of security issue. > Prefer usage of a sudoers file or use it at your own risk. Install dependencies: # yum install perl-devel 'perl(ExtUtils::Embed)' Compile the wrapper: # gcc -o cwrapper_perl cwrapper_perl.c `perl -MExtUtils::Embed -e ccopts -e ldopts` Create a fatpack: https://github.com/centreon/centreon-plugins/blob/master/doc/en/user/guide.rst#can-i-have-one-standalone-perl-file- Comment following lines in the end of fatpack file: use strict; use warnings; # Not perl embedded compliant at all #use FindBin; #use lib "$FindBin::Bin"; # use lib '/usr/lib/nagios/plugins/'; use centreon::plugins::script; centreon::plugins::script->new()->run(); Set setuid right: # chown root:root cwrapper_perl # chmod 4775 cwrapper_perl Test it: $ cwrapper_perl centreon_protocol_udp.pl --plugin --mode=connection --hostname=10.30.2.65 --port=161 centreon-plugins-20220113/contrib/check_plugins.pl000077500000000000000000000047701417000230700220620ustar00rootroot00000000000000#!/usr/bin/perl # # Copyright 2021 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # 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. # use strict; use warnings; use FindBin; my $plugins = []; sub check_directory { my ($directory) = @_; opendir(my $dh, $directory) || return ; while (my $filename = readdir $dh) { check_directory($directory . '/' . $filename) if ($filename !~ /^\./ && -d $directory . '/' . $filename); if ($filename eq 'plugin.pm') { push @$plugins, $directory . '/' . $filename; } } closedir $dh; } sub check_custommode { my (%options) = @_; my $cmodes = `$options{bin} --plugin=$options{plugin} --list-custommode`; if ($cmodes !~ /Custom Modes Available:\n(.*)/ms) { print " mode: $options{mode}, result=$cmodes"; return ; } foreach my $cmode (split /\n/, $1) { $cmode =~ s/\s+//g; my $result = `$options{bin} --plugin=$options{plugin} --custommode=$cmode --mode=$options{mode}`; print " mode: $options{mode}, custommode: $cmode, result=$result"; } } my $plugin = "$FindBin::Bin/../centreon_plugins.pl"; check_directory("$FindBin::Bin/.."); foreach my $plugin_path (@$plugins) { $plugin_path =~ s{$FindBin::Bin/../}{}; print "plugin: $plugin_path\n"; my $modes = `$plugin --plugin=$plugin_path --list-mode`; if ($modes =~ /Modes Available:\n(.*)/ms) { foreach my $mode (split /\n/, $1) { $mode =~ s/\s+//g; my $result = `$plugin --plugin=$plugin_path --mode=$mode`; if ($result =~ /Need to specify '--custommode'/i) { check_custommode(bin => $plugin, plugin => $plugin_path, mode => $mode); } else { print " mode: $mode, result=$result"; } } } else { print "error: $modes\n"; } print "\n"; } exit(0); centreon-plugins-20220113/contrib/cwrapper_perl.c000066400000000000000000000013171417000230700217070ustar00rootroot00000000000000#include #include static PerlInterpreter *my_perl; static void xs_init (pTHX); EXTERN_C void boot_DynaLoader (pTHX_ CV* cv); EXTERN_C void xs_init(pTHX) { char *file = __FILE__; /* DynaLoader is a special case */ newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file); } int main (int argc, char **argv, char **env) { int exitstatus = 0; PERL_SYS_INIT3(&argc, &argv, &env); my_perl = perl_alloc(); perl_construct(my_perl); PL_exit_flags |= PERL_EXIT_DESTRUCT_END; perl_parse(my_perl, xs_init, argc, argv, (char **)NULL); exitstatus = perl_run(my_perl); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); exit(exitstatus); } centreon-plugins-20220113/database/000077500000000000000000000000001417000230700170005ustar00rootroot00000000000000centreon-plugins-20220113/database/cassandra/000077500000000000000000000000001417000230700207375ustar00rootroot00000000000000centreon-plugins-20220113/database/cassandra/jmx/000077500000000000000000000000001417000230700215355ustar00rootroot00000000000000centreon-plugins-20220113/database/cassandra/jmx/mode/000077500000000000000000000000001417000230700224615ustar00rootroot00000000000000centreon-plugins-20220113/database/cassandra/jmx/mode/cachesusage.pm000066400000000000000000000165151417000230700253020ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::cassandra::jmx::mode::cachesusage; 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 => 'ccache', type => 1, cb_prefix_output => 'prefix_ccache_output', message_multiple => 'All caches are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{ccache} = [ { label => 'used', nlabel => 'ccache.utilization.percentage', set => { key_values => [ { name => 'Capacity_Value' }, { name => 'Size_Value' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_output => $self->can('custom_usage_output'), threshold_use => 'prct_used', perfdatas => [ { label => 'used', value => 'prct_used', template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'hits', nlabel => 'ccache.hits.percentage', set => { key_values => [ { name => 'Requests_Count', diff => 1 }, { name => 'Hits_Count', diff => 1 }, { name => 'display' } ], closure_custom_calc => $self->can('custom_hits_calc'), output_template => 'Hits = %.2f %%', output_use => 'hits_prct', threshold_use => 'hits_prct', perfdatas => [ { label => 'hits', value => 'hits_prct', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } 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) = @_; return -10 if ($options{new_datas}->{$self->{instance} . '_Capacity_Value'} <= 0); $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_Capacity_Value'}; $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_Size_Value'}; $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 custom_hits_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; my $delta_value = $options{new_datas}->{$self->{instance} . '_Hits_Count'} - $options{old_datas}->{$self->{instance} . '_Hits_Count'}; my $delta_total = $options{new_datas}->{$self->{instance} . '_Requests_Count'} - $options{old_datas}->{$self->{instance} . '_Requests_Count'}; $self->{result_values}->{hits_prct} = 0; if ($delta_total > 0) { $self->{result_values}->{hits_prct} = $delta_value * 100 / $delta_total; } return 0; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, }); return $self; } sub prefix_ccache_output { my ($self, %options) = @_; return "Cache '" . $options{instance_value}->{display} . "' "; } sub manage_selection { my ($self, %options) = @_; $self->{ccache} = {}; $self->{request} = [ { mbean => 'org.apache.cassandra.metrics:name=Requests,scope=*,type=Cache', attributes => [ { name => 'Count' } ] }, { mbean => 'org.apache.cassandra.metrics:name=Hits,scope=*,type=Cache', attributes => [ { name => 'Count' } ] }, { mbean => 'org.apache.cassandra.metrics:name=Capacity,scope=*,type=Cache', attributes => [ { name => 'Value' } ] }, # bytes { mbean => 'org.apache.cassandra.metrics:name=Size,scope=*,type=Cache', attributes => [ { name => 'Value' } ] }, # bytes ]; my $result = $options{custom}->get_attributes(request => $self->{request}, nothing_quit => 1); foreach my $mbean (keys %{$result}) { $mbean =~ /scope=(.*?)(?:,|$)/; my $scope = $1; $mbean =~ /name=(.*?)(?:,|$)/; my $name = $1; if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $scope !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $scope . "': no matching filter.", debug => 1); next; } $self->{ccache}->{$scope} = { display => $scope } if (!defined($self->{ccache}->{$scope})); foreach (keys %{$result->{$mbean}}) { $self->{ccache}->{$scope}->{$name . '_' . $_} = $result->{$mbean}->{$_}; } } if (scalar(keys %{$self->{ccache}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No cache found."); $self->{output}->option_exit(); } $self->{cache_name} = "cassandra_" . $self->{mode} . '_' . md5_hex($options{custom}->get_connection_info()) . '_' . (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check cache usage. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='latency' =item B<--filter-name> Filter name (can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'used' (%), 'hits' (%). =back =cut centreon-plugins-20220113/database/cassandra/jmx/mode/clientrequestsusage.pm000066400000000000000000000137441417000230700271270ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::cassandra::jmx::mode::clientrequestsusage; 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 => 'cr', type => 1, cb_prefix_output => 'prefix_cr_output', message_multiple => 'All client requests are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{cr} = [ { label => 'total-latency', nlabel => 'client.request.latency.microsecond', set => { key_values => [ { name => 'TotalLatency_Count', diff => 1 }, { name => 'display' } ], output_template => 'Total Latency : %s us', perfdatas => [ { label => 'total_latency', value => 'TotalLatency_Count', template => '%s', min => 0, unit => 'us', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'timeouts', nlabel => 'client.request.timeout.count', set => { key_values => [ { name => 'Timeouts_Count', diff => 1 }, { name => 'display' } ], output_template => 'Timeouts : %s', perfdatas => [ { label => 'timeouts', value => 'Timeouts_Count', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'unavailables', nlabel => 'client.request.unavailable.count', set => { key_values => [ { name => 'Unavailables_Count', diff => 1 }, { name => 'display' } ], output_template => 'Unavailables : %s', perfdatas => [ { label => 'unavailbles', value => 'Unavailables_Count', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'failures', nlabel => 'client.request.failure.count', set => { key_values => [ { name => 'Failures_Count', diff => 1 }, { name => 'display' } ], output_template => 'Failures : %s', perfdatas => [ { label => 'failures', value => 'Failures_Count', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, }); return $self; } sub prefix_cr_output { my ($self, %options) = @_; return "Client Request '" . $options{instance_value}->{display} . "' "; } sub manage_selection { my ($self, %options) = @_; $self->{cr} = {}; $self->{request} = [ { mbean => 'org.apache.cassandra.metrics:name=TotalLatency,scope=*,type=ClientRequest', attributes => [ { name => 'Count' } ] }, { mbean => 'org.apache.cassandra.metrics:name=Timeouts,scope=*,type=ClientRequest', attributes => [ { name => 'Count' } ] }, { mbean => 'org.apache.cassandra.metrics:name=Unavailables,scope=*,type=ClientRequest', attributes => [ { name => 'Count' } ] }, { mbean => 'org.apache.cassandra.metrics:name=Failures,scope=*,type=ClientRequest', attributes => [ { name => 'Count' } ] }, ]; my $result = $options{custom}->get_attributes(request => $self->{request}, nothing_quit => 1); foreach my $mbean (keys %{$result}) { $mbean =~ /scope=(.*?)(?:,|$)/; my $scope = $1; $mbean =~ /name=(.*?)(?:,|$)/; my $name = $1; if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $scope !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $scope . "': no matching filter.", debug => 1); next; } $self->{cr}->{$scope} = { display => $scope } if (!defined($self->{cr}->{$scope})); foreach (keys %{$result->{$mbean}}) { $self->{cr}->{$scope}->{$name . '_' . $_} = $result->{$mbean}->{$_}; } } if (scalar(keys %{$self->{cr}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No client request found."); $self->{output}->option_exit(); } $self->{cache_name} = "cassandra_" . $self->{mode} . '_' . md5_hex($options{custom}->get_connection_info()) . '_' . (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check client requests usage. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='latency' =item B<--filter-name> Filter name (can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'total-latency', 'timeouts', 'unavailables', 'failures'. =back =cut centreon-plugins-20220113/database/cassandra/jmx/mode/threadpoolsusage.pm000066400000000000000000000155611417000230700264000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::cassandra::jmx::mode::threadpoolsusage; 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 => 'thpool', type => 1, cb_prefix_output => 'prefix_thpool_output', message_multiple => 'All thread pools are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{thpool} = [ { label => 'active-tasks', nlabel => 'thread.tasks.active.count', set => { key_values => [ { name => 'ActiveTasks_Value' }, { name => 'display' } ], output_template => 'Current Active Tasks : %s', perfdatas => [ { label => 'active_tasks', value => 'ActiveTasks_Value', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'pending-tasks', nlabel => 'thread.tasks.pending.count', set => { key_values => [ { name => 'PendingTasks_Value' }, { name => 'display' } ], output_template => 'Current Pending Tasks : %s', perfdatas => [ { label => 'pending_tasks', value => 'PendingTasks_Value', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'total-completed-tasks', nlabel => 'thread.tasks.completed.count', set => { key_values => [ { name => 'CompletedTasks_Value', diff => 1 }, { name => 'display' } ], output_template => 'Total Completed Tasks : %s', perfdatas => [ { label => 'total_completed_tasks', value => 'CompletedTasks_Value', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'total-blocked-tasks', nlabel => 'thread.tasks.blocked.count', set => { key_values => [ { name => 'TotalBlockedTasks_Count', diff => 1 }, { name => 'display' } ], output_template => 'Total Blocked Tasks : %s', perfdatas => [ { label => 'total_blocked_tasks', value => 'TotalBlockedTasks_Count', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'current-blocked-tasks', nlabel => 'thread.tasks.blocked.current.count', set => { key_values => [ { name => 'CurrentlyBlockedTasks_Count', diff => 1 }, { name => 'display' } ], output_template => 'Currently Blocked Tasks : %s', perfdatas => [ { label => 'current_blocked_tasks', value => 'CurrentlyBlockedTasks_Count', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, }); return $self; } sub prefix_thpool_output { my ($self, %options) = @_; return "Thread Pool '" . $options{instance_value}->{display} . "' "; } sub manage_selection { my ($self, %options) = @_; $self->{thpool} = {}; $self->{request} = [ { mbean => 'org.apache.cassandra.metrics:name=ActiveTasks,path=request,scope=*,type=ThreadPools', attributes => [ { name => 'Value' } ] }, { mbean => 'org.apache.cassandra.metrics:name=PendingTasks,path=request,scope=*,type=ThreadPools', attributes => [ { name => 'Value' } ] }, { mbean => 'org.apache.cassandra.metrics:name=CompletedTasks,path=request,scope=*,type=ThreadPools', attributes => [ { name => 'Value' } ] }, { mbean => 'org.apache.cassandra.metrics:name=TotalBlockedTasks,path=request,scope=*,type=ThreadPools', attributes => [ { name => 'Count' } ] }, { mbean => 'org.apache.cassandra.metrics:name=CurrentlyBlockedTasks,path=request,scope=*,type=ThreadPools', attributes => [ { name => 'Count' } ] }, ]; my $result = $options{custom}->get_attributes(request => $self->{request}, nothing_quit => 1); foreach my $mbean (keys %{$result}) { $mbean =~ /scope=(.*?)(?:,|$)/; my $scope = $1; $mbean =~ /name=(.*?)(?:,|$)/; my $name = $1; if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $scope !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $scope . "': no matching filter.", debug => 1); next; } $self->{thpool}->{$scope} = { display => $scope } if (!defined($self->{thpool}->{$scope})); foreach (keys %{$result->{$mbean}}) { $self->{thpool}->{$scope}->{$name . '_' . $_} = $result->{$mbean}->{$_}; } } if (scalar(keys %{$self->{thpool}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No thread pool found."); $self->{output}->option_exit(); } $self->{cache_name} = "cassandra_" . $self->{mode} . '_' . md5_hex($options{custom}->get_connection_info()) . '_' . (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check thread pools usage. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='active-tasks' =item B<--filter-name> Filter name (can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'active-tasks', 'pending-tasks', 'total-completed-tasks', 'total-blocked-tasks', 'current-blocked-tasks'. =back =cut centreon-plugins-20220113/database/cassandra/jmx/plugin.pm000066400000000000000000000030021417000230700233640ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::cassandra::jmx::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}} = ( 'caches-usage' => 'database::cassandra::jmx::mode::cachesusage', 'client-requests-usage' => 'database::cassandra::jmx::mode::clientrequestsusage', 'thread-pools-usage' => 'database::cassandra::jmx::mode::threadpoolsusage', ); $self->{custom_modes}{jolokia} = 'centreon::common::protocols::jmx::custom::jolokia'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Cassandra in JMX. Need Jolokia agent. =cut centreon-plugins-20220113/database/couchdb/000077500000000000000000000000001417000230700204075ustar00rootroot00000000000000centreon-plugins-20220113/database/couchdb/restapi/000077500000000000000000000000001417000230700220565ustar00rootroot00000000000000centreon-plugins-20220113/database/couchdb/restapi/custom/000077500000000000000000000000001417000230700233705ustar00rootroot00000000000000centreon-plugins-20220113/database/couchdb/restapi/custom/api.pm000066400000000000000000000152261417000230700245050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::couchdb::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use JSON::XS; 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 => { 'api-username:s' => { name => 'api_username' }, 'api-password:s' => { name => 'api_password' }, 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'timeout:s' => { name => 'timeout' }, 'unknown-http-status:s' => { name => 'unknown_http_status' }, 'warning-http-status:s' => { name => 'warning_http_status' }, 'critical-http-status:s' => { name => 'critical_http_status' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 5984; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'http'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : ''; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : ''; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or (%{http_code} >= 300 && %{http_code} != 404)'; $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; if (!defined($self->{hostname}) || $self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; if (defined($self->{api_username}) && $self->{api_username} ne '') { $self->{option_results}->{credentials} = 1; $self->{option_results}->{basic} = 1; $self->{option_results}->{username} = $self->{api_username}; $self->{option_results}->{password} = $self->{api_password}; } } sub settings { my ($self, %options) = @_; return if (defined($self->{settings_done})); $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->add_header(key => 'Content-Type', value => 'application/json'); $self->{http}->set_options(%{$self->{option_results}}); $self->{settings_done} = 1; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub request_api { my ($self, %options) = @_; $self->settings(); my $content = $self->{http}->request( %options, unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status}, ); if (!defined($content) || $content eq '') { $self->{output}->add_option_msg(short_msg => "API returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } if ($self->{http}->get_code() == 404) { $self->{output}->add_option_msg(short_msg => 'Cannot get response: maybe the server is in maintenance mode'); $self->{output}->option_exit(); } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } return $decoded; } 1; __END__ =head1 NAME CouchDB Rest API =head1 REST API OPTIONS CouchDB Rest API =over 8 =item B<--hostname> CouchDB hostname. =item B<--port> Port used (Default: 5984) =item B<--proto> Specify https if needed (Default: 'http') =item B<--api-username> API username. =item B<--api-password> API password. =item B<--timeout> Set timeout in seconds (Default: 10). =item B<--unknown-http-status> Threshold unknown for http response code (Default: '%{http_code} < 200 or (%{http_code} >= 300 && %{http_code} != 404)') =item B<--warning-http-status> Threshold warning for http response code =item B<--critical-http-status> Threshold critical for http response code =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/database/couchdb/restapi/mode/000077500000000000000000000000001417000230700230025ustar00rootroot00000000000000centreon-plugins-20220113/database/couchdb/restapi/mode/server.pm000066400000000000000000000211441417000230700246500ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::couchdb::restapi::mode::server; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); use JSON::XS; sub custom_server_output { my ($self, %options) = @_; my $msg = 'server status is ' . $self->{result_values}->{status}; return $msg; } sub custom_compaction_output { my ($self, %options) = @_; my $msg = "compaction status is '" . $self->{result_values}->{compaction_status} . "'"; return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'database', type => 1, cb_prefix_output => 'prefix_db_output', message_multiple => 'All databases are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_server_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold, } }, ]; $self->{maps_counters}->{database} = [ { label => 'compaction-status', threshold => 0, set => { key_values => [ { name => 'compaction_status' }, { name => 'display' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_compaction_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold, } }, { label => 'database-size-active', nlabel => 'server.database.size.active.bytes', set => { key_values => [ { name => 'sizes_active' }, { name => 'display' } ], output_template => 'live data size: %s %s', output_change_bytes => 1, perfdatas => [ { value => 'sizes_active', template => '%d', min => 0, unit => 'B', label_extra_instance => 1, instance_use => 'display' } ], } }, { label => 'database-size-file', nlabel => 'server.database.size.file.bytes', set => { key_values => [ { name => 'sizes_file' }, { name => 'display' } ], output_template => 'file size: %s %s', output_change_bytes => 1, perfdatas => [ { value => 'sizes_file', template => '%d', min => 0, unit => 'B', label_extra_instance => 1, instance_use => 'display' } ], } }, { label => 'database-documents-current', nlabel => 'server.database.documents.currrent.count', display_ok => 0, set => { key_values => [ { name => 'doc_count' }, { name => 'display' } ], output_template => 'number of documents: %s', perfdatas => [ { value => 'doc_count', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' } ], } }, { label => 'database-documents-deleted', nlabel => 'server.database.documents.deleted.count', display_ok => 0, set => { key_values => [ { name => 'doc_del_count' }, { name => 'display' } ], output_template => 'number of deleted documents: %s', perfdatas => [ { value => 'doc_del_count', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' } ], } }, ]; } 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-db-name:s' => { name => 'filter_db_name' }, 'unknown-status:s' => { name => 'unknown_status', default => '' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{status} !~ /^ok/i' }, 'unknown-compaction-status:s' => { name => 'unknown_compaction_status', default => '' }, 'warning-compaction-status:s' => { name => 'warning_compaction_status', default => '' }, 'critical-compaction-status:s' => { name => 'critical_compaction_status', default => '' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => [ 'warning_status', 'critical_status', 'unknown_status', 'warning_compaction_status', 'critical_compaction_status', 'unknown_compaction_status' ]); } sub prefix_db_output { my ($self, %options) = @_; return "Database '" . $options{instance_value}->{display} . "' "; } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->request_api(url_path => '/_up'); $self->{global} = { status => $results->{status} }; $results = $options{custom}->request_api(url_path => '/_all_dbs'); my $db = { keys => $results }; my $encoded; eval { $encoded = JSON::XS->new->utf8->encode($db); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot encode json request"); $self->{output}->option_exit(); } $results = $options{custom}->request_api( method => 'POST', url_path => '/_dbs_info', query_form_post => $encoded ); $self->{database} = {}; foreach (@$results) { if (defined($self->{option_results}->{filter_db_name}) && $self->{option_results}->{filter_db_name} ne '' && $_->{info}->{db_name} !~ /$self->{option_results}->{filter_db_name}/) { $self->{output}->output_add(long_msg => "skipping database '" . $_->{info}->{db_name} . "': no matching filter.", debug => 1); next; } $self->{database}->{$_->{info}->{db_name}} = { display => $_->{info}->{db_name}, compaction_status => $_->{info}->{compact_running} ? 'running' : 'notRunning', doc_count => $_->{info}->{doc_count}, doc_del_count => $_->{info}->{doc_del_count}, sizes_active => $_->{info}->{sizes}->{active}, sizes_file => $_->{info}->{sizes}->{file} }; } } 1; __END__ =head1 MODE Check server status and database stastistics. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^status$' =item B<--filter-db-name> Filter database name (can be a regexp). =item B<--unknown-status> Set unknown threshold for status (Default: ''). Can used special variables like: %{status} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status} =item B<--critical-status> Set critical threshold for status (Default: '%{status} !~ /^ok/i'). Can used special variables like: %{status} =item B<--unknown-compaction-status> Set unknown threshold for status (Default: ''). Can used special variables like: %{compaction_status}, %{display} =item B<--warning-compaction-status> Set warning threshold for status (Default: ''). Can used special variables like: %{compaction_status}, %{display} =item B<--critical-compaction-status> Set critical threshold for status (Default: ''). Can used special variables like: %{compaction_status}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'database-size-active' (B), 'database-size-file' (B), 'database-documents-deleted', 'database-documents-current'. =back =cut centreon-plugins-20220113/database/couchdb/restapi/plugin.pm000066400000000000000000000024461417000230700237200ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::couchdb::restapi::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} } = ( 'server' => 'database::couchdb::restapi::mode::server', ); $self->{custom_modes}{api} = 'database::couchdb::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check CouchDB in Rest API. =cut centreon-plugins-20220113/database/db2/000077500000000000000000000000001417000230700174475ustar00rootroot00000000000000centreon-plugins-20220113/database/db2/dbi.pm000066400000000000000000000063031417000230700205450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::db2::dbi; use base qw(centreon::plugins::dbi); use strict; use warnings; use POSIX qw(:signal_h); sub connect_db2 { my ($self, %options) = @_; $self->{instance} = DBI->connect( 'DBI:' . $self->{data_source}, $self->{username}, $self->{password}, { RaiseError => 0, PrintError => 0, AutoCommit => 1, %{$self->{connect_options_hash}} } ); } sub connect { my ($self, %options) = @_; my $dontquit = (defined($options{dontquit}) && $options{dontquit} == 1) ? 1 : 0; if ($self->{data_source} =~ /PROTOCOL=TCPIP/) { $self->{data_source} .= 'UID=' . $self->{username} . ';' if ($self->{data_source} !~ /UID/ && defined($self->{username})); $self->{data_source} .= 'PWD=' . $self->{password} . ';' if ($self->{data_source} !~ /PWD/ && defined($self->{password})); } # Set ENV if (defined($self->{env})) { foreach (keys %{$self->{env}}) { $ENV{$_} = $self->{env}->{$_}; } } if (defined($self->{timeout})) { my $mask = POSIX::SigSet->new(SIGALRM); my $action = POSIX::SigAction->new( sub { $self->handle_ALRM() }, $mask, ); my $oldaction = POSIX::SigAction->new(); sigaction(SIGALRM, $action, $oldaction); eval { eval { alarm($self->{timeout}); $self->connect_db2(); }; alarm(0); }; sigaction(SIGALRM, $oldaction); } else { $self->connect_db2(); } if (!defined($self->{instance})) { my $err_msg = sprintf('Cannot connect: %s', defined($DBI::errstr) ? $DBI::errstr : '(no error string)'); if ($dontquit == 0) { $self->{output}->add_option_msg(short_msg => $err_msg); $self->{output}->option_exit(exit_litteral => $self->{sql_errors_exit}); } return (-1, $err_msg); } $self->set_version(); return 0; } sub get_dbh { my ($self, %options) = @_; return $self->{instance}; } sub fetchrow_arrayref { my ($self, %options) = @_; return $self->{statement_handle}->fetchrow_arrayref(); } sub get_database_name { my ($self, %options) = @_; my $dbname = 'unknown'; $dbname = $1 if ($self->{data_source} =~ /DATABASE=([^;]*)/i); $dbname = $1 if ($self->{data_source} =~ /DBI:DB2:(.*)/); $dbname =~ s/^\s+//g; $dbname =~ s/\s+$//g; return $dbname; } 1; __END__ centreon-plugins-20220113/database/db2/mode/000077500000000000000000000000001417000230700203735ustar00rootroot00000000000000centreon-plugins-20220113/database/db2/mode/connectedusers.pm000066400000000000000000000060611417000230700237600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::db2::mode::connectedusers; 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 } ]; $self->{maps_counters}->{global} = [ { label => 'connected', nlabel => 'users.connected.count', set => { key_values => [ { name => 'connected' } ], output_template => 'connected users: %d', perfdatas => [ { template => '%d', min => 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-appl-name:s' => { name => 'filter_appl_name' }, 'exclude-appl-name:s' => { name => 'exclude_appl_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); $options{sql}->query(query => q{ SELECT appl_name FROM sysibmadm.applications }); $self->{global} = { connected => 0 }; while (my $row = $options{sql}->fetchrow_arrayref()) { if (defined($self->{option_results}->{filter_appl_name}) && $self->{option_results}->{filter_appl_name} ne '' && $row->[0] !~ /$self->{option_results}->{filter_appl_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $row->[0] . "': no matching filter.", debug => 1); next; } if (defined($self->{option_results}->{exclude_appl_name}) && $self->{option_results}->{exclude_appl_name} ne '' && $row->[0] =~ /$self->{option_results}->{exclude_appl_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $row->[0] . "': no matching filter.", debug => 1); next; } $self->{global}->{connected}++; } } 1; __END__ =head1 MODE Check connected users. =over 8 =item B<--filter-appl-name> Filter users by application name (Can be a regex). =item B<--exclude-appl-name> Exclude users by application name (Can be a regex). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'connected'. =back =cut centreon-plugins-20220113/database/db2/mode/databaselogs.pm000066400000000000000000000150641417000230700233700ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::db2::mode::databaselogs; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_usage_output { my ($self, %options) = @_; my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); return sprintf( 'usage total: %s used: %s (%.2f%%) free: %s (%.2f%%)', $total_size_value . " " . $total_size_unit, $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}, $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free} ); } sub custom_usage_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel}, unit => 'B', instances => [$self->{result_values}->{dbname}, $self->{result_values}->{partition}], value => $self->{result_values}->{used}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}), min => 0, max => $self->{result_values}->{total} ); } sub custom_usage_free_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel}, unit => 'B', instances => [$self->{result_values}->{dbname}, $self->{result_values}->{partition}], value => $self->{result_values}->{free}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}), min => 0, max => $self->{result_values}->{total} ); } sub custom_usage_prct_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel}, unit => '%', instances => [$self->{result_values}->{dbname}, $self->{result_values}->{partition}], value => sprintf('%.2f', $self->{result_values}->{prct_used}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}), min => 0, max => 100 ); } sub prefix_log_output { my ($self, %options) = @_; return sprintf( "database '%s' log '%s' ", $options{instance_value}->{dbname}, $options{instance_value}->{partition} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'logs', type => 1, cb_prefix_output => 'prefix_log_output', message_multiple => 'All database logs are ok' } ]; $self->{maps_counters}->{logs} = [ { label => 'log-usage', nlabel => 'database.log.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' }, { name => 'dbname' }, { name => 'partition' } ], closure_custom_output => $self->can('custom_usage_output'), closure_custom_perfdata => $self->can('custom_usage_perfdata') } }, { label => 'log-usage-free', nlabel => 'database.log.free.bytes', display_ok => 0, set => { key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' }, { name => 'dbname' }, { name => 'partition' } ], closure_custom_output => $self->can('custom_usage_output'), closure_custom_perfdata => $self->can('custom_usage_free_perfdata') } }, { label => 'log-usage-prct', nlabel => 'database.log.usage.percentage', display_ok => 0, set => { key_values => [ { name => 'prct_used' }, { name => 'used' }, { name => 'free' }, { name => 'prct_free' }, { name => 'total' }, { name => 'dbname' }, { name => 'partition' } ], closure_custom_output => $self->can('custom_usage_output'), closure_custom_perfdata => $self->can('custom_usage_prct_perfdata') } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); $options{sql}->query(query => q{ SELECT dbpartitionnum, total_log_used_kb, total_log_available_kb FROM sysibmadm.log_utilization }); my $dbname = $options{sql}->get_database_name(); $self->{logs} = {}; while (my $row = $options{sql}->fetchrow_arrayref()) { my $used = $row->[1] * 1024; my $total = $used + ($row->[2] * 1024); $self->{logs}->{ $row->[0] } = { dbname => $dbname, partition => $row->[0], total => $total, used => $used, free => $total - $used, prct_used => $used * 100 / $total, prct_free => 100 - ($used * 100 / $total) }; } } 1; __END__ =head1 MODE Check database logs utilization. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'usage', 'usage-free', 'usage-prct'. =back =cut centreon-plugins-20220113/database/db2/mode/databaseusage.pm000066400000000000000000000145601417000230700235300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::db2::mode::databaseusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use DBD::DB2::Constants; sub custom_usage_output { my ($self, %options) = @_; my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); return sprintf( 'space usage total: %s used: %s (%.2f%%) free: %s (%.2f%%)', $total_size_value . " " . $total_size_unit, $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}, $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free} ); } sub custom_usage_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel}, unit => 'B', instances => $self->{result_values}->{dbname}, value => $self->{result_values}->{used}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}), min => 0, max => $self->{result_values}->{total} ); } sub custom_usage_free_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel}, unit => 'B', instances => $self->{result_values}->{dbname}, value => $self->{result_values}->{free}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}), min => 0, max => $self->{result_values}->{total} ); } sub custom_usage_prct_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel}, unit => '%', instances => $self->{result_values}->{dbname}, value => sprintf('%.2f', $self->{result_values}->{prct_used}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}), min => 0, max => 100 ); } sub prefix_output { my ($self, %options) = @_; return sprintf( "database '%s' ", $options{instance_value}->{dbname} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_output' } ]; $self->{maps_counters}->{global} = [ { label => 'space-usage', nlabel => 'database.space.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' }, { name => 'dbname' } ], closure_custom_output => $self->can('custom_usage_output'), closure_custom_perfdata => $self->can('custom_usage_perfdata') } }, { label => 'space-usage-free', nlabel => 'database.space.free.bytes', display_ok => 0, set => { key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' }, { name => 'dbname' } ], closure_custom_output => $self->can('custom_usage_output'), closure_custom_perfdata => $self->can('custom_usage_free_perfdata') } }, { label => 'space-usage-prct', nlabel => 'database.space.usage.percentage', display_ok => 0, set => { key_values => [ { name => 'prct_used' }, { name => 'used' }, { name => 'free' }, { name => 'prct_free' }, { name => 'total' }, { name => 'dbname' } ], closure_custom_output => $self->can('custom_usage_output'), closure_custom_perfdata => $self->can('custom_usage_prct_perfdata') } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); my $dbh = $options{sql}->get_dbh(); my ($snapshot_timestamp, $db_size, $db_capacity) = ('', 0, 0); my $sth = $dbh->prepare(q{ CALL SYSPROC.GET_DBSIZE_INFO(?, ?, ?, 0) }); $sth->bind_param_inout(1, \$snapshot_timestamp, 30, { db2_param_type=>SQL_PARAM_OUTPUT() }); $sth->bind_param_inout(2, \$db_size, 30, { db2_param_type=>SQL_PARAM_OUTPUT() }); $sth->bind_param_inout(3, \$db_capacity, 30, { db2_param_type=>SQL_PARAM_OUTPUT() }); $sth->execute(); if (!defined($snapshot_timestamp) || $snapshot_timestamp eq '') { $self->{output}->add_option_msg(short_msg => 'Cannot execute query: ' . $dbh->errstr()); $self->{output}->option_exit(); } $self->{global} = { dbname => $options{sql}->get_database_name(), total => $db_capacity, used => $db_size, free => $db_capacity - $db_size, prct_used => $db_size * 100 / $db_capacity, prct_free => 100 - ($db_size * 100 / $db_capacity) }; } 1; __END__ =head1 MODE Check database space usage. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'space-usage', 'space-usage-free', 'space-usage-prct'. =back =cut centreon-plugins-20220113/database/db2/mode/hadr.pm000066400000000000000000000223531417000230700216540ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::db2::mode::hadr; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use Digest::MD5 qw(md5_hex); sub custom_role_output { my ($self, %options) = @_; return sprintf( 'role: %s [primary member: %s] [standby member: %s]', $self->{result_values}->{role}, $self->{result_values}->{primaryMember}, $self->{result_values}->{standbyMember} ); } sub custom_role_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; $self->{result_values}->{role} = $options{new_datas}->{$self->{instance} . '_role'}; $self->{result_values}->{roleLast} = $options{old_datas}->{$self->{instance} . '_role'}; $self->{result_values}->{primaryMember} = $options{new_datas}->{$self->{instance} . '_primaryMember'}; $self->{result_values}->{primaryMemberLast} = $options{old_datas}->{$self->{instance} . '_primaryMember'}; $self->{result_values}->{standbyMember} = $options{new_datas}->{$self->{instance} . '_standbyMember'}; $self->{result_values}->{standbyMemberLast} = $options{old_datas}->{$self->{instance} . '_standbyMember'}; if (!defined($options{old_datas}->{ $self->{instance} . '_role' })) { $self->{error_msg} = "buffer creation"; return -2; } return 0; } sub server_long_output { my ($self, %options) = @_; return "checking database instance '" . $options{instance} . "'"; } sub prefix_server_output { my ($self, %options) = @_; return "database instance '" . $options{instance} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'servers', type => 3, cb_prefix_output => 'prefix_server_output', cb_long_output => 'server_long_output', indent_long_output => ' ', message_multiple => 'All database instances are ok', group => [ { name => 'role', type => 0, skipped_code => { -10 => 1 } }, { name => 'connection', type => 0, skipped_code => { -10 => 1 } }, { name => 'state', type => 0, skipped_code => { -10 => 1 } }, { name => 'position', type => 0, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'standby-running', nlabel => 'hadr.instances.standby.count', display_ok => 0, set => { key_values => [ { name => 'standby_running' } ], output_template => 'number of standby instances running: %s', perfdatas => [ { template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{role} = [ { label => 'role', type => 2, set => { key_values => [ { name => 'role' }, { name => 'primaryMember' }, { name => 'standbyMember' }, { name => 'standbyId' } ], closure_custom_calc => $self->can('custom_role_calc'), closure_custom_output => $self->can('custom_role_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{connection} = [ { label => 'connection-status', type => 2, warning_default => '%{status} eq "congested"', critical_default => '%{status} eq "disconnected"', set => { key_values => [ { name => 'status' }, { name => 'primaryMember' }, { name => 'standbyMember' }, { name => 'standbyId' } ], output_template => 'connection status: %s', closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{state} = [ { label => 'state', type => 2, critical_default => '%{state} ne "peer"', set => { key_values => [ { name => 'state' }, { name => 'primaryMember' }, { name => 'standbyMember' }, { name => 'standbyId' } ], output_template => 'state: %s', closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{position} = [ { label => 'log-gap', nlabel => 'hadr.instance.log.gap.bytes', set => { key_values => [ { name => 'logGap' } ], output_template => 'log gap: %s %s', output_change_bytes => 1, perfdatas => [ { template => '%d', unit => 'B', label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); $options{sql}->query(query => q{ SELECT STANDBY_ID, HADR_ROLE, HADR_STATE, HADR_CONNECT_STATUS, PRIMARY_MEMBER_HOST, STANDBY_MEMBER_HOST, HADR_LOG_GAP FROM TABLE(MON_GET_HADR(-2)) AS t }); $self->{global} = { standby_running => 0 }; $self->{servers} = {}; while (my $row = $options{sql}->fetchrow_arrayref()) { $self->{servers}->{ $row->[0] } = { role => { standbyId => $row->[0], role => lc($row->[1]), primaryMember => $row->[4], standbyMember => $row->[5] }, connection => { standbyId => $row->[0], status => lc($row->[3]), primaryMember => $row->[4], standbyMember => $row->[5] }, state => { standbyId => $row->[0], state => lc($row->[2]), primaryMember => $row->[4], standbyMember => $row->[5] }, position => { logGap => $row->[6] } }; $self->{global}->{standby_running}++; } $self->{cache_name} = 'db2_' . $self->{mode} . '_' . $options{sql}->get_unique_id4save() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check high availability disaster recovery. =over 8 =item B<--unknown-connection-status> Set unknown threshold for connection status. Can used special variables like: %{status}, %{primaryMember}, %{standbyMember}, %{standbyId} =item B<--warning-connection-status> Set warning threshold for connection status (Default: '%{status} eq "congested"'). Can used special variables like: %{status}, %{primaryMember}, %{standbyMember}, %{standbyId} =item B<--critical-connection-status> Set critical threshold for connection status (Default: '%{status} eq "disconnected"'). Can used special variables like: %{status}, %{primaryMember}, %{standbyMember}, %{standbyId} =item B<--unknown-state> Set unknown threshold for state. Can used special variables like: %{state}, %{primaryMember}, %{standbyMember}, %{standbyId} =item B<--warning-state> Set warning threshold for state. Can used special variables like: %{state}, %{primaryMember}, %{standbyMember}, %{standbyId} =item B<--critical-state> Set critical threshold for state (Default: '%{state} ne "peer"'). Can used special variables like: %{state}, %{primaryMember}, %{standbyMember}, %{standbyId} =item B<--unknown-role> Set unknown threshold for role status. Can used special variables like: %{role}, %{roleLast}, %{primaryMember}, %{primaryMemberLast}, %{standbyMember}, %{standbyMemberLast}, %{standbyId} =item B<--warning-role> Set warning threshold for role status. Can used special variables like: %{role}, %{roleLast}, %{primaryMember}, %{primaryMemberLast}, %{standbyMember}, %{standbyMemberLast}, %{standbyId} =item B<--critical-role> Set critical threshold for role status. Can used special variables like: %{role}, %{roleLast}, %{primaryMember}, %{primaryMemberLast}, %{standbyMember}, %{standbyMemberLast}, %{standbyId} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'standby-running', 'log-gap'. =back =cut centreon-plugins-20220113/database/db2/mode/listtablespaces.pm000066400000000000000000000057361417000230700241260ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::db2::mode::listtablespaces; use base qw(centreon::plugins::mode); use strict; use warnings; my $order = ['name', 'type', 'datatype']; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'notemp' => { name => 'notemp' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); $options{sql}->query(query => q{SELECT tbspace, tbspacetype, datatype FROM syscat.tablespaces}); my $tablespaces = {}; while (my $row = $options{sql}->fetchrow_arrayref()) { if (defined($self->{option_results}->{notemp}) && ($row->[2] eq 'T' || $row->[2] eq 'U')) { $self->{output}->output_add(long_msg => "skipping '" . $row->[0] . "': temporary or undo.", debug => 1); next; } $tablespaces->{ $row->[0] } = { name => $row->[0], type => $row->[1] =~ /^[dD]/ ? 'dms' : 'sms', datatype => $row->[2] }; } return $tablespaces; } sub run { my ($self, %options) = @_; my $tablespaces = $self->manage_selection(%options); foreach (sort keys %$tablespaces) { my $entry = ''; foreach my $label (@$order) { $entry .= '[' . $label . ': ' . $tablespaces->{$_}->{$label} . '] '; } $self->{output}->output_add(long_msg => $entry); } $self->{output}->output_add( severity => 'OK', short_msg => 'List tablespaces:' ); $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 => $order); } sub disco_show { my ($self, %options) = @_; my $tablespaces = $self->manage_selection(%options); foreach (sort keys %$tablespaces) { $self->{output}->add_disco_entry(%{$tablespaces->{$_}}); } } 1; __END__ =head1 MODE List tablespaces. =over 8 =item B<--notemp> skip tablespaces for temporary tables. =back =cut centreon-plugins-20220113/database/db2/mode/tablespaces.pm000066400000000000000000000255071417000230700232300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::db2::mode::tablespaces; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf( 'state: %s', $self->{result_values}->{state} ); } sub custom_usage_output { my ($self, %options) = @_; my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); return sprintf( 'space usage total: %s used: %s (%.2f%%) free: %s (%.2f%%)', $total_size_value . " " . $total_size_unit, $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}, $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free} ); } sub custom_usage_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel}, unit => 'B', instances => [$self->{result_values}->{dbname}, $self->{result_values}->{tbsname}], value => $self->{result_values}->{used}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}), min => 0, max => $self->{result_values}->{total} ); } sub custom_usage_free_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel}, unit => 'B', instances => [$self->{result_values}->{dbname}, $self->{result_values}->{tbsname}], value => $self->{result_values}->{free}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}), min => 0, max => $self->{result_values}->{total} ); } sub custom_usage_prct_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel}, unit => '%', instances => [$self->{result_values}->{dbname}, $self->{result_values}->{tbsname}], value => sprintf('%.2f', $self->{result_values}->{prct_used}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}), min => 0, max => 100 ); } sub prefix_tbs_output { my ($self, %options) = @_; return sprintf( "tablespace '%s' ", $options{instance_value}->{tbsname} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'tbs', type => 1, cb_prefix_output => 'prefix_tbs_output', message_multiple => 'All tablespaces are ok' } ]; $self->{maps_counters}->{tbs} = [ { label => 'status', type => 2, critical_default => '%{state} !~ /normal/i', set => { key_values => [ { name => 'state' }, { name => 'tbsname' }, { name => 'type' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'space-usage', nlabel => 'tablespace.space.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' }, { name => 'tbsname' }, { name => 'dbname' } ], closure_custom_output => $self->can('custom_usage_output'), closure_custom_perfdata => $self->can('custom_usage_perfdata') } }, { label => 'space-usage-free', nlabel => 'tablespace.space.free.bytes', display_ok => 0, set => { key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' }, { name => 'tbsname' }, { name => 'dbname' } ], closure_custom_output => $self->can('custom_usage_output'), closure_custom_perfdata => $self->can('custom_usage_free_perfdata') } }, { label => 'space-usage-prct', nlabel => 'tablespace.space.usage.percentage', display_ok => 0, set => { key_values => [ { name => 'prct_used' }, { name => 'used' }, { name => 'free' }, { name => 'prct_free' }, { name => 'total' }, { name => 'tbsname' }, { name => 'dbname' } ], closure_custom_output => $self->can('custom_usage_output'), closure_custom_perfdata => $self->can('custom_usage_prct_perfdata') } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'filter-type:s' => { name => 'filter_type' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); # from: https://labs.consol.de/nagios/check_db2_health/ $options{sql}->query(query => q{ SELECT tbsp_name, tbsp_type, tbsp_state, tbsp_usable_size_kb, tbsp_total_size_kb, tbsp_used_size_kb, tbsp_free_size_kb, COALESCE(tbsp_using_auto_storage, 0), COALESCE(tbsp_auto_resize_enabled, 0), -- COALESCE(tbsp_increase_size,0), --bigint, conversion problems with dbd CASE WHEN tbsp_increase_size IS NULL OR tbsp_increase_size = 0 THEN 0 ELSE 1 END, COALESCE(tbsp_increase_size_percent, 0) FROM sysibmadm.tbsp_utilization WHERE tbsp_type = 'DMS' UNION ALL SELECT tu.tbsp_name, tu.tbsp_type, tu.tbsp_state, tu.tbsp_usable_size_kb, tu.tbsp_total_size_kb, tu.tbsp_used_size_kb, (cu.fs_total_size_kb - cu.fs_used_size_kb) AS tbsp_free_size_kb, 0, 0, 0, 0 FROM sysibmadm.tbsp_utilization tu INNER JOIN ( SELECT tbsp_id, 1 AS fs_total_size_kb, 0 AS fs_used_size_kb FROM sysibmadm.container_utilization WHERE (fs_total_size_kb IS NULL OR fs_used_size_kb IS NULL) GROUP BY tbsp_id ) cu ON (tu.tbsp_type = 'SMS' AND tu.tbsp_id = cu.tbsp_id) UNION ALL SELECT tu.tbsp_name, tu.tbsp_type, tu.tbsp_state, tu.tbsp_usable_size_kb, tu.tbsp_total_size_kb, tu.tbsp_used_size_kb, (cu.fs_total_size_kb - cu.fs_used_size_kb) AS tbsp_free_size_kb, 0, 0, 0, 0 FROM sysibmadm.tbsp_utilization tu INNER JOIN ( SELECT tbsp_id, SUM(fs_total_size_kb) AS fs_total_size_kb, SUM(fs_used_size_kb) AS fs_used_size_kb FROM sysibmadm.container_utilization WHERE (fs_total_size_kb IS NOT NULL AND fs_used_size_kb IS NOT NULL) GROUP BY tbsp_id ) cu ON (tu.tbsp_type = 'SMS' AND tu.tbsp_id = cu.tbsp_id) }); $self->{tbs} = {}; my $dbname = $options{sql}->get_database_name(); while (my $row = $options{sql}->fetchrow_arrayref()) { my $type = $row->[1] =~ /^[dD]/ ? 'dms' : 'sms'; if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $row->[0] !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping tablespace '" . $row->[0] . "': no matching filter.", debug => 1); next; } if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' && $type !~ /$self->{option_results}->{filter_type}/) { $self->{output}->output_add(long_msg => "skipping tablespace '" . $row->[0] . "': no matching filter.", debug => 1); next; } my $total = $row->[3] * 1024; # usable_size my $used = $row->[5] * 1024; # used_size if ($type eq 'sms') { $total = ($row->[5] * 1024) + ($row->[6] * 1024); # used_size + free_size } $self->{tbs}->{ $row->[0] } = { dbname => $dbname, tbsname => $row->[0], type => $type, state => $row->[2], total => $total, used => $used, free => $total - $used, prct_used => $used * 100 / $total, prct_free => 100 - ($used * 100 / $total) }; } } 1; __END__ =head1 MODE Check tablespaces. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='status' =item B<--filter-type> Filter tablespaces by type (can be a regexp). =item B<--filter-name> Filter tablespaces by name (can be a regexp). =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{tbsname}, %{type}, %{state} =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{tbsname}, %{type}, %{state} =item B<--critical-status> Set critical threshold for status (Default: '%{state} !~ /normal/i'). Can used special variables like: %{tbsname}, %{type}, %{state} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'space-usage', 'space-usage-free', 'space-usage-prct'. =back =cut centreon-plugins-20220113/database/db2/plugin.pm000066400000000000000000000074021417000230700213060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::db2::plugin; use strict; use warnings; use base qw(centreon::plugins::script_sql); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $self->{version} = '0.1'; $self->{modes} = { 'collection' => 'centreon::common::protocols::sql::mode::collection', 'connection-time' => 'centreon::common::protocols::sql::mode::connectiontime', 'connected-users' => 'database::db2::mode::connectedusers', 'database-logs' => 'database::db2::mode::databaselogs', 'database-usage' => 'database::db2::mode::databaseusage', 'hadr' => 'database::db2::mode::hadr', 'list-tablespaces' => 'database::db2::mode::listtablespaces', 'tablespaces' => 'database::db2::mode::tablespaces' }; $self->{sql_modes}->{dbi} = 'database::db2::dbi'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options( arguments => { 'server:s@' => { name => 'server' }, 'port:s@' => { name => 'port' }, 'database:s' => { name => 'database' } } ); $self->{options}->parse_options(); my $options_result = $self->{options}->get_options(); $self->{options}->clean(); if (defined($options_result->{server})) { $self->{sqldefault}->{dbi} = []; for (my $i = 0; $i < scalar(@{$options_result->{server}}); $i++) { next if ($options_result->{server}->[$i] eq ''); $self->{sqldefault}->{dbi}->[$i] = { data_source => 'DB2:PROTOCOL=TCPIP;HOSTNAME=' . $options_result->{server}->[$i] }; if (!defined($options_result->{database}) || $options_result->{database} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --database option'); $self->{output}->option_exit(); } if (!defined($options_result->{port}->[$i]) || $options_result->{port}->[$i] eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --port option'); $self->{output}->option_exit(); } $self->{sqldefault}->{dbi}->[$i]->{data_source} .= ';PORT=' . $options_result->{port}->[$i]; $self->{sqldefault}->{dbi}->[$i]->{data_source} .= ';DATABASE=' . $options_result->{database} . ';'; } } elsif (defined($options_result->{database}) && $options_result->{database} ne '') { $self->{sqldefault}->{dbi} = [ { data_source => 'DB2;' . $options_result->{database} } ]; } $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check DB2 Server. =over 8 =item B<--server> Domain name or IP address of the Db2 database system (Uncataloged database connections) =item B<--port> TCP/IP server port number that is assigned to the Db2 database system =item B<--database> Name for the Db2 database system. If --server is not set, it's a cataloged connection (database alias). =back =cut centreon-plugins-20220113/database/elasticsearch/000077500000000000000000000000001417000230700216125ustar00rootroot00000000000000centreon-plugins-20220113/database/elasticsearch/restapi/000077500000000000000000000000001417000230700232615ustar00rootroot00000000000000centreon-plugins-20220113/database/elasticsearch/restapi/custom/000077500000000000000000000000001417000230700245735ustar00rootroot00000000000000centreon-plugins-20220113/database/elasticsearch/restapi/custom/api.pm000066400000000000000000000116461417000230700257120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::elasticsearch::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use JSON::XS; 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 => { 'hostname:s@' => { name => 'hostname' }, 'port:s@' => { name => 'port' }, 'proto:s@' => { name => 'proto' }, 'username:s@' => { name => 'username' }, 'password:s@' => { name => 'password' }, 'timeout:s@' => { name => 'timeout' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? shift(@{$self->{option_results}->{hostname}}) : undef; $self->{port} = (defined($self->{option_results}->{port})) ? shift(@{$self->{option_results}->{port}}) : 9200; $self->{proto} = (defined($self->{option_results}->{proto})) ? shift(@{$self->{option_results}->{proto}}) : 'http'; $self->{username} = (defined($self->{option_results}->{username})) ? shift(@{$self->{option_results}->{username}}) : ''; $self->{password} = (defined($self->{option_results}->{password})) ? shift(@{$self->{option_results}->{password}}) : ''; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? shift(@{$self->{option_results}->{timeout}}) : 10; if (!defined($self->{hostname})) { $self->{output}->add_option_msg(short_msg => "Need to specify hostname option."); $self->{output}->option_exit(); } if (!defined($self->{hostname}) || scalar(@{$self->{option_results}->{hostname}}) == 0) { return 0; } return 1; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; if (defined($self->{username}) && $self->{username} ne '') { $self->{option_results}->{credentials} = 1; $self->{option_results}->{basic} = 1; $self->{option_results}->{username} = $self->{username}; $self->{option_results}->{password} = $self->{password}; } } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->set_options(%{$self->{option_results}}); } sub get { my ($self, %options) = @_; $self->settings(); my $response = $self->{http}->request(url_path => $options{path}, critical_status => '', warning_status => ''); my $content; eval { $content = JSON::XS->new->utf8->decode($response); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } if (defined($content->{errmsg})) { $self->{output}->add_option_msg(short_msg => "Cannot get data: " . $content->{errmsg}); $self->{output}->option_exit(); } return $content; } 1; __END__ =head1 NAME Elasticsearch REST API =head1 SYNOPSIS Elasticsearch Rest API custom mode =head1 REST API OPTIONS =over 8 =item B<--hostname> Elasticsearch hostname. =item B<--port> Port used (Default: 9200) =item B<--proto> Specify https if needed (Default: 'http') =item B<--username> Elasticsearch username. =item B<--password> Elasticsearch password. =item B<--timeout> Set HTTP timeout =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/database/elasticsearch/restapi/mode/000077500000000000000000000000001417000230700242055ustar00rootroot00000000000000centreon-plugins-20220113/database/elasticsearch/restapi/mode/clusterstatistics.pm000066400000000000000000000263441417000230700303500ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::elasticsearch::restapi::mode::clusterstatistics; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = "Cluster '" . $self->{result_values}->{display} . "' Status '" . $self->{result_values}->{status} . "'"; return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; $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 }, ]; $self->{maps_counters}->{global} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { 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 => \&catalog_status_threshold, } }, { label => 'nodes-total', nlabel => 'nodes.total.count', set => { key_values => [ { name => 'nodes_total' } ], output_template => 'Nodes: %d', perfdatas => [ { value => 'nodes_total', template => '%d', min => 0 }, ], } }, { label => 'nodes-data', nlabel => 'nodes.data.count', display_ok => 0, set => { key_values => [ { name => 'nodes_data' }, { name => 'nodes_total' } ], output_template => 'Nodes Data: %d', perfdatas => [ { value => 'nodes_data', template => '%d', min => 0, max => 'nodes_total' }, ], } }, { label => 'nodes-coordinating', nlabel => 'nodes.coordinating.count', display_ok => 0, set => { key_values => [ { name => 'nodes_coordinating' }, { name => 'nodes_total' } ], output_template => 'Nodes Coordinating: %d', perfdatas => [ { value => 'nodes_coordinating', template => '%d', min => 0, max => 'nodes_total' }, ], } }, { label => 'nodes-master', nlabel => 'nodes.master.count', display_ok => 0, set => { key_values => [ { name => 'nodes_master' }, { name => 'nodes_total' } ], output_template => 'Nodes Master: %d', perfdatas => [ { value => 'nodes_master', template => '%d', min => 0, max => 'nodes_total' }, ], } }, { label => 'nodes-ingest', nlabel => 'nodes.ingest.count', display_ok => 0, set => { key_values => [ { name => 'nodes_ingest' }, { name => 'nodes_total' } ], output_template => 'Nodes Ingest: %d', perfdatas => [ { value => 'nodes_ingest', template => '%d', min => 0, max => 'nodes_total' }, ], } }, { label => 'indices-total', nlabel => 'indices.total.count', set => { key_values => [ { name => 'indices_count' } ], output_template => 'Indices: %d', perfdatas => [ { value => 'indices_count', template => '%d', min => 0 }, ], } }, { label => 'shards-total', nlabel => 'shards.total.count', set => { key_values => [ { name => 'shards_total' } ], output_template => 'Shards: %d', perfdatas => [ { value => 'shards_total', template => '%d', min => 0 }, ], } }, { label => 'shards-active-count', nlabel => 'shards.active.count', display_ok => 0, set => { key_values => [ { name => 'shards_active' } ], output_template => 'Shards Active: %d', perfdatas => [ { value => 'shards_active', template => '%d', min => 0, max => 'shards_total' }, ], } }, { label => 'shards-active-percentage', nlabel => 'shards.active.percentage', display_ok => 0, set => { key_values => [ { name => 'active_shards_percent' } ], output_template => 'Shards Active: %.2f%%', perfdatas => [ { value => 'active_shards_percent', template => '%.2f', min => 0, max => 100, unit => '%' }, ], } }, { label => 'shards-unassigned', nlabel => 'shards.unassigned.count', set => { key_values => [ { name => 'shards_unassigned' }, { name => 'shards_total' } ], output_template => 'Shards Unassigned: %d', perfdatas => [ { value => 'shards_unassigned', template => '%d', min => 0, max => 'shards_total' }, ], } }, { label => 'shards-relocating', nlabel => 'shards.relocating.count', display_ok => 0, set => { key_values => [ { name => 'shards_relocating' }, { name => 'shards_total' } ], output_template => 'Shards Relocating: %d', perfdatas => [ { value => 'shards_relocating', template => '%d', min => 0, max => 'shards_total' }, ], } }, { label => 'shards-initializing', nlabel => 'shards.initializing.count', display_ok => 0, set => { key_values => [ { name => 'shards_initializing' }, { name => 'shards_total' } ], output_template => 'Shards Initializing: %d', perfdatas => [ { value => 'shards_initializing', template => '%d', min => 0, max => 'shards_total' }, ], } }, { label => 'tasks-pending', nlabel => 'tasks.pending.count', set => { key_values => [ { name => 'tasks_pending' } ], output_template => 'Tasks Pending: %d', perfdatas => [ { value => 'tasks_pending', template => '%d', min => 0 }, ], } }, { label => 'documents-total', nlabel => 'documents.total.count', set => { key_values => [ { name => 'docs_count' } ], output_template => 'Documents: %d', perfdatas => [ { value => 'docs_count', template => '%d', min => 0 }, ], } }, { label => 'data-size', nlabel => 'data.size.bytes', set => { key_values => [ { name => 'size_in_bytes' } ], output_template => 'Data: %s%s', output_change_bytes => 1, perfdatas => [ { value => 'size_in_bytes', template => '%s', min => 0, unit => 'B' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { "warning-status:s" => { name => 'warning_status', default => '%{status} =~ /yellow/i' }, "critical-status:s" => { name => 'critical_status', default => '%{status} =~ /red/i' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; my $cluster_health = $options{custom}->get(path => '/_cluster/health'); my $cluster_stats = $options{custom}->get(path => '/_cluster/stats'); $self->{global} = { display => $cluster_stats->{cluster_name}, status => $cluster_stats->{status}, nodes_total => $cluster_stats->{nodes}->{count}->{total}, nodes_data => $cluster_stats->{nodes}->{count}->{data}, nodes_coordinating => $cluster_stats->{nodes}->{count}->{coordinating_only}, nodes_master => $cluster_stats->{nodes}->{count}->{master}, nodes_ingest => $cluster_stats->{nodes}->{count}->{ingest}, indices_count => $cluster_stats->{indices}->{count}, shards_total => $cluster_stats->{indices}->{shards}->{total}, shards_active => $cluster_health->{active_shards}, shards_unassigned => $cluster_health->{unassigned_shards}, shards_relocating => $cluster_health->{relocating_shards}, shards_initializing => $cluster_health->{initializing_shards}, active_shards_percent => $cluster_health->{active_shards_percent_as_number}, tasks_pending => $cluster_health->{number_of_pending_tasks}, docs_count => $cluster_stats->{indices}->{docs}->{count}, size_in_bytes => $cluster_stats->{indices}->{store}->{size_in_bytes}, }; } 1; __END__ =head1 MODE Check cluster statistics. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^status$' =item B<--warning-*> Threshold warning. Can be: 'nodes-total', 'nodes-data', 'nodes-coordinating', 'nodes-master', 'nodes-ingest', 'indices-total', 'shards-total', 'shards-active-count', 'shards-active-percentage', 'shards-unassigned', 'shards-relocating', 'shards-initializing', 'tasks-pending', 'documents-total', 'data-size'. =item B<--critical-*> Threshold critical. Can be: 'nodes-total', 'nodes-data', 'nodes-coordinating', 'nodes-master', 'nodes-ingest', 'indices-total', 'shards-total', 'shards-active-count', 'shards-active-percentage', 'shards-unassigned', 'shards-relocating', 'shards-initializing', 'tasks-pending', 'documents-total', 'data-size'. =item B<--warning-status> Set warning threshold for status (Default: '%{status} =~ /yellow/i') Can used special variables like: %{status}. =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /red/i'). Can used special variables like: %{status}. =back =cut centreon-plugins-20220113/database/elasticsearch/restapi/mode/indicestatistics.pm000066400000000000000000000167241417000230700301230ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::elasticsearch::restapi::mode::indicestatistics; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; return "Status '" . $self->{result_values}->{status} . "'"; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'indices', type => 1, cb_prefix_output => 'prefix_indices_output', message_multiple => 'All indices are ok' }, ]; $self->{maps_counters}->{indices} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { 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 => \&catalog_status_threshold, } }, { label => 'documents-total', nlabel => 'indice.documents.total.count', set => { key_values => [ { name => 'docs_count' }, { name => 'display' } ], output_template => 'Documents: %d', perfdatas => [ { value => 'docs_count', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'data-size-primaries', nlabel => 'indice.data.primaries.size.bytes', set => { key_values => [ { name => 'size_in_bytes_primaries' }, { name => 'display' } ], output_template => 'Data Primaries: %s%s', output_change_bytes => 1, perfdatas => [ { value => 'size_in_bytes_primaries', template => '%s', min => 0, unit => 'B', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'data-size-total', nlabel => 'indice.data.total.size.bytes', set => { key_values => [ { name => 'size_in_bytes_total' }, { name => 'display' } ], output_template => 'Data Total: %s%s', output_change_bytes => 1, perfdatas => [ { value => 'size_in_bytes_total', template => '%s', min => 0, unit => 'B', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'shards-active', nlabel => 'shards.active.count', set => { key_values => [ { name => 'shards_active' }, { name => 'display' } ], output_template => 'Shards Active: %d', perfdatas => [ { value => 'shards_active', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'shards-unassigned', nlabel => 'shards.unassigned.count', set => { key_values => [ { name => 'shards_unassigned' }, { name => 'display' } ], output_template => 'Shards Unassigned: %d', perfdatas => [ { value => 'shards_unassigned', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "warning-status:s" => { name => 'warning_status', default => '%{status} =~ /yellow/i' }, "critical-status:s" => { name => 'critical_status', default => '%{status} =~ /red/i' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub prefix_indices_output { my ($self, %options) = @_; return "Indices '" . $options{instance_value}->{display} . "' "; } sub manage_selection { my ($self, %options) = @_; $self->{indices} = {}; my $indices = $options{custom}->get(path => '/_cluster/health?level=indices'); my $stats = $options{custom}->get(path => '/_stats'); foreach my $indice (keys %{$indices->{indices}}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $indice !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $indice . "': no matching filter.", debug => 1); next; } $self->{indices}->{$indice} = { display => $indice, status => $indices->{indices}->{$indice}->{status}, shards_active => $indices->{indices}->{$indice}->{active_shards}, shards_unassigned => $indices->{indices}->{$indice}->{unassigned_shards}, docs_count => $stats->{indices}->{$indice}->{primaries}->{docs}->{count}, size_in_bytes_primaries => $stats->{indices}->{$indice}->{primaries}->{store}->{size_in_bytes}, size_in_bytes_total => $stats->{indices}->{$indice}->{total}->{store}->{size_in_bytes}, }; } if (scalar(keys %{$self->{indices}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No indices found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check indices statistics. =over 8 =item B<--filter-name> Filter name (can be a regexp). =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^status$' =item B<--warning-*> Threshold warning. Can be: 'documents-total', 'data-size-primaries', 'data-size-total', 'shards-active', 'shards-unassigned'. =item B<--critical-*> Threshold critical. Can be: 'documents-total', 'data-size-primaries', 'data-size-total', 'shards-active', 'shards-unassigned'. =item B<--warning-status> Set warning threshold for status (Default: '%{status} =~ /yellow/i') Can used special variables like: %{display}, %{status}. =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /red/i'). Can used special variables like: %{display}, %{status}. =back =cut centreon-plugins-20220113/database/elasticsearch/restapi/mode/license.pm000066400000000000000000000062451417000230700261740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::elasticsearch::restapi::mode::license; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf( "License Status '%s' [type: %s] [issued to: %s] [issue date: %s]", $self->{result_values}->{status}, $self->{result_values}->{type}, $self->{result_values}->{issued_to}, $self->{result_values}->{issue_date} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, ]; $self->{maps_counters}->{global} = [ { label => 'status', type => 2, critical_default => '%{status} !~ /active/i', set => { key_values => [ { name => 'status' }, { name => 'type' }, { name => 'issued_to' }, { name => 'issue_date' }, { name => 'expiry_date_in_seconds' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->get(path => '/_license'); $self->{global} = { type => $result->{license}->{type}, status => $result->{license}->{status}, issued_to => $result->{license}->{issued_to}, issue_date => $result->{license}->{issue_date}, expiry_date_in_seconds => defined($result->{license}->{expiry_date_in_millis}) ? int($result->{license}->{expiry_date_in_millis} / 1000) : "n/a" }; } 1; __END__ =head1 MODE Check license. =over 8 =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{status}, %{type}, %{issued_to}, %{expiry_date_in_seconds}. =item B<--critical-status> Set critical threshold for status (Default: '%{status} !~ /active/i'). Can used special variables like: %{status}, %{type}, %{issued_to}, %{expiry_date_in_seconds}. =back =cut centreon-plugins-20220113/database/elasticsearch/restapi/mode/listindices.pm000066400000000000000000000046021417000230700270570ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::elasticsearch::restapi::mode::listindices; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{results} = $options{custom}->get(path => '/_cluster/health?level=indices'); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $indice (keys %{$self->{results}->{indices}}) { $self->{output}->output_add(long_msg => sprintf("[name = %s][status = %s]", $indice, $self->{results}->{indices}->{$indice}->{status}) ); } $self->{output}->output_add(severity => 'OK', short_msg => "List indices:"); $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', 'status']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $indice (keys %{$self->{results}->{indices}}) { $self->{output}->add_disco_entry( name => $indice, status => $self->{results}->{indices}->{$indice}->{status} ); } } 1; __END__ =head1 MODE List indices =over 8 =back =cut centreon-plugins-20220113/database/elasticsearch/restapi/mode/listnodes.pm000066400000000000000000000050301417000230700265450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::elasticsearch::restapi::mode::listnodes; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{results} = $options{custom}->get(path => '/_nodes/stats'); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $node (keys %{$self->{results}->{nodes}}) { $self->{output}->output_add(long_msg => sprintf("[name = %s][host = %s][ip = %s]", $self->{results}->{nodes}->{$node}->{name}, $self->{results}->{nodes}->{$node}->{host}, $self->{results}->{nodes}->{$node}->{ip}) ); } $self->{output}->output_add(severity => 'OK', short_msg => "List nodes:"); $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', 'host', 'ip']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $node (keys %{$self->{results}->{nodes}}) { $self->{output}->add_disco_entry( name => $self->{results}->{nodes}->{$node}->{name}, host => $self->{results}->{nodes}->{$node}->{host}, ip => $self->{results}->{nodes}->{$node}->{ip} ); } } 1; __END__ =head1 MODE List nodes =over 8 =back =cut centreon-plugins-20220113/database/elasticsearch/restapi/mode/nodestatistics.pm000066400000000000000000000145531417000230700276130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::elasticsearch::restapi::mode::nodestatistics; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'nodes', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All nodes are ok' }, ]; $self->{maps_counters}->{nodes} = [ { label => 'jvm-heap-usage', nlabel => 'node.jvm.heap.usage.percentage', set => { key_values => [ { name => 'heap_used_percent' }, { name => 'display' } ], output_template => 'JVM Heap: %d%%', perfdatas => [ { value => 'heap_used_percent', template => '%d', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'jvm-heap-usage-bytes', nlabel => 'node.jvm.heap.usage.bytes', display_ok => 0, set => { key_values => [ { name => 'heap_used_in_bytes' }, { name => 'heap_max_in_bytes' }, { name => 'display' } ], output_template => 'JVM Heap Bytes: %s%s', output_change_bytes => 1, perfdatas => [ { value => 'heap_used_in_bytes', template => '%s', min => 0, max => 'heap_max_in_bytes', unit => 'B', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'disk-free', nlabel => 'node.disk.free.bytes', set => { key_values => [ { name => 'available_in_bytes' }, { name => 'total_in_bytes' }, { name => 'display' } ], output_template => 'Free Disk Space: %s%s', output_change_bytes => 1, perfdatas => [ { value => 'available_in_bytes', template => '%s', min => 0, max => 'total_in_bytes', unit => 'B', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'documents-total', nlabel => 'node.documents.total.count', set => { key_values => [ { name => 'docs_count' }, { name => 'display' } ], output_template => 'Documents: %d', perfdatas => [ { value => 'docs_count', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'data-size', nlabel => 'node.data.size.bytes', set => { key_values => [ { name => 'size_in_bytes' }, { name => 'display' } ], output_template => 'Data: %s%s', output_change_bytes => 1, perfdatas => [ { value => 'size_in_bytes', template => '%s', min => 0, unit => 'B', label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub prefix_output { my ($self, %options) = @_; return "Node '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{nodes} = {}; my $nodes_stats = $options{custom}->get(path => '/_nodes/stats'); foreach my $node (keys %{$nodes_stats->{nodes}}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $nodes_stats->{nodes}->{$node}->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $nodes_stats->{nodes}->{$node}->{name} . "': no matching filter.", debug => 1); next; } $self->{nodes}->{$node} = { display => $nodes_stats->{nodes}->{$node}->{name}, indices_count => $nodes_stats->{indices}->{count}, heap_used_percent => $nodes_stats->{nodes}->{$node}->{jvm}->{mem}->{heap_used_percent}, heap_used_in_bytes => $nodes_stats->{nodes}->{$node}->{jvm}->{mem}->{heap_used_in_bytes}, heap_max_in_bytes => $nodes_stats->{nodes}->{$node}->{jvm}->{mem}->{heap_max_in_bytes}, available_in_bytes => $nodes_stats->{nodes}->{$node}->{fs}->{total}->{available_in_bytes}, total_in_bytes => $nodes_stats->{nodes}->{$node}->{fs}->{total}->{total_in_bytes}, docs_count => $nodes_stats->{nodes}->{$node}->{indices}->{docs}->{count}, size_in_bytes => $nodes_stats->{nodes}->{$node}->{indices}->{store}->{size_in_bytes}, }; } if (scalar(keys %{$self->{nodes}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No nodes found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check nodes statistics. =over 8 =item B<--filter-name> Filter name (can be a regexp). =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='heap' =item B<--warning-*> Threshold warning. Can be: 'data-size', 'disk-free', 'documents-total', 'jvm-heap-usage' (in %), 'jvm-heap-usage-bytes'. =item B<--critical-*> Threshold critical. Can be: 'data-size', 'disk-free', 'documents-total', 'jvm-heap-usage' (in %), 'jvm-heap-usage-bytes'. =back =cut centreon-plugins-20220113/database/elasticsearch/restapi/plugin.pm000066400000000000000000000034401417000230700251160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::elasticsearch::restapi::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} = { 'cluster-statistics' => 'database::elasticsearch::restapi::mode::clusterstatistics', 'indice-statistics' => 'database::elasticsearch::restapi::mode::indicestatistics', 'license' => 'database::elasticsearch::restapi::mode::license', 'list-indices' => 'database::elasticsearch::restapi::mode::listindices', 'list-nodes' => 'database::elasticsearch::restapi::mode::listnodes', 'node-statistics' => 'database::elasticsearch::restapi::mode::nodestatistics' }; $self->{custom_modes}->{api} = 'database::elasticsearch::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Elasticsearch through HTTP/REST API. =cut centreon-plugins-20220113/database/firebird/000077500000000000000000000000001417000230700205665ustar00rootroot00000000000000centreon-plugins-20220113/database/firebird/mode/000077500000000000000000000000001417000230700215125ustar00rootroot00000000000000centreon-plugins-20220113/database/firebird/mode/longqueries.pm000066400000000000000000000132031417000230700244040ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::firebird::mode::longqueries; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::misc; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning:s" => { name => 'warning', }, "critical:s" => { name => 'critical', }, "seconds:s" => { name => 'seconds', default => 60 }, "filter-user:s" => { name => 'filter_user' }, "filter-state:s" => { name => 'filter_state', default => '^(?!(0)$)' }, }); 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}->{seconds}) || $self->{option_results}->{seconds} !~ /^[0-9]+$/) { $self->{output}->add_option_msg(short_msg => "Please set the option --seconds."); $self->{output}->option_exit(); } } sub run { my ($self, %options) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); $self->{sql}->query(query => q{SELECT ma.MON$USER as MYUSER, ms.MON$STATE as MYSTATE, ms.MON$SQL_TEXT as MYQUERY, (DATEDIFF(second, timestamp '1/1/1970 00:00:00', ms.MON$TIMESTAMP)) as MYTIME FROM MON$STATEMENTS ms, MON$ATTACHMENTS ma WHERE ms.MON$ATTACHMENT_ID = ma.MON$ATTACHMENT_ID}); my $long_queries = 0; my @queries = (); while ((my $row = $self->{sql}->fetchrow_hashref())) { $row->{MYUSER} = centreon::plugins::misc::trim($row->{MYUSER}); $row->{MYQUERY} = '-' if (!defined($row->{MYQUERY})); next if (!defined($row->{MYTIME})); next if (defined($self->{option_results}->{filter_user}) && $self->{option_results}->{filter_user} ne '' && $row->{MYUSER} !~ /$self->{option_results}->{filter_user}/i); next if (defined($self->{option_results}->{filter_state}) && $self->{option_results}->{filter_state} ne '' && $row->{MYSTATE} !~ /$self->{option_results}->{filter_state}/i); if (defined($self->{option_results}->{seconds}) && $self->{option_results}->{seconds} ne '' && (time() - $row->{MYTIME}) >= $self->{option_results}->{seconds}) { push @queries, { time => time() - $row->{MYTIME}, query => $row->{MYQUERY} }; $long_queries++; } } my $exit_code = $self->{perfdata}->threshold_check(value => $long_queries, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("%s queries over %s seconds", $long_queries, $self->{option_results}->{seconds})); $self->{output}->perfdata_add(label => 'longqueries', nlabel => 'longqueries.count', value => $long_queries, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0); for (my $i = 0; $i < 10 && $i < scalar(@queries); $i++) { $queries[$i]->{query} =~ s/\|/-/mg; $self->{output}->output_add(long_msg => sprintf("[time: %s] [query: %s]", $queries[$i]->{time}, substr($queries[$i]->{query}, 0, 1024))); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check current number of long queries on the database (firebird version >= 2.1) =over 8 =item B<--warning> Threshold warning (number of long queries). =item B<--critical> Threshold critical (number of long queries). =item B<--seconds> Filter queries over X seconds (Default: 60). =item B<--filter-user> Filter by user (can be a regexp). =item B<--filter-state> Filter by state (can be a regexp. Default: '^(?!(0)$)'). =back =cut centreon-plugins-20220113/database/firebird/mode/memory.pm000066400000000000000000000200511417000230700233560ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::firebird::mode::memory; 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, cb_prefix_output => 'prefix_output' } ]; $self->{maps_counters}->{global} = [ { label => 'used', nlabel => 'database.usage.bytes', set => { key_values => [ { name => 'database_used' }, { name => 'database_allocated' } ], closure_custom_calc => $self->can('custom_unit_calc'), closure_custom_calc_extra_options => { label_ref => 'database' }, closure_custom_output => $self->can('custom_used_output'), threshold_use => 'prct', closure_custom_perfdata => $self->can('custom_used_perfdata') } }, { label => 'attachment', nlabel => 'attachment.usage.bytes', set => { key_values => [ { name => 'attachment_used' }, { name => 'attachment_allocated' } ], closure_custom_calc => $self->can('custom_unit_calc'), closure_custom_calc_extra_options => { label_ref => 'attachment' }, closure_custom_output => $self->can('custom_unit_output'), threshold_use => 'prct', closure_custom_perfdata => $self->can('custom_unit_perfdata') } }, { label => 'transaction', nlabel => 'transaction.usage.bytes', set => { key_values => [ { name => 'transaction_used' }, { name => 'transaction_allocated' } ], closure_custom_calc => $self->can('custom_unit_calc'), closure_custom_calc_extra_options => { label_ref => 'transaction' }, closure_custom_output => $self->can('custom_unit_output'), threshold_use => 'prct', closure_custom_perfdata => $self->can('custom_unit_perfdata') } }, { label => 'statement', nlabel => 'statement.usage.bytes', set => { key_values => [ { name => 'statement_used' }, { name => 'statement_allocated' } ], closure_custom_calc => $self->can('custom_unit_calc'), closure_custom_calc_extra_options => { label_ref => 'statement' }, closure_custom_output => $self->can('custom_unit_output'), threshold_use => 'prct', closure_custom_perfdata => $self->can('custom_unit_perfdata') } }, { label => 'call', nlabel => 'call.usage.bytes', set => { key_values => [ { name => 'call_used' }, { name => 'call_allocated' } ], closure_custom_calc => $self->can('custom_unit_calc'), closure_custom_calc_extra_options => { label_ref => 'call' }, closure_custom_output => $self->can('custom_unit_output'), threshold_use => 'prct', closure_custom_perfdata => $self->can('custom_unit_perfdata') } }, ]; } sub custom_used_output { my ($self, %options) = @_; my $free = $self->{result_values}->{total} - $self->{result_values}->{used}; my ($total_value, $total_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); my ($used_value, $used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); my ($free_value, $free_unit) = $self->{perfdata}->change_bytes(value => $free); return sprintf( "Total: %s Used : %s (%.2f %%) Free : %s (%.2f %%)", $total_value . ' ' . $total_unit, $used_value . ' ' . $used_unit, $self->{result_values}->{prct}, $free_value . ' ' . $free_unit, 100 - $self->{result_values}->{prct} ); } sub custom_used_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => 'used', unit => 'B', nlabel => $self->{nlabel}, value => $self->{result_values}->{used}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), min => 0, max => $self->{result_values}->{total} ); } sub custom_unit_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => $self->{result_values}->{label}, unit => 'B', nlabel => $self->{nlabel}, value => $self->{result_values}->{used}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), min => 0, max => $self->{result_values}->{total} ); } sub custom_unit_output { my ($self, %options) = @_; my ($used_value, $used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); return sprintf( "%s : %s (%.2f %%)", ucfirst($self->{result_values}->{label}), $used_value . ' ' . $used_unit, $self->{result_values}->{prct} ); } sub custom_unit_calc { my ($self, %options) = @_; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_database_allocated'}; if ($self->{result_values}->{total} == 0) { $self->{error_msg} = "skipped"; return -2; } $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{label_ref} . '_used'}; $self->{result_values}->{prct} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; $self->{result_values}->{label} = $options{extra_options}->{label_ref}; return 0; } sub prefix_output { my ($self, %options) = @_; return "Memory "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); $options{sql}->query(query => q{SELECT MON$STAT_GROUP as MYGROUP, MON$MEMORY_ALLOCATED AS MYTOTAL, MON$MEMORY_USED AS MYUSED FROM MON$MEMORY_USAGE}); my %map_group = (0 => 'database', 1 => 'attachment', 2 => 'transaction', 3 => 'statement', 4 => 'call'); $self->{global} = {}; while ((my $row = $options{sql}->fetchrow_hashref())) { if (!defined($self->{firebird}->{$map_group{$row->{MYGROUP}} . '_used'})) { $self->{global}->{$map_group{ $row->{MYGROUP} } . '_used'} = 0; $self->{global}->{$map_group{ $row->{MYGROUP} } . '_allocated'} = 0; } $self->{global}->{$map_group{ $row->{MYGROUP} } . '_used'} += $row->{MYUSED}; $self->{global}->{$map_group{ $row->{MYGROUP} } . '_allocated'} += $row->{MYTOTAL}; } } 1; __END__ =head1 MODE Check memory usage. =over 8) =item B<--warning-*> Threshold warning. Can be: 'used' (%), 'attachment' (%), 'transaction' (%), 'statement' (%), 'call' (%). =item B<--critical-*> Threshold critical. Can be: 'used' (%), 'attachment' (%), 'transaction' (%), 'statement' (%), 'call' (%). =back =cut centreon-plugins-20220113/database/firebird/mode/pages.pm000066400000000000000000000077601417000230700231610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::firebird::mode::pages; 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 => 'global', type => 0, cb_prefix_output => 'prefix_output' } ]; $self->{maps_counters}->{global} = [ { label => 'reads', nlabel => 'pages.reads.persecond', set => { key_values => [ { name => 'reads', per_second => 1 } ], output_template => 'Reads : %.2f', perfdatas => [ { label => 'reads', template => '%.2f', unit => '/s', min => 0 } ] } }, { label => 'writes', nlabel => 'pages.writes.persecond', set => { key_values => [ { name => 'writes', per_second => 1 } ], output_template => 'Writes : %.2f', perfdatas => [ { label => 'writes', template => '%.2f', unit => '/s', min => 0 } ] } }, { label => 'fetches', nlabel => 'pages.fetches.persecond', set => { key_values => [ { name => 'fetches', per_second => 1 } ], output_template => 'Fetches : %.2f', perfdatas => [ { label => 'fetches', template => '%.2f', unit => '/s', min => 0 } ] } }, { label => 'marks', nlabel => 'pages.marks.persecond', set => { key_values => [ { name => 'marks', per_second => 1 } ], output_template => 'Marks : %.2f', perfdatas => [ { label => 'marks', template => '%.2f', unit => '/s', min => 0 } ] } } ]; } sub prefix_output { my ($self, %options) = @_; return "Page "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); $options{sql}->query(query => q{SELECT MON$PAGE_READS as PAGE_READS, MON$PAGE_WRITES as PAGE_WRITES, MON$PAGE_FETCHES as PAGE_FETCHES, MON$PAGE_MARKS as PAGE_MARKS FROM MON$IO_STATS mi WHERE mi.MON$STAT_GROUP = 0}); my $row = $options{sql}->fetchrow_hashref(); if (!defined($row)) { $self->{output}->add_option_msg(short_msg => "Cannot get page informations"); $self->{output}->option_exit(); } $self->{global} = { reads => $row->{PAGE_READS}, writes => $row->{PAGE_WRITES}, fetches => $row->{PAGE_FETCHES}, marks => $row->{PAGE_MARKS} }; $self->{cache_name} = 'firebird_' . $self->{mode} . '_' . $options{sql}->get_unique_id4save() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check page statistics on current database. =over 8) =item B<--warning-*> Threshold warning. Can be: 'reads', 'writes', 'fetches', 'marks'. =item B<--critical-*> Threshold critical. Can be: 'reads', 'writes', 'fetches', 'marks'. =back =cut centreon-plugins-20220113/database/firebird/mode/queries.pm000066400000000000000000000137051417000230700235330ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::firebird::mode::queries; 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 => 'global', type => 0, cb_prefix_output => 'prefix_output' } ]; $self->{maps_counters}->{global} = [ { label => 'total', nlabel => 'queries.total.persecond', set => { key_values => [ { name => 'total', per_second => 1 } ], output_template => 'Total : %d', perfdatas => [ { label => 'total', template => '%d', unit => '/s', min => 0 } ] } }, { label => 'seq-reads', nlabel => 'queries.sequentialreads.persecond', set => { key_values => [ { name => 'seq_reads', per_second => 1 } ], output_template => 'Seq Reads : %d', perfdatas => [ { label => 'seq_reads', template => '%d', unit => '/s', min => 0 } ] } }, { label => 'inserts', nlabel => 'queries.insert.persecond', set => { key_values => [ { name => 'inserts', per_second => 1 } ], output_template => 'Inserts : %d', perfdatas => [ { label => 'inserts', template => '%d', unit => '/s', min => 0 } ] } }, { label => 'updates', nlabel => 'queries.updates.persecond', set => { key_values => [ { name => 'updates', per_second => 1 } ], output_template => 'Updates : %d', perfdatas => [ { label => 'updates', template => '%d', unit => '/s', min => 0 } ] } }, { label => 'deletes', nlabel => 'queries.deletes.persecond', set => { key_values => [ { name => 'deletes', per_second => 1 } ], output_template => 'Deletes : %d', perfdatas => [ { label => 'deletes', template => '%d', unit => '/s', min => 0 } ] } }, { label => 'backouts', nlabel => 'queries.backout.persecond', set => { key_values => [ { name => 'backouts', per_second => 1 } ], output_template => 'Backouts : %d', perfdatas => [ { label => 'backouts', template => '%d', unit => '/s', min => 0 } ] } }, { label => 'purges', nlabel => 'queries.purges.persecond', set => { key_values => [ { name => 'purges', per_second => 1 } ], output_template => 'Purges : %d', perfdatas => [ { label => 'purges', template => '%d', unit => '/s', min => 0 } ] } }, { label => 'expunges', nlabel => 'queries.expunges.persecond', set => { key_values => [ { name => 'expunges', per_second => 1 } ], output_template => 'Expunges : %d', perfdatas => [ { label => 'expunges', template => '%d', unit => '/s', min => 0 } ] } } ]; } sub prefix_output { my ($self, %options) = @_; return "Records "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); $options{sql}->query(query => q{SELECT MON$RECORD_SEQ_READS as MYREADS,MON$RECORD_INSERTS as MYINSERTS, MON$RECORD_UPDATES as MYUPDATES, MON$RECORD_DELETES as MYDELETES, MON$RECORD_BACKOUTS as MYBACKOUTS, MON$RECORD_PURGES as MYPURGES, MON$RECORD_EXPUNGES as MYEXPUNGES FROM MON$RECORD_STATS mr WHERE mr.MON$STAT_GROUP = '0'} ); my $row = $options{sql}->fetchrow_hashref(); if (!defined($row)) { $self->{output}->add_option_msg(short_msg => 'Cannot get query informations'); $self->{output}->option_exit(); } $self->{global} = { seq_reads => $row->{MYREADS}, inserts => $row->{MYINSERTS}, updates => $row->{MYUPDATES}, deletes => $row->{MYDELETES}, backouts => $row->{MYBACKOUTS}, purges => $row->{MYPURGES}, expunges => $row->{MYEXPUNGES} }; $self->{global}->{total} = $row->{MYREADS} + $row->{MYINSERTS} + $row->{MYUPDATES} + $row->{MYDELETES} + $row->{MYBACKOUTS} + $row->{MYPURGES} + $row->{MYEXPUNGES}; $self->{cache_name} = 'firebird_' . $self->{mode} . '_' . $options{sql}->get_unique_id4save() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check queries statistics on current database. =over 8) =item B<--warning-*> Threshold warning. Can be: 'total', 'seq-reads', 'inserts', 'updates', 'deletes', 'backouts', 'purges', 'expunges'. =item B<--critical-*> Threshold critical. Can be: 'total', 'seq-reads', 'inserts', 'updates', 'deletes', 'backouts', 'purges', 'expunges'. =back =cut centreon-plugins-20220113/database/firebird/mode/users.pm000066400000000000000000000062051417000230700232140ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::firebird::mode::users; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { '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) = @_; $options{sql}->connect(); $options{sql}->query(query => q{SELECT COUNT(MON$USER) FROM MON$ATTACHMENTS WHERE MON$ATTACHMENT_ID <> CURRENT_CONNECTION}); my $result = $options{sql}->fetchrow_array(); if (!defined($result)) { $self->{output}->add_option_msg(short_msg => "Cannot get users."); $self->{output}->option_exit(); } my $exit_code = $self->{perfdata}->threshold_check(value => $result, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); my $msg = sprintf("%d user(s) connect to database", $result); $self->{output}->output_add( severity => $exit_code, short_msg => $msg ); $self->{output}->perfdata_add( label => 'users', value => $result, nlabel => 'users.count', warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0 ); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check current users connected on the database (firebird version >= 2.1) =over 8 =item B<--warning> Threshold warning. =item B<--critical> Threshold critical. =back =cut centreon-plugins-20220113/database/firebird/plugin.pm000066400000000000000000000066551417000230700224360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::firebird::plugin; use strict; use warnings; use base qw(centreon::plugins::script_sql); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $self->{version} = '0.1'; $self->{modes} = { 'connection-time' => 'centreon::common::protocols::sql::mode::connectiontime', 'users' => 'database::firebird::mode::users', 'pages' => 'database::firebird::mode::pages', 'memory' => 'database::firebird::mode::memory', 'queries' => 'database::firebird::mode::queries', 'long-queries' => 'database::firebird::mode::longqueries', 'sql' => 'centreon::common::protocols::sql::mode::sql' }; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options( arguments => { 'host:s@' => { name => 'db_host' }, 'port:s@' => { name => 'db_port' }, 'database:s@' => { name => 'db_name' } } ); $self->{options}->parse_options(); my $options_result = $self->{options}->get_options(); $self->{options}->clean(); if (defined($options_result->{db_host})) { @{$self->{sqldefault}->{dbi}} = (); @{$self->{sqldefault}->{firebirdcmd}} = (); for (my $i = 0; $i < scalar(@{$options_result->{db_host}}); $i++) { $self->{sqldefault}->{dbi}[$i] = { data_source => 'Firebird:host=' . $options_result->{db_host}[$i] }; $self->{sqldefault}->{firebirdcmd}[$i] = { host => $options_result->{db_host}[$i] }; if (defined($options_result->{db_port}[$i])) { $self->{sqldefault}->{dbi}[$i]->{data_source} .= ';port=' . $options_result->{db_port}[$i]; $self->{sqldefault}->{firebirdcmd}[$i]->{port} = $options_result->{db_port}[$i]; } $options_result->{db_name}[$i] = (defined($options_result->{db_name}[$i]) && $options_result->{db_name}[$i] ne '') ? $options_result->{db_name}[$i] : 'firebird'; $self->{sqldefault}->{dbi}[$i]->{data_source} .= ';database=' . $options_result->{db_name}[$i]; $self->{sqldefault}->{firebirdcmd}[$i]->{dbname} = $options_result->{db_name}[$i]; } } $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Firebird Server. It works with version >= 2.1 and sysdba user. =over 8 You can use following options or options from 'sqlmode' directly. =item B<--host> Hostname to query. =item B<--port> Database Server Port. =item B<--database> Path to Database. (eg:/opt/firebird/examples/empbuild/employee.fdb) =back =cut centreon-plugins-20220113/database/influxdb/000077500000000000000000000000001417000230700206135ustar00rootroot00000000000000centreon-plugins-20220113/database/influxdb/custom/000077500000000000000000000000001417000230700221255ustar00rootroot00000000000000centreon-plugins-20220113/database/influxdb/custom/api.pm000066400000000000000000000206401417000230700232360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::influxdb::custom::api; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::http; use URI::Encode; use JSON::XS; 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'timeout:s' => { name => 'timeout' }, 'unknown-http-status:s' => { name => 'unknown_http_status' }, 'warning-http-status:s' => { name => 'warning_http_status' }, 'critical-http-status:s' => { name => 'critical_http_status' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'CUSTOM MODE OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 8086; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'http'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{username} = (defined($self->{option_results}->{username})) ? $self->{option_results}->{username} : undef; $self->{password} = (defined($self->{option_results}->{password})) ? $self->{option_results}->{password} : undef; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300' ; $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; if (!defined($self->{hostname}) || $self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } return 0; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub get_port { my ($self, %options) = @_; return $self->{port}; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; if (defined($self->{username}) && $self->{username} ne '') { $self->{option_results}->{credentials} = 1; $self->{option_results}->{basic} = 1; $self->{option_results}->{username} = $self->{username}; $self->{option_results}->{password} = $self->{password}; } } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->set_options(%{$self->{option_results}}); } sub request { my ($self, %options) = @_; $self->settings(); $self->{output}->output_add(long_msg => "URL: '" . $self->{proto} . '://' . $self->{hostname} . ':' . $self->{port} . $options{url_path} . "'", debug => 1); $self->{output}->output_add(long_msg => "Parameters: '" . join(', ', @{$options{post_param}}) . "'", debug => 1) if (defined($options{post_param})); my $content = $self->{http}->request( %options, unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status}, ); if (!defined($content) || $content eq '') { $self->{output}->add_option_msg(short_msg => "API returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->output_add(long_msg => $content, debug => 1); $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } if (defined($decoded->{error})) { $self->{output}->add_option_msg(short_msg => "API returns error '" . $decoded->{error} . "'"); $self->{output}->option_exit(); } return $decoded; } sub query { my ($self, %options) = @_; my $data; foreach my $query (@{$options{queries}}) { my $results = $self->request( method => 'POST', url_path => '/query?epoch=s', post_param => ['q=' . $query] ); if (defined($results->{results}[0]->{error})) { $self->{output}->add_option_msg(short_msg => "API returns error '" . $results->{results}[0]->{error} . "'"); $self->{output}->option_exit(); } push @{$data}, @{$results->{results}[0]->{series}} if (defined($results->{results}[0]->{series})); } return $data; } sub compute { my ($self, %options) = @_; my $result; if ($options{aggregation} eq 'average') { my $points = 0; foreach my $value (@{$options{values}}) { $result = 0 if (!defined($result)); $result += $value->[$options{column}]; $points++; } $result /= $points; } elsif ($options{aggregation} eq 'minimum') { foreach my $value (@{$options{values}}) { $result = $value->[$options{column}] if (!defined($result) || $value->[$options{column}] < $result); } } elsif ($options{aggregation} eq 'maximum') { foreach my $value (@{$options{values}}) { $result = $value->[$options{column}] if (!defined($result) || $value->[$options{column}] > $result); } } elsif ($options{aggregation} eq 'sum') { foreach my $value (@{$options{values}}) { $result = 0 if (!defined($result)); $result += $value->[$options{column}]; } } return $result; } 1; __END__ =head1 NAME InfluxDB Rest API =head1 CUSTOM MODE OPTIONS InfluxDB Rest API =over 8 =item B<--hostname> Remote hostname or IP address. =item B<--port> Port used (Default: 8086) =item B<--proto> Specify https if needed (Default: 'http') =item B<--username> Specify username for authentication. =item B<--password> Specify password for authentication. =item B<--timeout> Set timeout in seconds (Default: 10). =item B<--unknown-http-status> Threshold unknown for http response code. (Default: '%{http_code} < 200 or %{http_code} >= 300') =item B<--warning-http-status> Threshold warning for http response code. =item B<--critical-http-status> Threshold critical for http response code. =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/database/influxdb/mode/000077500000000000000000000000001417000230700215375ustar00rootroot00000000000000centreon-plugins-20220113/database/influxdb/mode/connectiontime.pm000066400000000000000000000045071417000230700251210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::influxdb::mode::connectiontime; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Time::HiRes; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, ]; $self->{maps_counters}->{global} = [ { label => 'connection-time', nlabel => 'connection.time.milliseconds', set => { key_values => [ { name => 'connection_time' } ], output_template => 'Connection established in %d ms', perfdatas => [ { value => 'connection_time', template => '%d', unit => 'ms', min => 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 => {}); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{custom} = $options{custom}; my $start = Time::HiRes::time(); $self->{custom}->request(url_path => '/ping?verbose=true'); my $end = Time::HiRes::time(); $self->{global}->{connection_time} = ($end - $start) * 1000; } 1; __END__ =head1 MODE Check database connection time. =over 8 =item B<--warning-connection-time> Threshold warning in milliseconds. =item B<--critical-connection-time> Threshold critical in milliseconds. =back =cut centreon-plugins-20220113/database/influxdb/mode/databasestatistics.pm000066400000000000000000000075501417000230700257630ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::influxdb::mode::databasestatistics; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'databases', type => 1, cb_prefix_output => 'prefix_database_output', message_multiple => 'All databases statistics are ok' }, ]; $self->{maps_counters}->{databases} = [ { label => 'measurements', nlabel => 'database.measurements.count', set => { key_values => [ { name => 'numMeasurements' }, { name => 'display' } ], output_template => 'Measurements: %s', perfdatas => [ { value => 'numMeasurements', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'series', nlabel => 'database.series.count', set => { key_values => [ { name => 'numSeries' }, { name => 'display' } ], output_template => 'Series: %s', perfdatas => [ { value => 'numSeries', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub prefix_database_output { my ($self, %options) = @_; return "Database '" . $options{instance_value}->{display} . "' "; } 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-database:s" => { name => 'filter_database' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; $self->{custom} = $options{custom}; $self->{databases} = {}; my $results = $self->{custom}->query(queries => [ "SHOW STATS FOR 'database'" ]); foreach my $database (@{$results}) { next if (defined($self->{option_results}->{filter_database}) && $self->{option_results}->{filter_database} ne '' && $database->{tags}->{database} !~ /$self->{option_results}->{filter_database}/); $self->{databases}->{$database->{tags}->{database}}->{display} = $database->{tags}->{database}; my $i = 0; foreach my $column (@{$database->{columns}}) { $column =~ s/influxdb_//; $self->{databases}->{$database->{tags}->{database}}->{$column} = $database->{values}[0][$i]; $i++; } } if (scalar(keys %{$self->{databases}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No databases found'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check databases statistics =over 8 =item B<--filter-database> Filter database name (Can use regexp). =item B<--warning-*> Threshold warning. Can be: 'measurements', 'series'. =item B<--critical-*> Threshold warning. Can be: 'measurements', 'series'. =back =cut centreon-plugins-20220113/database/influxdb/mode/httpserverstatistics.pm000066400000000000000000000143331417000230700264220ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::influxdb::mode::httpserverstatistics; 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 => 'global', type => 0 }, ]; $self->{maps_counters}->{global} = [ { label => 'requests-query-count', nlabel => 'requests.query.count.persecond', set => { key_values => [ { name => 'queryReq', per_second => 1 } ], output_template => 'Query Requests: %.2f/s', perfdatas => [ { template => '%.2f', min => 0 }, ], } }, { label => 'requests-write-count', nlabel => 'requests.write.count.persecond', set => { key_values => [ { name => 'writeReq', per_second => 1 } ], output_template => 'Write Requests: %.2f/s', perfdatas => [ { template => '%.2f', min => 0 }, ], } }, { label => 'requests-ping-count', nlabel => 'requests.ping.count.persecond', set => { key_values => [ { name => 'pingReq', per_second => 1 } ], output_template => 'Ping Requests: %.2f/s', perfdatas => [ { template => '%.2f', min => 0 }, ], } }, { label => 'requests-status-count', nlabel => 'requests.status.count.persecond', set => { key_values => [ { name => 'statusReq', per_second => 1 } ], output_template => 'Status Requests: %.2f/s', perfdatas => [ { template => '%.2f', min => 0 }, ], } }, { label => 'requests-active', nlabel => 'requests.active.count', set => { key_values => [ { name => 'reqActive' } ], output_template => 'Active Requests: %d', perfdatas => [ { template => '%d', min => 0 }, ], } }, { label => 'requests-write-active', nlabel => 'requests.write.active.count', set => { key_values => [ { name => 'writeReqActive' } ], output_template => 'Active Write Requests: %d', perfdatas => [ { template => '%d', min => 0 }, ], } }, { label => 'requests-response-data', nlabel => 'requests.response.data.bytes', set => { key_values => [ { name => 'queryRespBytes', per_second => 1 } ], output_change_bytes => 1, output_template => 'Response Data: %s%s/s', perfdatas => [ { template => '%s', min => 0, unit => 'B/s' }, ], } }, { label => 'requests-write-data', nlabel => 'requests.write.data.bytes', set => { key_values => [ { name => 'writeReqBytes', per_second => 1 } ], output_change_bytes => 1, output_template => 'Write Data: %s%s/s', perfdatas => [ { template => '%s', min => 0, unit => 'B/s' }, ], } }, { label => 'errors-server', nlabel => 'errors.server.persecond', set => { key_values => [ { name => 'serverError', per_second => 1 } ], output_template => 'Server Errors: %.2f/s', perfdatas => [ { template => '%.2f', min => 0 }, ], } }, { label => 'errors-client', nlabel => 'errors.client.persecond', set => { key_values => [ { name => 'clientError', per_second => 1 } ], output_template => 'Client Errors: %.2f/s', perfdatas => [ { template => '%.2f', min => 0 }, ], } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{custom} = $options{custom}; $self->{global} = {}; my $results = $self->{custom}->query(queries => [ "SHOW STATS FOR 'httpd'" ]); my $i = 0; foreach my $column (@{$$results[0]->{columns}}) { $column =~ s/influxdb_//; $self->{global}->{$column} = $$results[0]->{values}[0][$i]; $i++; } $self->{cache_name} = "influxdb_" . $self->{mode} . '_' . $self->{custom}->get_hostname() . '_' . $self->{custom}->get_port() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check several statistics from the HTTP server serving API. =over 8 =item B<--warning-*> Threshold warning. Can be: 'requests-query-count', 'requests-write-count', 'requests-ping-count', 'requests-status-count', 'requests-active', 'requests-write-active', 'requests-response-data', 'requests-write-data', 'errors-server', 'errors-client'. =item B<--critical-*> Threshold critical. Can be: 'requests-query-count', 'requests-write-count', 'requests-ping-count', 'requests-status-count', 'requests-active', 'requests-write-active', 'requests-response-data', 'requests-write-data', 'errors-server', 'errors-client'. =back =cut centreon-plugins-20220113/database/influxdb/mode/listdatabases.pm000066400000000000000000000044551417000230700247300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::influxdb::mode::listdatabases; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{custom} = $options{custom}; my $results = $self->{custom}->query(queries => [ 'SHOW DATABASES' ]); foreach my $value (@{$$results[0]->{values}}) { push @{$self->{databases}}, $$value[0]; } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $database (sort @{$self->{databases}}) { $self->{output}->output_add(long_msg => sprintf("[name = %s]", $database)); } $self->{output}->output_add(severity => 'OK', short_msg => "List databases:"); $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->manage_selection(%options); foreach my $database (sort @{$self->{databases}}) { $self->{output}->add_disco_entry(name => $database); } } 1; __END__ =head1 MODE List databases. =over 8 =back =cut centreon-plugins-20220113/database/influxdb/mode/query.pm000066400000000000000000000203551417000230700232470ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::influxdb::mode::query; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_perfdata { my ($self, %options) = @_; foreach my $key (@{$self->{instance_mode}->{custom_keys}}) { $self->{output}->perfdata_add( label => $key, nlabel => $key, value => $self->{result_values}->{$key}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{instance} : undef ); } } sub custom_status_output { my ($self, %options) = @_; my $msg = $self->{instance_mode}->{option_results}->{output}; while ($msg =~ /%\{(.*?)\}/g) { my $key = $1; if (defined($self->{result_values}->{$key})) { $msg =~ s/%\{$key\}/$self->{result_values}->{$key}/g; } } return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{instance} = $options{new_datas}->{$self->{instance} . '_instance'}; foreach my $key (@{$self->{instance_mode}->{custom_keys}}) { $self->{result_values}->{$key} = $options{new_datas}->{$self->{instance} . '_' . $key}; } $self->{result_values}->{time} = time(); return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'queries_results', type => 1, message_multiple => 'All queries results are ok', skipped_code => { -11 => 1 } } ]; $self->{maps_counters}->{queries_results} = [ { label => 'status', type => 2, set => { key_values => [ { name => 'instance' } ], closure_custom_calc => $self->can('custom_status_calc'), closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => $self->can('custom_status_perfdata'), closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } 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 => { 'query:s@' => { name => 'query' }, 'instance:s' => { name => 'instance' }, 'aggregation:s' => { name => 'aggregation', default => 'average' }, 'output:s' => { name => 'output' }, 'multiple-output:s' => { name => 'multiple_output' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{output}) || $self->{option_results}->{output} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --output option."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{instance}) || $self->{option_results}->{instance} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --instance option."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{query})) { $self->{output}->add_option_msg(short_msg => "Need to specify --query option."); $self->{output}->option_exit(); } $self->{custom_keys} = []; $self->{queries} = {}; foreach my $query (@{$self->{option_results}->{query}}) { next if ($query !~ /^(.*?),(.*)$/); $self->{queries}->{$1} = $2; push @{$self->{maps_counters}->{queries_results}[0]->{set}->{key_values}}, { name => $1 }; push @{$self->{custom_keys}}, $1; } $self->{maps_counters_type}[0]->{message_multiple} = $self->{option_results}->{multiple_output} if (defined($self->{option_results}->{multiple_output})); } sub manage_selection { my ($self, %options) = @_; $self->{queries_results} = {}; my (@results, @queries); my $query_index = -1; foreach my $label (keys %{$self->{queries}}) { $query_index++; @queries = (); push @queries, $self->{queries}->{$label}; my $queries_results = $options{custom}->query(queries => \@queries); foreach my $result (@{$queries_results}) { next if (!defined($result->{tags}->{$self->{option_results}->{instance}})); my ($column_index) = grep { $result->{columns}[$_] eq $self->{custom_keys}[$query_index] } (0 .. @{$result->{columns}} - 1); my $value; $value = $options{custom}->compute(aggregation => $self->{option_results}->{aggregation}, values => $result->{values}, column => $column_index) if (defined($result->{values})); $self->{queries_results}->{$result->{tags}->{$self->{option_results}->{instance}}}->{instance} = $result->{tags}->{$self->{option_results}->{instance}}; $self->{queries_results}->{$result->{tags}->{$self->{option_results}->{instance}}}->{$result->{columns}[$column_index]} = $value; } } if (scalar(keys %{$self->{queries_results}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No queries found.'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Launch queries. Examples: # perl centreon_plugins.pl --plugin=database::influxdb::plugin --mode=query --hostname=localhost --port=8086 --query='cpu.utilization.percentage,SELECT last("cpu.utilization.percentage") AS "cpu.utilization.percentage" FROM "centreon"."autogen"."Cpu" GROUP BY "host"' --instance='host' --critical-status='%{cpu.utilization.percentage} > 90' --output="Host '%{instance}' Cpu Utilization: %{cpu.utilization.percentage}%" --multiple-output='All cpu utilization are ok' --verbose # perl centreon_plugins.pl --plugin=database::influxdb::plugin --mode=query --hostname=localhost --port=8086 --query='load1,SELECT last("load1") AS "load1" FROM "centreon"."autogen"."Load" GROUP BY "host"' --query='load5,SELECT last("load5") AS "load5" FROM "centreon"."autogen"."Load" GROUP BY "host"' --query='load15,SELECT last("load15") AS "load15" FROM "centreon"."autogen"."Load" GROUP BY "host"' --instance='host' --output="Host '%{instance}' Load1: %{load1} Load5: %{load5} Load15: %{load15}" --multiple-output='All load metrics are ok' --verbose =over 8 =item B<--query> Set a InfluxQL query. Query option must be like --query='label,query'. Query must contain an "AS" keyword to rename the column of the selected data, and must match the label. (Example: --query='mymetric,SELECT the_data AS "mymetric" FROM "database"."retention"."measurement" GROUP BY "instance"') =item B<--instance> Set the instance label on which the results should be calculate for (Example: --instance='name'). The instance label must be the same label as the "GROUP BY" keyword. =item B<--output> Set the output for each instances (Example: --output='Object %{instance} value is {label}'). =item B<--multiple-output> Set the global output in case everything is fine for multiple instances (Example: --multiple-output='All instance values are ok'). =item B<--warning-status> Set warning threshold for status (Default: ''). Can use special variables like %{instance} and any other labels you set through --query. =item B<--critical-status> Set critical threshold for status (Default: ''). Can use special variables like %{instance} and any other labels you set through --query. =item B<--aggregation> Set the aggregation on metric values (Can be: 'average', 'min', 'max', 'sum') (Default: 'average'). =over 8 =back =cut centreon-plugins-20220113/database/influxdb/mode/writestatistics.pm000066400000000000000000000100361417000230700253420ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::influxdb::mode::writestatistics; 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 => 'global', type => 0 }, ]; $self->{maps_counters}->{global} = [ { label => 'points-written', nlabel => 'points.written.persecond', set => { key_values => [ { name => 'pointReq', per_second => 1 } ], output_template => 'Points Written: %.2f/s', perfdatas => [ { template => '%.2f', min => 0 }, ], } }, { label => 'writes-ok', nlabel => 'writes.ok.persecond', set => { key_values => [ { name => 'writeOk', per_second => 1 } ], output_template => 'Writes Ok: %.2f/s', perfdatas => [ { template => '%.2f', min => 0 }, ], } }, { label => 'writes-error', nlabel => 'writes.error.persecond', set => { key_values => [ { name => 'writeError', per_second => 1 } ], output_template => 'Writes Error: %.2f/s', perfdatas => [ { template => '%.2f', min => 0 }, ], } }, { label => 'writes-drop', nlabel => 'writes.drop.persecond', set => { key_values => [ { name => 'writeDrop', per_second => 1 } ], output_template => 'Writes Drop: %.2f/s', perfdatas => [ { template => '%.2f', min => 0 }, ], } }, { label => 'writes-timeout', nlabel => 'writes.timeout.persecond', set => { key_values => [ { name => 'writeTimeout', per_second => 1 } ], output_template => 'Writes Timeout: %.2f/s', perfdatas => [ { template => '%.2f', min => 0 }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{custom} = $options{custom}; $self->{global} = {}; my $results = $self->{custom}->query(queries => [ "SHOW STATS FOR 'write'" ]); my $i = 0; foreach my $column (@{$$results[0]->{columns}}) { $column =~ s/influxdb_//; $self->{global}->{$column} = $$results[0]->{values}[0][$i]; $i++; } $self->{cache_name} = "influxdb_" . $self->{mode} . '_' . $self->{custom}->get_hostname() . '_' . $self->{custom}->get_port() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check writes statistics to the data node. =over 8 =item B<--warning-*> Threshold warning. Can be: 'points-written', 'writes-ok', 'writes-error', 'writes-drop', 'writes-timeout'. =item B<--critical-*> Threshold critical. Can be: 'points-written', 'writes-ok', 'writes-error', 'writes-drop', 'writes-timeout'. =back =cut centreon-plugins-20220113/database/influxdb/plugin.pm000066400000000000000000000033311417000230700224470ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::influxdb::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} = '1.0'; %{$self->{modes}} = ( 'connection-time' => 'database::influxdb::mode::connectiontime', 'database-statistics' => 'database::influxdb::mode::databasestatistics', 'http-server-statistics' => 'database::influxdb::mode::httpserverstatistics', 'list-databases' => 'database::influxdb::mode::listdatabases', 'query' => 'database::influxdb::mode::query', 'write-statistics' => 'database::influxdb::mode::writestatistics', ); $self->{custom_modes}{api} = 'database::influxdb::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check InfluxDB server. =cut centreon-plugins-20220113/database/informix/000077500000000000000000000000001417000230700206335ustar00rootroot00000000000000centreon-plugins-20220113/database/informix/snmp/000077500000000000000000000000001417000230700216105ustar00rootroot00000000000000centreon-plugins-20220113/database/informix/snmp/mode/000077500000000000000000000000001417000230700225345ustar00rootroot00000000000000centreon-plugins-20220113/database/informix/snmp/mode/archivelevel0.pm000066400000000000000000000120051417000230700256210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::informix::snmp::mode::archivelevel0; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use DateTime; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'dbspace', type => 1, cb_prefix_output => 'prefix_dbspace_output', message_multiple => 'All dbspace backups are ok' } ]; $self->{maps_counters}->{dbspace} = [ { label => 'time', set => { key_values => [ { name => 'seconds' }, { name => 'date'}, { name => 'display' } ], output_template => "archive level0 last execution date '%s'", output_use => 'date', perfdatas => [ { label => 'seconds', value => 'seconds', template => '%s', min => 0, unit => 's', label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub prefix_dbspace_output { my ($self, %options) = @_; return "Dbspace '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "timezone:s" => { name => 'timezone' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{option_results}->{timezone} = 'GMT' if (!defined($self->{option_results}->{timezone}) || $self->{option_results}->{timezone} eq ''); } sub manage_selection { my ($self, %options) = @_; my $oid_applName = '.1.3.6.1.2.1.27.1.1.2'; my $oid_onDbspaceName = '.1.3.6.1.4.1.893.1.1.1.6.1.2'; my $oid_onDbspaceLastFullBackupDate = '.1.3.6.1.4.1.893.1.1.1.6.1.15'; my $snmp_result = $options{snmp}->get_multiple_table(oids => [ { oid => $oid_applName }, { oid => $oid_onDbspaceName }, { oid => $oid_onDbspaceLastFullBackupDate }, ], return_type => 1, nothing_quit => 1 ); my $tz = centreon::plugins::misc::set_timezone(name => $self->{option_results}->{timezone}); $self->{dbspace} = {}; foreach my $oid (keys %{$snmp_result}) { next if ($oid !~ /^$oid_onDbspaceName\.(.*?)\.(.*)/); my ($applIndex, $dbSpaceIndex) = ($1, $2); my $name = 'default'; $name = $snmp_result->{$oid_applName . '.' . $applIndex} if (defined($snmp_result->{$oid_applName . '.' . $applIndex})); $name .= '.' . $snmp_result->{$oid_onDbspaceName . '.' . $applIndex. '.' . $dbSpaceIndex}; 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; } my ($seconds, $date) = (-1, 'never'); if (defined($snmp_result->{$oid_onDbspaceLastFullBackupDate . '.' . $applIndex. '.' . $dbSpaceIndex})) { my @dates = unpack('n C6 a C2', $snmp_result->{$oid_onDbspaceLastFullBackupDate . '.' . $applIndex. '.' . $dbSpaceIndex}); if ($dates[0] != 0) { my $dt = DateTime->new(year => $dates[0], month => $dates[1], day => $dates[2], hour => $dates[3], minute => $dates[4], second => $dates[5], %$tz); $seconds = time() - $dt->epoch; $date = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $dates[0], $dates[1], $dates[2], $dates[3], $dates[4], $dates[5]); } } $self->{dbspace}->{$name} = { display => $name, seconds => $seconds, date => $date, }; } if (scalar(keys %{$self->{dbspace}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No dbspace found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check last full backup. =over 8 =item B<--filter-name> Filter dbspace name (can be a regexp). =item B<--warning-time> Threshold warning in seconds. =item B<--critical-time> Threshold critical in seconds. =back =cut centreon-plugins-20220113/database/informix/snmp/mode/chunkstatus.pm000066400000000000000000000127761417000230700254630ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::informix::snmp::mode::chunkstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("status is '%s'", $self->{result_values}->{status}); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'chunk', type => 1, cb_prefix_output => 'prefix_chunk_output', message_multiple => 'All chunks are ok' } ]; $self->{maps_counters}->{chunk} = [ { label => 'status', set => { key_values => [ { name => 'status' }, { 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 => \&catalog_status_threshold, } }, ]; } sub prefix_chunk_output { my ($self, %options) = @_; return "Chunk '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "unknown-status:s" => { name => 'unknown_status' }, "warning-status:s" => { name => 'warning_status' }, "critical-status:s" => { name => 'critical_status', default => '%{status} =~ /inconsistent/' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['unknown_status', 'warning_status', 'critical_status']); } my %mapping_status = ( 1 => 'offline', 2 => 'online', 3 => 'recovering', 4 => 'inconsistent', 5 => 'dropped', ); my $mapping = { onChunkFileName => { oid => '.1.3.6.1.4.1.893.1.1.1.7.1.2' }, onChunkStatus => { oid => '.1.3.6.1.4.1.893.1.1.1.7.1.7', map => \%mapping_status }, }; sub manage_selection { my ($self, %options) = @_; my $oid_applName = '.1.3.6.1.2.1.27.1.1.2'; my $oid_onDbspaceName = '.1.3.6.1.4.1.893.1.1.1.6.1.2'; my $snmp_result = $options{snmp}->get_multiple_table(oids => [ { oid => $oid_applName }, { oid => $oid_onDbspaceName }, { oid => $mapping->{onChunkFileName}->{oid} }, { oid => $mapping->{onChunkStatus}->{oid} }, ], return_type => 1, nothing_quit => 1 ); $self->{chunk} = {}; foreach my $oid (keys %{$snmp_result}) { next if ($oid !~ /^$mapping->{onChunkFileName}->{oid}\.(.*?)\.(.*?)\.(.*)/); my ($applIndex, $dbSpaceIndex, $chunkIndex) = ($1, $2, $3); my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $applIndex . '.' . $dbSpaceIndex . '.' . $chunkIndex); my $name = 'default'; $name = $snmp_result->{$oid_applName . '.' . $applIndex} if (defined($snmp_result->{$oid_applName . '.' . $applIndex})); $name .= '.' . $snmp_result->{$oid_onDbspaceName . '.' . $applIndex. '.' . $dbSpaceIndex}; $name .= '.' . $result->{onChunkFileName}; 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->{chunk}->{$name} = { display => $name, status => $result->{onChunkStatus}, }; } if (scalar(keys %{$self->{chunk}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No chunk found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check chunk status. =over 8 =item B<--filter-name> Filter chunk name (can be a regexp). =item B<--unknown-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{display} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{display} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /inconsistent/'). Can used special variables like: %{status}, %{display} =back =cut centreon-plugins-20220113/database/informix/snmp/mode/dbspaceusage.pm000066400000000000000000000102111417000230700255130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::informix::snmp::mode::dbspaceusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 1, cb_prefix_output => 'prefix_dbspace_output', message_multiple => 'All dbspaces usage are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'usage', set => { key_values => [ { name => 'prct_used' }, { name => 'display' } ], output_template => 'Used: %.2f%%', perfdatas => [ { label => 'used', value => 'prct_used', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub prefix_dbspace_output { my ($self, %options) = @_; return "Dbspace '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, }); return $self; } my $mapping = { onDbspaceName => { oid => '.1.3.6.1.4.1.893.1.1.1.6.1.2' }, onDbspacePagesAllocated => { oid => '.1.3.6.1.4.1.893.1.1.1.6.1.11' }, onDbspacePagesUsed => { oid => '.1.3.6.1.4.1.893.1.1.1.6.1.12' }, }; sub manage_selection { my ($self, %options) = @_; my $oid_applName = '.1.3.6.1.2.1.27.1.1.2'; my $snmp_result = $options{snmp}->get_multiple_table(oids => [ { oid => $oid_applName }, { oid => $mapping->{onDbspaceName}->{oid} }, { oid => $mapping->{onDbspacePagesAllocated}->{oid} }, { oid => $mapping->{onDbspacePagesUsed}->{oid} }, ], return_type => 1, nothing_quit => 1 ); $self->{global} = {}; foreach my $oid (keys %{$snmp_result}) { next if ($oid !~ /^$mapping->{onDbspaceName}->{oid}\.(.*)/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); my $name = 'default'; $name = $snmp_result->{$oid_applName}->{$oid_applName . '.' . $instance} if (defined($snmp_result->{$oid_applName}->{$oid_applName . '.' . $instance})); $name .= '.' . $result->{onDbspaceName}; 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->{global}->{$name} = { display => $name, prct_used => $result->{onDbspacePagesUsed} * 100 / $result->{onDbspacePagesAllocated}, }; } if (scalar(keys %{$self->{global}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No dbspace found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check dbspaces usage. =over 8 =item B<--filter-name> Filter dbspace name (can be a regexp). =item B<--warning-usage> Threshold warning in percent. =item B<--critical-usage> Threshold critical in percent. =back =cut centreon-plugins-20220113/database/informix/snmp/mode/globalcache.pm000066400000000000000000000132271417000230700253230ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::informix::snmp::mode::globalcache; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); sub custom_usage_calc { my ($self, %options) = @_; my $diff_logical = $options{new_datas}->{$self->{instance} . '_rdbmsSrvInfoLogical' . $options{extra_options}->{label_ref}} - $options{old_datas}->{$self->{instance} . '_rdbmsSrvInfoLogical' . $options{extra_options}->{label_ref}}; my $diff_disk = $options{new_datas}->{$self->{instance} . '_rdbmsSrvInfoDisk' . $options{extra_options}->{label_ref}} - $options{old_datas}->{$self->{instance} . '_rdbmsSrvInfoDisk' . $options{extra_options}->{label_ref}}; $self->{result_values}->{prct} = $diff_logical <= 0 ? 0 : (100 * ($diff_logical - $diff_disk) / $diff_logical); return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 1, cb_prefix_output => 'prefix_instances_output', message_multiple => 'All instances are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'read', set => { key_values => [ { name => 'rdbmsSrvInfoDiskReads', diff => 1 }, { name => 'rdbmsSrvInfoLogicalReads', diff => 1 }, { name => 'display' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { label_ref => 'Reads' }, output_template => 'Read Cached hitrate at %.2f%%', threshold_use => 'prct', output_use => 'prct', perfdatas => [ { label => 'read', value => 'prct', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'write', set => { key_values => [ { name => 'rdbmsSrvInfoDiskWrites', diff => 1 }, { name => 'rdbmsSrvInfoLogicalWrites', diff => 1 }, { name => 'display' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { label_ref => 'Writes' }, output_template => 'Write Cached hitrate at %.2f%%', threshold_use => 'prct', output_use => 'prct', perfdatas => [ { label => 'write', value => 'prct', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub prefix_instances_output { my ($self, %options) = @_; return "Instance '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my $mapping = { rdbmsSrvInfoDiskReads => { oid => '.1.3.6.1.2.1.39.1.6.1.3' }, rdbmsSrvInfoLogicalReads => { oid => '.1.3.6.1.2.1.39.1.6.1.4' }, rdbmsSrvInfoDiskWrites => { oid => '.1.3.6.1.2.1.39.1.6.1.5' }, rdbmsSrvInfoLogicalWrites => { oid => '.1.3.6.1.2.1.39.1.6.1.6' }, }; sub manage_selection { my ($self, %options) = @_; my $oid_applName = '.1.3.6.1.2.1.27.1.1.2'; my $oid_rdbmsSrvInfoEntry = '.1.3.6.1.2.1.39.1.6.1'; my $snmp_result = $options{snmp}->get_multiple_table(oids => [ { oid => $oid_applName }, { oid => $oid_rdbmsSrvInfoEntry, start => $mapping->{rdbmsSrvInfoDiskReads}->{oid}, end => $mapping->{rdbmsSrvInfoLogicalWrites}->{oid} }, ], nothing_quit => 1 ); $self->{global} = {}; foreach my $oid (keys %{$snmp_result->{$oid_rdbmsSrvInfoEntry}}) { next if ($oid !~ /^$mapping->{rdbmsSrvInfoDiskReads}->{oid}\.(.*)/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result->{$oid_rdbmsSrvInfoEntry}, instance => $instance); my $name = 'default'; $name = $snmp_result->{$oid_applName}->{$oid_applName . '.' . $instance} if (defined($snmp_result->{$oid_applName}->{$oid_applName . '.' . $instance})); $self->{global}->{$name} = { display => $name, %$result }; } $self->{cache_name} = "informix_" . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check write/read cached. =over 8 =item B<--warning-read> Threshold read cached warning in percent. =item B<--critical-read> Threshold read cached critical in percent. =item B<--warning-write> Threshold write cached warning in percent. =item B<--critical-write> Threshold write cached critical in percent. =back =cut centreon-plugins-20220113/database/informix/snmp/mode/listdbspaces.pm000066400000000000000000000101721417000230700255530ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::informix::snmp::mode::listdbspaces; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-instance:s" => { name => 'filter_instance' }, "filter-dbspace:s" => { name => 'filter_dbspace' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; my $oid_applName = '.1.3.6.1.2.1.27.1.1.2'; my $oid_onDbspaceName = '.1.3.6.1.4.1.893.1.1.1.6.1.2'; my $snmp_result = $options{snmp}->get_multiple_table(oids => [ { oid => $oid_applName }, { oid => $oid_onDbspaceName }, ], nothing_quit => 1); $self->{dbspace} = {}; foreach my $oid (keys %{$snmp_result->{$oid_onDbspaceName}}) { $oid =~ /^$oid_onDbspaceName\.(.*?)\.(.*)/; my ($applIndex, $dbSpaceIndex) = ($1, $2); my $instance = 'default'; $instance = $snmp_result->{$oid_applName}->{$oid_applName . '.' . $applIndex} if (defined($snmp_result->{$oid_applName}->{$oid_applName . '.' . $applIndex})); my $dbspace = $snmp_result->{$oid_onDbspaceName}->{$oid}; if (defined($self->{option_results}->{filter_instance}) && $self->{option_results}->{filter_instance} ne '' && $instance !~ /$self->{option_results}->{filter_instance}/) { $self->{output}->output_add(long_msg => "skipping instance '" . $instance . "': no matching filter.", debug => 1); next; } if (defined($self->{option_results}->{filter_dbspace}) && $self->{option_results}->{filter_dbspace} ne '' && $dbspace !~ /$self->{option_results}->{filter_dbspace}/) { $self->{output}->output_add(long_msg => "skipping dbspace '" . $dbspace . "': no matching filter.", debug => 1); next; } $self->{dbspace}->{$applIndex . '.' . $dbSpaceIndex} = { instance => $instance, dbspace => $dbspace, }; } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $instance (sort keys %{$self->{dbspace}}) { $self->{output}->output_add(long_msg => '[instance = ' . $self->{dbspace}->{$instance}->{instance} . "] [dbspace = '" . $self->{dbspace}->{$instance}->{dbspace} . "']"); } $self->{output}->output_add(severity => 'OK', short_msg => 'List dbspaces:'); $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 => ['instance', 'dbspace']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $instance (sort keys %{$self->{dbspace}}) { $self->{output}->add_disco_entry( instance => $self->{dbspace}->{$instance}->{instance}, dbspace => $self->{dbspace}->{$instance}->{dbspace}, ); } } 1; __END__ =head1 MODE List informix instances. =over 8 =item B<--filter-instance> Filter by instance name (can be a regexp). =back =cut centreon-plugins-20220113/database/informix/snmp/mode/listinstances.pm000066400000000000000000000061001417000230700257520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::informix::snmp::mode::listinstances; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-instance:s" => { name => 'filter_instance' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; my $oid_applName = '.1.3.6.1.2.1.27.1.1.2'; my $snmp_result = $options{snmp}->get_table(oid => $oid_applName); $self->{instance} = {}; foreach my $oid (keys %{$snmp_result}) { my $name = $snmp_result->{$oid}; if (defined($self->{option_results}->{filter_instance}) && $self->{option_results}->{filter_instance} ne '' && $name !~ /$self->{option_results}->{filter_instance}/) { $self->{output}->output_add(long_msg => "skipping '" . $name . "': no matching filter.", debug => 1); next; } $self->{instance}->{$name} = { instance => $name }; } if (scalar(keys %{$self->{instance}}) == 0) { $self->{instance}->{default} = { instance => 'default' }; } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $instance (sort keys %{$self->{instance}}) { $self->{output}->output_add(long_msg => '[instance = ' . $self->{instance}->{$instance}->{instance} . ']'); } $self->{output}->output_add(severity => 'OK', short_msg => 'List instances:'); $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 => ['instance']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $instance (sort keys %{$self->{instance}}) { $self->{output}->add_disco_entry(instance => $self->{instance}->{$instance}->{instance}); } } 1; __END__ =head1 MODE List informix instances. =over 8 =item B<--filter-instance> Filter by instance name (can be a regexp). =back =cut centreon-plugins-20220113/database/informix/snmp/mode/lockstats.pm000066400000000000000000000124251417000230700251050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::informix::snmp::mode::lockstats; 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 => 'global', type => 1, cb_prefix_output => 'prefix_instances_output', message_multiple => 'All instances are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'lock-dead', set => { key_values => [ { name => 'onServerDeadLocks', diff => 1 }, { name => 'display' } ], output_template => 'Deadlocks %d', perfdatas => [ { label => 'lock_dead', value => 'onServerDeadLocks', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'lock-wait', set => { key_values => [ { name => 'onServerLockWaits', diff => 1 }, { name => 'display' } ], output_template => 'Lock Waits %d', perfdatas => [ { label => 'lock_wait', value => 'onServerLockWaits', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'lock-request', set => { key_values => [ { name => 'onServerLockRequests', diff => 1 }, { name => 'display' } ], output_template => 'Lock Requests %d', perfdatas => [ { label => 'lock_request', value => 'onServerLockRequests', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'lock-timeout', set => { key_values => [ { name => 'onServerLockTimeouts', diff => 1 }, { name => 'display' } ], output_template => 'Lock Timeouts %d', perfdatas => [ { label => 'lock_timeout', value => 'onServerLockTimeouts', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub prefix_instances_output { my ($self, %options) = @_; return "Instance '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my $mapping = { onServerLockRequests => { oid => '.1.3.6.1.4.1.893.1.1.1.1.1.11' }, onServerLockWaits => { oid => '.1.3.6.1.4.1.893.1.1.1.1.1.12' }, onServerDeadLocks => { oid => '.1.3.6.1.4.1.893.1.1.1.1.1.16' }, onServerLockTimeouts => { oid => '.1.3.6.1.4.1.893.1.1.1.1.1.17' }, }; sub manage_selection { my ($self, %options) = @_; my $oid_applName = '.1.3.6.1.2.1.27.1.1.2'; my $snmp_result = $options{snmp}->get_multiple_table(oids => [ { oid => $oid_applName }, { oid => $mapping->{onServerLockWaits}->{oid} }, { oid => $mapping->{onServerLockRequests}->{oid} }, { oid => $mapping->{onServerDeadLocks}->{oid} }, { oid => $mapping->{onServerLockTimeouts}->{oid} }, ], return_type => 1, nothing_quit => 1 ); $self->{global} = {}; foreach my $oid (keys %{$snmp_result}) { next if ($oid !~ /^$mapping->{onServerLockRequests}->{oid}\.(.*)/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); my $name = 'default'; $name = $snmp_result->{$oid_applName . '.' . $instance} if (defined($snmp_result->{$oid_applName . '.' . $instance})); $self->{global}->{$name} = { display => $name, %$result }; } $self->{cache_name} = "informix_" . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check instance locks. =over 8 =item B<--warning-*> Threshold warning. Can be: 'lock-dead', 'lock-wait', 'lock-request', 'lock-timeout'. =item B<--critical-*> Threshold critical. Can be: 'lock-dead', 'lock-wait', 'lock-request', 'lock-timeout'. =back =cut centreon-plugins-20220113/database/informix/snmp/mode/logfileusage.pm000066400000000000000000000110071417000230700255370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::informix::snmp::mode::logfileusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 1, cb_prefix_output => 'prefix_dbspace_output', message_multiple => 'All dbspace log files usage are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'usage', set => { key_values => [ { name => 'prct_used' }, { name => 'display' } ], output_template => 'Log Files Used: %.2f%%', perfdatas => [ { label => 'used', value => 'prct_used', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub prefix_dbspace_output { my ($self, %options) = @_; return "Dbspace '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, }); return $self; } my $mapping = { onLogicalLogDbspace => { oid => '.1.3.6.1.4.1.893.1.1.1.8.1.3' }, onLogicalLogPagesAllocated => { oid => '.1.3.6.1.4.1.893.1.1.1.8.1.7' }, onLogicalLogPagesUsed => { oid => '.1.3.6.1.4.1.893.1.1.1.8.1.8' }, }; sub manage_selection { my ($self, %options) = @_; my $oid_applName = '.1.3.6.1.2.1.27.1.1.2'; my $snmp_result = $options{snmp}->get_multiple_table(oids => [ { oid => $oid_applName }, { oid => $mapping->{onLogicalLogDbspace}->{oid} }, { oid => $mapping->{onLogicalLogPagesAllocated}->{oid} }, { oid => $mapping->{onLogicalLogPagesUsed}->{oid} }, ], return_type => 1, nothing_quit => 1 ); $self->{global} = {}; foreach my $oid (keys %{$snmp_result}) { next if ($oid !~ /^$mapping->{onLogicalLogDbspace}->{oid}\.(.*?)\.(.*)/); my ($applIndex, $logIndex) = ($1, $2); my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $applIndex . '.' . $logIndex); my $name = 'default'; $name = $snmp_result->{$oid_applName . '.' . $applIndex} if (defined($snmp_result->{$oid_applName . '.' . $applIndex})); $name .= '.' . $result->{onLogicalLogDbspace}; 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; } if (!defined($self->{global}->{$name})) { $self->{global}->{$name} = { display => $name, allocated => 0, used => 0 }; } $self->{global}->{$name}->{allocated} += $result->{onLogicalLogPagesAllocated}; $self->{global}->{$name}->{used} += $result->{onLogicalLogPagesUsed}; } foreach (keys %{$self->{global}}) { $self->{global}->{$_}->{prct_used} = $self->{global}->{$_}->{used} * 100 / $self->{global}->{$_}->{allocated}; } if (scalar(keys %{$self->{global}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No dbspace found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check log files usage. =over 8 =item B<--filter-name> Filter dbspace name (can be a regexp). =item B<--warning-usage> Threshold warning in percent. =item B<--critical-usage> Threshold critical in percent. =back =cut centreon-plugins-20220113/database/informix/snmp/mode/sessions.pm000066400000000000000000000066101417000230700247430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::informix::snmp::mode::sessions; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 1, cb_prefix_output => 'prefix_instances_output', message_multiple => 'All instances are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'sessions', set => { key_values => [ { name => 'sessions' }, { name => 'display' } ], output_template => '%d client sessions', perfdatas => [ { label => 'sessions', value => 'sessions', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub prefix_instances_output { my ($self, %options) = @_; return "Instance '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my $mapping = { onSessionUserName => { oid => '.1.3.6.1.4.1.893.1.1.1.10.1.2' }, onSessionUserProcessId => { oid => '.1.3.6.1.4.1.893.1.1.1.10.1.4' }, }; sub manage_selection { my ($self, %options) = @_; my $oid_applName = '.1.3.6.1.2.1.27.1.1.2'; my $snmp_result = $options{snmp}->get_multiple_table(oids => [ { oid => $oid_applName }, { oid => $mapping->{onSessionUserName}->{oid} }, { oid => $mapping->{onSessionUserProcessId}->{oid} }, ], return_type => 1, nothing_quit => 1 ); $self->{global} = {}; foreach my $oid (keys %{$snmp_result}) { next if ($oid !~ /^$mapping->{onSessionUserName}->{oid}\.(.*?)\.(.*)/); my ($applIndex, $sessionIndex) = ($1, $2); my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $applIndex . '.' . $sessionIndex); my $name = 'default'; $name = $snmp_result->{$oid_applName . '.' . $applIndex} if (defined($snmp_result->{$oid_applName . '.' . $applIndex})); if (!defined($self->{global}->{$name})) { $self->{global}->{$name} = { display => $name, sessions => 0 }; } $self->{global}->{$name}->{sessions}++; } } 1; __END__ =head1 MODE Check number of open sessions ('informix' user is not counted). =over 8 =item B<--warning-sessions> Threshold warning. =item B<--critical-sessions> Threshold critical. =back =cut centreon-plugins-20220113/database/informix/snmp/plugin.pm000066400000000000000000000035171417000230700234520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::informix::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}} = ( 'archivelevel0' => 'database::informix::snmp::mode::archivelevel0', 'chunk-status' => 'database::informix::snmp::mode::chunkstatus', 'dbspace-usage' => 'database::informix::snmp::mode::dbspaceusage', 'global-cache' => 'database::informix::snmp::mode::globalcache', 'list-dbspaces' => 'database::informix::snmp::mode::listdbspaces', 'list-instances' => 'database::informix::snmp::mode::listinstances', 'lock-stats' => 'database::informix::snmp::mode::lockstats', 'logfile-usage' => 'database::informix::snmp::mode::logfileusage', 'sessions' => 'database::informix::snmp::mode::sessions', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Informix in SNMP. =cut centreon-plugins-20220113/database/informix/sql/000077500000000000000000000000001417000230700214325ustar00rootroot00000000000000centreon-plugins-20220113/database/informix/sql/mode/000077500000000000000000000000001417000230700223565ustar00rootroot00000000000000centreon-plugins-20220113/database/informix/sql/mode/archivelevel0.pm000066400000000000000000000130211417000230700254420ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::informix::sql::mode::archivelevel0; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::misc; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning:s" => { name => 'warning', }, "critical:s" => { name => 'critical', }, "name:s" => { name => 'name', }, "regexp" => { name => 'use_regexp' }, }); 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) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); my $query = q{ SELECT name, level0 FROM sysdbstab }; $self->{sql}->query(query => $query); if (!defined($self->{option_results}->{name}) || defined($self->{option_results}->{use_regexp})) { $self->{output}->output_add(severity => 'OK', short_msg => 'All archive level0 backups are ok'); } my $count = 0; while ((my $row = $self->{sql}->fetchrow_hashref())) { my $name = centreon::plugins::misc::trim($row->{name}); next if (defined($self->{option_results}->{name}) && !defined($self->{option_results}->{use_regexp}) && $name ne $self->{option_results}->{name}); next if (defined($self->{option_results}->{name}) && defined($self->{option_results}->{use_regexp}) && $name !~ /$self->{option_results}->{name}/); $count++; if ($row->{level0} == 0) { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => sprintf("Dbspace '%s' archive level0 had never been executed", $name)); next; } my $diff_time = time() - $row->{level0}; $self->{output}->output_add(long_msg => sprintf("Dbspace '%s' archive level0 last execution date %s", $name, localtime($row->{level0}))); my $exit_code = $self->{perfdata}->threshold_check(value => $diff_time, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); if (!$self->{output}->is_status(value => $exit_code, compare => 'ok', litteral => 1) || (defined($self->{option_results}->{name}) && !defined($self->{option_results}->{use_regexp}))) { $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("Dbspace '%s' archive level0 last execution date %s", $name, localtime($row->{level0}))); } my $extra_label = ''; $extra_label = '_' . $name if (!defined($self->{option_results}->{name}) || defined($self->{option_results}->{use_regexp})); $self->{output}->perfdata_add(label => 'seconds' . $extra_label, value => $diff_time, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0); } if ($count == 0) { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => "Cannot find a dbspace (maybe the filter)."); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check archive level0 backup last execution. =over 8 =item B<--warning> Threshold warning in seconds since last execution. =item B<--critical> Threshold critical in seconds since last execution. =item B<--name> Set the dbspace (empty means 'check all dbspaces'). =item B<--regexp> Allows to use regexp to filter dbspaces (with option --name). =back =cut centreon-plugins-20220113/database/informix/sql/mode/checkpoints.pm000066400000000000000000000240461417000230700252340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::informix::sql::mode::checkpoints; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::misc; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning-cp:s" => { name => 'warning_cp', }, "critical-cp:s" => { name => 'critical_cp', }, "warning-flush:s" => { name => 'warning_flush', }, "critical-flush:s" => { name => 'critical_flush', }, "warning-crit:s" => { name => 'warning_crit', }, "critical-crit:s" => { name => 'critical_crit', }, "warning-block:s" => { name => 'warning_block', }, "critical-block:s" => { name => 'critical_block', }, "filter-trigger:s" => { name => 'filter_trigger', }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (($self->{perfdata}->threshold_validate(label => 'warning-cp', value => $self->{option_results}->{warning_cp})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning-cp threshold '" . $self->{option_results}->{warning_cp} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'critical-cp', value => $self->{option_results}->{critical_cp})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical-cp threshold '" . $self->{option_results}->{critical_cp} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'warning-flush', value => $self->{option_results}->{warning_flush})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning-flush threshold '" . $self->{option_results}->{warning_flush} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'critical-flush', value => $self->{option_results}->{critical_flush})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical-flush threshold '" . $self->{option_results}->{critical_flush} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'warning-crit', value => $self->{option_results}->{warning_crit})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning-crit threshold '" . $self->{option_results}->{warning_crit} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'critical-crit', value => $self->{option_results}->{critical_crit})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical-crit threshold '" . $self->{option_results}->{critical_crit} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'warning-block', value => $self->{option_results}->{warning_block})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning-block threshold '" . $self->{option_results}->{warning_block} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'critical-block', value => $self->{option_results}->{critical_block})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical-block threshold '" . $self->{option_results}->{critical_block} . "'."); $self->{output}->option_exit(); } } sub run { my ($self, %options) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); $self->{sql}->query(query => q{ SELECT intvl, caller, cp_time, block_time, flush_time, crit_time FROM syscheckpoint }); $self->{output}->output_add(severity => 'OK', short_msg => "All checkpoint times are ok."); my $count = 0; while ((my $row = $self->{sql}->fetchrow_hashref())) { my $id = $row->{intvl}; my $name = centreon::plugins::misc::trim($row->{caller}); my ($cp_time, $block_time, $flush_time, $crit_time) = ($row->{cp_time}, $row->{block_time}, $row->{flush_time}, $row->{crit_time}); next if (defined($self->{option_results}->{filter_trigger}) && $name !~ /$self->{option_results}->{filter_trigger}/); $count++; my $exit1 = $self->{perfdata}->threshold_check(value => $cp_time, threshold => [ { label => 'critical-cp', 'exit_litteral' => 'critical' }, { label => 'warning-cp', exit_litteral => 'warning' } ]); my $exit2 = $self->{perfdata}->threshold_check(value => $block_time, threshold => [ { label => 'critical-block', 'exit_litteral' => 'critical' }, { label => 'warning-block', exit_litteral => 'warning' } ]); my $exit3 = $self->{perfdata}->threshold_check(value => $flush_time, threshold => [ { label => 'critical-flush', 'exit_litteral' => 'critical' }, { label => 'warning-flush', exit_litteral => 'warning' } ]); my $exit4 = $self->{perfdata}->threshold_check(value => $crit_time, threshold => [ { label => 'critical-crit', 'exit_litteral' => 'critical' }, { label => 'warning-crit', exit_litteral => 'warning' } ]); my $exit = $self->{output}->get_most_critical(status => [ $exit1, $exit2, $exit3, $exit4 ]); $self->{output}->output_add(long_msg => sprintf("Checkpoint %s %s : Total Time %.4f, Block Time %.4f, Flush Time %.4f, Ckpt Time %.4f", $name, $id, $cp_time, $block_time, $flush_time, $crit_time) ); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Checkpoint %s %s : Total Time %.4f, Block Time %.4f, Flush Time %.4f, Ckpt Time %.4f", $name, $id, $cp_time, $block_time, $flush_time, $crit_time) ); } $self->{output}->perfdata_add(label => 'cp_' . $name . "_" . $id, value => sprintf("%.4f", $cp_time), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning_cp'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical_cp'), min => 0); $self->{output}->perfdata_add(label => 'block_' . $name . "_" . $id, value => sprintf("%.4f", $block_time), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning_block'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical_block'), min => 0); $self->{output}->perfdata_add(label => 'flush_' . $name . "_" . $id, value => sprintf("%.4f", $flush_time), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning_flush'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical_flush'), min => 0); $self->{output}->perfdata_add(label => 'crit_' . $name . "_" . $id, value => sprintf("%.4f", $crit_time), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning_crit'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical_crit'), min => 0); } if ($count == 0) { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => "Cannot find checkpoints (maybe the --name filter option)."); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check Informix Checkpoints. 4 values: - cp_time: Total checkpoint duration from request time to checkpoint completion. - flush_time: Time taken to flush all the bufferpools. - crit_time: This is the amount of time it takes for all transactions to recognize a checkpoint has been requested. - block_time: Transaction blocking time. =over 8 =item B<--warning-cp> Threshold warning 'cp_time' in seconds. =item B<--critical-cp> Threshold critical 'cp_time' in seconds. =item B<--warning-flush> Threshold warning 'flush_time' in seconds. =item B<--critical-flush> Threshold critical 'flush_time' in seconds. =item B<--warning-crit> Threshold warning 'crit_time' in seconds. =item B<--critical-crit> Threshold critical 'crit_time' in seconds. =item B<--warning-block> Threshold warning 'block_time' in seconds. =item B<--critical-block> Threshold critical 'block_time' in seconds. =item B<--filter-trigger> Filter events that can trigger a checkpoint with a regexp. =back =cut centreon-plugins-20220113/database/informix/sql/mode/chunkstates.pm000066400000000000000000000146751417000230700252650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::informix::sql::mode::chunkstates; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::misc; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning:s" => { name => 'warning', }, "critical:s" => { name => 'critical', }, "chunk-state:s" => { name => 'chunk_state', }, "name:s" => { name => 'name', }, "regexp" => { name => 'use_regexp' }, "global-ok-msg:s" => { name => 'global_ok_msg', default => 'All chunks are ok' }, "ok-msg:s" => { name => 'ok_msg', default => 'Chunk %s is ok' }, "error-msg:s" => { name => 'error_msg', default => 'Chunk %s has a problem' }, }); 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}->{chunk_state})) { $self->{output}->add_option_msg(short_msg => "Need to specify a chunk-state argument."); $self->{output}->option_exit(); } if ($self->{option_results}->{chunk_state} !~ /^(is_offline|is_recovering|is_blobchunk|is_inconsistent)$/ ) { $self->{output}->add_option_msg(short_msg => "Need to specify a valid chunk-state argument."); $self->{output}->option_exit(); } } sub run { my ($self, %options) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); my $query = " SELECT name, chknum, $self->{option_results}->{chunk_state} FROM sysdbspaces, syschunks WHERE sysdbspaces.dbsnum = syschunks.dbsnum "; $self->{sql}->query(query => $query); if (!defined($self->{option_results}->{name}) || defined($self->{option_results}->{use_regexp})) { $self->{output}->output_add(severity => 'OK', short_msg => $self->{option_results}->{global_ok_msg}); } my $count = 0; while ((my $row = $self->{sql}->fetchrow_hashref())) { my $name = centreon::plugins::misc::trim($row->{name}); next if (defined($self->{option_results}->{name}) && !defined($self->{option_results}->{use_regexp}) && $name ne $self->{option_results}->{name}); next if (defined($self->{option_results}->{name}) && defined($self->{option_results}->{use_regexp}) && $name !~ /$self->{option_results}->{name}/); $count++; $self->{output}->output_add(long_msg => sprintf("Chunk %s state '%s' is %s", $name . " " . $row->{chknum}, $self->{option_results}->{chunk_state}, $row->{$self->{option_results}->{chunk_state}})); my $exit_code = $self->{perfdata}->threshold_check(value => $row->{$self->{option_results}->{chunk_state}}, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); if (!$self->{output}->is_status(value => $exit_code, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit_code, short_msg => sprintf($self->{option_results}->{error_msg}, $name . " " . $row->{chknum})); } elsif (defined($self->{option_results}->{name}) && !defined($self->{option_results}->{use_regexp})) { $self->{output}->output_add(severity => $exit_code, short_msg => sprintf($self->{option_results}->{ok_msg}, $name . " " . $row->{chknum})); } } if ($count == 0) { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => "Cannot find a dbspace (maybe the filter)."); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check state (is_offline, is_recovering, is_blobchunk, is_inconsistent) chunks. Options example: xxxx --chunk-state="is_offline" --warning="@1:1" --error-msg="Chunk %s is down" =over 8 =item B<--warning> Threshold warning (can check 1 or 0). =item B<--critical> Threshold critical (can check 1 or 0). =item B<--chunk-state> State to check (Can be: is_offline, is_recovering, is_blobchunk, is_inconsistent). =item B<--error-msg> Display message when you have an error. (Default: 'Chunk %s has a problem') =item B<--ok-msg> Display message when chunk is ok. (Default: 'Chunk %s is ok') =item B<--global-ok-msg> Display global message when you have no errors. (Default: 'All chunks are ok') =item B<--name> Set the dbspace (empty means 'check all dbspaces'). =item B<--regexp> Allows to use regexp to filter dbspaces (with option --name). =back =cut centreon-plugins-20220113/database/informix/sql/mode/dbspacesusage.pm000066400000000000000000000131751417000230700255340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::informix::sql::mode::dbspacesusage; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::misc; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning:s" => { name => 'warning', }, "critical:s" => { name => 'critical', }, "name:s" => { name => 'name', }, "regexp" => { name => 'use_regexp' }, }); 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) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); my $query = q{ SELECT name dbspace, sum(chksize) pages_size, -- sum of all chunks size pages sum(nfree) pages_free -- sum of all chunks free pages FROM sysdbspaces d, syschunks c WHERE d.dbsnum = c.dbsnum GROUP BY d.name ORDER BY d.name }; $self->{sql}->query(query => $query); if (!defined($self->{option_results}->{name}) || defined($self->{option_results}->{use_regexp})) { $self->{output}->output_add(severity => 'OK', short_msg => 'All dbspaces usage are ok'); } my $count = 0; while ((my $row = $self->{sql}->fetchrow_hashref())) { my $name = centreon::plugins::misc::trim($row->{dbspace}); next if (defined($self->{option_results}->{name}) && !defined($self->{option_results}->{use_regexp}) && $name ne $self->{option_results}->{name}); next if (defined($self->{option_results}->{name}) && defined($self->{option_results}->{use_regexp}) && $name !~ /$self->{option_results}->{name}/); my $prct_used; if ($row->{pages_free} == 0) { $prct_used = 100; } else { $prct_used = ($row->{pages_size} - $row->{pages_free}) * 100 / $row->{pages_size}; } $count++; $self->{output}->output_add(long_msg => sprintf("Dbspace '%s': Used: %.2f%% Free: %.2f%%", $name, $prct_used, 100 - $prct_used)); my $exit_code = $self->{perfdata}->threshold_check(value => $prct_used, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); if (!$self->{output}->is_status(value => $exit_code, compare => 'ok', litteral => 1) || (defined($self->{option_results}->{name}) && !defined($self->{option_results}->{use_regexp}))) { $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("Dbspace '%s': Used: %.2f%% Free: %.2f%%", $name, $prct_used, 100 - $prct_used)); } my $extra_label = ''; $extra_label = '_' . $name if (!defined($self->{option_results}->{name}) || defined($self->{option_results}->{use_regexp})); $self->{output}->perfdata_add(label => 'used' . $extra_label, unit => '%', value => sprintf("%.2f", $prct_used), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0, max => 100); } if ($count == 0) { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => "Cannot find a dbspace (maybe the filter)."); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check usage for one or more dbspaces. =over 8 =item B<--warning> Threshold warning in percent. =item B<--critical> Threshold critical in percent. =item B<--name> Set the dbspace (empty means 'check all dbspaces'). =item B<--regexp> Allows to use regexp to filter dbspaces (with option --name). =back =cut centreon-plugins-20220113/database/informix/sql/mode/globalcache.pm000066400000000000000000000232131417000230700251410ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::informix::sql::mode::globalcache; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::statefile; use centreon::plugins::misc; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning-read:s" => { name => 'warning_read', }, "critical-read:s" => { name => 'critical_read', }, "warning-write:s" => { name => 'warning_write', }, "critical-write:s" => { name => 'critical_write', }, "lookback" => { name => 'lookback', }, }); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (($self->{perfdata}->threshold_validate(label => 'warning_read', value => $self->{option_results}->{warning_read})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning-read threshold '" . $self->{option_results}->{warning_read} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'critical_read', value => $self->{option_results}->{critical_read})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical-read threshold '" . $self->{option_results}->{critical_read} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'warning_write', value => $self->{option_results}->{warning_write})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning-read threshold '" . $self->{option_results}->{warning_write} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'critical_write', value => $self->{option_results}->{critical_write})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical-write threshold '" . $self->{option_results}->{critical_write} . "'."); $self->{output}->option_exit(); } $self->{statefile_cache}->check_options(%options); } sub run { my ($self, %options) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); $self->{sql}->query(query => q{SELECT name, value FROM sysprofile WHERE name IN ( 'dskreads', 'bufreads', 'bufwrites', 'dskwrites' ) }); my $new_datas = {dskreads => undef, bufreads => undef, bufwrites => undef, dskwrites => undef}; my $result = $self->{sql}->fetchall_arrayref(); foreach my $row (@{$result}) { $new_datas->{centreon::plugins::misc::trim($$row[0])} = $$row[1]; } foreach (keys %$new_datas) { if (!defined($new_datas->{$_})) { $self->{output}->add_option_msg(short_msg => "Cannot get '$_' variable."); $self->{output}->option_exit(); } } $self->{statefile_cache}->read(statefile => 'informix_' . $self->{mode} . '_' . $self->{sql}->get_unique_id4save()); my $old_timestamp = $self->{statefile_cache}->get(name => 'last_timestamp'); $new_datas->{last_timestamp} = time(); if (defined($old_timestamp)) { my $old_dskreads = $self->{statefile_cache}->get(name => 'dskreads'); my $old_bufreads = $self->{statefile_cache}->get(name => 'bufreads'); my $old_bufwrites = $self->{statefile_cache}->get(name => 'bufwrites'); my $old_dskwrites = $self->{statefile_cache}->get(name => 'dskwrites'); $old_dskreads = 0 if ($old_dskreads > $new_datas->{dskreads}); $old_bufreads = 0 if ($old_bufreads > $new_datas->{bufreads}); $old_bufwrites = 0 if ($old_bufwrites > $new_datas->{bufwrites}); $old_dskwrites = 0 if ($old_dskwrites > $new_datas->{dskwrites}); my $diff_bufreads = $new_datas->{bufreads} - $old_bufreads; my $diff_dskreads = $new_datas->{dskreads} - $old_dskreads; my $diff_bufwrites = $new_datas->{bufwrites} - $old_bufwrites; my $diff_dskwrites = $new_datas->{dskwrites} - $old_dskwrites; # 100 * (bufreads - dskreads) / bufreads # 100 * (bufwrits - dskwrits) / bufwrits my %prcts = (); $prcts{readcached_now} = ($diff_bufreads == 0) ? 0 : 100 * ($diff_bufreads - $diff_dskreads) / $diff_bufreads; $prcts{readcached} = ($new_datas->{bufreads} == 0) ? 0 : 100 * ($new_datas->{bufreads} - $new_datas->{dskreads}) / $new_datas->{bufreads}; $prcts{readcached_now} = 0 if ($prcts{readcached_now} < 0); $prcts{readcached} = 0 if ($prcts{readcached} < 0); $prcts{writecached_now} = ($diff_bufwrites == 0) ? 0 : 100 * ($diff_bufwrites - $diff_dskwrites) / $diff_bufwrites; $prcts{writecached} = ($new_datas->{bufwrites} == 0) ? 0 : 100 * ($new_datas->{bufwrites} - $new_datas->{dskwrites}) / $new_datas->{bufwrites}; $prcts{writecached_now} = 0 if ($prcts{writecached_now} < 0); $prcts{writecached} = 0 if ($prcts{writecached} < 0); my $exit_code = $self->{perfdata}->threshold_check(value => $prcts{'readcached' . ((defined($self->{option_results}->{lookback})) ? '' : '_now' )}, threshold => [ { label => 'critical_read', 'exit_litteral' => 'critical' }, { label => 'warning_read', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("Read Cached hitrate at %.2f%%", $prcts{'readcached' . ((defined($self->{option_results}->{lookback})) ? '' : '_now')}) ); $self->{output}->perfdata_add(label => 'readcached' . ((defined($self->{option_results}->{lookback})) ? '' : '_now'), unit => '%', value => sprintf("%.2f", $prcts{'readcached' . ((defined($self->{option_results}->{lookback})) ? '' : '_now')}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning_read'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical_read'), min => 0, max => 100); $self->{output}->perfdata_add(label => 'readcached' . ((defined($self->{option_results}->{lookback})) ? '_now' : ''), unit => '%', value => sprintf("%.2f", $prcts{'readcached' . ((defined($self->{option_results}->{lookback})) ? '_now' : '')}), min => 0, max => 100); $exit_code = $self->{perfdata}->threshold_check(value => $prcts{'writecached' . ((defined($self->{option_results}->{lookback})) ? '' : '_now' )}, threshold => [ { label => 'critical_write', 'exit_litteral' => 'critical' }, { label => 'warning_write', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("Write Cached hitrate at %.2f%%", $prcts{'writecached' . ((defined($self->{option_results}->{lookback})) ? '' : '_now')}) ); $self->{output}->perfdata_add(label => 'writecached' . ((defined($self->{option_results}->{lookback})) ? '' : '_now'), unit => '%', value => sprintf("%.2f", $prcts{'writecached' . ((defined($self->{option_results}->{lookback})) ? '' : '_now')}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning_write'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical_write'), min => 0, max => 100); $self->{output}->perfdata_add(label => 'writecached' . ((defined($self->{option_results}->{lookback})) ? '_now' : ''), unit => '%', value => sprintf("%.2f", $prcts{'writecached' . ((defined($self->{option_results}->{lookback})) ? '_now' : '')}), min => 0, max => 100); } $self->{statefile_cache}->write(data => $new_datas); if (!defined($old_timestamp)) { $self->{output}->output_add(severity => 'OK', short_msg => "Buffer creation..."); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check write/read cached. =over 8 =item B<--warning-read> Threshold read cached warning in percent. =item B<--critical-read> Threshold read cached critical in percent. =item B<--warning-write> Threshold write cached warning in percent. =item B<--critical-write> Threshold write cached critical in percent. =item B<--lookback> Threshold isn't on the percent calculated from the difference ('xxxcached_now'). =back =cut centreon-plugins-20220113/database/informix/sql/mode/listdatabases.pm000066400000000000000000000056711417000230700255500ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::informix::sql::mode::listdatabases; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::misc; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "exclude:s" => { name => 'exclude', }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{sql}->connect(); $self->{sql}->query(query => q{ SELECT name FROM sysdatabases ORDER BY name }); $self->{list_databases} = []; while ((my $row = $self->{sql}->fetchrow_hashref())) { if (defined($self->{option_results}->{exclude}) && $row->{name} !~ /$self->{option_results}->{exclude}/) { $self->{output}->output_add(long_msg => "Skipping database '" . centreon::plugins::misc::trim($row->{name}) . "': no matching filter name"); next; } push @{$self->{list_databases}}, centreon::plugins::misc::trim($row->{name}); } } sub run { my ($self, %options) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->manage_selection(); foreach my $name (sort @{$self->{list_databases}}) { $self->{output}->output_add(long_msg => "'" . $name . "'"); } $self->{output}->output_add(severity => 'OK', short_msg => "List of databases:"); $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->{sql} = $options{sql}; $self->manage_selection(); foreach (sort @{$self->{list_databases}}) { $self->{output}->add_disco_entry(name => $_); } } 1; __END__ =head1 MODE Display databases. =over 8 =item B<--exclude> Filter databases. =back =cut centreon-plugins-20220113/database/informix/sql/mode/listdbspaces.pm000066400000000000000000000056561417000230700254100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::informix::sql::mode::listdbspaces; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::misc; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "exclude:s" => { name => 'exclude', }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{sql}->connect(); $self->{sql}->query(query => q{ SELECT name FROM sysdbspaces ORDER BY name }); $self->{list_dbspaces} = []; while ((my $row = $self->{sql}->fetchrow_hashref())) { if (defined($self->{option_results}->{exclude}) && $row->{name} !~ /$self->{option_results}->{exclude}/) { $self->{output}->output_add(long_msg => "Skipping dbspace '" . centreon::plugins::misc::trim($row->{name}) . "': no matching filter name"); next; } push @{$self->{list_dbspaces}}, centreon::plugins::misc::trim($row->{name}); } } sub run { my ($self, %options) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->manage_selection(); foreach my $name (sort @{$self->{list_dbspaces}}) { $self->{output}->output_add(long_msg => "'" . $name . "'"); } $self->{output}->output_add(severity => 'OK', short_msg => "List of dbspaces:"); $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->{sql} = $options{sql}; $self->manage_selection(); foreach (sort @{$self->{list_dbspaces}}) { $self->{output}->add_disco_entry(name => $_); } } 1; __END__ =head1 MODE Display dbspaces =over 8 =item B<--exclude> Filter dbspaces. =back =cut centreon-plugins-20220113/database/informix/sql/mode/lockoverflow.pm000066400000000000000000000111571417000230700254350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::informix::sql::mode::lockoverflow; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::statefile; use centreon::plugins::misc; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning:s" => { name => 'warning', }, "critical:s" => { name => 'critical', }, }); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); 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(); } $self->{statefile_cache}->check_options(%options); } sub run { my ($self, %options) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); $self->{sql}->query(query => q{SELECT name, value FROM sysprofile WHERE name IN ( 'ovlock' ) }); my $new_datas = {ovlock => undef}; my $result = $self->{sql}->fetchall_arrayref(); foreach my $row (@{$result}) { $new_datas->{centreon::plugins::misc::trim($$row[0])} = $$row[1]; } foreach (keys %$new_datas) { if (!defined($new_datas->{$_})) { $self->{output}->add_option_msg(short_msg => "Cannot get '$_' variable."); $self->{output}->option_exit(); } } $self->{statefile_cache}->read(statefile => 'informix_' . $self->{mode} . '_' . $self->{sql}->get_unique_id4save()); my $old_timestamp = $self->{statefile_cache}->get(name => 'last_timestamp'); $new_datas->{last_timestamp} = time(); if (defined($old_timestamp)) { my $old_ovlock = $self->{statefile_cache}->get(name => 'ovlock'); $old_ovlock = 0 if ($old_ovlock > $new_datas->{ovlock}); my $diff_ovlock = $new_datas->{ovlock} - $old_ovlock; my $exit_code = $self->{perfdata}->threshold_check(value => $diff_ovlock, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("Lock Overflow: %d", $diff_ovlock) ); $self->{output}->perfdata_add(label => 'ovlock', value => $diff_ovlock, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0); } $self->{statefile_cache}->write(data => $new_datas); if (!defined($old_timestamp)) { $self->{output}->output_add(severity => 'OK', short_msg => "Buffer creation..."); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check the number of times Informix attempted to exceed the maximum number of locks. =over 8 =item B<--warning> Threshold warning in absolute. =item B<--critical> Threshold critical in absolute. =back =cut centreon-plugins-20220113/database/informix/sql/mode/logfilesusage.pm000066400000000000000000000103761417000230700255540ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::informix::sql::mode::logfilesusage; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "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) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); my $query = q{ SELECT uniqid, size, used FROM syslogs WHERE uniqid >= (SELECT min(tx_loguniq) FROM systrans WHERE tx_loguniq > 0) }; $self->{sql}->query(query => $query); $self->{output}->output_add(severity => 'OK', short_msg => 'All logfiles usage are ok'); my $count = 0; while ((my $row = $self->{sql}->fetchrow_hashref())) { my $id = $row->{uniqid}; my $prct_used = $row->{used} * 100 / $row->{size}; $count++; $self->{output}->output_add(long_msg => sprintf("Logfile '%s': Used: %.2f%% Free: %.2f%%", $id, $prct_used, 100 - $prct_used)); my $exit_code = $self->{perfdata}->threshold_check(value => $prct_used, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); if (!$self->{output}->is_status(value => $exit_code, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("Logfile '%s': Used: %.2f%% Free: %.2f%%", $id, $prct_used, 100 - $prct_used)); } $self->{output}->perfdata_add(label => 'used_' . $id, unit => '%', value => sprintf("%.2f", $prct_used), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0, max => 100); } if ($count == 0) { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => "Cannot find a logfile."); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check usage for log files. =over 8 =item B<--warning> Threshold warning in percent. =item B<--critical> Threshold critical in percent. =back =cut centreon-plugins-20220113/database/informix/sql/mode/longtxs.pm000066400000000000000000000066301417000230700244170ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::informix::sql::mode::longtxs; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "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) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); $self->{sql}->query(query => q{ SELECT count(*) as num FROM syssesprof WHERE longtxs=1 }); my ($number) = $self->{sql}->fetchrow_array(); if (!defined($number)) { $self->{output}->add_option_msg(short_msg => "Cannot get number of long transactions."); $self->{output}->option_exit(); } my $exit_code = $self->{perfdata}->threshold_check(value => $number, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("Current long transactions: %d", $number) ); $self->{output}->perfdata_add(label => 'count', value => $number, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check number of current long transactions. =over 8 =item B<--warning> Threshold warning in absolute. =item B<--critical> Threshold critical in absolute. =back =cut centreon-plugins-20220113/database/informix/sql/mode/sessions.pm000066400000000000000000000067211417000230700245700ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::informix::sql::mode::sessions; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "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) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); $self->{sql}->query(query => q{SELECT COUNT(*) FROM sysmaster:syssessions WHERE NOT (username = 'informix' OR pid = 0) }); my ($result) = $self->{sql}->fetchrow_array(); if (!defined($result)) { $self->{output}->add_option_msg(short_msg => "Cannot get number of sessions."); $self->{output}->option_exit(); } my $value = $result; my $exit_code = $self->{perfdata}->threshold_check(value => $value, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("%d client sessions", $value) ); $self->{output}->perfdata_add(label => 'sessions', value => $value, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check number of open sessions ('informix' user is not counted). =over 8 =item B<--warning> Threshold warning. =item B<--critical> Threshold critical. =back =cut centreon-plugins-20220113/database/informix/sql/mode/tablelocks.pm000066400000000000000000000363201417000230700250430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::informix::sql::mode::tablelocks; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::statefile; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning-deadlks:s" => { name => 'warning_deadlks', }, "critical-deadlks:s" => { name => 'critical_deadlks', }, "warning-lockwts:s" => { name => 'warning_lockwts', }, "critical-lockwts:s" => { name => 'critical_lockwts', }, "warning-lockreqs:s" => { name => 'warning_lockreqs', }, "critical-lockreqs:s" => { name => 'critical_lockreqs', }, "warning-lktouts:s" => { name => 'warning_lktouts', }, "critical-lktouts:s" => { name => 'critical_lktouts', }, "name:s" => { name => 'name', }, "regexp" => { name => 'use_regexp' }, "filter-tables:s" => { name => 'filter_tables' }, "only-databases" => { name => 'only_databases' }, }); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (($self->{perfdata}->threshold_validate(label => 'warning-deadlks', value => $self->{option_results}->{warning_deadlks})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning-deadlks threshold '" . $self->{option_results}->{warning_deadlks} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'critical-deadlks', value => $self->{option_results}->{critical_deadlks})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical-deadlks threshold '" . $self->{option_results}->{critical_deadlks} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'warning-lockwts', value => $self->{option_results}->{warning_lockwts})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning-lockwts threshold '" . $self->{option_results}->{warning_lockwts} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'critical-lockwts', value => $self->{option_results}->{critical_lockwts})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical-lockwts threshold '" . $self->{option_results}->{critical_lockwts} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'warning-lockreqs', value => $self->{option_results}->{warning_lockreqs})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning-lockreqs threshold '" . $self->{option_results}->{warning_lockreqs} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'critical-lockreqs', value => $self->{option_results}->{critical_lockreqs})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical-lockreqs threshold '" . $self->{option_results}->{critical_lockreqs} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'warning-lktouts', value => $self->{option_results}->{warning_block})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning-lktouts threshold '" . $self->{option_results}->{warning_block} . "'."); $self->{output}->option_exit(); } if (($self->{perfdata}->threshold_validate(label => 'critical-lktouts', value => $self->{option_results}->{critical_lktouts})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong critical-lktouts threshold '" . $self->{option_results}->{critical_lktouts} . "'."); $self->{output}->option_exit(); } $self->{statefile_cache}->check_options(%options); } sub run { my ($self, %options) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); my $query = q{ SELECT dbsname, tabname, deadlks, lockwts, lockreqs, lktouts FROM sysptprof ORDER BY dbsname, tabname }; $self->{sql}->query(query => $query); $self->{output}->output_add(severity => 'OK', short_msg => 'All database/table locks are ok'); my $new_datas = {}; $self->{statefile_cache}->read(statefile => 'informix_' . $self->{mode} . '_' . $self->{sql}->get_unique_id4save()); my $old_timestamp = $self->{statefile_cache}->get(name => 'last_timestamp'); $new_datas->{last_timestamp} = time(); my $count = 0; my $db_found = {}; while ((my $row = $self->{sql}->fetchrow_hashref())) { my $dbname = centreon::plugins::misc::trim($row->{dbsname}); my $tabname = centreon::plugins::misc::trim($row->{tabname}); my $longname = $dbname . '.' . $tabname; next if (defined($self->{option_results}->{name}) && !defined($self->{option_results}->{use_regexp}) && $dbname ne $self->{option_results}->{name}); next if (defined($self->{option_results}->{name}) && defined($self->{option_results}->{use_regexp}) && $dbname !~ /$self->{option_results}->{name}/); next if (defined($self->{option_results}->{filter_tables}) && $longname !~ /$self->{option_results}->{filter_tables}/); $count++; my $old_datas = {}; my $get_old_value = 0; $db_found->{$dbname} = {deadlks => 0, lockwts => 0, lockreqs => 0, lktouts => 0, process => 0} if (!defined($db_found->{$dbname})); foreach (('deadlks', 'lockwts', 'lockreqs', 'lktouts')) { $new_datas->{$dbname . '_' . $_} = 0 if (!defined($new_datas->{$dbname . '_' . $_})); $new_datas->{$dbname . '_' . $_} += $row->{$_}; $new_datas->{$longname . '_' . $_} = $row->{$_}; $old_datas->{$longname . '_' . $_} = $self->{statefile_cache}->get(name => $longname . '_' . $_); # Restart or onstat -z - we set to 0 $old_datas->{$longname . '_' . $_} = 0 if (defined($old_datas->{$longname . '_' . $_}) && $old_datas->{$longname . '_' . $_} > $new_datas->{$longname . '_' . $_}); # If we have a buffer or not if (defined($old_datas->{$longname . '_' . $_})) { $get_old_value = 1; $db_found->{$dbname}->{$_} += $old_datas->{$longname . '_' . $_}; } } # Buffer needed next if ($get_old_value == 0 || !defined($old_timestamp)); $db_found->{$dbname}->{process} = 1; next if ($self->{option_results}->{only_databases}); my $diff = {}; foreach (('deadlks', 'lockwts', 'lockreqs', 'lktouts')) { $diff->{$_} = $new_datas->{$longname . '_' . $_} - $old_datas->{$longname . '_' . $_}; } my $exit1 = $self->{perfdata}->threshold_check(value => $diff->{deadlks}, threshold => [ { label => 'critical-deadlks', 'exit_litteral' => 'critical' }, { label => 'warning-deadlks', exit_litteral => 'warning' } ]); my $exit2 = $self->{perfdata}->threshold_check(value => $diff->{lockwts}, threshold => [ { label => 'critical-lockwts', 'exit_litteral' => 'critical' }, { label => 'warning-lockwts', exit_litteral => 'warning' } ]); my $exit3 = $self->{perfdata}->threshold_check(value => $diff->{lockreqs}, threshold => [ { label => 'critical-lockreqs', 'exit_litteral' => 'critical' }, { label => 'warning-lockreqs', exit_litteral => 'warning' } ]); my $exit4 = $self->{perfdata}->threshold_check(value => $diff->{lktouts}, threshold => [ { label => 'critical-lktouts', 'exit_litteral' => 'critical' }, { label => 'warning-lktouts', exit_litteral => 'warning' } ]); my $exit = $self->{output}->get_most_critical(status => [ $exit1, $exit2, $exit3, $exit4 ]); $self->{output}->output_add(long_msg => sprintf("Table '%s': Deadlocks %d, Lock Waits %d, Lock Requests %d, Lock Timeouts %d", $longname, $diff->{deadlks}, $diff->{lockwts}, $diff->{lockreqs}, $diff->{lktouts})); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Table '%s': Deadlocks %d, Lock Waits %d, Lock Requests %d, Lock Timeouts %d", $longname, $diff->{deadlks}, $diff->{lockwts}, $diff->{lockreqs}, $diff->{lktouts})); } foreach (('deadlks', 'lockwts', 'lockreqs', 'lktouts')) { $self->{output}->perfdata_add(label => 'tbl_' . $_ . '_' . $longname, value => $diff->{$_}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $_), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $_), min => 0); } } foreach my $dbname (keys %{$db_found}) { next if ($db_found->{$dbname}->{process} == 0); my $exit1 = $self->{perfdata}->threshold_check(value => $new_datas->{$dbname . '_deadlks'} - $db_found->{$dbname}->{deadlks}, threshold => [ { label => 'critical-deadlks', 'exit_litteral' => 'critical' }, { label => 'warning-deadlks', exit_litteral => 'warning' } ]); my $exit2 = $self->{perfdata}->threshold_check(value => $new_datas->{$dbname . '_lockwts'} - $db_found->{$dbname}->{lockwts}, threshold => [ { label => 'critical-lockwts', 'exit_litteral' => 'critical' }, { label => 'warning-lockwts', exit_litteral => 'warning' } ]); my $exit3 = $self->{perfdata}->threshold_check(value => $new_datas->{$dbname . '_lockreqs'} - $db_found->{$dbname}->{lockreqs}, threshold => [ { label => 'critical-lockreqs', 'exit_litteral' => 'critical' }, { label => 'warning-lockreqs', exit_litteral => 'warning' } ]); my $exit4 = $self->{perfdata}->threshold_check(value => $new_datas->{$dbname . '_lktouts'} - $db_found->{$dbname}->{lktouts}, threshold => [ { label => 'critical-lktouts', 'exit_litteral' => 'critical' }, { label => 'warning-lktouts', exit_litteral => 'warning' } ]); my $exit = $self->{output}->get_most_critical(status => [ $exit1, $exit2, $exit3, $exit4 ]); $self->{output}->output_add(long_msg => sprintf("Database '%s': Deadlocks %d, Lock Waits %d, Lock Requests %d, lock timeouts %d", $dbname, $new_datas->{$dbname . '_deadlks'} - $db_found->{$dbname}->{deadlks}, $new_datas->{$dbname . '_lockwts'} - $db_found->{$dbname}->{lockwts}, $new_datas->{$dbname . '_lockreqs'} - $db_found->{$dbname}->{lockreqs}, $new_datas->{$dbname . '_lktouts'} - $db_found->{$dbname}->{lktouts})); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Database '%s': Deadlocks %d, Lock Waits %d, Lock Requests %d, lock timeouts %d", $dbname, $new_datas->{$dbname . '_deadlks'} - $db_found->{$dbname}->{deadlks}, $new_datas->{$dbname . '_lockwts'} - $db_found->{$dbname}->{lockwts}, $new_datas->{$dbname . '_lockreqs'} - $db_found->{$dbname}->{lockreqs}, $new_datas->{$dbname . '_lktouts'} - $db_found->{$dbname}->{lktouts})); } foreach (('deadlks', 'lockwts', 'lockreqs', 'lktouts')) { $self->{output}->perfdata_add(label => 'db_' . $_ . '_' . $dbname, value => $new_datas->{$dbname . '_' . $_} - $db_found->{$dbname}->{$_}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $_), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $_), min => 0); } } if ($count == 0) { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => "Cannot find a table (maybe filters)."); } $self->{statefile_cache}->write(data => $new_datas); if (!defined($old_timestamp)) { $self->{output}->output_add(severity => 'OK', short_msg => "Buffer creation..."); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check table locks: - deadlks: deadlocks. - lockwts: lock waits. - lockreqs: lock requests. - lktouts: lock timeouts. =over 8 =item B<--warning-deadlks> Threshold warning 'deadlks' in absolute. =item B<--critical-deadlks> Threshold critical 'deadlks' in absolute. =item B<--warning-lockwts> Threshold warning 'lockwts' in absolute. =item B<--critical-lockwts> Threshold critical 'lockwts' in absolute. =item B<--warning-lockreqs> Threshold warning 'lockreqs' in absolute. =item B<--critical-lockreqs> Threshold critical 'lockreqs' in absolute. =item B<--warning-lktouts> Threshold warning 'lktouts' in absolute. =item B<--critical-lktouts> Threshold critical 'lktouts' in absolute. =item B<--name> Set the database (empty means 'check all databases'). =item B<--regexp> Allows to use regexp to filter database (with option --name). =item B<--filter-tables> Filter tables (format of a table name: 'sysmater.dual'). =item B<--only-databases> only check locks globally on database (no output for tables). =back =cut centreon-plugins-20220113/database/informix/sql/plugin.pm000066400000000000000000000102741417000230700232720ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::informix::sql::plugin; use strict; use warnings; use base qw(centreon::plugins::script_sql); use File::Temp qw(tempfile); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $self->{version} = '0.1'; $self->{modes} = { 'archivelevel0' => 'database::informix::sql::mode::archivelevel0', 'collection' => 'centreon::common::protocols::sql::mode::collection', 'checkpoints' => 'database::informix::sql::mode::checkpoints', 'chunkstates' => 'database::informix::sql::mode::chunkstates', 'connection-time' => 'centreon::common::protocols::sql::mode::connectiontime', 'global-cache' => 'database::informix::sql::mode::globalcache', 'list-dbspaces' => 'database::informix::sql::mode::listdbspaces', 'list-databases' => 'database::informix::sql::mode::listdatabases', 'lockoverflow' => 'database::informix::sql::mode::lockoverflow', 'longtxs' => 'database::informix::sql::mode::longtxs', 'dbspace-usage' => 'database::informix::sql::mode::dbspacesusage', 'logfile-usage' => 'database::informix::sql::mode::logfilesusage', 'sessions' => 'database::informix::sql::mode::sessions', 'table-locks' => 'database::informix::sql::mode::tablelocks', 'sql' => 'centreon::common::protocols::sql::mode::sql', }; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options( arguments => { 'host:s@' => { name => 'db_host' }, 'port:s@' => { name => 'db_port' }, 'instance:s@' => { name => 'db_instance' }, } ); $self->{options}->parse_options(); my $options_result = $self->{options}->get_options(); $self->{options}->clean(); if (defined($options_result->{db_host})) { @{$self->{sqldefault}->{dbi}} = (); for (my $i = 0; $i < scalar(@{$options_result->{db_host}}); $i++) { if (!defined($options_result->{db_instance}[$i])) { $self->{output}->add_option_msg(short_msg => "Need to specify instance argument."); $self->{output}->option_exit(); } if (!defined($options_result->{db_port}[$i])) { $self->{output}->add_option_msg(short_msg => "Need to specify port argument."); $self->{output}->option_exit(); } my ($handle, $path) = tempfile("sqlhosts_" . $options_result->{db_instance}[$i] . "\_XXXXX", UNLINK => 1, TMPDIR => 1); print $handle $options_result->{db_instance}[$i] . " onsoctcp " . $options_result->{db_host}[$i] . " " . $options_result->{db_port}[$i] . "\n"; close($handle); $self->{sqldefault}->{dbi}[$i] = { data_source => 'Informix:sysmaster@' . $options_result->{db_instance}[$i], env => { INFORMIXSQLHOSTS => File::Spec->rel2abs($path), INFORMIXSERVER => $options_result->{db_instance}[$i] } }; } } $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Informix Server. =over 8 You need to specify the following options. =item B<--host> Hostname to query. =item B<--port> Database Server Port. =item B<--instance> Database Instance Name. =back =cut centreon-plugins-20220113/database/mongodb/000077500000000000000000000000001417000230700204255ustar00rootroot00000000000000centreon-plugins-20220113/database/mongodb/custom/000077500000000000000000000000001417000230700217375ustar00rootroot00000000000000centreon-plugins-20220113/database/mongodb/custom/driver.pm000066400000000000000000000135461417000230700236010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mongodb::custom::driver; use strict; use warnings; use DateTime; use MongoDB; use Hash::Ordered; use URI::Encode; 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'protocol:s' => { name => 'protocol' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'timeout:s' => { name => 'timeout' }, 'ssl-opt:s@' => { name => 'ssl_opt' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'DRIVER OPTIONS', once => 1); $self->{output} = $options{output}; return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : ''; $self->{protocol} = (defined($self->{option_results}->{protocol})) ? $self->{option_results}->{protocol} : 'mongodb'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{username} = (defined($self->{option_results}->{username})) ? $self->{option_results}->{username} : ''; $self->{password} = (defined($self->{option_results}->{password})) ? $self->{option_results}->{password} : ''; if (!defined($self->{hostname}) || $self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } foreach (@{$self->{option_results}->{ssl_opt}}) { $_ =~ /(\w+)\s*=>\s*(\w+)/; $self->{ssl_opts}->{$1} = $2; } return 0; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub get_port { my ($self, %options) = @_; return $self->{port}; } sub connect { my ($self, %options) = @_; my $uri = URI::Encode->new({encode_reserved => 1}); my $encoded_username = $uri->encode($self->{username}); my $encoded_password = $uri->encode($self->{password}); $uri = $self->{protocol} . '://'; $uri .= $encoded_username . ':' . $encoded_password . '@' if ($encoded_username ne '' && $encoded_password ne ''); $uri .= $self->{hostname} if ($self->{hostname} ne ''); $uri .= ':' . $self->{port} if ($self->{port} ne '' && $self->{protocol} ne 'mongodb+srv'); $self->{output}->output_add(long_msg => 'Connection URI: ' . $uri, debug => 1); my $ssl = (defined($self->{ssl_opts})) ? $self->{ssl_opts} : 0; $self->{client} = MongoDB::MongoClient->new(host => $uri, ssl => $ssl); $self->{client}->connect(); eval { my $conn_status = $self->run_command( database => 'admin', command => $self->ordered_hash(ping => 1), ); }; if ($@) { $self->{output}->output_add(long_msg => $@, debug => 1); $self->{output}->add_option_msg(short_msg => "Connection error (add --debug option to display error message)"); $self->{output}->option_exit(); } } sub ordered_hash { my ($self, %options) = @_; tie my %hash, 'Hash::Ordered'; my $oh = tied %hash; $oh->push(%options); return \%hash; } sub run_command { my ($self, %options) = @_; if (!defined($self->{client})) { $self->connect(); } my $db = $self->{client}->get_database($options{database}); return $db->run_command($options{command}); } sub list_databases { my ($self, %options) = @_; if (!defined($self->{client})) { $self->connect(); } my @dbs = $self->{client}->database_names; return \@dbs; } sub list_collections { my ($self, %options) = @_; if (!defined($self->{client})) { $self->connect(); } my $db = $self->{client}->get_database($options{database}); my @cls = $db->collection_names({ type => 'collection' }); return \@cls; } 1; __END__ =head1 NAME MongoDB driver =head1 DRIVER OPTIONS MongoDB driver =over 8 =item B<--hostname> MongoDB server hostname. =item B<--port> Port used by MongoDB. =item B<--protocol> Protocol used (Default: mongodb) DNS Seedlist Connection Format can be specified, i.e. 'mongodb+srv' =item B<--username> MongoDB username. =item B<--password> MongoDB password. =item B<--timeout> Set timeout in seconds (Default: 10). =item B<--ssl-opt> Set SSL Options (--ssl-opt="SSL_version => TLSv1" --ssl-opt="SSL_verify_mode => SSL_VERIFY_NONE"). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/database/mongodb/mode/000077500000000000000000000000001417000230700213515ustar00rootroot00000000000000centreon-plugins-20220113/database/mongodb/mode/collectionstatistics.pm000066400000000000000000000131501417000230700261550ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mongodb::mode::collectionstatistics; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'databases', type => 3, cb_long_output => 'long_output', message_multiple => 'All databases statistics are ok', indent_long_output => ' ', group => [ { name => 'collections', display_long => 1, cb_prefix_output => 'prefix_output_collection', message_multiple => 'All collections statistics are ok', type => 1 }, ] } ]; $self->{maps_counters}->{collections} = [ { label => 'storage-size', nlabel => 'collection.size.storage.bytes', set => { key_values => [ { name => 'storageSize' }, { name => 'display' } ], output_template => 'Storage Size: %s %s', output_change_bytes => 1, perfdatas => [ { value => 'storageSize', template => '%s', min => 0, unit => 'B', label_extra_instance => 1 }, ], } }, { label => 'index-size', nlabel => 'collection.size.index.bytes', set => { key_values => [ { name => 'totalIndexSize' }, { name => 'display' } ], output_template => 'Index Size: %s %s', output_change_bytes => 1, perfdatas => [ { value => 'totalIndexSize', template => '%s', min => 0, unit => 'B', label_extra_instance => 1 }, ], } }, { label => 'documents', nlabel => 'collection.documents.count', set => { key_values => [ { name => 'count' }, { name => 'display' } ], output_template => 'Documents: %s', perfdatas => [ { value => 'count', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, { label => 'indexes', nlabel => 'collection.indexes.count', set => { key_values => [ { name => 'nindexes' }, { name => 'display' } ], output_template => 'Indexes: %s', perfdatas => [ { value => 'nindexes', template => '%s', min => 0, label_extra_instance => 1 }, ], } }, ]; } sub long_output { my ($self, %options) = @_; return "Checking database '" . $options{instance_value}->{display} . "' "; } sub prefix_output_collection { my ($self, %options) = @_; return "Collection '" . $options{instance_value}->{display} . "' "; } 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-database:s" => { name => 'filter_database' }, }); return $self; } sub manage_selection { my ($self, %options) = @_; my $databases = $options{custom}->list_databases(); $self->{databases} = {}; foreach my $database (sort @{$databases}) { next if (defined($self->{option_results}->{filter_database}) && $self->{option_results}->{filter_database} ne '' && $database !~ /$self->{option_results}->{filter_database}/); my $collections = $options{custom}->list_collections(database => $database); $self->{databases}->{$database}->{display} = $database; foreach my $collection (sort @{$collections}) { my $cl_stats = $options{custom}->run_command( database => $database, command => $options{custom}->ordered_hash(collStats => $collection), ); $self->{databases}->{$database}->{collections}->{$collection} = { display => $collection, storageSize => $cl_stats->{storageSize}, totalIndexSize => $cl_stats->{totalIndexSize}, count => $cl_stats->{count}, nindexes => $cl_stats->{nindexes}, }; } } if (scalar(keys %{$self->{databases}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No databases found'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check collections statistics per databases =over 8 =item B<--filter-database> Filter database name (Can use regexp). =item B<--warning-subinstance-collection-size-*-bytes> Threshold warning. Can be: 'storage', 'index'. =item B<--critical-subinstance-collection-size-*-bytes> Threshold critical. Can be: 'storage', 'index'. =item B<--warning-subinstance-collection-*-count> Threshold warning. Can be: 'documents', 'indexes'. =item B<--critical-subinstance-collection-*-count> Threshold critical. Can be: 'documents', 'indexes'. =back =cut centreon-plugins-20220113/database/mongodb/mode/connections.pm000066400000000000000000000105471417000230700242400ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mongodb::mode::connections; 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 => 'global', type => 0, cb_prefix_output => 'prefix_output' }, ]; $self->{maps_counters}->{global} = [ { label => 'active', nlabel => 'connections.active.count', set => { key_values => [ { name => 'active' } ], output_template => 'Active: %d', perfdatas => [ { template => '%d', min => 0, unit => 'conn' }, ], } }, { label => 'current', nlabel => 'connections.current.count', set => { key_values => [ { name => 'current' } ], output_template => 'Current: %d', perfdatas => [ { template => '%d', min => 0, unit => 'conn' }, ], } }, { label => 'usage', nlabel => 'connections.usage.percentage', set => { key_values => [ { name => 'usage' } ], output_template => 'Usage: %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%' }, ], } }, { label => 'total-created', nlabel => 'connections.created.persecond', set => { key_values => [ { name => 'totalCreated', per_second => 1 } ], output_template => 'Created: %.2f/s', perfdatas => [ { template => '%.2f', min => 0, unit => 'conn/s' }, ], } }, ]; } sub prefix_output { my ($self, %options) = @_; return "Connections "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{global} = {}; my $server_stats = $options{custom}->run_command( database => 'admin', command => $options{custom}->ordered_hash(serverStatus => 1), ); $self->{global}->{active} = $server_stats->{connections}->{active}; $self->{global}->{current} = $server_stats->{connections}->{current}; $self->{global}->{usage} = $server_stats->{connections}->{current} / ($server_stats->{connections}->{current} + $server_stats->{connections}->{available}); $self->{global}->{totalCreated} = $server_stats->{connections}->{totalCreated}; $self->{cache_name} = "mongodb_" . $self->{mode} . '_' . $options{custom}->get_hostname() . '_' . $options{custom}->get_port() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check connections statistics =over 8 =item B<--warning-connections-*-count> Threshold warning. Can be: 'active', 'current'. =item B<--critical-connections-*-count> Threshold critical. Can be: 'active', 'current'. =item B<--warning-connections-usage-percentage> Threshold warning for connections usage (current over available) =item B<--critical-connections-usage-percentage> Threshold critical for connections usage (current over available) =item B<--warning-connections-created-persecond> Threshold warning for connections created per second. =item B<--critical-connections-created-persecond> Threshold critical for connections created per second. =back =cut centreon-plugins-20220113/database/mongodb/mode/connectiontime.pm000066400000000000000000000042321417000230700247260ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mongodb::mode::connectiontime; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Time::HiRes; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, ]; $self->{maps_counters}->{global} = [ { label => 'connection-time', nlabel => 'connection.time.milliseconds', set => { key_values => [ { name => 'connection_time' } ], output_template => 'Connection established in %d ms', perfdatas => [ { value => 'connection_time', template => '%d', unit => 'ms', min => 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 => {}); return $self; } sub manage_selection { my ($self, %options) = @_; my $start = Time::HiRes::time(); $options{custom}->connect(); my $end = Time::HiRes::time(); $self->{global}->{connection_time} = ($end - $start) * 1000; } 1; __END__ =head1 MODE Check database connection time. =over 8 =item B<--warning-connection-time> Threshold warning in milliseconds. =item B<--critical-connection-time> Threshold critical in milliseconds. =back =cut centreon-plugins-20220113/database/mongodb/mode/databasestatistics.pm000066400000000000000000000147701417000230700255770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mongodb::mode::databasestatistics; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'databases', type => 1, cb_prefix_output => 'prefix_database_output', message_multiple => 'All databases statistics are ok' }, ]; $self->{maps_counters}->{databases} = [ { label => 'storage-size', nlabel => 'database.size.storage.bytes', set => { key_values => [ { name => 'storageSize' }, { name => 'display' } ], output_template => 'Storage Size: %s %s', output_change_bytes => 1, perfdatas => [ { value => 'storageSize', template => '%s', min => 0, unit => 'B', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'data-size', nlabel => 'database.size.data.bytes', set => { key_values => [ { name => 'dataSize' }, { name => 'display' } ], output_template => 'Data Size: %s %s', output_change_bytes => 1, perfdatas => [ { value => 'dataSize', template => '%s', min => 0, unit => 'B', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'index-size', nlabel => 'database.size.index.bytes', set => { key_values => [ { name => 'indexSize' }, { name => 'display' } ], output_template => 'Index Size: %s %s', output_change_bytes => 1, perfdatas => [ { value => 'indexSize', template => '%s', min => 0, unit => 'B', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'collections', nlabel => 'database.collections.count', set => { key_values => [ { name => 'collections' }, { name => 'display' } ], output_template => 'Collections: %s', perfdatas => [ { value => 'collections', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'views', nlabel => 'database.views.count', set => { key_values => [ { name => 'views' }, { name => 'display' } ], output_template => 'Views: %s', perfdatas => [ { value => 'views', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'documents', nlabel => 'database.documents.count', set => { key_values => [ { name => 'documents' }, { name => 'display' } ], output_template => 'Documents: %s', perfdatas => [ { value => 'documents', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'indexes', nlabel => 'database.indexes.count', set => { key_values => [ { name => 'indexes' }, { name => 'display' } ], output_template => 'Indexes: %s', perfdatas => [ { value => 'indexes', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub prefix_database_output { my ($self, %options) = @_; return "Database '" . $options{instance_value}->{display} . "' "; } 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-database:s' => { name => 'filter_database' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $databases = $options{custom}->list_databases(); $self->{databases} = {}; foreach my $database (sort @{$databases}) { next if (defined($self->{option_results}->{filter_database}) && $self->{option_results}->{filter_database} ne '' && $database !~ /$self->{option_results}->{filter_database}/); my $db_stats = $options{custom}->run_command( database => $database, command => $options{custom}->ordered_hash(dbStats => 1), ); $self->{databases}->{$db_stats->{db}} = { display => $db_stats->{db}, collections => $db_stats->{collections}, views => $db_stats->{views}, documents => $db_stats->{objects}, storageSize => $db_stats->{storageSize}, indexSize => $db_stats->{indexSize}, dataSize => $db_stats->{dataSize}, indexes => $db_stats->{indexes}, } } if (scalar(keys %{$self->{databases}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No databases found'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check databases statistics =over 8 =item B<--filter-database> Filter database name (Can use regexp). =item B<--warning-instance-database-size-*-bytes> Threshold warning. Can be: 'storage', 'data', 'index'. =item B<--critical-instance-database-size-*-bytes> Threshold critical. Can be: 'storage', 'data', 'index'. =item B<--warning-instance-database-*-count> Threshold warning. Can be: 'collections', 'views', 'documents', 'indexes'. =item B<--critical-instance-database-*-count> Threshold critical. Can be: 'collections', 'views', 'documents', 'indexes'. =back =cut centreon-plugins-20220113/database/mongodb/mode/listdatabases.pm000066400000000000000000000042621417000230700245360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mongodb::mode::listdatabases; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{custom} = $options{custom}; $self->{databases} = $self->{custom}->list_databases(); } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $database (sort @{$self->{databases}}) { $self->{output}->output_add(long_msg => sprintf("[name = %s]", $database)); } $self->{output}->output_add(severity => 'OK', short_msg => "List databases:"); $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->manage_selection(%options); foreach my $database (sort @{$self->{databases}}) { $self->{output}->add_disco_entry(name => $database); } } 1; __END__ =head1 MODE List databases. =over 8 =back =cut centreon-plugins-20220113/database/mongodb/mode/queries.pm000066400000000000000000000077421417000230700233760ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mongodb::mode::queries; 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 => 'global', type => 0, cb_prefix_output => 'prefix_output' }, ]; $self->{maps_counters}->{global} = [ { label => 'total', nlabel => 'queries.total.persecond', set => { key_values => [ { name => 'total', per_second => 1 } ], output_template => 'Total : %d', perfdatas => [ { template => '%d', unit => '/s', min => 0 }, ], } }, ]; foreach ('insert', 'query', 'update', 'delete', 'getmore', 'command') { push @{$self->{maps_counters}->{global}}, { label => $_, nlabel => 'queries.' . $_ . '.persecond', display_ok => 0, set => { key_values => [ { name => $_, per_second => 1 } ], output_template => $_ . ' : %.2f', perfdatas => [ { template => '%.2f', unit => '/s', min => 0 } ] } }; push @{$self->{maps_counters}->{global}}, { label => $_ . '-count', , nlabel => 'queries.' . $_ . '.count', display_ok => 0, set => { key_values => [ { name => $_, diff => 1 } ], output_template => $_ . ' count : %d', perfdatas => [ { template => '%d', min => 0 } ] } }; } } sub prefix_output { my ($self, %options) = @_; return 'Requests '; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{global} = {}; my $server_stats = $options{custom}->run_command( database => 'admin', command => $options{custom}->ordered_hash(serverStatus => 1), ); foreach my $querie (keys %{$server_stats->{opcounters}}) { $self->{global}->{$querie} = $server_stats->{opcounters}->{$querie}; $self->{global}->{total} += $server_stats->{opcounters}->{$querie}; } $self->{cache_name} = 'mongodb_' . $self->{mode} . '_' . $options{custom}->get_hostname() . '_' . $options{custom}->get_port() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check number of queries executed (absolute and per second). =over 8 =item B<--warning-queries-*-persecond> Threshold warning. Can be: 'total', 'insert', 'query', 'update', 'delete', 'getmore', 'command' =item B<--critical-queries-*-persecond> Threshold critical. Can be: 'total', 'insert', 'query', 'update', 'delete', 'getmore', 'command' =item B<--warning-queries-*-count> Threshold warning. Can be: 'insert', 'query', 'update', 'delete', 'getmore', 'command' =item B<--critical-queries-*-count> Threshold critical. Can be: 'insert', 'query', 'update', 'delete', 'getmore', 'command' =back =cut centreon-plugins-20220113/database/mongodb/mode/replicationstatus.pm000066400000000000000000000213571417000230700254740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mongodb::mode::replicationstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); my %mapping_states = ( 0 => 'STARTUP', 1 => 'PRIMARY', 2 => 'SECONDARY', 3 => 'RECOVERING', 5 => 'STARTUP2', 6 => 'UNKNOWN', 7 => 'ARBITER', 8 => 'DOWN', 9 => 'ROLLBACK', 10 => 'REMOVED', ); my %mapping_health = ( 0 => 'down', 1 => 'up', ); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("Current member state is '%s'", $self->{result_values}->{state}); $msg .= sprintf(", syncing to '%s'", $self->{result_values}->{sync_host}) if ($self->{result_values}->{state} ne 'PRIMARY'); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{state} = $mapping_states{$options{new_datas}->{$self->{instance} . '_myState'}}; $self->{result_values}->{sync_host} = $options{new_datas}->{$self->{instance} . '_syncSourceHost'}; return 0; } sub custom_member_status_output { my ($self, %options) = @_; return sprintf("state is '%s' and health is '%s' [slave delay: %s] [priority: %s]", $self->{result_values}->{state}, $self->{result_values}->{health}, $self->{result_values}->{slave_delay}, $self->{result_values}->{priority} ); } sub custom_member_status_calc { my ($self, %options) = @_; $self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_name'}; $self->{result_values}->{state} = $options{new_datas}->{$self->{instance} . '_stateStr'}; $self->{result_values}->{slave_delay} = $options{new_datas}->{$self->{instance} . '_slaveDelay'}; $self->{result_values}->{health} = $mapping_health{$options{new_datas}->{$self->{instance} . '_health'}}; $self->{result_values}->{priority} = $options{new_datas}->{$self->{instance} . '_priority'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'members', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All members statistics are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ { label => 'status', set => { key_values => [ { name => 'myState' }, { name => 'syncSourceHost' } ], 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 => \&catalog_status_threshold, } }, ]; $self->{maps_counters}->{members} = [ { label => 'member-status', set => { key_values => [ { name => 'stateStr' }, { name => 'health' }, { name => 'slaveDelay' }, { name => 'priority' }, { name => 'name' } ], closure_custom_calc => $self->can('custom_member_status_calc'), closure_custom_output => $self->can('custom_member_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold, } }, { label => 'replication-lag', nlabel => 'replication.lag.seconds', set => { key_values => [ { name => 'lag' }, { name => 'name' } ], output_template => 'Replication Lag: %s s', perfdatas => [ { value => 'lag', template => '%d', unit => 's', min => 0, label_extra_instance => 1, instance_use => 'name' }, ], } }, ]; } sub prefix_output { my ($self, %options) = @_; return "Member '" . $options{instance_value}->{name} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '' }, 'warning-member-status:s' => { name => 'warning_member_status', default => '%{state} !~ /PRIMARY|SECONDARY/' }, 'critical-member-status:s' => { name => 'critical_member_status', default => '%{health} !~ /up/' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => [ 'warning_status', 'critical_status', 'warning_member_status', 'critical_member_status' ]); } sub manage_selection { my ($self, %options) = @_; my $ismaster = $options{custom}->run_command( database => 'admin', command => $options{custom}->ordered_hash(ismaster => 1), ); if (!defined($ismaster->{me})) { $self->{output}->add_option_msg(short_msg => "No replication detected"); $self->{output}->option_exit(); } $self->{global} = {}; $self->{members} = {}; my $repl_conf = $options{custom}->run_command( database => 'admin', command => $options{custom}->ordered_hash(replSetGetConfig => 1), ); my %config; foreach my $member (sort @{$repl_conf->{config}->{members}}) { $config{$member->{host}} = { priority => $member->{priority}, slaveDelay => $member->{slaveDelay} } } my $repl_status = $options{custom}->run_command( database => 'admin', command => $options{custom}->ordered_hash(replSetGetStatus => 1), ); $self->{global}->{myState} = $repl_status->{myState}; $self->{global}->{syncSourceHost} = (defined($repl_status->{syncSourceHost})) ? $repl_status->{syncSourceHost} : $repl_status->{syncingTo}; $self->{global}->{syncSourceHost} = '-' if (!defined($self->{global}->{syncSourceHost})); foreach my $member (sort @{$repl_status->{members}}) { $self->{members}->{$member->{name}} = { name => $member->{name}, stateStr => $member->{stateStr}, health => $member->{health}, optimeDate => $member->{optime}->{ts}->{seconds}, slaveDelay => $config{$member->{name}}->{slaveDelay}, priority => $config{$member->{name}}->{priority} } } foreach my $member (keys %{$self->{members}}) { next if ($self->{members}->{$member}->{stateStr} !~ /SECONDARY/); $self->{members}->{$member}->{lag} = $self->{members}->{$ismaster->{primary}}->{optimeDate} - $self->{members}->{$member}->{optimeDate} - $self->{members}->{$member}->{slaveDelay}; } if (scalar(keys %{$self->{members}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No members found'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check replication status =over 8 =item B<--warning-status> Set warning threshold for checked instance status (Default: ''). Can used special variables like: %{state}, %{sync_host}. =item B<--critical-status> Set critical threshold for checked instance status (Default: ''). Can used special variables like: %{state}, %{sync_host}. =item B<--warning-member-status> Set warning threshold for members status (Default: '%{state} !~ /PRIMARY|SECONDARY/'). Can used special variables like: %{name}, %{state}, %{health}, %{slave_delay}, %{priority}. =item B<--critical-member-status> Set critical threshold for members status (Default: '%{health} !~ /up/'). Can used special variables like: %{name}, %{state}, %{health}, %{slave_delay}, %{priority}. =item B<--warning-instance-replication-lag-seconds> Threshold warning for replication lag between primary and secondary members. Must not be over 0 (between minus slaveDelay and 0). =item B<--critical-instance-replication-lag-seconds> Threshold critical for replication lag between primary and secondary members. Must not be over 0 (between minus slaveDelay and 0). =back =cut centreon-plugins-20220113/database/mongodb/plugin.pm000066400000000000000000000034151417000230700222640ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mongodb::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} = '1.0'; %{$self->{modes}} = ( 'collection-statistics' => 'database::mongodb::mode::collectionstatistics', 'connections' => 'database::mongodb::mode::connections', 'connection-time' => 'database::mongodb::mode::connectiontime', 'database-statistics' => 'database::mongodb::mode::databasestatistics', 'list-databases' => 'database::mongodb::mode::listdatabases', 'queries' => 'database::mongodb::mode::queries', 'replication-status' => 'database::mongodb::mode::replicationstatus', ); $self->{custom_modes}{driver} = 'database::mongodb::custom::driver'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check MongoDB server. =cut centreon-plugins-20220113/database/mssql/000077500000000000000000000000001417000230700201375ustar00rootroot00000000000000centreon-plugins-20220113/database/mssql/dbi.pm000066400000000000000000000024161417000230700212360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mssql::dbi; use base qw(centreon::plugins::dbi); use strict; use warnings; sub set_version { my ($self) = @_; $self->{version} = $self->{instance}->get_info(18); # SQL_DBMS_VER return if (defined($self->{version}) && $self->{version} ne ''); return if ($self->query(query => q{SELECT CAST(SERVERPROPERTY('productversion') AS VARCHAR) as product_version}, continue_error => 1) == 1); my $row = $self->fetchrow_hashref(); $self->{version} = $row->{product_version}; } 1; __END__ centreon-plugins-20220113/database/mssql/mode/000077500000000000000000000000001417000230700210635ustar00rootroot00000000000000centreon-plugins-20220113/database/mssql/mode/backupage.pm000066400000000000000000000224751417000230700233550ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mssql::mode::backupage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; 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_duration_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel}, unit => 's', instances => [$self->{result_values}->{name}, $self->{result_values}->{type}], value => $self->{result_values}->{duration_seconds}, 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_backup_perfdata { my ($self, %options) = @_; $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}, $self->{result_values}->{type}], value => floor($self->{result_values}->{exec_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 => -1 ); } sub custom_backup_threshold { my ($self, %options) = @_; return $self->{perfdata}->threshold_check( value => floor($self->{result_values}->{exec_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_backup_output { my ($self, %options) = @_; my $msg; if ($self->{result_values}->{exec_seconds} == -1) { $msg = 'backup never executed'; } else { $msg = 'last backup execution: ' . $self->{result_values}->{exec_human}; } return $msg; } sub prefix_database_output { my ($self, %options) = @_; return "database '" . $options{instance} . "' "; } sub database_long_output { my ($self, %options) = @_; return "checking database '" . $options{instance} . "'"; } sub prefix_full_output { return 'full '; } sub prefix_incremental_output { return 'incremental '; } sub prefix_log_output { return 'log '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'databases', type => 3, cb_prefix_output => 'prefix_database_output', cb_long_output => 'database_long_output', indent_long_output => ' ', message_multiple => 'All databases are ok', group => [ { name => 'full', type => 0, cb_prefix_output => 'prefix_full_output', skipped_code => { -10 => 1 } }, { name => 'incremental', type => 0, cb_prefix_output => 'prefix_incremental_output', skipped_code => { -10 => 1 } }, { name => 'log', type => 0, cb_prefix_output => 'prefix_log_output', skipped_code => { -10 => 1 } } ] } ]; foreach ('full', 'incremental', 'log') { $self->{maps_counters}->{$_} = [ { label => $_ . '-last-execution', nlabel => 'backup.time.last.execution', set => { key_values => [ { name => 'exec_seconds' }, { name => 'exec_human' }, { name => 'name' }, { name => 'type' } ], closure_custom_output => $self->can('custom_backup_output'), closure_custom_perfdata => $self->can('custom_backup_perfdata'), closure_custom_threshold_check => $self->can('custom_backup_threshold') } }, { label => $_ . '-last-duration', nlabel => 'backup.time.last.duration.seconds', set => { key_values => [ { name => 'duration_seconds' }, { name => 'duration_human' }, { name => 'name' }, { name => 'type' } ], output_template => 'duration time: %s', output_use => 'duration_human', closure_custom_perfdata => $self->can('custom_duration_perfdata') } } ]; } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'unit:s' => { name => 'unit', default => 'd' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if ($self->{option_results}->{unit} eq '' || !defined($unitdiv->{$self->{option_results}->{unit}})) { $self->{option_results}->{unit} = 'd'; } } sub manage_selection { my ($self, %options) = @_; my $query = q{ SELECT a.name, a.recovery_model, DATEDIFF(SS, MAX(b.backup_finish_date), GETDATE()), DATEDIFF(SS, MAX(b.backup_start_date), MAX(b.backup_finish_date)), b.type FROM master.dbo.sysdatabases a LEFT OUTER JOIN msdb.dbo.backupset b ON b.database_name = a.name WHERE b.type IN ('D', 'I', 'L') GROUP BY a.name, b.type ORDER BY a.name }; if ($options{sql}->is_version_minimum(version => '9.x')) { $query = q{ SELECT D.name AS [database_name], D.recovery_model, BS1.last_backup, BS1.last_duration, BS1.type FROM sys.databases D LEFT JOIN ( SELECT BS.[database_name], BS.[type], DATEDIFF(SS, MAX(BS.[backup_finish_date]), GETDATE()) AS last_backup, DATEDIFF(SS, MAX(BS.[backup_start_date]), MAX(BS.[backup_finish_date])) AS last_duration FROM msdb.dbo.backupset BS WHERE BS.type IN ('D', 'I', 'L') GROUP BY BS.[database_name], BS.[type] ) BS1 ON D.name = BS1.[database_name] WHERE D.source_database_id IS NULL ORDER BY D.[name] }; } $options{sql}->connect(); $options{sql}->query(query => $query); my $result = $options{sql}->fetchall_arrayref(); my $map_type = { D => 'full', I => 'incremental', L => 'log' }; $self->{databases} = {}; foreach my $row (@$result) { next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $row->[0] !~ /$self->{option_results}->{filter_name}/); if (!defined($self->{databases}->{ $row->[0] })) { $self->{databases}->{ $row->[0] } = { full => { exec_seconds => -1, exec_human => '', type => 'full', name => $row->[0] }, incremental => { exec_seconds => -1, exec_human => '', type => 'incremental', name => $row->[0] }, log => { exec_seconds => -1, exec_human => '', type => 'log', name => $row->[0] } }; } next if (!defined($map_type->{ $row->[4] })); if (defined($row->[2])) { $self->{databases}->{ $row->[0] }->{ $map_type->{ $row->[4] } }->{exec_seconds} = $row->[2]; $self->{databases}->{ $row->[0] }->{ $map_type->{ $row->[4] } }->{exec_human} = centreon::plugins::misc::change_seconds( value => $row->[2] ); } if (defined($row->[3])) { $self->{databases}->{ $row->[0] }->{ $map_type->{ $row->[4] } }->{duration_seconds} = $row->[3]; $self->{databases}->{ $row->[0] }->{ $map_type->{ $row->[4] } }->{duration_human} = centreon::plugins::misc::change_seconds( value => $row->[3] ); } } } 1; __END__ =head1 MODE Check MSSQL backup. =over 8 =item B<--filter-name> Filter databases by name. =item B<--unit> Select the unit for expires threshold. May be 's' for seconds, 'm' for minutes, 'h' for hours, 'd' for days, 'w' for weeks. Default is days. =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'incremental-last-execution', 'incremental-last-duration', 'full-last-execution', 'full-last-duration', 'log-last-execution', 'log-last-duration'. =back =cut centreon-plugins-20220113/database/mssql/mode/blockedprocesses.pm000066400000000000000000000160671417000230700247650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mssql::mode::blockedprocesses; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use POSIX qw/floor/; use centreon::plugins::misc; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'processes', type => 1 }, ]; $self->{maps_counters}->{global} = [ { label => 'blocked-processes', set => { key_values => [ { name => 'blocked_processes' } ], output_template => 'Number of blocked processes : %s', perfdatas => [ { label => 'blocked_processes', value => 'blocked_processes', template => '%s', unit => '', min => 0 }, ], } }, ]; $self->{maps_counters}->{processes} = [ { label => 'wait-time', set => { key_values => [ { name => 'spid' }, { name => 'blocked' }, { name => 'status' }, { name => 'waittime' }, { name => 'program' }, { name => 'cmd' } ], closure_custom_calc => $self->can('custom_processes_calc'), closure_custom_output => $self->can('custom_processes_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => $self->can('custom_processes_threshold'), } }, ]; } sub custom_processes_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check(value => $self->{result_values}->{waittime}, threshold => [ { label => 'critical-wait-time', exit_litteral => 'critical' }, { label => 'warning-wait-time', exit_litteral => 'warning' } ]); return $exit; } sub custom_processes_output { my ($self, %options) = @_; my $msg = sprintf("Process ID '%s' is blocked by process ID '%s' for %s [status: %s] [program: %s] [command: %s]", $self->{result_values}->{spid}, $self->{result_values}->{blocked}, ($self->{result_values}->{waittime} > 0) ? centreon::plugins::misc::change_seconds(value => $self->{result_values}->{waittime}) : "0s", $self->{result_values}->{status}, $self->{result_values}->{program}, $self->{result_values}->{cmd}); return $msg; } sub custom_processes_calc { my ($self, %options) = @_; $self->{result_values}->{spid} = $options{new_datas}->{$self->{instance} . '_spid'}; $self->{result_values}->{blocked} = $options{new_datas}->{$self->{instance} . '_blocked'}; $self->{result_values}->{waittime} = (defined($options{new_datas}->{$self->{instance} . '_waittime'}) && $options{new_datas}->{$self->{instance} . '_waittime'} ne '') ? floor($options{new_datas}->{$self->{instance} . '_waittime'} / 1000) : '0'; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; $self->{result_values}->{program} = $options{new_datas}->{$self->{instance} . '_program'}; $self->{result_values}->{cmd} = $options{new_datas}->{$self->{instance} . '_cmd'}; return 0; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-status:s" => { name => 'filter_status' }, "filter-program:s" => { name => 'filter_program' }, "filter-command:s" => { name => 'filter_command' }, }); return $self; } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); $options{sql}->query(query => q{SELECT spid, blocked, waittime, status, program_name, cmd FROM master.dbo.sysprocesses WHERE blocked <> '0'}); $self->{global} = { blocked_processes => 0 }; $self->{processes} = {}; while (my $row = $options{sql}->fetchrow_hashref()) { my $status = centreon::plugins::misc::trim($row->{status}); my $program = centreon::plugins::misc::trim($row->{program_name}); my $cmd = centreon::plugins::misc::trim($row->{cmd}); if (defined($self->{option_results}->{filter_status}) && $self->{option_results}->{filter_status} ne '' && $status !~ /$self->{option_results}->{filter_status}/) { $self->{output}->output_add(debug => 1, long_msg => "Skipping process " . $row->{spid} . ": because status is not matching filter."); next; } if (defined($self->{option_results}->{filter_program}) && $self->{option_results}->{filter_program} ne '' && $program !~ /$self->{option_results}->{filter_program}/) { $self->{output}->output_add(debug => 1, long_msg => "Skipping process " . $row->{spid} . ": because program is not matching filter."); next; } if (defined($self->{option_results}->{filter_command}) && $self->{option_results}->{filter_command} ne '' && $cmd !~ /$self->{option_results}->{filter_command}/) { $self->{output}->output_add(debug => 1, long_msg => "Skipping process " . $row->{spid} . ": because command is not matching filter."); next } $self->{processes}->{$row->{spid}} = { waittime => $row->{waittime}, spid => $row->{spid}, blocked => $row->{blocked}, status => $status, program => $program, cmd => $cmd, }; $self->{global}->{blocked_processes}++; } } 1; __END__ =head1 MODE Checks if some processes are in a blocked state. =over 8 =item B<--filter-status> Filter results based on the status (can be a regexp). =item B<--filter-program> Filter results based on the program (client) name (can be a regexp). =item B<--filter-command> Filter results based on the command name (can be a regexp). =item B<--warning-blocked-processes> Threshold warning for total number of blocked processes. =item B<--critical-blocked-processes> Threshold critical for total number of blocked processes. =item B<--warning-wait-time> Threshold warning for blocked wait time. =item B<--critical-wait-time> Threshold critical for blocked wait time. =back =cut centreon-plugins-20220113/database/mssql/mode/cachehitratio.pm000066400000000000000000000073141417000230700242350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mssql::mode::cachehitratio; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "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) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); $self->{sql}->query(query => q{ SELECT CAST( ( SELECT CAST (cntr_value AS BIGINT) FROM sys.dm_os_performance_counters WHERE counter_name = 'Buffer cache hit ratio' )* 100.00 / ( SELECT CAST (cntr_value AS BIGINT) FROM sys.dm_os_performance_counters WHERE counter_name = 'Buffer cache hit ratio base' ) AS NUMERIC(6,3) ) }); my $hitratio = $self->{sql}->fetchrow_array(); my $exit_code = $self->{perfdata}->threshold_check(value => $hitratio, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("Buffer cache hit ratio is %.2f%%", $hitratio)); $self->{output}->perfdata_add(label => 'cache_hitratio', value => sprintf("%d",$hitratio), unit => '%', warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0, max => 100); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check MSSQL buffer cache hit ratio. =over 8 =item B<--warning> Threshold warning. =item B<--critical> Threshold critical. =back =cut centreon-plugins-20220113/database/mssql/mode/connectedusers.pm000066400000000000000000000062541417000230700244540ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mssql::mode::connectedusers; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "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) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); $self->{sql}->query(query => q{SELECT count(*) FROM master..sysprocesses WHERE spid >= '51'}); my $users = $self->{sql}->fetchrow_array(); my $exit_code = $self->{perfdata}->threshold_check(value => $users, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("%i Connected user(s).", $users)); $self->{output}->perfdata_add(label => 'connected_users', value => $users, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check MSSQL connected users. =over 8 =item B<--warning> Threshold warning. =item B<--critical> Threshold critical. =back =cut centreon-plugins-20220113/database/mssql/mode/databasessize.pm000066400000000000000000000410541417000230700242470ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mssql::mode::databasessize; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_space_usage_perfdata { my ($self, %options) = @_; my ($warning, $critical); if (!(defined($self->{instance_mode}->{option_results}->{ignore_unlimited}) && $self->{result_values}->{limit} eq 'unlimited')) { $warning = $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}); $critical = $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}); } $self->{output}->perfdata_add( nlabel => $self->{nlabel}, unit => 'B', instances => $self->{result_values}->{name}, value => $self->{result_values}->{used_space}, warning => $warning, critical => $critical, min => 0, max => $self->{result_values}->{total_space} ); } sub custom_space_free_perfdata { my ($self, %options) = @_; my ($warning, $critical); if (!(defined($self->{instance_mode}->{option_results}->{ignore_unlimited}) && $self->{result_values}->{limit} eq 'unlimited')) { $warning = $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}); $critical = $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}); } $self->{output}->perfdata_add( nlabel => $self->{nlabel}, unit => 'B', instances => $self->{result_values}->{name}, value => $self->{result_values}->{free_space}, warning => $warning, critical => $critical, min => 0, max => $self->{result_values}->{total_space} ); } sub custom_space_usage_prct_perfdata { my ($self, %options) = @_; my ($warning, $critical); if (!(defined($self->{instance_mode}->{option_results}->{ignore_unlimited}) && $self->{result_values}->{limit} eq 'unlimited')) { $warning = $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}); $critical = $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}); } $self->{output}->perfdata_add( nlabel => $self->{nlabel}, unit => '%', instances => $self->{result_values}->{name}, value => sprintf('%.2f', $self->{result_values}->{prct_used_space}), warning => $warning, critical => $critical, min => 0, max => 100 ); } sub custom_space_threshold { my ($self, %options) = @_; return 'ok' if ( defined($self->{instance_mode}->{option_results}->{ignore_unlimited}) && $self->{result_values}->{limit} eq 'unlimited' ); return $self->{perfdata}->threshold_check( value => $self->{result_values}->{ $self->{key_values}->[0]->{name} }, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel}, exit_litteral => 'warning' }, { label => 'unknown-'. $self->{thlabel}, exit_litteral => 'unknown' } ] ); } sub custom_space_output { my ($self, %options) = @_; my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total_space}); my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used_space}); my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free_space}); return sprintf( 'space 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_space}, $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free_space} ); } sub database_long_output { my ($self, %options) = @_; return "checking database '" . $options{instance_value}->{name} . "'"; } sub prefix_database_output { my ($self, %options) = @_; return "database '" . $options{instance_value}->{name} . "' "; } sub prefix_logfiles_output { my ($self, %options) = @_; return 'log files '; } sub prefix_datafiles_output { my ($self, %options) = @_; return 'data files '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'databases', type => 3, cb_prefix_output => 'prefix_database_output', cb_long_output => 'database_long_output', indent_long_output => ' ', message_multiple => 'All databases are ok', group => [ { name => 'datafiles', type => 0, cb_prefix_output => 'prefix_datafiles_output', skipped_code => { -10 => 1 } }, { name => 'logfiles', type => 0, cb_prefix_output => 'prefix_logfiles_output', skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{datafiles} = [ { label => 'datafiles-space-usage', nlabel => 'datafiles.space.usage.bytes', set => { key_values => [ { name => 'used_space' }, { name => 'free_space' }, { name => 'prct_used_space' }, { name => 'prct_free_space' }, { name => 'total_space' }, { name => 'name' }, { name => 'limit' } ], closure_custom_output => $self->can('custom_space_output'), closure_custom_threshold_check => $self->can('custom_space_threshold'), closure_custom_perfdata => $self->can('custom_space_usage_perfdata') } }, { label => 'datafiles-space-usage-free', nlabel => 'datafiles.space.free.bytes', display_ok => 0, set => { key_values => [ { name => 'free_space' }, { name => 'used_space' }, { name => 'prct_used_space' }, { name => 'prct_free_space' }, { name => 'total_space' }, { name => 'name' }, { name => 'limit' } ], closure_custom_output => $self->can('custom_space_output'), closure_custom_threshold_check => $self->can('custom_space_threshold'), closure_custom_perfdata => $self->can('custom_space_free_perfdata') } }, { label => 'datafiles-space-usage-prct', nlabel => 'datafiles.space.usage.percentage', display_ok => 0, set => { key_values => [ { name => 'prct_used_space' }, { name => 'used_space' }, { name => 'free_space' }, { name => 'prct_free_space' }, { name => 'total_space' }, { name => 'name' }, { name => 'limit' } ], closure_custom_output => $self->can('custom_space_output'), closure_custom_threshold_check => $self->can('custom_space_threshold'), closure_custom_perfdata => $self->can('custom_space_usage_prct_perfdata') } } ]; $self->{maps_counters}->{logfiles} = [ { label => 'logfiles-space-usage', nlabel => 'logfiles.space.usage.bytes', set => { key_values => [ { name => 'used_space' }, { name => 'free_space' }, { name => 'prct_used_space' }, { name => 'prct_free_space' }, { name => 'total_space' }, { name => 'name' }, { name => 'limit' } ], closure_custom_output => $self->can('custom_space_output'), closure_custom_threshold_check => $self->can('custom_space_threshold'), closure_custom_perfdata => $self->can('custom_space_usage_perfdata') } }, { label => 'logfiles-space-usage-free', nlabel => 'logfiles.space.free.bytes', display_ok => 0, set => { key_values => [ { name => 'free_space' }, { name => 'used_space' }, { name => 'prct_used_space' }, { name => 'prct_free_space' }, { name => 'total_space' }, { name => 'name' }, { name => 'limit' } ], closure_custom_output => $self->can('custom_space_output'), closure_custom_threshold_check => $self->can('custom_space_threshold'), closure_custom_perfdata => $self->can('custom_space_free_perfdata') } }, { label => 'logfiles-space-usage-prct', nlabel => 'logfiles.space.usage.percentage', display_ok => 0, set => { key_values => [ { name => 'prct_used_space' }, { name => 'used_space' }, { name => 'free_space' }, { name => 'prct_free_space' }, { name => 'total_space' }, { name => 'name' }, { name => 'limit' } ], closure_custom_output => $self->can('custom_space_output'), closure_custom_threshold_check => $self->can('custom_space_threshold'), closure_custom_perfdata => $self->can('custom_space_usage_prct_perfdata') } } ]; } 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-database:s' => { name => 'filter_database' }, 'datafiles-maxsize:s' => { name => 'datafiles_maxsize' }, 'logfiles-maxsize:s' => { name => 'logfiles_maxsize' }, 'datafiles-maxsize-unlimited:s' => { name => 'datafiles_maxsize_unlimited' }, 'logfiles-maxsize-unlimited:s' => { name => 'logfiles_maxsize_unlimited' }, 'check-underlying-disk' => { name => 'check_underlying_disk' }, 'ignore-unlimited' => { name => 'ignore_unlimited' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my ($unlimited_disk, $drives, $result) = ({}, {}); $options{sql}->connect(); if (defined($self->{option_results}->{check_underlying_disk})) { $options{sql}->query(query => qq{exec master.dbo.xp_fixeddrives}); $result = $options{sql}->fetchall_arrayref(); foreach my $row (@$result) { $drives->{ $row->[0] } = $row->[1] * 1024 * 1024; } } $options{sql}->query(query => qq{ EXEC sp_MSforeachdb 'USE [?] SELECT DB_NAME(), [name], physical_name, [File_Type] = CASE type WHEN 0 THEN ''data'' WHEN 1 THEN ''log'' END, [Total_Size] = [size], [Used_Space] = (CAST(FILEPROPERTY([name], ''SpaceUsed'') as int)), [Growth_Units] = CASE [is_percent_growth] WHEN 1 THEN CAST(growth AS varchar(20)) + ''%'' ELSE CAST(growth*8/1024 AS varchar(20)) + ''Mb'' END, [max_size] FROM sys.database_files' }); # limit can be: 'unlimited', 'overload', 'other'. $self->{databases} = {}; while ($result = $options{sql}->fetchall_arrayref()) { last if (scalar(@$result) <= 0); foreach my $row (@$result) { next if (!defined($row->[7])); if (defined($self->{option_results}->{filter_database}) && $self->{option_results}->{filter_database} ne '' && $row->[0] !~ /$self->{option_results}->{filter_database}/i) { $self->{output}->output_add(debug => 1, long_msg => "skipping database " . $row->[0] . ": no matching filter."); next; } if (!defined($self->{databases}->{ $row->[0] })) { $self->{databases}->{ $row->[0] } = { name => $row->[0], datafiles => { name => $row->[0], used_space => 0, total_space => 0, limit => 'other' }, logfiles => { name => $row->[0], used_space => 0, total_space => 0, limit => 'other' } }; } $self->{databases}->{ $row->[0] }->{$row->[3] . 'files'}->{used_space} += ($row->[5] * 8 * 1024); my $size = $row->[4] * 8 * 1024; #max_size = -1 (=unlimited) if ($row->[7] == -1) { $self->{databases}->{ $row->[0] }->{$row->[3] . 'files'}->{limit} = 'unlimited'; } if (defined($self->{option_results}->{check_underlying_disk})) { # look for the drives foreach my $drive_name (keys %$drives) { if ($row->[2] =~ /^$drive_name/) { if (($row->[7] > 0) && (($row->[7] * 8 * 1024) <= ($size + $drives->{$drive_name}))) { $size = $row->[7] * 8 * 1024; } elsif (!defined($unlimited_disk->{ $row->[0] . '_' . $row->[3] . 'files_' . $drive_name })) { $size += $drives->{$drive_name}; $unlimited_disk->{ $row->[0] . '_' . $row->[3] . 'files_' . $drive_name } = 1; } last; } } } elsif ($row->[7] > 0) { $size = $row->[7] * 8 * 1024; } $self->{databases}->{ $row->[0] }->{$row->[3] . 'files'}->{total_space} += $size; } } foreach my $dbname (keys %{$self->{databases}}) { foreach my $type (('data', 'log')) { my $options = [$type . 'files_maxsize']; unshift @$options, $type . 'files_maxsize_unlimited' if ($self->{databases}->{$dbname}->{$type . 'files'}->{limit} eq 'unlimited'); foreach my $option (@$options) { if (defined($self->{option_results}->{$option}) && $self->{option_results}->{$option} ne '' && $self->{option_results}->{$option} =~ /(\d+)/) { $self->{databases}->{$dbname}->{$type . 'files'}->{total_space} = $self->{option_results}->{$option} * 1024 * 1024; $self->{databases}->{$dbname}->{$type . 'files'}->{limit} = 'overload'; last; } } $self->{databases}->{$dbname}->{$type . 'files'}->{free_space} = $self->{databases}->{$dbname}->{$type . 'files'}->{total_space} - $self->{databases}->{$dbname}->{$type . 'files'}->{used_space}; $self->{databases}->{$dbname}->{$type . 'files'}->{prct_used_space} = $self->{databases}->{$dbname}->{$type . 'files'}->{used_space} * 100 / $self->{databases}->{$dbname}->{$type . 'files'}->{total_space}; $self->{databases}->{$dbname}->{$type . 'files'}->{prct_free_space} = 100 - $self->{databases}->{$dbname}->{$type . 'files'}->{prct_used_space}; $self->{databases}->{$dbname}->{$type . 'files'}->{prct_free_space} = 0 if ($self->{databases}->{$dbname}->{$type . 'files'}->{prct_free_space} < 0); } } } 1; __END__ =head1 MODE Check database data and log files. =over 8 =item B<--filter-database> Filter database by name (Can be a regex). =item B<--datafiles-maxsize> Overload all data files max size (in MB). =item B<--logfiles-maxsize> Overload all log files max size (in MB). =item B<--datafiles-maxsize-unlimited> Overload only unlimited autogrowth data files max size (in MB). =item B<--logfiles-maxsize-unlimited> Overload only unlimited autogrowth log files max size (in MB). =item B<--check-underlying-disk> Check and consider underlying disk space for data and log files. =item B<--ignore-unlimited> Thresholds not applied on unlimited autogrowth data and log files. =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'datafiles-space-usage', 'datafiles-space-usage-free', 'datafiles-space-usage-prct' 'logfiles-space-usage', 'logfiles-space-usage-free', 'logfiles-space-usage-prct'. =back =cut centreon-plugins-20220113/database/mssql/mode/deadlocks.pm000066400000000000000000000102421417000230700233510ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mssql::mode::deadlocks; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning:s" => { name => 'warning', }, "critical:s" => { name => 'critical', }, "filter:s" => { name => 'filter', }, }); 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) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); my $query = "SELECT instance_name, cntr_value FROM sys.dm_os_performance_counters WHERE object_name = 'SQLServer:Locks' AND counter_name = 'Number of Deadlocks/sec%' "; $self->{sql}->query(query => $query); my $result = $self->{sql}->fetchall_arrayref(); my $locks = 0; $self->{output}->output_add(severity => 'OK', short_msg => "0 dead locks/s."); foreach my $row (@$result) { next if (defined($self->{option_results}->{filter}) && $$row[0] !~ /$self->{option_results}->{filter}/); $locks += $$row[1]; } my $exit_code = $self->{perfdata}->threshold_check(value => $locks, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(long_msg => sprintf( "%i dead locks/s.", $locks)); if (!$self->{output}->is_status(value => $exit_code, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("%i dead locks/s.", $locks)); } $self->{output}->perfdata_add(label => 'dead_locks', value => $locks, unit => '/s', warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check MSSQL dead locks per second =over 8 =item B<--warning> Threshold warning number of dead locks per second. =item B<--critical> Threshold critical number of dead locks per second. =item B<--filter> Filter database to check. =back =cut centreon-plugins-20220113/database/mssql/mode/failedjobs.pm000066400000000000000000000163601417000230700235310ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mssql::mode::failedjobs; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Time::Local; use centreon::plugins::misc; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf( "job '%s' status %s [runtime: %s] [duration: %s]", $self->{result_values}->{name}, $self->{result_values}->{status}, $self->{result_values}->{runtime}, centreon::plugins::misc::change_seconds(value => $self->{result_values}->{duration}) ); } sub prefix_global_output { my ($self, %options) = @_; return 'Jobs '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }, { name => 'jobs', type => 2, message_multiple => '0 problem(s) detected', display_counter_problem => { nlabel => 'jobs.problems.current.count', min => 0 }, group => [ { name => 'job', skipped_code => { -11 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'jobs-total', nlabel => 'jobs.total.count', display_ok => 0, set => { key_values => [ { name => 'total' } ], output_template => 'total: %s', perfdatas => [ { template => '%s', min => 0 } ] } } ]; foreach (('failed', 'success', 'canceled', 'running', 'retry')) { push @{$self->{maps_counters}->{global}}, { label => 'jobs-' . $_, nlabel => 'jobs.' . $_ . '.count', display_ok => 0, set => { key_values => [ { name => $_ }, { name => 'total' } ], output_template => $_ . ': %s', perfdatas => [ { template => '%s', min => 0, max => 'total' } ] } }; } $self->{maps_counters}->{job} = [ { label => 'status', type => 2, set => { key_values => [ { name => 'name' }, { name => 'status' }, { name => 'runtime'}, { name => 'duration' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter:s' => { name => 'filter' }, 'warning:s' => { name => 'warning', redirect => 'warning-jobs-failed-count' }, # legacy 'critical:s' => { name => 'critical', redirect => 'critical-jobs-failed-count' }, # legacy 'lookback:s' => { name => 'lookback' } }); return $self; } my $map_state = { 0 => 'failed', 1 => 'success', 2 => 'retry', 3 => 'canceled', 4 => 'running' }; sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); my $query = " SELECT j.[name] AS [JobName], run_status, run_duration, h.run_date AS LastRunDate, h.run_time AS LastRunTime, CASE WHEN h.[run_date] IS NULL OR h.[run_time] IS NULL THEN NULL ELSE datediff(Minute, CAST( CAST(h.[run_date] AS CHAR(8)) + ' ' + STUFF( STUFF(RIGHT('000000' + CAST(h.[run_time] AS VARCHAR(6)), 6) , 3, 0, ':') , 6, 0, ':') AS DATETIME), current_timestamp) END AS [MinutesSinceStart] FROM msdb.dbo.sysjobhistory h INNER JOIN msdb.dbo.sysjobs j ON h.job_id = j.job_id WHERE j.enabled = 1 AND h.instance_id IN (SELECT MAX(h.instance_id) FROM msdb.dbo.sysjobhistory h GROUP BY (h.job_id))"; $options{sql}->query(query => $query); my $result = $options{sql}->fetchall_arrayref(); $self->{global} = { total => 0, failed => 0, success => 0, retry => 0, canceled => 0, running => 0 }; $self->{jobs}->{global} = { job => {} }; # run_date format = YYYYMMDD # run_time format = HHMMSS. Can be: HMMSS # run_duration format = HHMMSS foreach my $row (@$result) { next if (defined($self->{option_results}->{filter}) && $row->[0] !~ /$self->{option_results}->{filter}/); next if (defined($self->{option_results}->{lookback}) && $row->[5] > $self->{option_results}->{lookback}); my $job_name = $row->[0]; my $run_duration; my $run_date = $row->[3]; my ($year, $month, $day) = $run_date =~ /(\d{4})(\d{2})(\d{2})/; my $run_time = sprintf('%06d', $row->[4]); my ($hour, $minute, $second) = $run_time =~ /(\d{2})(\d{2})(\d{2})$/; if (defined($row->[2])) { my $run_duration_padding = sprintf('%06d', $row->[2]); my ($hour_duration, $minute_duration, $second_duration) = $run_duration_padding =~ /(\d{2})(\d{2})(\d{2})$/; $run_duration = ($hour_duration * 3600 + $minute_duration * 60 + $second_duration); } else { my $start_time = timelocal($second, $minute, $hour, $day, $month - 1, $year); $run_duration = (time() - $start_time); } $self->{jobs}->{global}->{job}->{$job_name} = { name => $job_name, status => $map_state->{ $row->[1] }, duration => $run_duration, runtime => (defined($year) ? $year . '-' . $month . '-' . $day : '') . $hour . ':' . $minute . ':' . $second }; $self->{global}->{total}++; $self->{global}->{ $map_state->{ $row->[1] } }++; } } 1; __END__ =head1 MODE Check MSSQL failed jobs. =over 8 =item B<--filter> Filter job. =item B<--lookback> Check job history in minutes. =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{name}, %{status}, %{duration} =item B<--critical-status> Set critical threshold for status. Can used special variables like: %{name}, %{status}, %{duration} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'jobs-total', 'jobs-failed', 'jobs-success', 'jobs-canceled', 'jobs-running', 'jobs-retry'. =back =cut centreon-plugins-20220113/database/mssql/mode/listdatabases.pm000066400000000000000000000072351417000230700242530ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mssql::mode::listdatabases; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-database:s" => { name => 'filter_database' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{sql} = $options{sql}; $self->{sql}->connect(); $self->{sql}->query(query => q{DBCC SQLPERF(LOGSPACE)}); my $result = $self->{sql}->fetchall_arrayref(); foreach my $database (@$result) { if (defined($self->{option_results}->{filter_database}) && $self->{option_results}->{filter_database} ne '' && $$database[0] !~ /$self->{option_results}->{filter_database}/i) { next; } $self->{sql}->query(query => "use [" . $$database[0] . "]; exec sp_spaceused;"); my $result2 = $self->{sql}->fetchall_arrayref(); foreach my $row (@$result2) { $self->{databases}->{$$row[0]} = { display => $$row[0], total => convert_bytes($$row[1]), }; } } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $database (sort keys %{$self->{databases}}) { $self->{output}->output_add(long_msg => sprintf("[name = %s] [total = %s]", $self->{databases}->{$database}->{display}, $self->{databases}->{$database}->{total})); } $self->{output}->output_add(severity => 'OK', short_msg => 'List databases:'); $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', 'total']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $database (sort keys %{$self->{databases}}) { $self->{output}->add_disco_entry( name => $self->{databases}->{$database}->{display}, total => $self->{databases}->{$database}->{total}, ); } } sub convert_bytes { my ($brut) = @_; my ($value,$unit) = split(/\s+/,$brut); if ($unit =~ /kb*/i) { $value = $value * 1024; } elsif ($unit =~ /mb*/i) { $value = $value * 1024 * 1024; } elsif ($unit =~ /gb*/i) { $value = $value * 1024 * 1024 * 1024; } elsif ($unit =~ /tb*/i) { $value = $value * 1024 * 1024 * 1024 * 1024; } return $value; } 1; __END__ =head1 MODE List MSSQL databases =over 8 =item B<--filter-database> Filter database by name (Can be a regex). =back =cut centreon-plugins-20220113/database/mssql/mode/lockswaits.pm000066400000000000000000000101131417000230700236000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mssql::mode::lockswaits; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning:s" => { name => 'warning', }, "critical:s" => { name => 'critical', }, "filter:s" => { name => 'filter', }, }); 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) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); my $query = "SELECT instance_name, cntr_value FROM sys.dm_os_performance_counters WHERE object_name = 'SQLServer:Locks' AND counter_name = 'Lock Waits/sec%' "; $self->{sql}->query(query => $query); my $result = $self->{sql}->fetchall_arrayref(); my $locks = 0; $self->{output}->output_add(severity => 'OK', short_msg => "0 Locks Waits/s."); foreach my $row (@$result) { next if (defined($self->{option_results}->{filter}) && $$row[0] !~ /$self->{option_results}->{filter}/); $locks += $$row[1]; } my $exit_code = $self->{perfdata}->threshold_check(value => $locks, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); if (!$self->{output}->is_status(value => $exit_code, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("%i Locks Waits/s.", $locks)); } $self->{output}->perfdata_add(label => 'locks_waits', value => $locks, unit => '/s', warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check MSSQL locks-waits per second =over 8 =item B<--warning> Threshold warning number of lock-waits per second. =item B<--critical> Threshold critical number of lock-waits per second. =item B<--filter> Filter database to check. =back =cut centreon-plugins-20220113/database/mssql/mode/pagelifeexpectancy.pm000066400000000000000000000044201417000230700252610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mssql::mode::pagelifeexpectancy; 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 }, ]; $self->{maps_counters}->{global} = [ { label => 'page-life-expectancy', nlabel => 'page.life.expectancy.seconds', set => { key_values => [ { name => 'page_life_expectancy'}], output_template => 'Page life expectancy : %d second(s)', perfdatas => [ { value => 'page_life_expectancy', template => '%d', unit => 's', min => 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 => {}); return $self; } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); $options{sql}->query(query => q{ SELECT cntr_value FROM sys.dm_os_performance_counters WHERE counter_name = 'Page life expectancy' AND object_name LIKE '%Manager%' }); $self->{global}->{page_life_expectancy} = $options{sql}->fetchrow_array(); } 1; __END__ =head1 MODE Check MSSQL page life expectancy. =over 8 =item B<--warning-page-life-expectancy> Threshold warning. =item B<--critical-page-life-expectancy> Threshold critical. =back =cut centreon-plugins-20220113/database/mssql/mode/tables.pm000066400000000000000000000162361417000230700227030ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mssql::mode::tables; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_database_output { my ($self, %options) = @_; return "Database '" . $options{instance_value}->{display} . "' "; } sub database_long_output { my ($self, %options) = @_; return "checking database '" . $options{instance_value}->{display} . "'"; } sub prefix_table_output { my ($self, %options) = @_; return "table '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'databases', type => 3, cb_prefix_output => 'prefix_database_output', cb_long_output => 'database_long_output', indent_long_output => ' ', message_multiple => 'All databases are ok', group => [ { name => 'global_db', type => 0, skipped_code => { -10 => 1 } }, { name => 'tables', display_long => 0, cb_prefix_output => 'prefix_table_output', message_multiple => 'all tables are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{global_db} = [ { label => 'db-usage', nlabel => 'database.space.usage.bytes', set => { key_values => [ { name => 'used' } ], output_template => 'used: %s %s', output_change_bytes => 1, perfdatas => [ { template => '%s', unit => 'B', min => 0, label_extra_instance => 1 } ] } }, { label => 'db-free', nlabel => 'database.space.free.bytes', set => { key_values => [ { name => 'free' } ], output_template => 'free: %s %s', output_change_bytes => 1, perfdatas => [ { template => '%s', unit => 'B', min => 0, label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{tables} = [ { label => 'table-usage', nlabel => 'table.space.usage.bytes', set => { key_values => [ { name => 'used' } ], output_template => 'used: %s %s', output_change_bytes => 1, perfdatas => [ { template => '%s', unit => 'B', min => 0, label_extra_instance => 1 } ] } }, { label => 'table-free', nlabel => 'table.space.free.bytes', set => { key_values => [ { name => 'free' } ], output_template => 'free: %s %s', output_change_bytes => 1, perfdatas => [ { template => '%s', unit => 'B', min => 0, label_extra_instance => 1 } ] } }, { label => 'table-rows', nlabel => 'table.rows.count', set => { key_values => [ { name => 'rows' } ], output_template => 'rows: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-database:s' => { name => 'filter_database' }, 'filter-table:s' => { name => 'filter_table' } }); return $self; } sub add_tables { my ($self, %options) = @_; # page size is 8KB my $dbname = $options{dbname}; $options{sql}->query(query => qq{ USE [$dbname] SELECT s.Name AS SchemaName, t.Name AS TableName, p.rows AS RowCounts, (SUM(a.used_pages * 8)) AS Used_KB, (SUM(a.total_pages * 8) - SUM(a.used_pages * 8)) AS Unused_KB, (SUM(a.total_pages * 8)) AS Total_KB FROM sys.tables t INNER JOIN sys.indexes i ON t.OBJECT_ID = i.object_id INNER JOIN sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id INNER JOIN sys.allocation_units a ON p.partition_id = a.container_id INNER JOIN sys.schemas s ON t.schema_id = s.schema_id GROUP BY t.Name, s.Name, p.Rows }); my $results = $options{sql}->fetchall_arrayref(); foreach my $row (@$results) { if (defined($self->{option_results}->{filter_table}) && $self->{option_results}->{filter_table} ne '' && $row->[1] !~ /$self->{option_results}->{filter_table}/) { $self->{output}->output_add(long_msg => "skipping '" . $row->[0] . '.' . $row->[1] . "': no matching filter.", debug => 1); next } $self->{databases}->{$dbname}->{tables}->{ $row->[1] } = { display => $row->[1], used => $row->[5] * 1024, free => $row->[4] * 1024, rows => $row->[2] }; $self->{databases}->{$dbname}->{global_db}->{free} += $row->[4] * 1024; $self->{databases}->{$dbname}->{global_db}->{used} += $row->[5] * 1024; } } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); $options{sql}->query(query => qq{ SELECT [name] as database_name FROM sys.databases }); $self->{databases} = {}; my $results = $options{sql}->fetchall_arrayref(); foreach my $row (@$results) { if (defined($self->{option_results}->{filter_database}) && $self->{option_results}->{filter_database} ne '' && $row->[0] !~ /$self->{option_results}->{filter_database}/) { $self->{output}->output_add(long_msg => "skipping '" . $row->[0] . "': no matching filter.", debug => 1); next } $self->{databases}->{ $row->[0] } = { display => $row->[0], global_db => { free => 0, used => 0 }, table => {} }; $self->add_tables(dbname => $row->[0], sql => $options{sql}); } if (scalar(keys %{$self->{databases}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No database found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check tables size. =over 8 =item B<--filter-database> Filter tables by database name (Can be a regexp). =item B<--filter-table> Filter tables by name (can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'db-usage', 'db-free', 'table-usage', 'table-free', 'table-rows'. =back =cut centreon-plugins-20220113/database/mssql/mode/transactions.pm000066400000000000000000000103171417000230700241330ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mssql::mode::transactions; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use Digest::MD5 qw(md5_hex); sub prefix_database_output { my ($self, %options) = @_; return "Database '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'database', type => 1, cb_prefix_output => 'prefix_database_output', message_multiple => 'All databases are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'databases-transactions', nlabel => 'databases.transactions.persecond', set => { key_values => [ { name => 'transactions', per_second => 1 } ], output_template => 'total transactions: %.2f/s', perfdatas => [ { template => '%.2f', unit => '/s', min => 0 } ] } } ]; $self->{maps_counters}->{database} = [ { label => 'database-transactions', nlabel => 'database.transactions.persecond', set => { key_values => [ { name => 'transactions', per_second => 1 }, { name => 'display' } ], output_template => 'transactions: %.2f/s', perfdatas => [ { template => '%.2f', unit => '/s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-database:s' => { name => 'filter_database' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); $options{sql}->query(query => q{SELECT instance_name, cntr_value FROM sys.dm_os_performance_counters WHERE UPPER(counter_name) = UPPER('transactions/sec')}); my $result = $options{sql}->fetchall_arrayref(); $self->{global} = {}; $self->{database} = {}; foreach my $row (@$result) { my $name = centreon::plugins::misc::trim($row->[0]); if ($name eq '_Total') { $self->{global}->{transactions} = $row->[1]; next; } if (defined($self->{option_results}->{filter_database}) && $self->{option_results}->{filter_database} ne '' && $name !~ /$self->{option_results}->{filter_database}/) { $self->{output}->output_add(long_msg => "skipping '" . $name . "': no matching filter.", debug => 1); next; } $self->{database}->{ $name } = { display => $name, transactions => $row->[1] }; } $self->{cache_name} = 'mssql_' . $self->{mode} . '_' . $options{sql}->get_unique_id4save() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_database}) ? md5_hex($self->{option_results}->{filter_database}) : md5_hex('all')); } 1; __END__ =head1 MODE Check MSSQL transactions. =over 8 =item B<--filter-database> Filter database name (can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'databases-transactions', 'database-transactions'. =back =cut centreon-plugins-20220113/database/mssql/plugin.pm000066400000000000000000000104661417000230700220020ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mssql::plugin; use strict; use warnings; use base qw(centreon::plugins::script_sql); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $self->{version} = '0.1'; $self->{modes} = { 'backup-age' => 'database::mssql::mode::backupage', 'blocked-processes' => 'database::mssql::mode::blockedprocesses', 'cache-hitratio' => 'database::mssql::mode::cachehitratio', 'collection' => 'centreon::common::protocols::sql::mode::collection', 'connected-users' => 'database::mssql::mode::connectedusers', 'connection-time' => 'centreon::common::protocols::sql::mode::connectiontime', 'dead-locks' => 'database::mssql::mode::deadlocks', 'databases-size' => 'database::mssql::mode::databasessize', 'failed-jobs' => 'database::mssql::mode::failedjobs', 'list-databases' => 'database::mssql::mode::listdatabases', 'locks-waits' => 'database::mssql::mode::lockswaits', 'page-life-expectancy' => 'database::mssql::mode::pagelifeexpectancy', 'sql' => 'centreon::common::protocols::sql::mode::sql', 'sql-string' => 'centreon::common::protocols::sql::mode::sqlstring', 'tables' => 'database::mssql::mode::tables', 'transactions' => 'database::mssql::mode::transactions' }; $self->{sql_modes}->{dbi} = 'database::mssql::dbi'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options( arguments => { 'hostname:s@' => { name => 'hostname' }, 'port:s@' => { name => 'port' }, 'server:s@' => { name => 'server' }, 'database:s' => { name => 'database' }, } ); $self->{options}->parse_options(); my $options_result = $self->{options}->get_options(); $self->{options}->clean(); if (defined($options_result->{server})) { @{$self->{sqldefault}->{dbi}} = (); for (my $i = 0; $i < scalar(@{$options_result->{server}}); $i++) { $self->{sqldefault}->{dbi}[$i] = { data_source => 'Sybase:server=' . $options_result->{server}[$i] }; if ((defined($options_result->{database})) && ($options_result->{database} ne '')) { $self->{sqldefault}->{dbi}[$i]->{data_source} .= ';database=' . $options_result->{database}; } } } if (defined($options_result->{hostname})) { @{$self->{sqldefault}->{dbi}} = (); for (my $i = 0; $i < scalar(@{$options_result->{hostname}}); $i++) { $self->{sqldefault}->{dbi}[$i] = { data_source => 'Sybase:host=' . $options_result->{hostname}[$i] }; if (defined($options_result->{port}[$i])) { $self->{sqldefault}->{dbi}[$i]->{data_source} .= ';port=' . $options_result->{port}[$i]; } if ((defined($options_result->{database})) && ($options_result->{database} ne '')) { $self->{sqldefault}->{dbi}[$i]->{data_source} .= ';database=' . $options_result->{database}; } } } $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check MSSQL Server. =over 8 =item B<--hostname> Hostname to query. =item B<--port> Database Server Port. =item B<--server> An alternative to hostname+port. will be looked up in the file freetds.conf. =item B<--database> Select database . =back =cut centreon-plugins-20220113/database/mysql/000077500000000000000000000000001417000230700201455ustar00rootroot00000000000000centreon-plugins-20220113/database/mysql/dbi.pm000066400000000000000000000023611417000230700212430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mysql::dbi; use base qw(centreon::plugins::dbi); use strict; use warnings; sub is_mariadb { my ($self) = @_; return $self->{is_mariadb}; } sub set_version { my ($self) = @_; $self->{is_mariadb} = 0; $self->{version} = $self->{instance}->get_info(18); # SQL_DBMS_VER # MariaDB: 5.5.5-10.1.36-MariaDB or 10.1.36-MariaDB if ($self->{version} =~ /([0-9\.]*?)-MariaDB/i) { $self->{version} = $1; $self->{is_mariadb} = 1; } } 1; __END__ centreon-plugins-20220113/database/mysql/mode/000077500000000000000000000000001417000230700210715ustar00rootroot00000000000000centreon-plugins-20220113/database/mysql/mode/backup.pm000066400000000000000000000136301417000230700226770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mysql::mode::backup; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; my $msg; if ($self->{result_values}->{has_backup} eq 'no') { $msg = 'never executed'; } else { $msg = sprintf( 'exit state: %s [last_error: %s]', $self->{result_values}->{exit_state}, $self->{result_values}->{last_error} ); } return $msg; } sub prefix_backup_output { my ($self, %options) = @_; return "Backup '" . $options{instance_value}->{type} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'backups', type => 1, cb_prefix_output => 'prefix_backup_output', message_multiple => 'All backup types are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{backups} = [ { label => 'status', type => 2, critical_default => '%{has_backup} eq "yes" and %{exit_state} ne "SUCCESS" and %{last_error} ne "NO_ERROR"', set => { key_values => [ { name => 'type' }, { name => 'exit_state' }, { name => 'last_error' }, { name => 'has_backup' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'time-last-execution', nlabel => 'backup.time.last.execution.seconds', set => { key_values => [ { name => 'last_execution_time' }, { name => 'last_execution_human' } ], output_template => 'last execution time: %s', output_use => 'last_execution_human', perfdatas => [ { template => '%d', min => 0, unit => 's', label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-type:s' => { name => 'filter_type' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); my $query = q{ SELECT backup_type, exit_state, last_error, UNIX_TIMESTAMP(start_time) FROM mysql.backup_history WHERE backup_id IN ( SELECT MAX(backup_id) FROM mysql.backup_history GROUP BY backup_type ) }; $options{sql}->query(query => $query); my $result = $options{sql}->fetchall_arrayref(); $self->{backups} = { FULL => { type => 'FULL', has_backup => 'no' , exit_state => '-', last_error => '-' }, PARTIAL => { type => 'PARTIAL', has_backup => 'no' , exit_state => '-', last_error => '-' }, DIFFERENTIAL => { type => 'DIFFERENTIAL', has_backup => 'no' , exit_state => '-', last_error => '-' }, INCREMENTAL => { type => 'INCREMENTAL', has_backup => 'no' , exit_state => '-', last_error => '-' }, TTS => { type => 'TTS', has_backup => 'no', exit_state => '-', last_error => '-' } }; foreach my $row (@$result) { my ($name, $state, $type, $total_mb, $usable_file_mb, $offline_disks, $free_mb) = @$row; if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' && $row->[0] !~ /$self->{option_results}->{filter_type}/) { $self->{output}->output_add(long_msg => "skipping '" . $row->[0] . "': no matching filter name.", debug => 1); next; } $self->{backups}->{ $row->[0] }->{has_backup} = 'yes'; $self->{backups}->{ $row->[0] }->{exit_state} = $row->[1]; $self->{backups}->{ $row->[0] }->{last_error} = $row->[2]; $self->{backups}->{ $row->[0] }->{last_execution_time} = time() - $row->[3]; $self->{backups}->{ $row->[0] }->{last_execution_human} = centreon::plugins::misc::change_seconds( value => $self->{backups}->{ $row->[0] }->{last_execution_time} ); } } 1; __END__ =head1 MODE Check backups (only with mysql enterprise backup). =over 8 =item B<--filter-type> Filter backups by type (regexp can be used). =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{has_backup}, %{last_error}, %{exit_state}, %{type} =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{has_backup}, %{last_error}, %{exit_state}, %{type} =item B<--critical-status> Set critical threshold for status (Default: '%{has_backup} eq "yes" and %{exit_state} ne "SUCCESS" and %{last_error} ne "NO_ERROR"'). Can used special variables like: %{has_backup}, %{last_error}, %{exit_state}, %{type} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'time-last-execution'. =back =cut centreon-plugins-20220113/database/mysql/mode/databasessize.pm000066400000000000000000000221421417000230700242520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mysql::mode::databasessize; 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, cb_prefix_output => 'prefix_global_output', cb_init => 'skip_global' }, { name => 'database', type => 3, cb_prefix_output => 'prefix_database_output', cb_long_output => 'database_long_output', indent_long_output => ' ', message_multiple => 'All databases are ok', group => [ { name => 'global_db', type => 0, skipped_code => { -10 => 1 } }, { name => 'table', display_long => 0, cb_prefix_output => 'prefix_table_output', message_multiple => 'All tables are ok', type => 1, skipped_code => { -10 => 1 } }, ] } ]; $self->{maps_counters}->{global} = [ { label => 'total-usage', nlabel => 'databases.space.usage.bytes', set => { key_values => [ { name => 'used' } ], output_template => 'Used Space: %s %s', output_change_bytes => 1, perfdatas => [ { value => 'used', template => '%s', unit => 'B', min => 0 }, ], } }, { label => 'total-free', nlabel => 'databases.space.free.bytes', set => { key_values => [ { name => 'free' } ], output_template => 'Free Space: %s %s', output_change_bytes => 1, perfdatas => [ { value => 'free', template => '%s', unit => 'B', min => 0 }, ], } }, ]; $self->{maps_counters}->{global_db} = [ { label => 'db-usage', nlabel => 'database.space.usage.bytes', set => { key_values => [ { name => 'used' } ], output_template => 'Used: %s %s', output_change_bytes => 1, perfdatas => [ { value => 'used', template => '%s', unit => 'B', min => 0, label_extra_instance => 1 }, ], } }, { label => 'db-free', nlabel => 'database.space.free.bytes', set => { key_values => [ { name => 'free' } ], output_template => 'Free: %s %s', output_change_bytes => 1, perfdatas => [ { value => 'free', template => '%s', unit => 'B', min => 0, label_extra_instance => 1 }, ], } }, ]; $self->{maps_counters}->{table} = [ { label => 'table-usage', nlabel => 'table.space.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'display' } ], output_template => 'Used: %s %s', output_change_bytes => 1, perfdatas => [ { value => 'used', template => '%s', unit => 'B', min => 0, label_extra_instance => 1 }, ], } }, { label => 'table-free', nlabel => 'table.space.free.bytes', set => { key_values => [ { name => 'free' }, { name => 'display' } ], output_template => 'Free: %s %s', output_change_bytes => 1, perfdatas => [ { value => 'free', template => '%s', unit => 'B', min => 0, label_extra_instance => 1 }, ], } }, { label => 'table-frag', nlabel => 'table.fragmentation.percentage', set => { key_values => [ { name => 'frag' }, { name => 'display' } ], output_template => 'Fragmentation: %.2f %%', perfdatas => [ { value => 'frag', template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1 }, ], } }, ]; } sub skip_global { my ($self, %options) = @_; scalar(keys %{$self->{database}}) > 1 ? return(0) : return(1); } sub prefix_global_output { my ($self, %options) = @_; return "Databases Total "; } sub prefix_database_output { my ($self, %options) = @_; return "Database '" . $options{instance_value}->{display} . "' "; } sub database_long_output { my ($self, %options) = @_; return "Checking Database '" . $options{instance_value}->{display} . "'"; } sub prefix_table_output { my ($self, %options) = @_; return "Table '" . $options{instance_value}->{display} . "' "; } 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-database:s' => { name => 'filter_database' }, 'filter-table:s' => { name => 'filter_table' }, }); return $self; } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); if (!($options{sql}->is_version_minimum(version => '5'))) { $self->{output}->add_option_msg(short_msg => "MySQL version '" . $self->{sql}->{version} . "' is not supported."); $self->{output}->option_exit(); } $options{sql}->query( query => q{show variables like 'innodb_file_per_table'} ); my ($name, $value) = $options{sql}->fetchrow_array(); my $innodb_per_table = 0; $innodb_per_table = 1 if ($value =~ /on/i); $options{sql}->query( query => q{SELECT table_schema, table_name, engine, data_free, data_length+index_length as data_used, (DATA_FREE / (DATA_LENGTH+INDEX_LENGTH)) as TAUX_FRAG FROM information_schema.tables WHERE table_type = 'BASE TABLE' AND engine IN ('InnoDB', 'MyISAM')} ); my $result = $options{sql}->fetchall_arrayref(); my $innodb_ibdata_done = 0; $self->{global} = { free => 0, used => 0 }; $self->{database} = {}; foreach my $row (@$result) { if (defined($self->{option_results}->{filter_database}) && $self->{option_results}->{filter_database} ne '' && $row->[0] !~ /$self->{option_results}->{filter_database}/) { $self->{output}->output_add(long_msg => "skipping '" . $row->[0] . '.' . $row->[1] . "': no matching filter.", debug => 1); next } if (defined($self->{option_results}->{filter_table}) && $self->{option_results}->{filter_table} ne '' && $row->[1] !~ /$self->{option_results}->{filter_table}/) { $self->{output}->output_add(long_msg => "skipping '" . $row->[0] . '.' . $row->[1] . "': no matching filter.", debug => 1); next } if (!defined($self->{database}->{$row->[0]})) { $self->{database}->{$row->[0]} = { display => $row->[0], global_db => { free => 0, used => 0 }, table => {} }; } $self->{database}->{$row->[0]}->{table}->{$row->[1]} = { display => $row->[1] }; # For a table located in the shared tablespace, this is the free space of the shared tablespace. if ($row->[2] !~ /innodb/i || $innodb_per_table == 1) { $self->{global}->{free} += $row->[3]; $self->{database}->{$row->[0]}->{global_db}->{free} += $row->[3]; $self->{database}->{$row->[0]}->{table}->{$row->[1]}->{free} = $row->[3]; $self->{database}->{$row->[0]}->{table}->{$row->[1]}->{frag} = $row->[5]; } elsif ($innodb_ibdata_done == 0) { $self->{global}->{free} += $row->[3]; $innodb_ibdata_done = 1; } $self->{global}->{used} += $row->[4]; $self->{database}->{$row->[0]}->{global_db}->{used} += $row->[4]; $self->{database}->{$row->[0]}->{table}->{$row->[1]}->{used} = $row->[4]; } if (scalar(keys %{$self->{database}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No database found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check MySQL databases size and tables. =over 8 =item B<--filter-database> Filter database to checks (Can be a regexp). =item B<--filter-table> Filter table name (can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds (Can be: 'total-usage', 'total-free', 'db-usage', 'db-free', 'table-usage', 'table-free', 'table-frag'). =back =cut centreon-plugins-20220113/database/mysql/mode/innodbbufferpoolhitrate.pm000066400000000000000000000150071417000230700263500ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mysql::mode::innodbbufferpoolhitrate; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::statefile; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning:s" => { name => 'warning', }, "critical:s" => { name => 'critical', }, "lookback" => { name => 'lookback', }, }); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); 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(); } $self->{statefile_cache}->check_options(%options); } sub run { my ($self, %options) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); if (!($self->{sql}->is_version_minimum(version => '5'))) { $self->{output}->add_option_msg(short_msg => "MySQL version '" . $self->{sql}->{version} . "' is not supported (need version >= '5.x')."); $self->{output}->option_exit(); } $self->{sql}->query(query => q{SHOW /*!50000 global */ STATUS WHERE Variable_name IN ('Innodb_buffer_pool_read_requests', 'Innodb_buffer_pool_reads')}); my $new_datas = {Innodb_buffer_pool_read_requests => undef, Innodb_buffer_pool_reads => undef}; my $result = $self->{sql}->fetchall_arrayref(); foreach my $row (@{$result}) { $new_datas->{$$row[0]} = $$row[1]; } foreach (keys %$new_datas) { if (!defined($new_datas->{$_})) { $self->{output}->add_option_msg(short_msg => "Cannot get '$_' variable."); $self->{output}->option_exit(); } } $self->{statefile_cache}->read(statefile => 'mysql_' . $self->{mode} . '_' . $self->{sql}->get_unique_id4save()); my $old_timestamp = $self->{statefile_cache}->get(name => 'last_timestamp'); $new_datas->{last_timestamp} = time(); my $old_read_request = $self->{statefile_cache}->get(name => 'Innodb_buffer_pool_read_requests'); my $old_read = $self->{statefile_cache}->get(name => 'Innodb_buffer_pool_reads'); if (defined($old_read_request) && defined($old_read) && $new_datas->{Innodb_buffer_pool_read_requests} >= $old_read_request && $new_datas->{Innodb_buffer_pool_reads} >= $old_read) { my %prcts = (); my $total_read_requests = $new_datas->{Innodb_buffer_pool_read_requests} - $old_read_request; my $total_read_disk = $new_datas->{Innodb_buffer_pool_reads} - $old_read; $prcts{bufferpool_hitrate_now} = ($total_read_requests == 0) ? 100 : ($total_read_requests - $total_read_disk) * 100 / $total_read_requests; $prcts{bufferpool_hitrate} = ($new_datas->{Innodb_buffer_pool_read_requests} == 0) ? 100 : ($new_datas->{Innodb_buffer_pool_read_requests} - $new_datas->{Innodb_buffer_pool_reads}) * 100 / $new_datas->{Innodb_buffer_pool_read_requests}; my $exit_code = $self->{perfdata}->threshold_check(value => $prcts{'bufferpool_hitrate' . ((defined($self->{option_results}->{lookback})) ? '' : '_now' )}, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("innodb buffer pool hitrate at %.2f%%", $prcts{'bufferpool_hitrate' . ((defined($self->{option_results}->{lookback})) ? '' : '_now')}) ); $self->{output}->perfdata_add(label => 'bufferpool_hitrate' . ((defined($self->{option_results}->{lookback})) ? '' : '_now'), unit => '%', value => sprintf("%.2f", $prcts{'bufferpool_hitrate' . ((defined($self->{option_results}->{lookback})) ? '' : '_now')}), 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 => 'bufferpool_hitrate' . ((defined($self->{option_results}->{lookback})) ? '_now' : ''), unit => '%', value => sprintf("%.2f", $prcts{'bufferpool_hitrate' . ((defined($self->{option_results}->{lookback})) ? '_now' : '')}), min => 0); } $self->{statefile_cache}->write(data => $new_datas); if (!defined($old_timestamp)) { $self->{output}->output_add(severity => 'OK', short_msg => "Buffer creation..."); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check hitrate in the InnoDB Buffer Pool. =over 8 =item B<--warning> Threshold warning. =item B<--critical> Threshold critical. =item B<--lookback> Threshold isn't on the percent calculated from the difference ('bufferpool_hitrate_now'). =back =cut centreon-plugins-20220113/database/mysql/mode/longqueries.pm000066400000000000000000000117071417000230700237720ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mysql::mode::longqueries; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'warning:s' => { name => 'warning', }, 'critical:s' => { name => 'critical', }, 'seconds:s' => { name => 'seconds', default => 60 }, 'filter-user:s' => { name => 'filter_user' }, 'filter-command:s' => { name => 'filter_command', default => '^(?!(sleep)$)' }, }); 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}->{seconds}) || $self->{option_results}->{seconds} !~ /^[0-9]+$/) { $self->{output}->add_option_msg(short_msg => "Please set the option --seconds."); $self->{output}->option_exit(); } } sub run { my ($self, %options) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); $self->{sql}->query(query => q{SELECT USER, COMMAND, TIME, INFO FROM information_schema.processlist ORDER BY TIME DESC}); my $long_queries = 0; my @queries = (); while ((my $row = $self->{sql}->fetchrow_hashref())) { next if (defined($self->{option_results}->{filter_user}) && $self->{option_results}->{filter_user} ne '' && $row->{USER} !~ /$self->{option_results}->{filter_user}/i); next if (defined($self->{option_results}->{filter_command}) && $self->{option_results}->{filter_command} ne '' && $row->{COMMAND} !~ /$self->{option_results}->{filter_command}/i); if (defined($self->{option_results}->{seconds}) && $self->{option_results}->{seconds} ne '' && $row->{TIME} >= $self->{option_results}->{seconds}) { push @queries, { time => $row->{TIME}, query => $row->{INFO} }; $long_queries++; } } my $exit_code = $self->{perfdata}->threshold_check(value => $long_queries, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add( severity => $exit_code, short_msg => sprintf( "%s queries over %s seconds", $long_queries, $self->{option_results}->{seconds} ) ); $self->{output}->perfdata_add( label => 'longqueries', value => $long_queries, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0 ); for (my $i = 0; $i < 10 && $i < scalar(@queries); $i++) { $queries[$i]->{query} =~ s/\|/-/mg if (defined($queries[$i]->{query})); $self->{output}->output_add(long_msg => sprintf( "[time: %s] [query: %s]", $queries[$i]->{time}, defined($queries[$i]->{query}) ? substr($queries[$i]->{query}, 0, 1024) : '-' ) ); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check current number of long queries. =over 8 =item B<--warning> Threshold warning (number of long queries). =item B<--critical> Threshold critical (number of long queries). =item B<--seconds> The minimum execution time in seconds for a long query (Default: 60). =item B<--filter-user> Filter by user (can be a regexp). =item B<--filter-command> Filter by command (can be a regexp. Default: '^(?!(sleep)$)'). =back =cut centreon-plugins-20220113/database/mysql/mode/myisamkeycachehitrate.pm000066400000000000000000000144401417000230700260070ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mysql::mode::myisamkeycachehitrate; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::statefile; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning:s" => { name => 'warning', }, "critical:s" => { name => 'critical', }, "lookback" => { name => 'lookback', }, }); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); 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(); } $self->{statefile_cache}->check_options(%options); } sub run { my ($self, %options) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); if (!($self->{sql}->is_version_minimum(version => '5'))) { $self->{output}->add_option_msg(short_msg => "MySQL version '" . $self->{sql}->{version} . "' is not supported (need version >= '5.x')."); $self->{output}->option_exit(); } $self->{sql}->query(query => q{SHOW /*!50000 global */ STATUS WHERE Variable_name IN ('Key_read_requests', 'Key_reads')}); my $new_datas = {Key_read_requests => undef, Key_reads => undef}; my $result = $self->{sql}->fetchall_arrayref(); foreach my $row (@{$result}) { $new_datas->{$$row[0]} = $$row[1]; } foreach (keys %$new_datas) { if (!defined($new_datas->{$_})) { $self->{output}->add_option_msg(short_msg => "Cannot get '$_' variable."); $self->{output}->option_exit(); } } $self->{statefile_cache}->read(statefile => 'mysql_' . $self->{mode} . '_' . $self->{sql}->get_unique_id4save()); my $old_timestamp = $self->{statefile_cache}->get(name => 'last_timestamp'); $new_datas->{last_timestamp} = time(); my $old_read_request = $self->{statefile_cache}->get(name => 'Key_read_requests'); my $old_read = $self->{statefile_cache}->get(name => 'Key_reads'); if (defined($old_read_request) && defined($old_read) && $new_datas->{Key_read_requests} >= $old_read_request && $new_datas->{Key_reads} >= $old_read) { my %prcts = (); my $total_read_requests = $new_datas->{Key_read_requests} - $old_read_request; my $total_read_disk = $new_datas->{Key_reads} - $old_read; $prcts{keycache_hitrate_now} = ($total_read_requests == 0) ? 100 : ($total_read_requests - $total_read_disk) * 100 / $total_read_requests; $prcts{keycache_hitrate} = ($new_datas->{Key_read_requests} == 0) ? 100 : ($new_datas->{Key_read_requests} - $new_datas->{Key_reads}) * 100 / $new_datas->{Key_read_requests}; my $exit_code = $self->{perfdata}->threshold_check(value => $prcts{'keycache_hitrate' . ((defined($self->{option_results}->{lookback})) ? '' : '_now' )}, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("myisam keycache hitrate at %.2f%%", $prcts{'keycache_hitrate' . ((defined($self->{option_results}->{lookback})) ? '' : '_now')}) ); $self->{output}->perfdata_add(label => 'keycache_hitrate' . ((defined($self->{option_results}->{lookback})) ? '' : '_now'), unit => '%', value => sprintf("%.2f", $prcts{'keycache_hitrate' . ((defined($self->{option_results}->{lookback})) ? '' : '_now')}), 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 => 'keycache_hitrate' . ((defined($self->{option_results}->{lookback})) ? '_now' : ''), unit => '%', value => sprintf("%.2f", $prcts{'keycache_hitrate' . ((defined($self->{option_results}->{lookback})) ? '_now' : '')}), min => 0); } $self->{statefile_cache}->write(data => $new_datas); if (!defined($old_timestamp)) { $self->{output}->output_add(severity => 'OK', short_msg => "Buffer creation..."); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check hitrate in the Myisam Key Cache. =over 8 =item B<--warning> Threshold warning. =item B<--critical> Threshold critical. =item B<--lookback> Threshold isn't on the percent calculated from the difference ('keycache_hitrate_now'). =back =cut centreon-plugins-20220113/database/mysql/mode/openfiles.pm000066400000000000000000000075631417000230700234260ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mysql::mode::openfiles; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { '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) = @_; $options{sql}->connect(); if (!($options{sql}->is_version_minimum(version => '5'))) { $self->{output}->add_option_msg(short_msg => "MySQL version '" . $options{sql}->{version} . "' is not supported (need version >= '5.x')."); $self->{output}->option_exit(); } $options{sql}->query(query => q{SHOW VARIABLES LIKE 'open_files_limit'}); my ($dummy, $open_files_limit) = $options{sql}->fetchrow_array(); if (!defined($open_files_limit)) { $self->{output}->add_option_msg(short_msg => "Cannot get open files limit."); $self->{output}->option_exit(); } $options{sql}->query(query => q{SHOW /*!50000 global */ STATUS LIKE 'Open_files'}); ($dummy, my $open_files) = $options{sql}->fetchrow_array(); if (!defined($open_files)) { $self->{output}->add_option_msg(short_msg => "Cannot get open files."); $self->{output}->option_exit(); } my $prct_open = 100 * $open_files / $open_files_limit; my $exit_code = $self->{perfdata}->threshold_check(value => $prct_open, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add( severity => $exit_code, short_msg => sprintf( "%.2f%% of the open files limit reached (%s of max. %s)", $prct_open, $open_files, $open_files_limit ) ); $self->{output}->perfdata_add( label => 'open_files', value => $open_files, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning', total => $open_files_limit, cast_int => 1), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical', total => $open_files_limit, cast_int => 1), min => 0 ); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check number of open files. =over 8 =item B<--warning> Threshold warning in percent. =item B<--critical> Threshold critical in percent. =back =cut centreon-plugins-20220113/database/mysql/mode/opentables.pm000066400000000000000000000102711417000230700235640ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mysql::mode::opentables; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "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) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); if (!($self->{sql}->is_version_minimum(version => '5'))) { $self->{output}->add_option_msg(short_msg => "MySQL version '" . $self->{sql}->{version} . "' is not supported (need version >= '5.x')."); $self->{output}->option_exit(); } $self->{sql}->query(query => q{SHOW VARIABLES LIKE 'table_open_cache'}); my ($dummy, $open_tables_limit) = $self->{sql}->fetchrow_array(); if (!defined($open_tables_limit)) { $self->{output}->add_option_msg(short_msg => "Cannot get open table limit."); $self->{output}->option_exit(); } $self->{sql}->query(query => q{SHOW /*!50000 global */ STATUS LIKE 'Open_tables'}); ($dummy, my $open_tables) = $self->{sql}->fetchrow_array(); if (!defined($open_tables)) { $self->{output}->add_option_msg(short_msg => "Cannot get open tables."); $self->{output}->option_exit(); } my $prct_open = int(100 * $open_tables / $open_tables_limit); my $exit_code = $self->{perfdata}->threshold_check(value => $prct_open, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("%.2f%% of the open files limit reached (%d of max. %d)", $prct_open, $open_tables, $open_tables_limit)); $self->{output}->perfdata_add(label => 'open_tables', value => $open_tables, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning', total => $open_tables_limit, cast_int => 1), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical', total => $open_tables_limit, cast_int => 1), min => 0); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check number of open tables. =over 8 =item B<--warning> Threshold warning in percent. =item B<--critical> Threshold critical in percent. =back =cut centreon-plugins-20220113/database/mysql/mode/passwordexpiration.pm000066400000000000000000000156311417000230700254020ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mysql::mode::passwordexpiration; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use DateTime; use centreon::plugins::misc; use centreon::plugins::statefile; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf( "[user: %s] [password updated: %s] [expired: %s] expire in: %s", $self->{result_values}->{user}, scalar(localtime($self->{result_values}->{password_last_changed})), $self->{result_values}->{expire} eq 'never' ? $self->{result_values}->{expire} : $self->{result_values}->{expire} . ' days', centreon::plugins::misc::change_seconds(value => $self->{result_values}->{expire_time}) ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'users', type => 2, format_output => '%s user(s) detected', display_counter_problem => { label => 'users', min => 0 }, group => [ { name => 'user', skipped_code => { -11 => 1 } } ] } ]; $self->{maps_counters}->{user} = [ { label => 'status', type => 2, critical_default => '%{expire} ne "never" and %{expire_time} == 0', set => { key_values => [ { name => 'user' }, { name => 'expire' }, { name => 'expire_time' }, { name => 'password_last_changed' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub get_database_timezone { my ($self, %options) = @_; $options{sql}->query( query => q{SELECT @@GLOBAL.time_zone, @@system_time_zone} ); my @row = $options{sql}->fetchrow_array(); my $timezone = $row[0]; if ($row[0] eq 'SYSTEM') { $timezone = $row[1]; } return $timezone; } sub get_expire_time { my ($self, %options) = @_; my $current_time = time(); my $dt = DateTime->from_epoch(epoch => $options{epoch}, time_zone => $options{timezone}); $dt->add(days => $options{days}); my $expire_in = $dt->epoch() - time(); $expire_in = 0 if ($expire_in < 0); return $expire_in; } sub get_password_mariadb { my ($self, %options) = @_; my $timezone = $self->get_database_timezone(sql => $options{sql}); $options{sql}->query( query => q{show variables like 'default_password_lifetime'} ); my ($name, $default_password_lifetime) = $options{sql}->fetchrow_array(); my $query = q{ SELECT Host, User, JSON_EXTRACT(Priv, '$.password_last_changed') as password_last_changed, JSON_EXTRACT(Priv, '$.password_lifetime') as password_lifetime FROM mysql.global_priv }; $options{sql}->query(query => $query); my $i = 1; while ((my @row = $options{sql}->fetchrow_array())) { my $expire = 'never'; if ((!defined($row[3]) || $row[3] == -1) && $default_password_lifetime > 0) { $expire = $default_password_lifetime; } elsif (defined($row[3]) && $row[3] > 0) { $expire = $row[3]; } my $expire_time = 0; if ($expire ne 'never') { $expire_time = $self->get_expire_time( epoch => $row[2], days => $expire, timezone => $timezone ); } $self->{users}->{global}->{user}->{$i} = { user => $row[0] . '@' . $row[1], password_last_changed => $row[2], expire => $expire, expire_time => $expire_time }; $i++; } } sub get_password_mysql { my ($self, %options) = @_; my $timezone = $self->get_database_timezone(sql => $options{sql}); $options{sql}->query( query => q{show variables like 'default_password_lifetime'} ); my ($name, $default_password_lifetime) = $options{sql}->fetchrow_array(); my $query = q{ SELECT User, Host, UNIX_TIMESTAMP(password_last_changed), password_lifetime FROM mysql.user }; $options{sql}->query(query => $query); my $i = 1; while ((my @row = $options{sql}->fetchrow_array())) { my $expire = 'never'; if (!defined($row[3]) && $default_password_lifetime > 0) { $expire = $default_password_lifetime; } elsif (defined($row[3]) && $row[3] > 0) { $expire = $row[3]; } my $expire_time = 0; if ($expire ne 'never') { $expire_time = $self->get_expire_time( epoch => $row[2], days => $expire, timezone => $timezone ); } $self->{users}->{global}->{user}->{$i} = { user => $row[0] . '@' . $row[1], password_last_changed => $row[2], expire => $expire, expire_time => $expire_time }; $i++; } } sub manage_selection { my ($self, %options) = @_; $self->{users}->{global} = { user => {} }; $options{sql}->connect(); if ($options{sql}->is_mariadb() && $options{sql}->is_version_minimum(version => '10.4.3')) { $self->get_password_mariadb(sql => $options{sql}); } elsif (!$options{sql}->is_mariadb() && $options{sql}->is_version_minimum(version => '5.7.4')) { $self->get_password_mysql(sql => $options{sql}); } else { $self->{output}->add_option_msg(short_msg => 'unsupported password policy.'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check user password expiration. =over 8 =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{user}, %{expire}, %{expire_time} =item B<--critical-status> Set critical threshold for status (Default: '%{expire} ne "never" and %{expire_time} == 0'). Can used special variables like: %{user}, %{expire}, %{expire_time} =back =cut centreon-plugins-20220113/database/mysql/mode/qcachehitrate.pm000066400000000000000000000162131417000230700242370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mysql::mode::qcachehitrate; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::statefile; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning:s" => { name => 'warning', }, "critical:s" => { name => 'critical', }, "lookback" => { name => 'lookback', }, }); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); 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(); } $self->{statefile_cache}->check_options(%options); } sub run { my ($self, %options) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); if (!($self->{sql}->is_version_minimum(version => '5'))) { $self->{output}->add_option_msg(short_msg => "MySQL version '" . $self->{sql}->{version} . "' is not supported (need version >= '5.x')."); $self->{output}->option_exit(); } $self->{sql}->query(query => q{SHOW /*!50000 global */ STATUS WHERE Variable_name IN ('Com_select', 'Qcache_hits')}); my $new_datas = {Com_select => undef, Qcache_hits => undef}; my $result = $self->{sql}->fetchall_arrayref(); foreach my $row (@{$result}) { $new_datas->{$$row[0]} = $$row[1]; } foreach (keys %$new_datas) { if (!defined($new_datas->{$_})) { $self->{output}->add_option_msg(short_msg => "Cannot get '$_' variable."); $self->{output}->option_exit(); } } $self->{sql}->query(query => q{SHOW VARIABLES WHERE Variable_name IN ('have_query_cache', 'query_cache_size')}); my ($dummy, $have_query_cache) = $self->{sql}->fetchrow_array(); if (!defined($have_query_cache)) { $self->{output}->add_option_msg(short_msg => "Cannot get have_query_cache variable."); $self->{output}->option_exit(); } ($dummy, my $query_cache_size) = $self->{sql}->fetchrow_array(); if (!defined($query_cache_size)) { $self->{output}->add_option_msg(short_msg => "Cannot get query_cache_size variable."); $self->{output}->option_exit(); } if ($have_query_cache !~ /^yes$/i || $query_cache_size == 0) { $self->{output}->output_add(severity => 'OK', short_msg => "Query cache is turned off."); $self->{output}->display(); $self->{output}->exit(); } $self->{statefile_cache}->read(statefile => 'mysql_' . $self->{mode} . '_' . $self->{sql}->get_unique_id4save()); my $old_timestamp = $self->{statefile_cache}->get(name => 'last_timestamp'); $new_datas->{last_timestamp} = time(); my $old_com_select = $self->{statefile_cache}->get(name => 'Com_select'); my $old_qcache_hits = $self->{statefile_cache}->get(name => 'Qcache_hits'); if (defined($old_com_select) && defined($old_qcache_hits) && $new_datas->{Com_select} >= $old_com_select && $new_datas->{Qcache_hits} >= $old_qcache_hits) { my %prcts = (); my $total_select_requests = ($new_datas->{Com_select} - $old_com_select) + ($new_datas->{Qcache_hits} - $old_qcache_hits); my $total_hits = $new_datas->{Qcache_hits} - $old_qcache_hits; $prcts{qcache_hitrate_now} = ($total_select_requests == 0) ? 100 : ($total_hits) * 100 / $total_select_requests; $prcts{qcache_hitrate} = (($new_datas->{Qcache_hits} + $new_datas->{Com_select}) == 0) ? 100 : ($new_datas->{Qcache_hits}) * 100 / ($new_datas->{Qcache_hits} + $new_datas->{Com_select}); my $exit_code = $self->{perfdata}->threshold_check(value => $prcts{'qcache_hitrate' . ((defined($self->{option_results}->{lookback})) ? '' : '_now' )}, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("query cache hitrate at %.2f%%", $prcts{'qcache_hitrate' . ((defined($self->{option_results}->{lookback})) ? '' : '_now')}) ); $self->{output}->perfdata_add(label => 'qcache_hitrate' . ((defined($self->{option_results}->{lookback})) ? '' : '_now'), unit => '%', value => sprintf("%.2f", $prcts{'qcache_hitrate' . ((defined($self->{option_results}->{lookback})) ? '' : '_now')}), 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 => 'qcache_hitrate' . ((defined($self->{option_results}->{lookback})) ? '_now' : ''), unit => '%', value => sprintf("%.2f", $prcts{'qcache_hitrate' . ((defined($self->{option_results}->{lookback})) ? '_now' : '')}), min => 0); } $self->{statefile_cache}->write(data => $new_datas); if (!defined($old_timestamp)) { $self->{output}->output_add(severity => 'OK', short_msg => "Buffer creation..."); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check hitrate in the Query Cache. =over 8 =item B<--warning> Threshold warning. =item B<--critical> Threshold critical. =item B<--lookback> Threshold isn't on the percent calculated from the difference ('qcache_hitrate_now'). =back =cut centreon-plugins-20220113/database/mysql/mode/queries.pm000066400000000000000000000100221417000230700230770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mysql::mode::queries; 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 => 'global', type => 0, cb_prefix_output => 'prefix_output' }, ]; $self->{maps_counters}->{global} = [ { label => 'total', nlabel => 'queries.total.persecond', set => { key_values => [ { name => 'Queries', per_second => 1 } ], output_template => 'Total : %d', perfdatas => [ { label => 'total_requests', template => '%d', unit => '/s', min => 0 }, ], } }, ]; foreach ('update', 'delete', 'insert', 'truncate', 'select', 'commit', 'begin') { push @{$self->{maps_counters}->{global}}, { label => $_, nlabel => 'queries.' . $_ . '.persecond', display_ok => 0, set => { key_values => [ { name => 'Com_' . $_, per_second => 1 } ], output_template => $_ . ' : %d', perfdatas => [ { label => $_ . '_requests', template => '%d', unit => '/s', min => 0 } ] } }; push @{$self->{maps_counters}->{global}}, { label => $_ . '-count', , nlabel => 'queries.' . $_ . '.count', display_ok => 0, set => { key_values => [ { name => 'Com_' . $_, diff => 1 } ], output_template => $_ . ' count : %d', perfdatas => [ { label => $_ . '_count', template => '%d', min => 0 } ] } }; } } sub prefix_output { my ($self, %options) = @_; return "Requests "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); if (!($options{sql}->is_version_minimum(version => '5.0.76'))) { $self->{output}->add_option_msg(short_msg => "MySQL version '" . $self->{sql}->{version} . "' is not supported (need version >= '5.0.76')."); $self->{output}->option_exit(); } $options{sql}->query(query => q{ SHOW /*!50000 global */ STATUS WHERE Variable_name IN ('Queries', 'Com_update', 'Com_delete', 'Com_insert', 'Com_truncate', 'Com_select', 'Com_commit', 'Com_begin') }); $self->{global} = {}; my $result = $options{sql}->fetchall_arrayref(); foreach my $row (@{$result}) { $self->{global}->{$$row[0]} = $$row[1]; } $self->{cache_name} = "mysql_" . $self->{mode} . '_' . $options{sql}->get_unique_id4save() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check average number of queries executed. =over 8 =item B<--warning-*> Threshold warning. Can be: 'total', 'update', 'insert', 'delete', 'truncate', 'select', 'begin', 'commit'. =item B<--critical-*> Threshold critical. Can be: 'total', 'update', 'insert', 'delete', 'truncate', 'select', 'begin', 'commit'. =back =cut centreon-plugins-20220113/database/mysql/mode/replication.pm000066400000000000000000000335311417000230700237450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mysql::mode::replication; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_connection_output { my ($self, %options) = @_; return sprintf( 'connection status: %s%s', $self->{result_values}->{status}, $self->{result_values}->{status} ne 'ok' ? ' [error message: ' . $self->{result_values}->{error_message} . ']' : '' ); } sub custom_thread_sql_output { my ($self, %options) = @_; return sprintf( 'thread sql running: %s%s', $self->{result_values}->{running}, $self->{result_values}->{running} ne 'yes' ? ' [last error message: ' . $self->{result_values}->{error_message} . ']' : '' ); } sub custom_thread_io_output { my ($self, %options) = @_; return sprintf( 'thread io running: %s%s', $self->{result_values}->{running}, $self->{result_values}->{running} ne 'yes' ? ' [last error message: ' . $self->{result_values}->{error_message} . ']' : '' ); } sub custom_replication_output { my ($self, %options) = @_; return sprintf( 'replication status: %s', $self->{result_values}->{replication_status} ); } sub server_long_output { my ($self, %options) = @_; return "checking database instance '" . $options{instance_value}->{display} . "'"; } sub prefix_server_output { my ($self, %options) = @_; return "database instance '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'servers', type => 3, cb_prefix_output => 'prefix_server_output', cb_long_output => 'server_long_output', indent_long_output => ' ', message_multiple => 'All database instances are ok', group => [ { name => 'connection', type => 0, skipped_code => { -10 => 1 } }, { name => 'thread_sql', type => 0, skipped_code => { -10 => 1 } }, { name => 'thread_io', type => 0, skipped_code => { -10 => 1 } }, { name => 'position', type => 0, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'slaves-running', nlabel => 'instance.slaves.running.count', set => { key_values => [ { name => 'slaves_running' }, { name => 'total' } ], output_template => 'number of slave instances running: %s', perfdatas => [ { template => '%s', min => 0, max => 'total' } ] } } ]; $self->{maps_counters}->{connection} = [ { label => 'connection-status', type => 2, critical_default => '%{status} ne "ok"', set => { key_values => [ { name => 'status' }, { name => 'error_message' }, { name => 'display' } ], closure_custom_output => $self->can('custom_connection_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{thread_sql} = [ { label => 'thread-sql-status', type => 2, set => { key_values => [ { name => 'running' }, { name => 'error_message' }, { name => 'display' } ], closure_custom_output => $self->can('custom_thread_sql_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{thread_io} = [ { label => 'thread-io-status', type => 2, set => { key_values => [ { name => 'running' }, { name => 'error_message' }, { name => 'display' } ], closure_custom_output => $self->can('custom_thread_io_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{position} = [ { label => 'slave-latency', nlabel => 'instance.slave.latency.seconds', set => { key_values => [ { name => 'latency' } ], output_template => 'slave has %s seconds latency behind master', perfdatas => [ { template => '%d', unit => 's', label_extra_instance => 1 } ] } }, { label => 'replication-status', unknown_default => '%{replication_status} =~ /configurationIssue/i', warning_default => '%{replication_status} =~ /inProgress/i', critical_default => '%{replication_status} =~ /connectIssueToMaster/i', type => 2, set => { key_values => [ { name => 'replication_status' }, { name => 'display' } ], closure_custom_output => $self->can('custom_replication_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub sql_query_show_slave_status { my ($self, %options) = @_; if ($options{sql}->is_mariadb() && $options{sql}->is_version_minimum(version => '10.2.x')) { $options{sql}->query(query => q{ SHOW ALL SLAVES STATUS }); } else { $options{sql}->query(query => q{ SHOW SLAVE STATUS }); } } sub check_connection { my ($self, %options) = @_; my ($exit, $msg_error) = $options{sql}->connect(dontquit => 1); if ($exit == -1) { $self->{servers}->{ $options{name} }->{connection}->{status} = 'error'; $self->{servers}->{ $options{name} }->{connection}->{error_message} = $msg_error; } } sub check_slave { my ($self, %options) = @_; return if ($self->{servers}->{ $options{name} }->{connection}->{status} ne 'ok'); $self->sql_query_show_slave_status(sql => $options{sql}); my $result = $options{sql}->fetchrow_hashref(); my $slave_running = 0; if (defined($result->{Slave_IO_Running})) { my $running = 'no'; if ($result->{Slave_IO_Running} =~ /^yes$/i) { $slave_running = 1; $running = 'yes'; } $self->{servers}->{ $options{name} }->{thread_io} = { display => $options{name}, running => $running, error_message => defined($result->{Last_Error}) ? $result->{Last_Error} : '' }; } if (defined($result->{Slave_SQL_Running})) { my $running = 'no'; if ($result->{Slave_SQL_Running} =~ /^yes$/i) { $slave_running = 1; $running = 'yes'; } $self->{servers}->{ $options{name} }->{thread_sql} = { display => $options{name}, running => $running, error_message => defined($result->{Last_Error}) ? $result->{Last_Error} : '' }; } $self->{servers}->{ $options{name} }->{is_slave} = $slave_running; $self->{global}->{slaves_running} += $slave_running; } sub check_master_slave_position { my ($self, %options) = @_; return if ($self->{servers}->{ $options{name_master} }->{connection}->{status} ne 'ok'); return if ($self->{servers}->{ $options{name_slave} }->{connection}->{status} ne 'ok'); return if ($self->{servers}->{ $options{name_slave} }->{is_slave} == 0); $options{sql_master}->query(query => q{ SHOW MASTER STATUS }); my $master_result = $options{sql_master}->fetchrow_hashref(); $self->sql_query_show_slave_status(sql => $options{sql_slave}); my $slave_result = $options{sql_slave}->fetchrow_hashref(); $self->{servers}->{ $options{name_slave} }->{position} = { display => $options{name_slave}, latency => $slave_result->{Seconds_Behind_Master}, replication_status => 'ok' }; $options{sql_slave}->query(query => q{ SHOW FULL PROCESSLIST }); my ($slave_sql_thread_ko, $slave_sql_thread_warning, $slave_sql_thread_ok) = (1, 1, 1); while ((my $row = $options{sql_slave}->fetchrow_hashref())) { my $state = $row->{State}; $slave_sql_thread_ko = 0 if (defined($state) && $state =~ /^(Waiting to reconnect after a failed binlog dump request|Connecting to master|Reconnecting after a failed binlog dump request|Waiting to reconnect after a failed master event read|Waiting for the slave SQL thread to free enough relay log space)$/i); $slave_sql_thread_warning = 0 if (defined($state) && $state =~ /^Waiting for the next event in relay log|Reading event from the relay log$/i); $slave_sql_thread_ok = 0 if (defined($state) && $state =~ /^Has read all relay log; waiting for the slave I\/O thread to update it$/i); } if ($slave_sql_thread_ko == 0) { $self->{servers}->{ $options{name_slave} }->{position}->{replication_status} = 'connectIssueToMaster'; } elsif (($master_result->{File} ne $slave_result->{Master_Log_File} || $master_result->{Position} != $slave_result->{Read_Master_Log_Pos}) && ($slave_sql_thread_warning == 0 || $slave_sql_thread_ok == 0) ) { $self->{servers}->{ $options{name_slave} }->{position}->{replication_status} = 'inProgress'; } else { $master_result->{File} =~ /(\d+)$/; my $master_bin_num = $1; $slave_result->{Master_Log_File} =~ /(\d+)$/; my $slave_bin_num = $1; my $diff_binlog = abs($master_bin_num - $slave_bin_num); # surely of missconfiguration of the plugin if ($diff_binlog > 1 && $slave_result->{Seconds_Behind_Master} < 10) { $self->{servers}->{ $options{name_slave} }->{position}->{replication_status} = 'configurationIssue'; } } } sub manage_selection { my ($self, %options) = @_; if (ref($options{sql}) ne 'ARRAY') { $self->{output}->add_option_msg(short_msg => "Need to use --multiple options."); $self->{output}->option_exit(); } if (scalar(@{$options{sql}}) < 2) { $self->{output}->add_option_msg(short_msg => "Need to specify two MySQL Server."); $self->{output}->option_exit(); } my ($sql_server1, $sql_server2) = @{$options{sql}}; my ($server1_name, $server2_name) = ($sql_server1->get_id(), $sql_server2->get_id()); $self->{global} = { total => 2, slaves_running => 0 }; $self->{servers} = { $server1_name => { display => $server1_name, connection => { display => $server1_name, status => 'ok', error_message => '' } }, $server2_name => { display => $server2_name, connection => { display => $server2_name, status => 'ok', error_message => '' } } }; $self->check_connection(name => $server1_name, sql => $sql_server1); $self->check_connection(name => $server2_name, sql => $sql_server2); $self->check_slave(name => $server1_name, sql => $sql_server1); $self->check_slave(name => $server2_name, sql => $sql_server2); $self->check_master_slave_position( name_master => $server1_name, name_slave => $server2_name, sql_master => $sql_server1, sql_slave => $sql_server2 ); $self->check_master_slave_position( name_master => $server2_name, name_slave => $server1_name, sql_master => $sql_server2, sql_slave => $sql_server1 ); } 1; __END__ =head1 MODE Check MySQL replication (need to use --multiple). =over 8 =item B<--unknown-connection-status> Set unknown threshold for status. Can used special variables like: %{status}, %{error_message}, %{display} =item B<--warning-connection-status> Set warning threshold for status. Can used special variables like: %{status}, %{error_message}, %{display} =item B<--critical-connection-status> Set critical threshold for status (Default: '%{status} ne "ok"'). Can used special variables like: %{status}, %{error_message}, %{display} =item B<--unknown-replication-status> Set unknown threshold for status (Default: '%{replication_status} =~ /configurationIssue/i'). Can used special variables like: %{replication_status}, %{display} =item B<--warning-replication-status> Set warning threshold for status (Default: '%{replication_status} =~ /inProgress/i'). Can used special variables like: %{replication_status}, %{display} =item B<--critical-replication-status> Set critical threshold for status (Default: '%{replication_status} =~ /connectIssueToMaster/i'). Can used special variables like: %{replication_status}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'slaves-running', 'slave-latency' (s). =back =cut centreon-plugins-20220113/database/mysql/mode/slowqueries.pm000066400000000000000000000120271417000230700240130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mysql::mode::slowqueries; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::statefile; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning:s" => { name => 'warning', }, "critical:s" => { name => 'critical', }, }); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); 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(); } $self->{statefile_cache}->check_options(%options); } sub run { my ($self, %options) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); if (!($self->{sql}->is_version_minimum(version => '5'))) { $self->{output}->add_option_msg(short_msg => "MySQL version '" . $self->{sql}->{version} . "' is not supported (need version >= '5.x')."); $self->{output}->option_exit(); } $self->{sql}->query(query => q{SHOW /*!50000 global */ STATUS LIKE 'Slow_queries'}); my ($name, $result) = $self->{sql}->fetchrow_array(); if (!defined($result)) { $self->{output}->add_option_msg(short_msg => "Cannot get slow queries."); $self->{output}->option_exit(); } my $new_datas = {}; $self->{statefile_cache}->read(statefile => 'mysql_' . $self->{mode} . '_' . $self->{sql}->get_unique_id4save()); my $old_timestamp = $self->{statefile_cache}->get(name => 'last_timestamp'); $new_datas->{last_timestamp} = time(); if (defined($old_timestamp) && $new_datas->{last_timestamp} - $old_timestamp == 0) { $self->{output}->add_option_msg(short_msg => "Need at least one second between two checks."); $self->{output}->option_exit(); } $new_datas->{$name} = $result; my $old_val = $self->{statefile_cache}->get(name => $name); if (defined($old_val) && $result >= $old_val) { my $value = sprintf("%.2f", ($result - $old_val) / ($new_datas->{last_timestamp} - $old_timestamp)); my $exit_code = $self->{perfdata}->threshold_check(value => $value, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("%d slow queries in %d seconds (%.2f/sec)", ($result - $old_val), ($new_datas->{last_timestamp} - $old_timestamp), $value) ); $self->{output}->perfdata_add(label => 'slow_queries_rate', value => $value, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0); } $self->{statefile_cache}->write(data => $new_datas); if (!defined($old_timestamp)) { $self->{output}->output_add(severity => 'OK', short_msg => "Buffer creation..."); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check average number of queries detected as "slow" (per seconds). =over 8 =item B<--warning> Threshold warning in queries per seconds. =item B<--critical> Threshold critical in queries per seconds. =back =cut centreon-plugins-20220113/database/mysql/mode/tablescount.pm000066400000000000000000000077421417000230700237640ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mysql::mode::tablescount; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning:s" => { name => 'warning', }, "critical:s" => { name => 'critical', }, "filter:s" => { name => 'filter', }, }); 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) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); $self->{sql}->query(query => 'SELECT table_schema AS NAME, COUNT(*) FROM information_schema.tables GROUP BY table_schema'); my $result = $self->{sql}->fetchall_arrayref(); $self->{output}->output_add(severity => 'OK', short_msg => "All databases are ok."); foreach my $row (@$result) { next if (defined($self->{option_results}->{filter}) && $$row[0] !~ /$self->{option_results}->{filter}/); my $exit_code = $self->{perfdata}->threshold_check(value => $$row[1], threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); my $value = $$row[1]; $self->{output}->output_add(long_msg => sprintf("DB '" . $$row[0] . "' tables count: %s", $value)); if (!$self->{output}->is_status(value => $exit_code, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("DB '" . $$row[0] . "' tables count: %s", $value)); } $self->{output}->perfdata_add(label => $$row[0] . '_tablescount', unit => '', value => $$row[1], warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check MySQL tables count by db. =over 8 =item B<--warning> Threshold warning. =item B<--critical> Threshold critical. =item B<--filter> Filter database to checks. =back =cut centreon-plugins-20220113/database/mysql/mode/threadsconnected.pm000066400000000000000000000152001417000230700247420ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mysql::mode::threadsconnected; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_usage_output { my ($self, %options) = @_; return sprintf( 'Client connected threads total: %s used: %s (%.2f%%) free: %s (%.2f%%)', $self->{result_values}->{total}, $self->{result_values}->{used}, $self->{result_values}->{prct_used}, $self->{result_values}->{free}, $self->{result_values}->{prct_free} ); } sub prefix_databse_output { my ($self, %options) = @_; return "Database '" . $options{instance_value}->{name} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, message_separator => ' - ', skipped_code => { -10 => 1 } }, { name => 'databases', type => 1, cb_prefix_output => 'prefix_database_output', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'usage', nlabel => 'threads.connected.count', set => { key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total' }, ] } }, { label => 'usage-prct', nlabel => 'threads.connected.percentage', display_ok => 0, set => { key_values => [ { name => 'prct_used' }, { name => 'free' }, { name => 'used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%' } ] } } ]; $self->{maps_counters}->{databases} = [ { label => 'database-threads-connected', nlabel => 'database.threads.connected.count', display_ok => 0, set => { key_values => [ { name => 'threads_connected' } ], output_template => 'threads connected: %s', perfdatas => [ { template => '%d', min => 0, label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'add-databases' => { name => 'add_databases' } }); return $self; } sub add_databases { my ($self, %options) = @_; $options{sql}->query(query => q{ SELECT schema_name, SUM(case when DB is not null then 1 else 0 end) as numbers FROM information_schema.schemata LEFT JOIN information_schema.processlist ON schemata.schema_name = DB GROUP BY schemata.schema_name }); $self->{databases} = {}; my $result = $options{sql}->fetchall_arrayref(); foreach my $row (@$result) { $self->{databases}->{ $row->[0] } = { name => $row->[0], threads_connected => $row->[1] }; } } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); if (!($options{sql}->is_version_minimum(version => '5'))) { $self->{output}->add_option_msg(short_msg => "MySQL version '" . $self->{sql}->{version} . "' is not supported (need version >= '5.x')."); $self->{output}->option_exit(); } my $infos = {}; if (!$options{sql}->is_mariadb() && $options{sql}->is_version_minimum(version => '5.7.6')) { $options{sql}->query(query => q{ SELECT 'max_connections' as name, @@GLOBAL.max_connections as value UNION SELECT VARIABLE_NAME as name, VARIABLE_VALUE as value FROM performance_schema.global_status WHERE VARIABLE_NAME = 'Threads_connected' }); while (my ($name, $value) = $options{sql}->fetchrow_array()) { $infos->{lc($name)} = $value; } } elsif ($options{sql}->is_version_minimum(version => '5.1.12')) { $options{sql}->query(query => q{ SELECT 'max_connections' as name, @@GLOBAL.max_connections as value UNION SELECT VARIABLE_NAME as name, VARIABLE_VALUE as value FROM information_schema.GLOBAL_STATUS WHERE VARIABLE_NAME = 'Threads_connected' }); while (my ($name, $value) = $options{sql}->fetchrow_array()) { $infos->{lc($name)} = $value; } } else { $options{sql}->query(query => q{SELECT 'max_connections' as name, @@GLOBAL.max_connections as value}); if (my ($name, $value) = $options{sql}->fetchrow_array()) { $infos->{lc($name)} = $value } $options{sql}->query(query => q{SHOW /*!50000 global */ STATUS LIKE 'Threads_connected'}); if (my ($name, $value) = $options{sql}->fetchrow_array()) { $infos->{lc($name)} = $value } } if (scalar(keys %$infos) == 0) { $self->{output}->add_option_msg(short_msg => 'Cannot get number of open connections.'); $self->{output}->option_exit(); } my $prct_used = $infos->{threads_connected} * 100 / $infos->{max_connections}; $self->{global} = { total => $infos->{max_connections}, used => $infos->{threads_connected}, free => $infos->{max_connections} - $infos->{threads_connected}, prct_used => $prct_used, prct_free => 100 - $prct_used }; if (defined($self->{option_results}->{add_databases})) { $self->add_databases(sql => $options{sql}); } } 1; __END__ =head1 MODE Check number of open connections. =over 8 =item B<--add-databases> Add threads by databases. =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'usage', 'usage-prct' (%), 'database-threads-connected'. =back =cut centreon-plugins-20220113/database/mysql/mode/uptime.pm000066400000000000000000000074711417000230700227430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mysql::mode::uptime; use base qw(centreon::plugins::mode); use strict; use warnings; use POSIX; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning:s" => { name => 'warning', }, "critical:s" => { name => 'critical', }, "seconds" => { name => 'seconds', }, }); 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) = @_; $options{sql}->connect(); if (!($options{sql}->is_version_minimum(version => '5'))) { $self->{output}->add_option_msg(short_msg => "MySQL version '" . $self->{sql}->{version} . "' is not supported (need version >= '5.x')."); $self->{output}->option_exit(); } $options{sql}->query(query => q{SHOW /*!50000 global */ STATUS LIKE 'Uptime'}); my ($name, $value) = $options{sql}->fetchrow_array(); if (!defined($value)) { $self->{output}->add_option_msg(short_msg => "Cannot get uptime."); $self->{output}->option_exit(); } my $exit_code = $self->{perfdata}->threshold_check(value => $value, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); my $msg = sprintf("database is up since %d days", floor($value / 86400)); if (defined($self->{option_results}->{seconds})) { $msg = sprintf("database is up since %d seconds", $value); } $self->{output}->output_add(severity => $exit_code, short_msg => $msg); $self->{output}->perfdata_add(label => 'uptime', unit => 's', value => $value, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check MySQL uptime. =over 8 =item B<--warning> Threshold warning. =item B<--critical> Threshold critical. =item B<--seconds> Display uptime in seconds. =back =cut centreon-plugins-20220113/database/mysql/mysqlcmd.pm000066400000000000000000000231611417000230700223370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mysql::mysqlcmd; use strict; use warnings; use centreon::plugins::misc; use Digest::MD5 qw(md5_hex); sub new { my ($class, %options) = @_; my $self = {}; bless $self, $class; # $options{options} = options object # $options{output} = output object # $options{exit_value} = integer # $options{noptions} = integer if (!defined($options{output})) { print "Class mysqlcmd: Need to specify 'output' argument.\n"; exit 3; } if (!defined($options{options})) { $options{output}->add_option_msg(short_msg => "Class Mysqlcmd: Need to specify 'options' argument."); $options{output}->option_exit(); } if (!defined($options{noptions})) { $options{options}->add_options(arguments => { 'mysql-cmd:s' => { name => 'mysql_cmd', default => '/usr/bin/mysql' }, 'host:s@' => { name => 'host' }, 'port:s@' => { name => 'port' }, 'username:s@' => { name => 'username' }, 'password:s@' => { name => 'password' }, 'socket:s@' => { name => 'socket' }, 'sql-errors-exit:s' => { name => 'sql_errors_exit', default => 'unknown' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'MYSQLCMD OPTIONS', once => 1); $self->{output} = $options{output}; $self->{sqlmode_name} = $options{sqlmode_name}; $self->{args} = undef; $self->{stdout} = undef; $self->{columns} = undef; $self->{version} = undef; $self->{host} = undef; $self->{port} = undef; $self->{socket} = undef; $self->{username} = undef; $self->{password} = undef; return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults { my ($self, %options) = @_; foreach (keys %{$options{default}}) { if ($_ eq $self->{sqlmode_name}) { 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->{host} = (defined($self->{option_results}->{host})) ? shift(@{$self->{option_results}->{host}}) : undef; $self->{port} = (defined($self->{option_results}->{port})) ? shift(@{$self->{option_results}->{port}}) : undef; $self->{socket} = (defined($self->{option_results}->{socket})) ? shift(@{$self->{option_results}->{socket}}) : undef; $self->{username} = (defined($self->{option_results}->{username})) ? shift(@{$self->{option_results}->{username}}) : undef; $self->{password} = (defined($self->{option_results}->{password})) ? shift(@{$self->{option_results}->{password}}) : undef; $self->{sql_errors_exit} = $self->{option_results}->{sql_errors_exit}; $self->{mysql_cmd} = $self->{option_results}->{mysql_cmd}; if (!defined($self->{host}) || $self->{host} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify host argument.'); $self->{output}->option_exit(exit_litteral => $self->{sql_errors_exit}); } $self->{args} = ['--batch', '--raw', '--host', $self->{host}]; if (defined($self->{port})) { push @{$self->{args}}, "--port", $self->{port}; } if (defined($self->{username})) { push @{$self->{args}}, "--user", $self->{username}; } if (defined($self->{password}) && $self->{password} ne '') { push @{$self->{args}}, "-p" . $self->{password}; } if (defined($self->{socket}) && $self->{socket} ne '') { push @{$self->{args}}, "--socket", $self->{socket}; } if (scalar(@{$self->{option_results}->{host}}) == 0) { return 0; } return 1; } sub is_version_minimum { my ($self, %options) = @_; # $options{version} = string version to check my @version_src = split /\./, $self->{version}; my @versions = split /\./, $options{version}; for (my $i = 0; $i < scalar(@versions); $i++) { return 1 if ($versions[$i] eq 'x'); return 1 if (!defined($version_src[$i])); $version_src[$i] =~ /^([0-9]*)/; next if ($versions[$i] == int($1)); return 0 if ($versions[$i] > int($1)); return 1 if ($versions[$i] < int($1)); } return 1; } sub get_id { my ($self, %options) = @_; my $msg = $self->{host}; if (defined($self->{port})) { $msg .= ":" . $self->{port}; } return $msg; } sub get_unique_id4save { my ($self, %options) = @_; my $msg = $self->{host}; if (defined($self->{port})) { $msg .= ":" . $self->{port}; } return md5_hex($msg); } sub quote { my $self = shift; return undef; } sub command_execution { my ($self, %options) = @_; my ($lerror, $stdout, $exit_code) = centreon::plugins::misc::backtick( command => $self->{mysql_cmd}, arguments => [@{$self->{args}}, '-e', $options{request}], timeout => 30, wait_exit => 1, redirect_stderr => 1 ); if ($exit_code <= -1000) { if ($exit_code == -1000) { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => $stdout); } $self->{output}->display(); $self->{output}->exit(); } return ($exit_code, $stdout); } sub disconnect {} sub is_mariadb { my ($self) = @_; return $self->{is_mariadb}; } sub set_version { my ($self, %options) = @_; $self->{is_mariadb} = 0; $self->{version} = $options{version}; # MariaDB: 5.5.5-10.1.36-MariaDB or 10.1.36-MariaDB if ($self->{version} =~ /([0-9\.]*?)-MariaDB/i) { $self->{version} = $1; $self->{is_mariadb} = 1; } } sub connect { my ($self, %options) = @_; my $dontquit = (defined($options{dontquit}) && $options{dontquit} == 1) ? 1 : 0; (my $exit_code, $self->{stdout}) = $self->command_execution(request => "SHOW VARIABLES LIKE 'version'"); if ($exit_code != 0) { if ($dontquit == 0) { $self->{output}->add_option_msg(short_msg => 'Cannot connect: ' . $self->{stdout}); $self->{output}->option_exit(exit_litteral => $self->{sql_errors_exit}); } return (-1, 'Cannot connect: ' . $self->{stdout}); } my $row = $self->fetchrow_hashref(); $self->set_version(version => $row->{Value}); return 0; } sub fetchall_arrayref { my ($self, %options) = @_; my $array_ref = []; if (!defined($self->{columns})) { $self->{stdout} =~ s/^(.*?)(\n|$)//; @{$self->{columns}} = split(/\t/, $1); } foreach (split /\n/, $self->{stdout}) { push @$array_ref, [map({ s/\\n/\x{0a}/g; s/\\t/\x{09}/g; s/\\/\x{5c}/g; $_; } split(/\t/, $_))]; } return $array_ref; } sub fetchrow_array { my ($self, %options) = @_; my @array_result = (); if (!defined($self->{columns})) { $self->{stdout} =~ s/^(.*?)(\n|$)//; @{$self->{columns}} = split(/\t/, $1); } if (($self->{stdout} =~ s/^(.*?)(\n|$)//)) { push @array_result, map({ s/\\n/\x{0a}/g; s/\\t/\x{09}/g; s/\\/\x{5c}/g; $_; } split(/\t/, $1)); } return @array_result; } sub fetchrow_hashref { my ($self, %options) = @_; my $array_result = undef; if (!defined($self->{columns})) { $self->{stdout} =~ s/^(.*?)(\n|$)//; @{$self->{columns}} = split(/\t/, $1); } if ($self->{stdout} ne '' && $self->{stdout} =~ s/^(.*?)(\n|$)//) { $array_result = {}; my @values = split(/\t/, $1); for (my $i = 0; $i < scalar(@values); $i++) { my $value = $values[$i]; $value =~ s/\\n/\x{0a}/g; $value =~ s/\\t/\x{09}/g; $value =~ s/\\/\x{5c}/g; $array_result->{$self->{columns}[$i]} = $value; } } return $array_result; } sub query { my ($self, %options) = @_; $self->{columns} = undef; (my $exit_code, $self->{stdout}) = $self->command_execution(request => $options{query}); if ($exit_code != 0) { $self->{output}->add_option_msg(short_msg => 'Cannot execute query: ' . $self->{stdout}); $self->{output}->option_exit(exit_litteral => $self->{sql_errors_exit}); } } 1; __END__ =head1 NAME mysqlcmd global =head1 SYNOPSIS mysqlcmd class =head1 MYSQLCMD OPTIONS =over 8 =item B<--mysql-cmd> mysql command (Default: '/usr/bin/mysql'). =item B<--host> Database hostname. =item B<--port> Database port. =item B<--username> Database username. =item B<--password> Database password. =item B<--sql-errors-exit> Exit code for DB Errors (default: unknown) =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/database/mysql/plugin.pm000066400000000000000000000102631417000230700220030ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::mysql::plugin; use strict; use warnings; use base qw(centreon::plugins::script_sql); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $self->{version} = '0.1'; $self->{modes} = { 'backup' => 'database::mysql::mode::backup', 'collection' => 'centreon::common::protocols::sql::mode::collection', 'connection-time' => 'centreon::common::protocols::sql::mode::connectiontime', 'databases-size' => 'database::mysql::mode::databasessize', 'innodb-bufferpool-hitrate' => 'database::mysql::mode::innodbbufferpoolhitrate', 'long-queries' => 'database::mysql::mode::longqueries', 'myisam-keycache-hitrate' => 'database::mysql::mode::myisamkeycachehitrate', 'open-files' => 'database::mysql::mode::openfiles', 'password-expiration' => 'database::mysql::mode::passwordexpiration', 'qcache-hitrate' => 'database::mysql::mode::qcachehitrate', 'queries' => 'database::mysql::mode::queries', 'replication' => 'database::mysql::mode::replication', 'slow-queries' => 'database::mysql::mode::slowqueries', 'sql' => 'centreon::common::protocols::sql::mode::sql', 'sql-string' => 'centreon::common::protocols::sql::mode::sqlstring', 'threads-connected' => 'database::mysql::mode::threadsconnected', 'uptime' => 'database::mysql::mode::uptime' }; $self->{sql_modes}->{dbi} = 'database::mysql::dbi'; $self->{sql_modes}->{mysqlcmd} = 'database::mysql::mysqlcmd'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options( arguments => { 'host:s@' => { name => 'db_host' }, 'port:s@' => { name => 'db_port' }, 'socket:s@' => { name => 'db_socket' } } ); $self->{options}->parse_options(); my $options_result = $self->{options}->get_options(); $self->{options}->clean(); if (defined($options_result->{db_host})) { @{$self->{sqldefault}->{dbi}} = (); @{$self->{sqldefault}->{mysqlcmd}} = (); for (my $i = 0; $i < scalar(@{$options_result->{db_host}}); $i++) { $self->{sqldefault}->{dbi}->[$i] = { data_source => 'mysql:host=' . $options_result->{db_host}[$i] }; $self->{sqldefault}->{mysqlcmd}->[$i] = { host => $options_result->{db_host}[$i] }; if (defined($options_result->{db_port}[$i])) { $self->{sqldefault}->{dbi}->[$i]->{data_source} .= ';port=' . $options_result->{db_port}[$i]; $self->{sqldefault}->{mysqlcmd}->[$i]->{port} = $options_result->{db_port}[$i]; } if (defined($options_result->{db_socket}[$i])) { $self->{sqldefault}->{dbi}->[$i]->{data_source} .= ';mysql_socket=' . $options_result->{db_socket}[$i]; $self->{sqldefault}->{mysqlcmd}->[$i]->{socket} = $options_result->{db_socket}[$i]; } } } $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check MySQL Server. =over 8 You can use following options or options from 'sqlmode' directly. =item B<--host> Hostname to query. =item B<--port> Database Server Port. =back =cut centreon-plugins-20220113/database/oracle/000077500000000000000000000000001417000230700202455ustar00rootroot00000000000000centreon-plugins-20220113/database/oracle/dbi.pm000066400000000000000000000054221417000230700213440ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::oracle::dbi; use base qw(centreon::plugins::dbi); use strict; use warnings; use POSIX qw(:signal_h); sub connect_oracle { my ($self, %options) = @_; $self->{instance} = DBI->connect( 'DBI:' . $self->{data_source}, $self->{username}, $self->{password}, { RaiseError => 0, PrintError => 0, AutoCommit => 1, %{$self->{connect_options_hash}} } ); } sub check_options { my ($self, %options) = @_; $self->{container} = defined($self->{option_results}->{container}[0]) ? $self->{option_results}->{container}[0] : undef; return $self->SUPER::check_options(%options); } sub connect { my ($self, %options) = @_; my $dontquit = (defined($options{dontquit}) && $options{dontquit} == 1) ? 1 : 0; # Set ENV if (defined($self->{env})) { foreach (keys %{$self->{env}}) { $ENV{$_} = $self->{env}->{$_}; } } if (defined($self->{timeout})) { my $mask = POSIX::SigSet->new(SIGALRM); my $action = POSIX::SigAction->new( sub { $self->handle_ALRM() }, $mask, ); my $oldaction = POSIX::SigAction->new(); sigaction(SIGALRM, $action, $oldaction); eval { eval { alarm($self->{timeout}); $self->connect_oracle(); }; alarm(0); }; sigaction(SIGALRM, $oldaction); } else { $self->connect_oracle(); } if (!defined($self->{instance})) { my $err_msg = sprintf('Cannot connect: %s', defined($DBI::errstr) ? $DBI::errstr : '(no error string)'); if ($dontquit == 0) { $self->{output}->add_option_msg(short_msg => $err_msg); $self->{output}->option_exit(exit_litteral => $self->{sql_errors_exit}); } return (-1, $err_msg); } $self->set_version(); if (defined($self->{container}) and $self->{container} ne '') { $self->query(query => "alter session set container=$self->{container}"); } return 0; } 1; __END__ centreon-plugins-20220113/database/oracle/mode/000077500000000000000000000000001417000230700211715ustar00rootroot00000000000000centreon-plugins-20220113/database/oracle/mode/asmdiskgroupusage.pm000066400000000000000000000316231417000230700252710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::oracle::mode::asmdiskgroupusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_offline_output { my ($self, %options) = @_; my $msg = 'Offline disks : ' . $self->{result_values}->{offline_disks}; return $msg; } sub custom_offline_calc { my ($self, %options) = @_; $self->{result_values}->{offline_disks} = $options{new_datas}->{$self->{instance} . '_offline_disks'}; $self->{result_values}->{type} = $options{new_datas}->{$self->{instance} . '_type'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub custom_status_output { my ($self, %options) = @_; my $msg = 'status: ' . $self->{result_values}->{status}; return $msg; } sub custom_status_threshold { my ($self, %options) = @_; my $status = catalog_status_threshold($self, %options); $self->{instance_mode}->{last_status} = 0; if (!$self->{output}->is_status(value => $status, compare => 'ok', litteral => 1)) { $self->{instance_mode}->{last_status} = 1; } return $status; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; return 0; } sub custom_usage_perfdata { my ($self, %options) = @_; my $label = 'used'; my $value_perf = $self->{result_values}->{used}; if ($self->{result_values}->{total} > 0 && defined($self->{instance_mode}->{option_results}->{free})) { $label = 'free'; $value_perf = $self->{result_values}->{free}; } $label .= '_' . $self->{result_values}->{label_ref} if (defined($self->{result_values}->{label_ref})); my %total_options = (); if ($self->{result_values}->{total} > 0 && $self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } $self->{output}->perfdata_add( label => $label, unit => 'B', instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, 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} ); } sub custom_usage_threshold { my ($self, %options) = @_; # cannot use '%' or free option with unlimited system return 'ok' if ($self->{result_values}->{total} <= 0 && ($self->{instance_mode}->{option_results}->{units} eq '%' || $self->{instance_mode}->{option_results}->{free})); my ($exit, $threshold_value); $threshold_value = $self->{result_values}->{used}; $threshold_value = $self->{result_values}->{free} if (defined($self->{instance_mode}->{option_results}->{free})); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; $threshold_value = $self->{result_values}->{prct_free} if (defined($self->{instance_mode}->{option_results}->{free})); } $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel}, exit_litteral => 'warning' } ]); return $exit; } sub custom_usage_output { my ($self, %options) = @_; my $label = 'Disk '; if (defined($self->{result_values}->{label_ref})) { $label = 'Disk Failure'; } my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); my $msg; if ($self->{result_values}->{total} <= 0) { $msg = sprintf("%s Used: %s (unlimited)", $label, $total_used_value . " " . $total_used_unit); } else { my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); $msg = sprintf("%s Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", $label, $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) = @_; return -10 if (defined($self->{instance_mode}->{last_status}) && $self->{instance_mode}->{last_status} == 0); my $label_used = 'used'; $label_used .= '_' . $options{extra_options}->{label_ref} if (defined($options{extra_options}->{label_ref})); $self->{result_values}->{label_ref} = defined($options{extra_options}->{label_ref}) ? $options{extra_options}->{label_ref} : undef; $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} . '_' . $label_used}; return 0 if ($self->{result_values}->{total} == 0); $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}; $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 => 'dg', type => 1, cb_prefix_output => 'prefix_dg_output', message_multiple => 'All diskgroups are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{dg} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' } ], 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_output'), } }, { label => 'offline-disks', set => { key_values => [ { name => 'offline_disks' }, { name => 'type' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_offline_calc'), closure_custom_output => $self->can('custom_offline_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold, } }, { label => 'usage', set => { key_values => [ { name => 'used' }, { name => 'total' }, { name => 'display' } ], 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 => 'usage-failure', set => { key_values => [ { name => 'used_failure' }, { name => 'total' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { label_ref => 'failure' }, 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 prefix_dg_output { my ($self, %options) = @_; return "Diskgroup '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "unknown-status:s" => { name => 'unknown_status', default => '' }, "warning-status:s" => { name => 'warning_status', default => '' }, "critical-status:s" => { name => 'critical_status', default => '' }, "warning-offline-disks:s" => { name => 'warning_offline_disks', default => '(%{offline_disks} > 0 && %{type} eq "extern") || (%{offline_disks} > 1 && %{type} eq "high")' }, "critical-offline-disks:s" => { name => 'critical_offline_disks', default => '%{offline_disks} > 0 && %{type} =~ /^normal|high$/' }, "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); $self->change_macros(macros => [ 'warning_offline_disks', 'critical_offline_disks', 'warning_status', 'critical_status', 'unknown_status', ]); } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); my $query = q{SELECT name, state, type, total_mb, usable_file_mb, offline_disks, FREE_MB FROM V$ASM_DISKGROUP}; $options{sql}->query(query => $query); my $result = $options{sql}->fetchall_arrayref(); $options{sql}->disconnect(); $self->{dg} = {}; foreach my $row (@$result) { my ($name, $state, $type, $total_mb, $usable_file_mb, $offline_disks, $free_mb) = @$row; 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 name.", debug => 1); next; } my $used_failure = ($total_mb * 1024 * 1024) - ($usable_file_mb * 1024 * 1024); if ($usable_file_mb < 0) { $used_failure = ($total_mb * 1024 * 1024); } $self->{dg}->{$name} = { display => $name, total => $total_mb * 1024 * 1024, used => ($total_mb * 1024 * 1024) - ($free_mb * 1024 * 1024), used_failure => $used_failure, status => $state, type => lc($type), offline_disks => $offline_disks }; } if (scalar(keys %{$self->{dg}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No diskgroup found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check Oracle ASM diskgroup usage and status. =over 8 =item B<--warning-usage> Threshold warning. =item B<--critical-usage> Threshold critical. =item B<--warning-usage-failure> Threshold warning. =item B<--critical-usage-failure> Threshold critical. =item B<--unknown-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{display} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{display} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{status}, %{display} =item B<--warning-offline-disks> Set warning threshold for offline disks (Default: '(%{offline_disks} > 0 && %{type} eq "extern") || (%{offline_disks} > 1 && %{type} eq "high")'). Can used special variables like: %{offline_disks}, %{type}, %{display} =item B<--critical-offline-disks> Set critical threshold for offline disks (Default: '%{offline_disks} > 0 && %{type} =~ /^normal|high$/'). Can used special variables like: %{offline_disks}, %{type}, %{display} =item B<--units> Units of thresholds (Default: '%') ('%', 'B'). =item B<--free> Thresholds are on free space left. =item B<--filter-name> Filter by name (regexp can be used). =back =cut centreon-plugins-20220113/database/oracle/mode/connectedusers.pm000066400000000000000000000061301417000230700245530ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::oracle::mode::connectedusers; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "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) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); $self->{sql}->query(query => q{SELECT COUNT(*) FROM v$session WHERE type = 'USER'}); my $users = $self->{sql}->fetchrow_array(); $self->{sql}->disconnect(); my $exit_code = $self->{perfdata}->threshold_check(value => $users, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("%i Connected user(s).", $users)); $self->{output}->perfdata_add(label => 'connected_users', value => $users, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check Oracle connected users. =over 8 =item B<--warning> Threshold warning. =item B<--critical> Threshold critical. =back =cut centreon-plugins-20220113/database/oracle/mode/corruptedblocks.pm000066400000000000000000000062041417000230700247360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::oracle::mode::corruptedblocks; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "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) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); $self->{sql}->query(query => q{SELECT COUNT(*) FROM v$database_block_corruption}); my $corrupted_blocks = $self->{sql}->fetchrow_array(); $self->{sql}->disconnect(); my $exit_code = $self->{perfdata}->threshold_check(value => $corrupted_blocks, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("%i corrupted blocks.", $corrupted_blocks)); $self->{output}->perfdata_add(label => 'corrupted_blocks', value => $corrupted_blocks, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check Oracle corrupted blocks. =over 8 =item B<--warning> Threshold warning. =item B<--critical> Threshold critical. =back =cut centreon-plugins-20220113/database/oracle/mode/datacachehitratio.pm000066400000000000000000000071761417000230700252030ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::oracle::mode::datacachehitratio; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); sub custom_hitratio_calc { my ($self, %options) = @_; my $delta_phys = ($options{new_datas}->{$self->{instance} . '_physical_reads'} - $options{old_datas}->{$self->{instance} . '_physical_reads'}); my $delta_cache = ($options{new_datas}->{$self->{instance} . '_db_block_gets'} - $options{old_datas}->{$self->{instance} . '_db_block_gets'}) + ($options{new_datas}->{$self->{instance} . '_consistent_gets'} - $options{old_datas}->{$self->{instance} . '_consistent_gets'}); $self->{result_values}->{hit_ratio} = ($delta_cache == 0) ? 0 : ((1 - ($delta_phys / $delta_cache)) * 100); return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, ]; $self->{maps_counters}->{global} = [ { label => 'usage', set => { key_values => [ { name => 'physical_reads', diff => 1 }, { name => 'db_block_gets', diff => 1 }, { name => 'consistent_gets', diff => 1 } ], closure_custom_calc => $self->can('custom_hitratio_calc'), output_template => 'Buffer cache hit ratio is %.2f%%', output_error_template => 'Buffer cache hit ratio: %s', output_use => 'hit_ratio', threshold_use => 'hit_ratio', perfdatas => [ { label => 'sga_data_buffer_hit_ratio', value => 'hit_ratio', template => '%.2f', min => 0, max => 100, unit => '%' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $query = q{ SELECT SUM(DECODE(name, 'physical reads', value, 0)), SUM(DECODE(name, 'db block gets', value, 0)), SUM(DECODE(name, 'consistent gets', value, 0)) FROM sys.v_$sysstat }; $options{sql}->connect(); $options{sql}->query(query => $query); my @result = $options{sql}->fetchrow_array(); $options{sql}->disconnect(); $self->{global} = { physical_reads => $result[0], db_block_gets => $result[1], consistent_gets => $result[2], }; $self->{cache_name} = "oracle_" . $self->{mode} . '_' . $options{sql}->get_unique_id4save() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check Oracle buffer cache hit ratio. =over 8 =item B<--warning-usage> Threshold warning. =item B<--critical-usage> Threshold critical. =back =cut centreon-plugins-20220113/database/oracle/mode/datafilesstatus.pm000066400000000000000000000232551417000230700247360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::oracle::mode::datafilesstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); use Digest::MD5 qw(md5_hex); sub custom_traffic_calc { my ($self, %options) = @_; my $total_traffic = -1; foreach (keys %{$options{new_datas}}) { if (/^(.*)_(phyrds|phywrts)$/) { my $new_total = $options{new_datas}->{$_}; next if (!defined($options{old_datas}->{$_})); $total_traffic = 0 if ($total_traffic == -1); my $old_total = $options{old_datas}->{$_}; if ($old_total > $new_total) { $options{old_datas}->{$_} = 0; $old_total = 0; } my $diff_total = $new_total - $old_total; $total_traffic += $diff_total; } } if ($total_traffic == -1) { $self->{error_msg} = "Buffer creation"; return -1; } $self->{result_values}->{traffic} = $total_traffic / $options{delta_time}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'df', type => 1, cb_prefix_output => 'prefix_df_output', message_multiple => 'All data files are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ { label => 'total-traffic', nlabel => 'datafiles.traffic.io.usage.iops', set => { key_values => [], manual_keys => 1, closure_custom_calc => $self->can('custom_traffic_calc'), threshold_use => 'traffic', output_use => 'traffic', output_template => 'Total Traffic IOPs %.2f', perfdatas => [ { label => 'total_traffic', value => 'traffic', template => '%.2f', min => 0 , unit => 'iops' }, ], } }, ]; $self->{maps_counters}->{df} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { 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 => \&catalog_status_threshold } }, { label => 'online-status', threshold => 0, set => { key_values => [ { name => 'online_status' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_online_status_calc'), closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } }, ]; } sub custom_status_output { my ($self, %options) = @_; my $msg = $self->{result_values}->{label_display} . ' : ' . $self->{result_values}->{$self->{result_values}->{label_th}}; return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{label_display} = 'Status'; $self->{result_values}->{label_th} = 'status'; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub custom_online_status_calc { my ($self, %options) = @_; $self->{result_values}->{label_display} = 'Online Status'; $self->{result_values}->{label_th} = 'online_status'; $self->{result_values}->{online_status} = $options{new_datas}->{$self->{instance} . '_online_status'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-tablespace:s' => { name => 'filter_tablespace' }, 'filter-data-file:s' => { name => 'filter_data_file' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{status} =~ /offline|invalid/i' }, 'warning-online-status:s' => { name => 'warning_online_status', default => '%{online_status} =~ /sysoff/i' }, 'critical-online-status:s' => { name => 'critical_online_status', default => '%{online_status} =~ /offline|recover/i' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status', 'warning_online_status', 'critical_online_status']); } sub prefix_df_output { my ($self, %options) = @_; return "Data file '" . $options{instance_value}->{display} . "' "; } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); if ($options{sql}->is_version_minimum(version => '10')) { $options{sql}->query(query => q{ SELECT a.file_name, a.tablespace_name, a.status, b.phyrds, b.phywrts, a.online_status FROM dba_data_files a, v$filestat b WHERE a.file_id = b.file# UNION SELECT a.name, c.name, a.status, b.phyrds, b.phywrts, NULL FROM v$tempfile a, v$tablespace c, v$tempstat b WHERE a.ts#= c.ts# AND a.file# = b.file# }); } else { $options{sql}->query(query => q{ SELECT a.file_name, a.tablespace_name, a.status, b.phyrds, b.phywrts FROM dba_data_files a, v$filestat b WHERE a.file_id = b.file# UNION SELECT a.name, c.name, a.status, b.phyrds, b.phywrts FROM v$tempfile a, v$tablespace c, v$tempstat b WHERE a.ts#= c.ts# AND a.file# = b.file# }); } my $result = $options{sql}->fetchall_arrayref(); $options{sql}->disconnect(); $self->{global} = {}; $self->{df} = {}; foreach my $row (@$result) { if (defined($self->{option_results}->{filter_data_file}) && $self->{option_results}->{filter_data_file} ne '' && $$row[0] !~ /$self->{option_results}->{filter_data_file}/) { $self->{output}->output_add(long_msg => "skipping '" . $$row[0] . "': no matching filter.", debug => 1); next; } if (defined($self->{option_results}->{filter_tablespace}) && $self->{option_results}->{filter_tablespace} ne '' && $$row[1] !~ /$self->{option_results}->{filter_tablespace}/) { $self->{output}->output_add(long_msg => "skipping '" . $$row[1] . "': no matching filter.", debug => 1); next } my $name = $$row[1] . '/' . $$row[0]; $self->{df}->{$name} = { status => $$row[2], online_status => defined($$row[5]) ? $$row[5] : undef, display => $name }; $self->{global}->{$name . '_phyrds'} = $$row[3]; $self->{global}->{$name . '_phywrts'} = $$row[4]; } if (scalar(keys %{$self->{df}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No data file found"); $self->{output}->option_exit(); } $self->{cache_name} = "oracle_" . $self->{mode} . '_' . $options{sql}->get_unique_id4save() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_tablespace}) ? md5_hex($self->{option_results}->{filter_tablespace}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_data_file}) ? md5_hex($self->{option_results}->{filter_data_file}) : md5_hex('all')); } 1; __END__ =head1 MODE Check data files status. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). =item B<--filter-tablespace> Filter tablespace name (can be a regexp). =item B<--filter-data-file> Filter data file name (can be a regexp). =item B<--warning-status> Set warning threshold for status (Default: none). Can used special variables like: %{display}, %{status} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /offline|invalid/i'). Can used special variables like: %{display}, %{status} =item B<--warning-online-status> Set warning threshold for online status (Default: '%{online_status} =~ /sysoff/i'). Can used special variables like: %{display}, %{online_status} =item B<--critical-online-status> Set critical threshold for online status (Default: '%{online_status} =~ /offline|recover/i'). Can used special variables like: %{display}, %{online_status} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'total-traffic'. =back =cut centreon-plugins-20220113/database/oracle/mode/dataguard.pm000066400000000000000000000157441417000230700234760ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::oracle::mode::dataguard; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; return sprintf( "dataguard role '%s' [open mode: '%s'] - managed recovery process %s status is %s [log transport: %s]", $self->{result_values}->{role}, $self->{result_values}->{open_mode}, $self->{result_values}->{mrp_process}, $self->{result_values}->{mrp_status}, $self->{result_values}->{log_transport} ); } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{roleLast} = $options{old_datas}->{$self->{instance} . '_role'}; $self->{result_values}->{role} = $options{new_datas}->{$self->{instance} . '_role'}; $self->{result_values}->{open_mode} = $options{new_datas}->{$self->{instance} . '_open_mode'}; $self->{result_values}->{mrp_status} = $options{new_datas}->{$self->{instance} . '_mrp_status'}; $self->{result_values}->{mrp_process} = $options{new_datas}->{$self->{instance} . '_mrp_process'}; $self->{result_values}->{log_transport} = $options{new_datas}->{$self->{instance} . '_log_transport'}; if (!defined($options{old_datas}->{$self->{instance} . '_role'})) { $self->{error_msg} = "buffer creation"; return -2; } return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'role' }, { name => 'open_mode' }, { name => 'mrp_status' }, { name => 'mrp_process' }, { name => 'log_transport' } ], 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 => \&catalog_status_threshold, } }, { label => 'standby-lag', nlabel => 'dataguard.standby.lag.minutes', set => { key_values => [ { name => 'lag_minutes' } ], output_template => 'dataguard standby lag %d minutes: %s', perfdatas => [ { value => 'lag_minutes', template => '%s', min => 0, unit => 'm' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'unknown-status:s' => { name => 'unknown_status', default => '%{mrp_status} =~ /undefined/ || %{log_transport} =~ /undefined/' }, 'warning-status:s' => { name => 'warning_status', default => '%{mrp_status} =~ /WAIT_FOR_LOG/i and %{log_transport} =~ /LGWR/i' }, 'critical-status:s' => { name => 'critical_status', default => '%{roleLast} ne %{role} || %{mrp_status} !~ /undefined|APPLYING_LOG|WAIT_FOR_LOG/i' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros( macros => [ 'unknown_status', 'warning_status', 'critical_status' ] ); } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); $options{sql}->query( query => q{ SELECT name, open_mode, database_role FROM v$database } ); my @result = $options{sql}->fetchrow_array(); $self->{global} = { role => $result[2], open_mode => $result[1] }; $options{sql}->query( query => q{ SELECT process, status FROM v$managed_standby WHERE process LIKE 'MR%' } ); @result = $options{sql}->fetchrow_array(); $self->{global}->{mrp_process} = defined($result[0]) && $result[0] ne '' ? $result[0] : 'undefined'; $self->{global}->{mrp_status} = defined($result[1]) && $result[1] ne '' ? $result[1] : 'undefined'; $options{sql}->query( query => q{ SELECT DECODE(COUNT(*),0,'ARCH','LGWR') AS log_transport FROM v$managed_standby WHERE client_process = 'LGWR' } ); @result = $options{sql}->fetchrow_array(); $self->{global}->{log_transport} = defined($result[0]) && $result[0] ne '' ? $result[0] : 'undefined'; $options{sql}->query( query => q{ SELECT TO_CHAR(MAX(first_time),'YYYYMMDDHH24MISS'), CEIL((SYSDATE - MAX(first_time)) * 24 * 60) FROM v$archived_log WHERE applied NOT IN ('NO') AND registrar = 'RFS' } ); @result = $options{sql}->fetchrow_array(); $self->{global}->{lag_minutes} = defined($result[1]) && $result[1] ne '' ? $result[1] : -1; $options{sql}->disconnect(); $self->{cache_name} = "oracle_" . $self->{mode} . '_' . $options{sql}->get_unique_id4save() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check oracle dataguard. =over 8 =item B<--unknown-status> Set unknown threshold for status (Default: '%{mrp_status} =~ /undefined/ || %{log_transport} =~ /undefined/'). Can used special variables like: %{roleLast}, %{role}, %{open_mode}, %{mrp_status}, %{mrp_process}, %{log_transport} =item B<--warning-status> Set warning threshold for status (Default: '%{mrp_status} =~ /WAIT_FOR_LOG/i and %{log_transport} =~ /LGWR/i'). Can used special variables like: %{roleLast}, %{role}, %{open_mode}, %{mrp_status}, %{mrp_process}, %{log_transport} =item B<--critical-status> Set critical threshold for status (Default: '%{roleLast} ne %{role} || %{mrp_status} !~ /undefined|APPLYING_LOG|WAIT_FOR_LOG/i'). Can used special variables like: %{roleLast}, %{role}, %{open_mode}, %{mrp_status}, %{mrp_process}, %{log_transport} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'standby-lag'. =back =cut centreon-plugins-20220113/database/oracle/mode/dictionarycacheusage.pm000066400000000000000000000064361417000230700257160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::oracle::mode::dictionarycacheusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); sub custom_hitratio_calc { my ($self, %options) = @_; my $delta_total = ($options{new_datas}->{$self->{instance} . '_gets'} - $options{old_datas}->{$self->{instance} . '_gets'}); my $delta_cache = ($options{new_datas}->{$self->{instance} . '_getmisses'} - $options{old_datas}->{$self->{instance} . '_getmisses'}); $self->{result_values}->{hit_ratio} = $delta_total ? (100 * $delta_cache / $delta_total) : 0; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', cb_prefix_output => 'prefix_global_output', type => 0 }, ]; $self->{maps_counters}->{global} = [ { label => 'get-hits', nlabel => 'dictionary.cache.get.hitratio.percentage', set => { key_values => [ { name => 'getmisses', diff => 1 }, { name => 'gets', diff => 1 } ], closure_custom_calc => $self->can('custom_hitratio_calc'), output_template => 'get hit ratio %.2f%%', output_use => 'hit_ratio', threshold_use => 'hit_ratio', perfdatas => [ { label => 'get_hit_ratio', value => 'hit_ratio', template => '%.2f', min => 0, max => 100, unit => '%' }, ], } }, ]; } sub prefix_global_output { my ($self, %options) = @_; return 'SGA dictionary cache '; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $query = q{ SELECT SUM(gets), SUM(gets-getmisses) FROM v$rowcache }; $options{sql}->connect(); $options{sql}->query(query => $query); my @result = $options{sql}->fetchrow_array(); $options{sql}->disconnect(); $self->{global} = { gets => $result[0], getmisses => $result[1], }; $self->{cache_name} = "oracle_" . $self->{mode} . '_' . $options{sql}->get_unique_id4save() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check Oracle dictionary cache usage. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'get-hits'. =back =cut centreon-plugins-20220113/database/oracle/mode/eventwaitsusage.pm000066400000000000000000000202411417000230700247440ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::oracle::mode::eventwaitsusage; 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 => 'event_count', type => 0 }, { name => 'event', type => 1, cb_prefix_output => 'prefix_event_output', message_multiple => 'All event waits are OK', skipped_code => { -11 => 1, -10 => 1 } }, ]; $self->{maps_counters}->{event_count} = [ { label => 'event-count', set => { key_values => [ { name => 'count' } ], output_template => 'Event Wait Count : %s events', perfdatas => [ { label => 'event_wait_count', template => '%s', min => 0 } ], } }, ]; $self->{maps_counters}->{event} = [ { label => 'total-waits-sec', set => { key_values => [ { name => 'total_waits', per_second => 1 }, { name => 'display' } ], output_template => 'Total Waits : %.2f/s', perfdatas => [ { label => 'total_waits', template => '%.2f', unit => '/s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'total-waits-time', set => { key_values => [ { name => 'time_waited_micro', diff => 1 }, { name => 'display' } ], closure_custom_calc => $self->can('custom_usage_calc'), output_template => 'Total Waits Time : %.2f %%', output_use => 'prct_wait', threshold_use => 'prct_wait', perfdatas => [ { label => 'total_waits_time', value => 'prct_wait', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' }, ], } }, ], } sub custom_usage_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; my $delta_total = $options{new_datas}->{$self->{instance} . '_time_waited_micro'} - $options{old_datas}->{$self->{instance} . '_time_waited_micro'}; $self->{result_values}->{prct_wait} = 100 * ($delta_total / 1000000) / $options{delta_time}; return 0; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'wait-time-min:s' => { name => 'wait_time_min', default => 1000 }, 'show-details' => { name => 'show_details' } }); return $self; } sub prefix_event_output { my ($self, %options) = @_; return "Event '" . $options{instance_value}->{display} . "' "; } sub event_count_and_details { my ($self, %options) = @_; my $query_count = "SELECT count(*) as NB FROM v\$session WHERE WAIT_TIME_MICRO>" . $self->{option_results}->{wait_time_min} . " AND status='ACTIVE' and WAIT_CLASS <>'Idle'"; $self->{sql}->query(query => $query_count); my $result = $self->{sql}->fetchrow_hashref(); $self->{event_count}->{count} = $result->{NB}; if (defined($self->{option_results}->{show_details})) { my $query_details = "SELECT a.username USERNAME, a.program PROGRAM, a.event EVENT, round(a.WAIT_TIME_MICRO/1000000,0) SEC_WAIT, d.sql_text SQL_TEXT FROM v\$session a, v\$sqlstats d WHERE a.sql_id = d.sql_id and a.status='ACTIVE' and a.wait_class <> 'Idle' and WAIT_TIME_MICRO>" . $self->{option_results}->{wait_time_min} . " and a.sid not in (SELECT SID FROM V\$SESSION WHERE audsid = userenv('SESSIONID')) ORDER BY a.WAIT_TIME_MICRO desc"; $self->{sql}->query(query => $query_details ); while (my $result = $self->{sql}->fetchrow_hashref()) { $self->{output}->output_add(long_msg => sprintf("Username: '%s', Program: '%s' Event: '%s', Second wait: '%s's, Details: '%s'\n", $result->{USERNAME}, $result->{PROGRAM}, $result->{EVENT}, $result->{SEC_WAIT}, $result->{SQL_TEXT})); } } } sub manage_selection { my ($self, %options) = @_; $self->{sql} = $options{sql}; $self->{sql}->connect(); my $query = q{ SELECT e.event#, e.name, NVL(s.total_waits, 0), NVL(s.total_timeouts, 0), NVL(s.time_waited, 0), NVL(s.time_waited_micro, 0), NVL(s.average_wait, 0) FROM v$event_name e LEFT JOIN sys.v_$system_event s ON e.name = s.event }; if ($self->{sql}->is_version_minimum(version => '10')) { $query = q{ SELECT e.event_id, e.name, NVL(s.total_waits, 0), NVL(s.total_timeouts, 0), NVL(s.time_waited, 0), NVL(s.time_waited_micro, 0), NVL(s.average_wait, 0) FROM v$event_name e LEFT JOIN sys.v_$system_event s ON e.name = s.event }; } $self->{sql}->query(query => $query); my $result = $self->{sql}->fetchall_arrayref(); $self->{event} = {}; foreach my $row (@$result) { my ($name, $total_waits, $time_waited_micro) = ($row->[1], $row->[2], $row->[5]); 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->{event}->{$name} = { display => $name, total_waits => $total_waits, time_waited_micro => $time_waited_micro }; } if ($self->{sql}->is_version_minimum(version => '10')) { $self->event_count_and_details(); } $self->{sql}->disconnect(); if (scalar(keys %{$self->{event}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No event found."); $self->{output}->option_exit(); } $self->{cache_name} = "oracle_" . $self->{mode} . '_' . $self->{sql}->get_unique_id4save() . '_' . (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 Oracle event wait usage. =over 8 =item B<--warning-*> Threshold warning. Can be: 'total-waits-sec', 'total-waits-time', 'event-count'. =item B<--critical-*> Threshold critical. Can be: 'total-waits-sec', 'total-waits-time', 'event-count'. =item B<--filter-name> Filter by event name. Can be a regex. =item B<--wait-time-min> Time in ms above which we count an event as waiting =item B<--show-details> Print details of waiting events (user, query, ...) in long output =back =cut centreon-plugins-20220113/database/oracle/mode/frausage.pm000066400000000000000000000110411417000230700233210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::oracle::mode::frausage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'file', type => 1, cb_prefix_output => 'prefix_file_output', message_multiple => 'All recovery areas are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{file} = [ { label => 'space-usage', nlabel => 'recoveryarea.space.usage.percentage', set => { key_values => [ { name => 'percent_space_usage' }, { name => 'display' } ], output_template => 'used : %.2f %%', perfdatas => [ { value => 'percent_space_usage', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'space-reclaimable', nlabel => 'recoveryarea.space.reclaimable.percentage', set => { key_values => [ { name => 'percent_space_reclaimable' }, { name => 'display' } ], output_template => 'reclaimable : %.2f %%', perfdatas => [ { value => 'percent_space_reclaimable', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } 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-type:s' => { name => 'filter_type' }, }); return $self; } sub prefix_file_output { my ($self, %options) = @_; return "File type '" . $options{instance_value}->{display} . "' recovery area "; } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); if ($options{sql}->is_version_minimum(version => '11')) { $options{sql}->query(query => q{ SELECT file_type, percent_space_used, percent_space_reclaimable FROM v$recovery_area_usage }); } else { $options{sql}->query(query => q{ SELECT name, space_used, space_reclaimable, space_limit FROM v$recovery_file_dest }); } my $result = $options{sql}->fetchall_arrayref(); $options{sql}->disconnect(); $self->{file} = {}; foreach my $row (@$result) { if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' && $row->[0] !~ /$self->{option_results}->{filter_type}/i) { $self->{output}->output_add(long_msg => "skipping '" . $row->[0] . "': no matching filter.", debug => 1); next; } $self->{file}->{$row->[0]} = { display => $row->[0] }; if ($options{sql}->is_version_minimum(version => '11')) { $self->{file}->{$row->[0]}->{percent_space_usage} = $row->[1]; $self->{file}->{$row->[0]}->{percent_space_reclaimable} = $row->[2]; } else { $self->{file}->{$row->[0]}->{percent_space_usage} = $row->[1] * 100 / $row->[3]; $self->{file}->{$row->[0]}->{percent_space_reclaimable} = $row->[2] * 100 / $row->[3]; } } if (scalar(keys %{$self->{file}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No file type found"); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check fast recovery area space usage =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). =item B<--filter-type> Filter file type (can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'space-usage', 'space-reclaimable'. =back =cut centreon-plugins-20220113/database/oracle/mode/invalidobject.pm000066400000000000000000000154231417000230700243510ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::oracle::mode::invalidobject; 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, cb_prefix_output => 'prefix_invalid_output', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ { label => 'objects', set => { key_values => [ { name => 'invalid_objects' } ], output_template => 'objects : %s', perfdatas => [ { label => 'invalid_objects', value => 'invalid_objects', template => '%d', min => 0 }, ], } }, { label => 'indexes', set => { key_values => [ { name => 'invalid_indexes' } ], output_template => 'indexes : %s', perfdatas => [ { label => 'invalid_indexes', value => 'invalid_indexes', template => '%d', min => 0 }, ], } }, { label => 'ind-partitions', set => { key_values => [ { name => 'invalid_ind_partitions' } ], output_template => 'index partitions : %s', perfdatas => [ { label => 'invalid_ind_partitions', value => 'invalid_ind_partitions', template => '%d', min => 0 }, ], } }, { label => 'ind-subpartitions', set => { key_values => [ { name => 'invalid_ind_subpartitions' } ], output_template => 'index subpartitions : %s', perfdatas => [ { label => 'invalid_ind_subpartitions', value => 'invalid_ind_subpartitions', template => '%d', min => 0 }, ], } }, { label => 'registry-components', set => { key_values => [ { name => 'invalid_registry_components' } ], output_template => 'registry components : %s', perfdatas => [ { label => 'invalid_registry_components', value => 'invalid_registry_components', template => '%d', min => 0 }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-message:s" => { name => 'filter_message' }, "retention-objects:s" => { name => 'retention_objects', default => 3 }, }); return $self; } sub prefix_invalid_output { my ($self, %options) = @_; return "Invalid "; } sub get_invalids { my ($self, %options) = @_; $self->{global}->{$options{type}} = 0; $options{sql}->query(query => $options{query}); my $result = $options{sql}->fetchall_arrayref(); foreach (@$result) { if (defined($self->{option_results}->{filter_message}) && $self->{option_results}->{filter_message} ne '' && $_->[0] !~ /$self->{option_results}->{filter_message}/) { $self->{output}->output_add(long_msg => "skipping $options{type} => '" . $_->[0] . "': no matching filter.", debug => 1); next; } $self->{global}->{$options{type}}++; } } sub manage_selection { my ($self, %options) = @_; $self->{global} = {}; $options{sql}->connect(); $self->get_invalids(%options, type => 'invalid_objects', query => q{ SELECT O.object_type||' '||O.owner||'.'||O.object_name||' is '||O.status FROM dba_objects O LEFT OUTER JOIN DBA_MVIEW_refresh_times V ON O.object_name = V.NAME AND O.owner = V.owner WHERE (LAST_REFRESH <= (SELECT sysdate - } . $self->{option_results}->{retention_objects} . q{ FROM dual) OR LAST_REFRESH is null) AND STATUS = 'INVALID' AND O.object_name NOT LIKE 'BIN$%' }); $self->get_invalids(%options, type => 'invalid_indexes', query => q{ SELECT index_type||' index '||owner||'.'||index_name||' of '||table_owner||'.'||table_name||' is '||status FROM dba_indexes WHERE status <> 'VALID' AND status <> 'N/A' }); $self->get_invalids(%options, type => 'invalid_ind_partitions', query => q{ SELECT partition_name||' of '||index_owner||'.'||index_name||' is '||status FROM dba_ind_partitions WHERE status <> 'USABLE' AND status <> 'N/A' }); if ($options{sql}->is_version_minimum(version => '10.x')) { $self->get_invalids(%options, type => 'invalid_ind_subpartitions', query => q{ SELECT subpartition_name||' of '||partition_name||' of '||index_owner||'.'||index_name||' is '||status FROM dba_ind_subpartitions WHERE status <> 'USABLE' AND status <> 'N/A' }); } if ($options{sql}->is_version_minimum(version => '10.x')) { $self->get_invalids(%options, type => 'invalid_registry_components', query => q{ SELECT namespace||'.'||comp_name||'-'||version||' is '||status FROM dba_registry WHERE status <> 'VALID' AND status <> 'OPTION OFF' }); } else { $self->get_invalids(%options, type => 'invalid_registry_components', query => q{ SELECT 'SCHEMA.'||comp_name||'-'||version||' is '||status FROM dba_registry WHERE status <> 'VALID' AND status <> 'OPTION OFF' }); } $options{sql}->disconnect(); } 1; __END__ =head1 MODE Check faulty objects, indices, partitions. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^indexes$' =item B<--retention-objects> Retention in days for invalid objects (default : 3). =item B<--filter-message> Filter by message (can be a regexp). =item B<--warning-*> Threshold warning. Can be: 'objects', 'indexes', 'ind-partitions', 'ind-subpartitions', 'registry-components'. =item B<--critical-*> Threshold critical. Can be: 'objects', 'indexes', 'ind-partitions', 'ind-subpartitions', 'registry-components'. =back =cut centreon-plugins-20220113/database/oracle/mode/librarycacheusage.pm000066400000000000000000000124161417000230700252100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::oracle::mode::librarycacheusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); sub custom_pin_hitratio_calc { my ($self, %options) = @_; my $delta_total = ($options{new_datas}->{$self->{instance} . '_pins'} - $options{old_datas}->{$self->{instance} . '_pins'}); my $delta_cache = ($options{new_datas}->{$self->{instance} . '_pin_hits'} - $options{old_datas}->{$self->{instance} . '_pin_hits'}); $self->{result_values}->{hit_ratio} = $delta_total ? (100 * $delta_cache / $delta_total) : 0; return 0; } sub custom_get_hitratio_calc { my ($self, %options) = @_; my $delta_total = ($options{new_datas}->{$self->{instance} . '_gets'} - $options{old_datas}->{$self->{instance} . '_gets'}); my $delta_cache = ($options{new_datas}->{$self->{instance} . '_get_hits'} - $options{old_datas}->{$self->{instance} . '_get_hits'}); $self->{result_values}->{hit_ratio} = $delta_total ? (100 * $delta_cache / $delta_total) : 0; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', cb_prefix_output => 'prefix_global_output', type => 0 }, ]; $self->{maps_counters}->{global} = [ { label => 'get-hits', nlabel => 'library.cache.get.hitratio.percentage', set => { key_values => [ { name => 'get_hits', diff => 1 }, { name => 'gets', diff => 1 } ], closure_custom_calc => $self->can('custom_get_hitratio_calc'), output_template => 'get hit ratio %.2f%%', output_use => 'hit_ratio', threshold_use => 'hit_ratio', perfdatas => [ { label => 'get_hit_ratio', value => 'hit_ratio', template => '%.2f', min => 0, max => 100, unit => '%' }, ], } }, { label => 'pin-hits', nlabel => 'library.cache.pin.hitratio.percentage', set => { key_values => [ { name => 'pin_hits', diff => 1 }, { name => 'pins', diff => 1 } ], closure_custom_calc => $self->can('custom_pin_hitratio_calc'), output_template => 'pin hit ratio %.2f%%', output_use => 'hit_ratio', threshold_use => 'hit_ratio', perfdatas => [ { label => 'pin_hit_ratio', value => 'hit_ratio', template => '%.2f', min => 0, max => 100, unit => '%' }, ], } }, { label => 'reloads', nlabel => 'library.cache.reloads.persecond', set => { key_values => [ { name => 'reloads', per_second => 1 }, ], output_template => 'reloads %.2f/s', perfdatas => [ { label => 'reloads', template => '%.2f', min => 0, unit => '/s' }, ], } }, { label => 'invalids', nlabel => 'library.cache.invalids.persecond', set => { key_values => [ { name => 'invalids', per_second => 1 }, ], output_template => 'invalids %.2f/s', perfdatas => [ { label => 'invalids', template => '%.2f', min => 0, unit => '/s' }, ], } } ]; } sub prefix_global_output { my ($self, %options) = @_; return 'SGA library cache '; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $query = q{ SELECT SUM(gethits), SUM(gets), SUM(pinhits), SUM(pins), SUM(reloads), SUM(invalidations) FROM v$librarycache }; $options{sql}->connect(); $options{sql}->query(query => $query); my @result = $options{sql}->fetchrow_array(); $options{sql}->disconnect(); $self->{global} = { get_hits => $result[0], gets => $result[1], pin_hits => $result[2], pins => $result[3], reloads => $result[4], invalids => $result[5], }; $self->{cache_name} = "oracle_" . $self->{mode} . '_' . $options{sql}->get_unique_id4save() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check Oracle library cache usage. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'get-hits', 'pin-hits', 'reloads', 'invalid'. =back =cut centreon-plugins-20220113/database/oracle/mode/listasmdiskgroups.pm000066400000000000000000000055141417000230700253230ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::oracle::mode::listasmdiskgroups; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::misc; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{sql}->connect(); $self->{sql}->query(query => q{ SELECT name, state, type FROM V$ASM_DISKGROUP }); $self->{list_dg} = {}; my $result = $self->{sql}->fetchall_arrayref(); foreach my $row (@$result) { $self->{list_dg}->{$row->[0]} = { state => $row->[1], type => $row->[2], }; } $self->{sql}->disconnect(); } sub run { my ($self, %options) = @_; $self->{sql} = $options{sql}; $self->manage_selection(); foreach my $name (sort keys %{$self->{list_dg}}) { $self->{output}->output_add(long_msg => '[name = ' . $name . '] ' . '[state = ' . $self->{list_dg}->{$name}->{state} . '] ' . '[type = ' . $self->{list_dg}->{$name}->{type} . '] ' ); } $self->{output}->output_add(severity => 'OK', short_msg => "List of asm disk groups:"); $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', 'type']); } sub disco_show { my ($self, %options) = @_; $self->{sql} = $options{sql}; $self->manage_selection(); foreach my $name (sort keys %{$self->{list_dg}}) { $self->{output}->add_disco_entry( name => $name, state => $self->{list_dg}->{$name}->{state}, type => $self->{list_dg}->{$name}->{type} ); } } 1; __END__ =head1 MODE List asm diskgroup. =over 8 =back =cut centreon-plugins-20220113/database/oracle/mode/listtablespaces.pm000066400000000000000000000337321417000230700247210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::oracle::mode::listtablespaces; use base qw(centreon::plugins::mode); use strict; use warnings; my $order = ['name', 'total', 'free', 'used', 'prct_used', 'type', 'status']; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-tablespace:s' => { name => 'filter_tablespace' }, 'notemp' => { name => 'notemp' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); # request from check_oracle_health. my $query; if ($options{sql}->is_version_minimum(version => '11')) { $query = sprintf( q{ SELECT tum.tablespace_name "Tablespace", t.status "Status", t.contents "Type", t.extent_management "Extent Mgmt", tum.used_space*t.block_size bytes, tum.tablespace_size*t.block_size bytes_max FROM DBA_TABLESPACE_USAGE_METRICS tum INNER JOIN dba_tablespaces t on tum.tablespace_name=t.tablespace_name %s }, defined($self->{option_results}->{notemp}) ? "WHERE (t.contents != 'TEMPORARY' AND t.contents != 'UNDO')" : '' ); } elsif ($options{sql}->is_version_minimum(version => '9')) { my $tbs_sql_undo = q{ SELECT tablespace_name, bytes_expired FROM ( SELECT a.tablespace_name, SUM (a.bytes) bytes_expired, a.status FROM dba_undo_extents a GROUP BY tablespace_name, status ) WHERE status = 'EXPIRED' }; my $tbs_sql_undo_empty = q{ SELECT NULL AS tablespace_name, NULL AS bytes_expired FROM DUAL }; my $tbs_sql_temp = q{ UNION ALL SELECT d.tablespace_name "Tablespace", b.status "Status", b.contents "Type", b.extent_management "Extent Mgmt", sum(a.bytes_free + a.bytes_used) bytes, -- allocated SUM(DECODE(d.autoextensible, 'YES', d.maxbytes, 'NO', d.bytes)) bytes_max, SUM(a.bytes_free + a.bytes_used - NVL(c.bytes_used, 0)) bytes_free FROM sys.v_$TEMP_SPACE_HEADER a, sys.dba_tablespaces b, sys.v_$Temp_extent_pool c, dba_temp_files d WHERE c.file_id(+) = a.file_id and c.tablespace_name(+) = a.tablespace_name and d.file_id = a.file_id and d.tablespace_name = a.tablespace_name and b.tablespace_name = a.tablespace_name GROUP BY b.status, b.contents, b.extent_management, d.tablespace_name ORDER BY 1 }; $query = sprintf( q{ SELECT /*+ opt_param('optimizer_adaptive_features','false') */ a.tablespace_name "Tablespace", b.status "Status", b.contents "Type", b.extent_management "Extent Mgmt", a.bytes bytes, a.maxbytes bytes_max, c.bytes_free + NVL(d.bytes_expired,0) bytes_free FROM ( -- belegter und maximal verfuegbarer platz pro datafile -- nach tablespacenamen zusammengefasst -- => bytes -- => maxbytes SELECT a.tablespace_name, SUM(a.bytes) bytes, SUM(DECODE(a.autoextensible, 'YES', a.maxbytes, 'NO', a.bytes)) maxbytes FROM dba_data_files a GROUP BY tablespace_name ) a, sys.dba_tablespaces b, ( -- freier platz pro tablespace -- => bytes_free SELECT a.tablespace_name, SUM(a.bytes) bytes_free FROM dba_free_space a GROUP BY tablespace_name ) c, ( %s ) d WHERE a.tablespace_name = c.tablespace_name (+) AND a.tablespace_name = b.tablespace_name AND a.tablespace_name = d.tablespace_name (+) %s %s }, defined($self->{option_results}->{notemp}) ? $tbs_sql_undo_empty : $tbs_sql_undo, defined($self->{option_results}->{notemp}) ? "AND (b.contents != 'TEMPORARY' AND b.contents != 'UNDO')" : '', defined($self->{option_results}->{notemp}) ? "" : $tbs_sql_temp ); } elsif ($options{sql}->is_version_minimum(version => '8')) { $query = q{SELECT a.tablespace_name "Tablespace", b.status "Status", b.contents "Type", b.extent_management "Extent Mgmt", a.bytes bytes, a.maxbytes bytes_max, c.bytes_free bytes_free FROM ( -- belegter und maximal verfuegbarer platz pro datafile -- nach tablespacenamen zusammengefasst -- => bytes -- => maxbytes SELECT a.tablespace_name, SUM(a.bytes) bytes, SUM(DECODE(a.autoextensible, 'YES', a.maxbytes, 'NO', a.bytes)) maxbytes FROM dba_data_files a GROUP BY tablespace_name ) a, sys.dba_tablespaces b, ( -- freier platz pro tablespace -- => bytes_free SELECT a.tablespace_name, SUM(a.bytes) bytes_free FROM dba_free_space a GROUP BY tablespace_name ) c WHERE a.tablespace_name = c.tablespace_name (+) AND a.tablespace_name = b.tablespace_name AND (b.contents = 'PERMANENT' OR (b.contents <> 'PERMANENT' AND a.tablespace_name=(select value from v$parameter where name='undo_tablespace'))) UNION ALL SELECT a.tablespace_name "Tablespace", b.status "Status", b.contents "Type", b.extent_management "Extent Mgmt", sum(a.bytes_free + a.bytes_used) bytes, -- allocated d.maxbytes bytes_max, SUM(a.bytes_free + a.bytes_used - NVL(c.bytes_used, 0)) bytes_free FROM sys.v_$TEMP_SPACE_HEADER a, sys.dba_tablespaces b, sys.v_$Temp_extent_pool c, dba_temp_files d WHERE c.file_id(+) = a.file_id and c.tablespace_name(+) = a.tablespace_name and d.file_id = a.file_id and d.tablespace_name = a.tablespace_name and b.tablespace_name = a.tablespace_name GROUP BY a.tablespace_name, b.status, b.contents, b.extent_management, d.maxbytes ORDER BY 1 }; } else { $query = q{ SELECT a.tablespace_name "Tablespace", b.status "Status", b.contents "Type", 'DICTIONARY' "Extent Mgmt", a.bytes bytes, a.maxbytes bytes_max, c.bytes_free bytes_free FROM ( -- belegter und maximal verfuegbarer platz pro datafile -- nach tablespacenamen zusammengefasst -- => bytes -- => maxbytes SELECT a.tablespace_name, SUM(a.bytes) bytes, SUM(a.bytes) maxbytes FROM dba_data_files a GROUP BY tablespace_name ) a, sys.dba_tablespaces b, ( -- freier platz pro tablespace -- => bytes_free SELECT a.tablespace_name, SUM(a.bytes) bytes_free FROM dba_free_space a GROUP BY tablespace_name ) c WHERE a.tablespace_name = c.tablespace_name (+) AND a.tablespace_name = b.tablespace_name }; } $options{sql}->query(query => $query); my $result = $options{sql}->fetchall_arrayref(); my $tablespaces = {}; foreach my $row (@$result) { my ($name, $status, $type, $extentmgmt, $bytes, $bytes_max, $bytes_free) = @$row; if (defined($self->{option_results}->{notemp}) && ($type eq 'UNDO' || $type eq 'TEMPORARY')) { $self->{output}->output_add(long_msg => "skipping '" . $name . "': temporary or undo.", debug => 1); next; } if (defined($self->{option_results}->{filter_tablespace}) && $self->{option_results}->{filter_tablespace} ne '' && $name !~ /$self->{option_results}->{filter_tablespace}/) { $self->{output}->output_add(long_msg => "skipping '" . $name . "': no matching filter.", debug => 1); next; } if (!defined($bytes)) { # seems corrupted, cannot get value $self->{output}->output_add(long_msg => sprintf("tbs '%s' cannot get data", $name), debug => 1); next; } if (defined($self->{option_results}->{skip}) && $status eq 'OFFLINE') { $self->{output}->output_add(long_msg => "skipping '" . $name . "': tbs is offline", debug => 1); next; } my ($percent_used, $percent_free, $used, $free, $size); if ($options{sql}->is_version_minimum(version => '11')) { $percent_used = $bytes / $bytes_max * 100; $size = $bytes_max; $free = $bytes_max - $bytes; $used = $bytes; } elsif ((!defined($bytes_max)) || ($bytes_max eq '')) { $self->{output}->output_add(long_msg => "skipping '" . $name . "': bytes max not defined.", debug => 1); next; } elsif ($bytes_max > $bytes) { $percent_used = ($bytes - $bytes_free) / $bytes_max * 100; $size = $bytes_max; $free = $bytes_free + ($bytes_max - $bytes); $used = $size - $free; } else { $percent_used = ($bytes - $bytes_free) / $bytes * 100; $size = $bytes; $free = $bytes_free; $used = $size - $free; } $tablespaces->{$name} = { used => $used, free => $free, total => $size, prct_used => $percent_used, name => $name, type => $type, status => $status }; } $options{sql}->disconnect(); return $tablespaces; } sub run { my ($self, %options) = @_; my $tablespaces = $self->manage_selection(%options); foreach (sort keys %$tablespaces) { my $entry = ''; foreach my $label (@$order) { $entry .= '[' . $label . ' = ' . $tablespaces->{$_}->{$label} . '] '; } $self->{output}->output_add(long_msg => $entry); } $self->{output}->output_add( severity => 'OK', short_msg => 'List tablespaces:' ); $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 => $order); } sub disco_show { my ($self, %options) = @_; my $tablespaces = $self->manage_selection(%options); foreach (sort keys %$tablespaces) { $self->{output}->add_disco_entry(%{$tablespaces->{$_}}); } } 1; __END__ =head1 MODE List oracle tablespaces. =over 8 =item B<--filter-tablespace> Filter tablespace by name. Can be a regex. =item B<--notemp> skip temporary or undo tablespaces. =back =cut centreon-plugins-20220113/database/oracle/mode/longqueries.pm000066400000000000000000000153661417000230700240770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::oracle::mode::longqueries; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::statefile; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("query [status: %s] [sql: %s] %s", $self->{result_values}->{status}, $self->{result_values}->{sql_text}, $self->{result_values}->{generation_time}); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; $self->{result_values}->{sql_text} = $options{new_datas}->{$self->{instance} . '_sql_text'}; $self->{result_values}->{username} = $options{new_datas}->{$self->{instance} . '_username'}; $self->{result_values}->{since} = $options{new_datas}->{$self->{instance} . '_since'}; $self->{result_values}->{generation_time} = $options{new_datas}->{$self->{instance} . '_generation_time'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'alarms', type => 2, message_multiple => '0 problem(s) detected', display_counter_problem => { label => 'alerts', min => 0 }, group => [ { name => 'alarm', skipped_code => { -11 => 1 } } ] } ]; $self->{maps_counters}->{alarm} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'sql_text' }, { name => 'since' }, { name => 'username' }, { name => 'generation_time' } ], 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 => \&catalog_status_threshold, } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning-status:s" => { name => 'warning_status', default => '' }, "critical-status:s" => { name => 'critical_status', default => '' }, "memory" => { name => 'memory' }, "timezone:s" => { name => 'timezone' }, }); centreon::plugins::misc::mymodule_load(output => $self->{output}, module => 'DateTime', error_msg => "Cannot load module 'DateTime'."); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->check_options(%options); } if (defined($self->{option_results}->{timezone}) && $self->{option_results}->{timezone} ne '') { $ENV{TZ} = $self->{option_results}->{timezone}; } } sub manage_selection { my ($self, %options) = @_; $self->{sql} = $options{sql}; $self->{sql}->connect(); if (!$self->{sql}->is_version_minimum(version => '11')) { $self->{output}->add_option_msg(short_msg => "Need oracle version >= 11"); $self->{output}->option_exit(); } $self->{alarms}->{global} = { alarm => {} }; my $query = q{ SELECT status, ((sql_exec_start - date '1970-01-01')*24*60*60) as sql_exec_start, elapsed_time FROM v$sql_monitor }; if ($self->{sql}->is_version_minimum(version => '12')) { $query = q{ SELECT status, ((sql_exec_start - date '1970-01-01')*24*60*60) as sql_exec_start, elapsed_time, username, sql_text FROM v$sql_monitor }; } $self->{sql}->query(query => $query); my $last_time; if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->read(statefile => "cache_oracle_" . $self->{mode} . $self->{sql}->get_unique_id4save()); $last_time = $self->{statefile_cache}->get(name => 'last_time'); } my ($i, $current_time) = (1, time()); while ((my @row = $self->{sql}->fetchrow_array())) { # can be: 1541985283,999999999999999999999999999996 $row[1] =~ s/,/./; my @values = localtime($row[1]); my $dt = DateTime->new( year => $values[5] + 1900, month => $values[4] + 1, day => $values[3], hour => $values[2], minute => $values[1], second => $values[0], time_zone => 'UTC', ); next if (defined($self->{option_results}->{memory}) && defined($last_time) && $last_time > $dt->epoch); $row[4] =~ s/(\n|\|)/-/ms if (defined($row[4])); my $since = $row[2] / 1000000; $self->{alarms}->{global}->{alarm}->{$i} = { status => $row[0], sql_text => defined($row[4]) ? $row[4] : '-', username => defined($row[5]) ? $row[5] : '-', since => $since, generation_time => centreon::plugins::misc::change_seconds(value => $since) }; $i++; } if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->write(data => { last_time => $current_time }); } $self->{sql}->disconnect(); } 1; __END__ =head1 MODE Check long sql queries. =over 8 =item B<--warning-status> Set warning threshold for status (Default: '') Can used special variables like: %{username}, %{sql_text}, %{since}, %{status} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{username}, %{sql_text}, %{since}, %{status} =item B<--timezone> Timezone of oracle server (If not set, we use current server execution timezone). =item B<--memory> Only check new queries. =back =cut centreon-plugins-20220113/database/oracle/mode/passwordexpiration.pm000066400000000000000000000123301417000230700254730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::oracle::mode::passwordexpiration; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::statefile; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("[username: %s] [account status: %s] expired in : %s", $self->{result_values}->{username}, $self->{result_values}->{account_status}, $self->{result_values}->{expire_time} ); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{account_status} = $options{new_datas}->{$self->{instance} . '_account_status'}; $self->{result_values}->{username} = $options{new_datas}->{$self->{instance} . '_username'}; $self->{result_values}->{expire} = $options{new_datas}->{$self->{instance} . '_expire'}; $self->{result_values}->{expire_time} = $options{new_datas}->{$self->{instance} . '_expire_time'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'users', type => 2, format_output => '%s user(s) detected', display_counter_problem => { label => 'users', min => 0 }, group => [ { name => 'user', skipped_code => { -11 => 1 } } ] } ]; $self->{maps_counters}->{user} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'username' }, { name => 'account_status' }, { name => 'expire' }, { name => 'expire_time' } ], 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 => \&catalog_status_threshold, } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning-status:s" => { name => 'warning_status', default => '' }, "critical-status:s" => { name => 'critical_status', default => '' }, "timezone:s" => { name => 'timezone' }, }); centreon::plugins::misc::mymodule_load(output => $self->{output}, module => 'DateTime', error_msg => "Cannot load module 'DateTime'."); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); $self->{users}->{global} = { user => {} }; my $query = q{ SELECT username, account_status, ((expiry_date - date '1970-01-01')*24*60*60) FROM dba_users WHERE expiry_date is not null AND account_status NOT LIKE '%EXPIRED%' }; $options{sql}->query(query => $query); my $tz = centreon::plugins::misc::set_timezone(name => $self->{option_results}->{timezone}); my $i = 1; while ((my @row = $options{sql}->fetchrow_array())) { # can be: 1541985283,999999999999999999999999999996 $row[2] =~ s/,/./; my @values = localtime($row[2]); my $dt = DateTime->new( year => $values[5] + 1900, month => $values[4] + 1, day => $values[3], hour => $values[2], minute => $values[1], second => $values[0], %$tz ); my $expire = abs(time() - $dt->epoch); $self->{users}->{global}->{user}->{$i} = { account_status => $row[1], username => $row[0], expire => $expire, expire_time => centreon::plugins::misc::change_seconds(value => $expire) }; $i++; } $options{sql}->disconnect(); } 1; __END__ =head1 MODE Check user password expiration. =over 8 =item B<--warning-status> Set warning threshold for status (Default: '') Can used special variables like: %{username}, %{account_status}, %{expire} =item B<--critical-status> Set critical threshold for status (Default: ''). Can used special variables like: %{username}, %{account_status}, %{expire} =item B<--timezone> Timezone of oracle server (If not set, we use current server execution timezone). =back =cut centreon-plugins-20220113/database/oracle/mode/processusage.pm000066400000000000000000000062671417000230700242450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::oracle::mode::processusage; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "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) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); $self->{sql}->query(query => q{SELECT current_utilization/limit_value*100 FROM v$resource_limit WHERE resource_name = 'processes'}); my $session = $self->{sql}->fetchrow_array(); $self->{sql}->disconnect(); my $exit_code = $self->{perfdata}->threshold_check(value => $session, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("%.2f%% of process resources used.", $session)); $self->{output}->perfdata_add(label => 'process_used', unit => '%', value => sprintf("%.2f", $session), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0, max => 100); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check Oracle process used. =over 8 =item B<--warning> Threshold warning. =item B<--critical> Threshold critical. =back =cut centreon-plugins-20220113/database/oracle/mode/redologusage.pm000066400000000000000000000077611417000230700242220ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::oracle::mode::redologusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); sub custom_get_hitratio_calc { my ($self, %options) = @_; my $delta_total = ($options{new_datas}->{$self->{instance} . '_redo_entries'} - $options{old_datas}->{$self->{instance} . '_redo_entries'}); my $delta_retry = ($options{new_datas}->{$self->{instance} . '_redo_buffer_alloc_retries'} - $options{old_datas}->{$self->{instance} . '_redo_buffer_alloc_retries'}); $self->{result_values}->{retry_ratio} = $delta_total ? (100 * $delta_retry / $delta_total) : 0; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', cb_prefix_output => 'prefix_global_output', type => 0 } ]; $self->{maps_counters}->{global} = [ { label => 'retry-ratio', nlabel => 'redolog.retry.ratio.percentage', set => { key_values => [ { name => 'redo_buffer_alloc_retries', diff => 1 }, { name => 'redo_entries', diff => 1 } ], closure_custom_calc => $self->can('custom_get_hitratio_calc'), output_template => 'retry ratio %.2f%%', output_use => 'retry_ratio', threshold_use => 'retry_ratio', perfdatas => [ { label => 'retry_ratio', value => 'retry_ratio', template => '%.2f', min => 0, max => 100, unit => '%' } ] } }, { label => 'traffic-io', nlabel => 'redolog.traffic.io.bytespersecond', set => { key_values => [ { name => 'redo_size', per_second => 1 } ], output_change_bytes => 1, output_template => 'traffic io %s %s/s', perfdatas => [ { label => 'traffic_io', template => '%s', min => 0, unit => 'B/s' } ] } } ]; } sub prefix_global_output { my ($self, %options) = @_; return 'Redo log '; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $query = q{ SELECT a.value, b.value, c.value FROM v$sysstat a, v$sysstat b, v$sysstat c WHERE a.name = 'redo buffer allocation retries' AND b.name = 'redo entries' AND c.name = 'redo size' }; $options{sql}->connect(); $options{sql}->query(query => $query); my @result = $options{sql}->fetchrow_array(); $options{sql}->disconnect(); $self->{global} = { redo_buffer_alloc_retries => $result[0], redo_entries => $result[1], redo_size => $result[2], }; $self->{cache_name} = "oracle_" . $self->{mode} . '_' . $options{sql}->get_unique_id4save() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check Oracle redo log usage. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'retry-ratio', 'traffic-io'. =back =cut centreon-plugins-20220113/database/oracle/mode/rmanbackupage.pm000066400000000000000000000204021417000230700243250ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::oracle::mode::rmanbackupage; use base qw(centreon::plugins::mode); use strict; use warnings; use DateTime; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'skip-no-backup' => { name => 'skip_no_backup', }, 'filter-type:s' => { name => 'filter_type', }, 'timezone:s' => { name => 'timezone', }, 'incremental-level' => { name => 'incremental_level', }, }); foreach (('db incr', 'db full', 'archivelog', 'controlfile')) { my $label = $_; $label =~ s/ /-/g; $options{options}->add_options(arguments => { 'warning-' . $label . ':s' => { name => 'warning-' . $label }, 'critical-' . $label . ':s' => { name => 'critical-' . $label }, 'no-' . $label => { name => 'no-' . $label }, }); } return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); foreach (('db incr', 'db full', 'archivelog', 'controlfile')) { my $label = $_; $label =~ s/ /-/g; foreach my $threshold (('warning', 'critical')) { if (($self->{perfdata}->threshold_validate(label => $threshold . '-' . $label, value => $self->{option_results}->{$threshold . '-' . $label})) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong " . $threshold . '-' . $label . " threshold '" . $self->{option_results}->{warning_db_incr} . "'."); $self->{output}->option_exit(); } } } if (defined($self->{option_results}->{timezone}) && $self->{option_results}->{timezone} ne '') { $ENV{TZ} = $self->{option_results}->{timezone}; } if (defined($self->{option_results}->{incremental_level})) { # the special request don't retrieve controlfiles. But controlfiles are saved with archivelog. $self->{option_results}->{'no-controlfile'} = 1; } } sub run { my ($self, %options) = @_; $options{sql}->connect(); my $query; if (defined($self->{option_results}->{incremental_level})) { $query = q{ SELECT v$rman_status.object_type, ((max(v$rman_status.start_time) - date '1970-01-01')*24*60*60) as last_time, SUM(v$backup_set_details.incremental_level) FROM v$rman_status LEFT JOIN v$backup_set_details ON v$rman_status.session_recid = v$backup_set_details.session_recid WHERE operation='BACKUP' GROUP BY object_type, v$backup_set_details.session_recid ORDER BY last_time DESC }; } else { $query = q{ SELECT object_type, ((max(start_time) - date '1970-01-01')*24*60*60) as last_time FROM v$rman_status WHERE operation='BACKUP' GROUP BY object_type }; } $options{sql}->query(query => $query); my $result = $options{sql}->fetchall_arrayref(); $options{sql}->disconnect(); $self->{output}->output_add( severity => 'OK', short_msg => sprintf("Rman backup age are ok.") ); my $count_backups = 0; my $already_checked = {}; foreach (('db full', 'db incr', 'archivelog', 'controlfile')) { my $executed = 0; my $label = $_; $label =~ s/ /-/g; foreach my $row (@$result) { if (defined($self->{option_results}->{incremental_level})) { # db incr with incremental level 0 = DB FULL if (/db full/ && $$row[0] =~ /db incr/i && (!defined($$row[2]) || $$row[2] == 0)) { # it's a full. we get $$row[0] = 'DB FULL'; } else { next if (/db incr/ && $$row[0] =~ /db incr/i && (!defined($$row[2]) || $$row[2] == 0)); # it's a full. we skip. next if ($$row[0] !~ /$_/i); } } else { next if ($$row[0] !~ /$_/i); } next if (defined($already_checked->{$$row[0]})); $already_checked->{$$row[0]} = 1; $count_backups++; $executed = 1; my ($type, $last_time) = @$row; next if (defined($self->{option_results}->{filter_type}) && $type !~ /$self->{option_results}->{filter_type}/); $last_time =~ s/,/./g; my @values = localtime($last_time); my $dt = DateTime->new( year => $values[5] + 1900, month => $values[4] + 1, day => $values[3], hour => $values[2], minute => $values[1], second => $values[0], time_zone => 'UTC' ); my $offset = $last_time - $dt->epoch; $last_time = $last_time + $offset; my $backup_age = time() - $last_time; my $backup_age_convert = centreon::plugins::misc::change_seconds(value => $backup_age); my $type_perfdata = $type; $type_perfdata =~ s/ /_/g; $self->{output}->output_add(long_msg => sprintf("Last Rman '%s' backups : %s", $type, $backup_age_convert)); $self->{output}->perfdata_add( label => sprintf('%s_backup_age', $type_perfdata), value => $backup_age, unit => 's', warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $label), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $label), min => 0 ); my $exit_code = $self->{perfdata}->threshold_check(value => $backup_age, threshold => [ { label => 'critical-' . $label, exit_litteral => 'critical' }, { label => 'warning-' . $label, exit_litteral => 'warning' } ]); if (!$self->{output}->is_status(value => $exit_code, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit_code, short_msg => sprintf("Last Rman '%s' backups : %s", $type, $backup_age_convert) ); } } if ($executed == 0 && !defined($self->{option_results}->{'no-' . $label})) { $self->{output}->output_add( severity => 'CRITICAL', short_msg => sprintf("Rman '%s' backups never executed", uc($_)) ); } } if (($count_backups == 0) && (!defined($self->{option_results}->{skip_no_backup}))) { $self->{output}->output_add( severity => 'CRITICAL', short_msg => sprintf("Rman backups never executed.") ); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check Oracle rman backup age. =over 8 =item B<--warning-*> Threshold warning in seconds. Can be: 'db-incr', 'db-full', 'archivelog', 'controlfile'. =item B<--critical-*> Threshold critical in seconds. Can be: 'db-incr', 'db-full', 'archivelog', 'controlfile'. =item B< --no-*> Skip error if never executed. Can be: 'db-incr', 'db-full', 'archivelog', 'controlfile'. =item B<--filter-type> Filter backup type. (type can be : 'DB INCR', 'DB FULL', 'ARCHIVELOG') =item B<--skip-no-backup> Return ok if no backup found. =item B<--timezone> Timezone of oracle server (If not set, we use current server execution timezone). =item B<--incremental-level> Please use the following option if your using incremental level 0 for full backup. =back =cut centreon-plugins-20220113/database/oracle/mode/rmanbackupproblems.pm000066400000000000000000000067771417000230700254370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::oracle::mode::rmanbackupproblems; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning:s" => { name => 'warning', }, "critical:s" => { name => 'critical', }, "retention:s" => { name => 'retention', default => 3 }, }); 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) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); my $retention = $self->{option_results}->{retention}; my $query = q{SELECT COUNT(*) FROM v$rman_status WHERE operation = 'BACKUP' AND status != 'COMPLETED' AND status != 'RUNNING' AND start_time > sysdate-} . $retention; $self->{sql}->query(query => $query); my $rman_backup_problems = $self->{sql}->fetchrow_array(); $self->{sql}->disconnect(); my $exit_code = $self->{perfdata}->threshold_check(value => $rman_backup_problems, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("rman had %i problems during the last %i days", $rman_backup_problems, $self->{option_results}->{retention})); $self->{output}->perfdata_add(label => 'rman_backup_problems', value => $rman_backup_problems, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check Oracle rman backup problems. =over 8 =item B<--warning> Threshold warning. =item B<--critical> Threshold critical. =item B<--retention> Retention in days (default : 3). =back =cut centreon-plugins-20220113/database/oracle/mode/rmanonlinebackupage.pm000066400000000000000000000105041417000230700255340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::oracle::mode::rmanonlinebackupage; use base qw(centreon::plugins::mode); use strict; use warnings; use DateTime; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'warning:s' => { name => 'warning' }, 'critical:s' => { name => 'critical' }, 'timezone:s' => { name => 'timezone' } }); 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}->{timezone}) && $self->{option_results}->{timezone} ne '') { $ENV{TZ} = $self->{option_results}->{timezone}; } } sub run { my ($self, %options) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); my $query = q{ SELECT min(((time - date '1970-01-01') * 86400)) as last_time FROM v$backup WHERE STATUS='ACTIVE' }; $self->{sql}->query(query => $query); my $result = $self->{sql}->fetchall_arrayref(); $self->{sql}->disconnect(); $self->{output}->output_add( severity => 'OK', short_msg => sprintf("Backup online modes are ok.") ); foreach my $row (@$result) { next if (!defined($$row[0])); my $last_time = $$row[0]; my @values = localtime($last_time); my $dt = DateTime->new( year => $values[5] + 1900, month => $values[4] + 1, day => $values[3], hour => $values[2], minute => $values[1], second => $values[0], time_zone => 'UTC' ); my $offset = $last_time - $dt->epoch; $last_time = $last_time + $offset; my $launched = time() - $last_time; my $launched_convert = centreon::plugins::misc::change_seconds(value => $launched); $self->{output}->output_add( long_msg => sprintf( "backup online mode since %s (%s)", $launched_convert, localtime($last_time) ) ); my $exit_code = $self->{perfdata}->threshold_check(value => $launched, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); if (!$self->{output}->is_status(value => $exit_code, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit_code, short_msg => sprintf("backup online mode since %s (%s)", $launched_convert, localtime($last_time)) ); } } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check Oracle backup online mode. =over 8 =item B<--warning> Threshold warning in seconds. =item B<--critical> Threshold critical in seconds. =item B<--timezone> Timezone of oracle server (If not set, we use current server execution timezone) =back =cut centreon-plugins-20220113/database/oracle/mode/rollbacksegmentusage.pm000066400000000000000000000147641417000230700257440ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::oracle::mode::rollbacksegmentusage; 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 => 'segment', type => 0, cb_prefix_output => 'prefix_output' }, ]; $self->{maps_counters}->{segment} = [ { label => 'extends', set => { key_values => [ { name => 'extends', per_second => 1 } ], output_template => 'Extends : %.2f/s', perfdatas => [ { label => 'extends', template => '%.2f', unit => '/s', min => 0 }, ], } }, { label => 'wraps', set => { key_values => [ { name => 'wraps', per_second => 1 } ], output_template => 'Wraps : %.2f/s', perfdatas => [ { label => 'wraps', template => '%.2f', unit => '/s', min => 0 }, ], } }, { label => 'header-contention', set => { key_values => [ { name => 'undoheader', diff => 1 }, { name => 'complete', diff => 1 } ], closure_custom_calc => $self->can('custom_contention_calc'), closure_custom_calc_extra_options => { label_ref => 'header' }, output_template => 'Header Contention : %.2f %%', output_use => 'header_prct', threshold_use => 'header_prct', perfdatas => [ { label => 'header_contention', value => 'header_prct', template => '%.2f', min => 0, max => 100, unit => '%' }, ], } }, { label => 'block-contention', set => { key_values => [ { name => 'undoblock', diff => 1 }, { name => 'complete', diff => 1 } ], closure_custom_calc => $self->can('custom_contention_calc'), closure_custom_calc_extra_options => { label_ref => 'block' }, output_template => 'Block Contention : %.2f %%', output_use => 'block_prct', threshold_use => 'block_prct', perfdatas => [ { label => 'block_contention', value => 'block_prct', template => '%.2f', min => 0, max => 100, unit => '%' }, ], } }, { label => 'hit-ratio', set => { key_values => [ { name => 'waits', diff => 1 }, { name => 'gets', diff => 1 } ], closure_custom_calc => $self->can('custom_hitratio_calc'), output_template => 'gets/waits Ratio : %.2f %%', output_use => 'hit_ratio', threshold_use => 'hit_ratio', perfdatas => [ { label => 'hit_ratio', value => 'hit_ratio', template => '%.2f', min => 0, max => 100, unit => '%' }, ], } }, ]; } sub custom_hitratio_calc { my ($self, %options) = @_; my $delta_waits = $options{new_datas}->{$self->{instance} . '_waits'} - $options{old_datas}->{$self->{instance} . '_waits'}; my $delta_gets = $options{new_datas}->{$self->{instance} . '_gets'} - $options{old_datas}->{$self->{instance} . '_gets'}; $self->{result_values}->{hit_ratio} = $delta_gets == 0 ? 100 : (100 - 100 * $delta_waits / $delta_gets); return 0; } sub custom_contention_calc { my ($self, %options) = @_; my $delta_waits = $options{new_datas}->{$self->{instance} . '_complete'} - $options{old_datas}->{$self->{instance} . '_complete'}; my $delta_undo = $options{new_datas}->{$self->{instance} . '_undo' . $options{extra_options}->{label_ref}} - $options{old_datas}->{$self->{instance} . '_undo' . $options{extra_options}->{label_ref}}; $self->{result_values}->{$options{extra_options}->{label_ref} . '_prct'} = $delta_waits == 0 ? 0 : (100 * $delta_undo / $delta_waits); return 0; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub prefix_output { my ($self, %options) = @_; return "Rollback Segment "; } sub manage_selection { my ($self, %options) = @_; $self->{sql} = $options{sql}; $self->{sql}->connect(); my $query = q{ SELECT SUM(waits), SUM(gets), SUM(extends), SUM(wraps) FROM v$rollstat }; $self->{sql}->query(query => $query); my @result = $self->{sql}->fetchrow_array(); $self->{segment} = { waits => $result[0], gets => $result[1], extends => $result[2], wraps => $result[3] }; $query = q{ SELECT ( SELECT SUM(count) FROM v$waitstat WHERE class = 'undo header' OR class = 'system undo header' ) undoheader, ( SELECT SUM(count) FROM v$waitstat WHERE class = 'undo block' OR class = 'system undo block' ) undoblock, ( SELECT SUM(count) FROM v$waitstat ) complete FROM DUAL }; $self->{sql}->query(query => $query); @result = $self->{sql}->fetchrow_array(); $self->{segment}->{undoheader} = $result[0]; $self->{segment}->{undoblock} = $result[1]; $self->{segment}->{complete} = $result[2]; $self->{cache_name} = "oracle_" . $self->{mode} . '_' . $self->{sql}->get_unique_id4save() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); $self->{sql}->disconnect(); } 1; __END__ =head1 MODE Check Oracle rollback segment usage. =over 8 =item B<--warning-*> Threshold warning. Can be: 'header-contention', 'block-contention', 'hit-ratio', 'extends', 'wraps'. =item B<--critical-*> Threshold critical. Can be: 'header-contention', 'block-contention', 'hit-ratio', 'extends', 'wraps'. =back =cut centreon-plugins-20220113/database/oracle/mode/sessionusage.pm000066400000000000000000000063171417000230700242460ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::oracle::mode::sessionusage; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "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) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); $self->{sql}->query(query => q{SELECT current_utilization/limit_value*100 FROM v$resource_limit WHERE resource_name = 'sessions'}); my $session = $self->{sql}->fetchrow_array(); $self->{sql}->disconnect(); $session =~ s/,/./g; my $exit_code = $self->{perfdata}->threshold_check(value => $session, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("%.2f%% of session resources used.", $session)); $self->{output}->perfdata_add(label => 'session_used', unit => '%', value => sprintf("%.2f", $session), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0, max => 100); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check Oracle session used. =over 8 =item B<--warning> Threshold warning. =item B<--critical> Threshold critical. =back =cut centreon-plugins-20220113/database/oracle/mode/tablespaceusage.pm000066400000000000000000000604201417000230700246610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::oracle::mode::tablespaceusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'tablespace', type => 1, cb_prefix_output => 'prefix_tablespace_output', message_multiple => 'All tablespaces are OK' }, ]; $self->{maps_counters}->{tablespace} = [ { label => 'tablespace', set => { key_values => [ { name => 'prct_used' }, { name => 'used' }, { name => 'free' }, { name => 'total' }, { name => 'display' } ], closure_custom_calc => \&custom_usage_calc, closure_custom_output => \&custom_usage_output, closure_custom_perfdata => \&custom_usage_perfdata, closure_custom_threshold_check => \&custom_usage_threshold, } }, ]; } sub custom_usage_perfdata { my ($self, %options) = @_; my $label = 'tbs_' . $self->{result_values}->{display} . '_usage'; my $value_perf = $self->{result_values}->{used}; if (defined($self->{instance_mode}->{option_results}->{free})) { $label = 'tbs_' . $self->{result_values}->{display} . '_free'; $value_perf = $self->{result_values}->{free}; } my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } $self->{output}->perfdata_add( label => $label, unit => 'B', instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, 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} ); } sub custom_usage_threshold { my ($self, %options) = @_; my ($exit, $threshold_value); $threshold_value = $self->{result_values}->{used}; $threshold_value = $self->{result_values}->{free} if (defined($self->{instance_mode}->{option_results}->{free})); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; $threshold_value = $self->{result_values}->{prct_free} if (defined($self->{instance_mode}->{option_results}->{free})); } $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel}, 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("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}->{prct_used} = $options{new_datas}->{$self->{instance} . '_prct_used'}; $self->{result_values}->{free} = $options{new_datas}->{$self->{instance} . '_free'}; $self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used}; return 0; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-tablespace:s' => { name => 'filter_tablespace' }, 'units:s' => { name => 'units', default => '%' }, 'free' => { name => 'free' }, 'skip' => { name => 'skip' }, 'notemp' => { name => 'notemp' }, 'add-container' => { name => 'add_container' }, }); return $self; } sub prefix_tablespace_output { my ($self, %options) = @_; return "Tablespace '" . $options{instance_value}->{display} . "' "; } sub manage_container { my ($self, %options) = @_; return if (!defined($self->{option_results}->{add_container})); # request from check_oracle_health. return if (!$self->{sql}->is_version_minimum(version => '9')); my $tbs_sql_undo = q{ -- freier platz durch expired extents -- speziell fuer undo tablespaces -- => bytes_expired SELECT tablespace_name, bytes_expired, con_id FROM ( SELECT tablespace_name, SUM (bytes) bytes_expired, status, con_id FROM cdb_undo_extents GROUP BY con_id, tablespace_name, status ) WHERE status = 'EXPIRED' }; my $tbs_sql_undo_empty = q{ SELECT NULL AS tablespace_name, NULL AS bytes_expired, NULL AS con_id FROM DUAL }; my $tbs_sql_temp = q{ UNION ALL SELECT e.name||'_'||b.tablespace_name "Tablespace", b.status "Status", b.contents "Type", b.extent_management "Extent Mgmt", sum(a.bytes_free + a.bytes_used) bytes, -- allocated SUM(DECODE(d.autoextensible, 'YES', d.maxbytes, 'NO', d.bytes)) bytes_max, SUM(a.bytes_free + a.bytes_used - NVL(c.bytes_used, 0)) bytes_free FROM sys.v_$TEMP_SPACE_HEADER a, -- has con_id sys.cdb_tablespaces b, -- has con_id sys.v_$Temp_extent_pool c, cdb_temp_files d, -- has con_id v$containers e WHERE a.file_id = c.file_id(+) AND a.file_id = d.file_id AND a.tablespace_name = c.tablespace_name(+) AND a.tablespace_name = d.tablespace_name AND a.tablespace_name = b.tablespace_name AND a.con_id = c.con_id(+) AND a.con_id = d.con_id AND a.con_id = b.con_id AND a.con_id = e.con_id GROUP BY e.name, b.con_id, b.status, b.contents, b.extent_management, b.tablespace_name ORDER BY 1 }; my $query = sprintf( q{ SELECT /*+ opt_param('optimizer_adaptive_features','false') */ e.name||'_'||a.tablespace_name "Tablespace", b.status "Status", b.contents "Type", b.extent_management "Extent Mgmt", a.bytes bytes, a.maxbytes bytes_max, c.bytes_free + NVL(d.bytes_expired,0) bytes_free FROM ( -- belegter und maximal verfuegbarer platz pro datafile -- nach tablespacenamen zusammengefasst -- => bytes -- => maxbytes SELECT a.con_id, a.tablespace_name, SUM(a.bytes) bytes, SUM(DECODE(a.autoextensible, 'YES', a.maxbytes, 'NO', a.bytes)) maxbytes FROM cdb_data_files a GROUP BY con_id, tablespace_name ) a, sys.cdb_tablespaces b, ( -- freier platz pro tablespace -- => bytes_free SELECT a.con_id, a.tablespace_name, SUM(a.bytes) bytes_free FROM cdb_free_space a GROUP BY con_id, tablespace_name ) c, ( %s ) d, v$containers e WHERE a.tablespace_name = c.tablespace_name (+) AND a.tablespace_name = b.tablespace_name AND a.tablespace_name = d.tablespace_name (+) AND a.con_id = c.con_id(+) AND a.con_id = b.con_id AND a.con_id = d.con_id(+) AND a.con_id = e.con_id %s %s }, defined($self->{option_results}->{notemp}) ? $tbs_sql_undo_empty : $tbs_sql_undo, defined($self->{option_results}->{notemp}) ? "AND (b.contents != 'TEMPORARY' AND b.contents != 'UNDO')" : '', defined($self->{option_results}->{notemp}) ? "" : $tbs_sql_temp ); $self->{sql}->query(query => $query); my $result = $self->{sql}->fetchall_arrayref(); foreach my $row (@$result) { my ($name, $status, $type, $extentmgmt, $bytes, $bytes_max, $bytes_free) = @$row; if (defined($self->{option_results}->{notemp}) && ($type eq 'UNDO' || $type eq 'TEMPORARY')) { $self->{output}->output_add(long_msg => "skipping '" . $name . "': temporary or undo.", debug => 1); next; } if (defined($self->{option_results}->{filter_tablespace}) && $self->{option_results}->{filter_tablespace} ne '' && $name !~ /$self->{option_results}->{filter_tablespace}/) { $self->{output}->output_add(long_msg => "skipping '" . $name . "': no matching filter.", debug => 1); next; } if (!defined($bytes)) { # seems corrupted, cannot get value $self->{output}->output_add(long_msg => sprintf("tbs '%s' cannot get data", $name), debug => 1); next; } if (defined($self->{option_results}->{skip}) && $status eq 'OFFLINE') { $self->{output}->output_add(long_msg => "skipping '" . $name . "': tbs is offline", debug => 1); next; } my ($percent_used, $percent_free, $used, $free, $size); if ((!defined($bytes_max)) || ($bytes_max eq '')) { $self->{output}->output_add(long_msg => "skipping '" . $name . "': bytes max not defined.", debug => 1); next; } elsif ($bytes_max > $bytes) { $percent_used = ($bytes - $bytes_free) / $bytes_max * 100; $size = $bytes_max; $free = $bytes_free + ($bytes_max - $bytes); $used = $size - $free; } else { $percent_used = ($bytes - $bytes_free) / $bytes * 100; $size = $bytes; $free = $bytes_free; $used = $size - $free; } $self->{tablespace}->{$name} = { used => $used, free => $free, total => $size, prct_used => $percent_used, display => lc($name) }; } } sub manage_selection { my ($self, %options) = @_; $self->{sql} = $options{sql}; $self->{sql}->connect(); # request from check_oracle_health. my $query; if ($self->{sql}->is_version_minimum(version => '11')) { $query = sprintf( q{ SELECT tum.tablespace_name "Tablespace", t.status "Status", t.contents "Type", t.extent_management "Extent Mgmt", tum.used_space*t.block_size bytes, tum.tablespace_size*t.block_size bytes_max FROM DBA_TABLESPACE_USAGE_METRICS tum INNER JOIN dba_tablespaces t on tum.tablespace_name=t.tablespace_name %s }, defined($self->{option_results}->{notemp}) ? "WHERE (t.contents != 'TEMPORARY' AND t.contents != 'UNDO')" : '' ); } elsif ($self->{sql}->is_version_minimum(version => '9')) { my $tbs_sql_undo = q{ SELECT tablespace_name, bytes_expired FROM ( SELECT a.tablespace_name, SUM (a.bytes) bytes_expired, a.status FROM dba_undo_extents a GROUP BY tablespace_name, status ) WHERE status = 'EXPIRED' }; my $tbs_sql_undo_empty = q{ SELECT NULL AS tablespace_name, NULL AS bytes_expired FROM DUAL }; my $tbs_sql_temp = q{ UNION ALL SELECT d.tablespace_name "Tablespace", b.status "Status", b.contents "Type", b.extent_management "Extent Mgmt", sum(a.bytes_free + a.bytes_used) bytes, -- allocated SUM(DECODE(d.autoextensible, 'YES', d.maxbytes, 'NO', d.bytes)) bytes_max, SUM(a.bytes_free + a.bytes_used - NVL(c.bytes_used, 0)) bytes_free FROM sys.v_$TEMP_SPACE_HEADER a, sys.dba_tablespaces b, sys.v_$Temp_extent_pool c, dba_temp_files d WHERE c.file_id(+) = a.file_id and c.tablespace_name(+) = a.tablespace_name and d.file_id = a.file_id and d.tablespace_name = a.tablespace_name and b.tablespace_name = a.tablespace_name GROUP BY b.status, b.contents, b.extent_management, d.tablespace_name ORDER BY 1 }; $query = sprintf( q{ SELECT /*+ opt_param('optimizer_adaptive_features','false') */ a.tablespace_name "Tablespace", b.status "Status", b.contents "Type", b.extent_management "Extent Mgmt", a.bytes bytes, a.maxbytes bytes_max, c.bytes_free + NVL(d.bytes_expired,0) bytes_free FROM ( -- belegter und maximal verfuegbarer platz pro datafile -- nach tablespacenamen zusammengefasst -- => bytes -- => maxbytes SELECT a.tablespace_name, SUM(a.bytes) bytes, SUM(DECODE(a.autoextensible, 'YES', a.maxbytes, 'NO', a.bytes)) maxbytes FROM dba_data_files a GROUP BY tablespace_name ) a, sys.dba_tablespaces b, ( -- freier platz pro tablespace -- => bytes_free SELECT a.tablespace_name, SUM(a.bytes) bytes_free FROM dba_free_space a GROUP BY tablespace_name ) c, ( %s ) d WHERE a.tablespace_name = c.tablespace_name (+) AND a.tablespace_name = b.tablespace_name AND a.tablespace_name = d.tablespace_name (+) %s %s }, defined($self->{option_results}->{notemp}) ? $tbs_sql_undo_empty : $tbs_sql_undo, defined($self->{option_results}->{notemp}) ? "AND (b.contents != 'TEMPORARY' AND b.contents != 'UNDO')" : '', defined($self->{option_results}->{notemp}) ? "" : $tbs_sql_temp ); } elsif ($self->{sql}->is_version_minimum(version => '8')) { $query = q{SELECT a.tablespace_name "Tablespace", b.status "Status", b.contents "Type", b.extent_management "Extent Mgmt", a.bytes bytes, a.maxbytes bytes_max, c.bytes_free bytes_free FROM ( -- belegter und maximal verfuegbarer platz pro datafile -- nach tablespacenamen zusammengefasst -- => bytes -- => maxbytes SELECT a.tablespace_name, SUM(a.bytes) bytes, SUM(DECODE(a.autoextensible, 'YES', a.maxbytes, 'NO', a.bytes)) maxbytes FROM dba_data_files a GROUP BY tablespace_name ) a, sys.dba_tablespaces b, ( -- freier platz pro tablespace -- => bytes_free SELECT a.tablespace_name, SUM(a.bytes) bytes_free FROM dba_free_space a GROUP BY tablespace_name ) c WHERE a.tablespace_name = c.tablespace_name (+) AND a.tablespace_name = b.tablespace_name AND (b.contents = 'PERMANENT' OR (b.contents <> 'PERMANENT' AND a.tablespace_name=(select value from v$parameter where name='undo_tablespace'))) UNION ALL SELECT a.tablespace_name "Tablespace", b.status "Status", b.contents "Type", b.extent_management "Extent Mgmt", sum(a.bytes_free + a.bytes_used) bytes, -- allocated d.maxbytes bytes_max, SUM(a.bytes_free + a.bytes_used - NVL(c.bytes_used, 0)) bytes_free FROM sys.v_$TEMP_SPACE_HEADER a, sys.dba_tablespaces b, sys.v_$Temp_extent_pool c, dba_temp_files d WHERE c.file_id(+) = a.file_id and c.tablespace_name(+) = a.tablespace_name and d.file_id = a.file_id and d.tablespace_name = a.tablespace_name and b.tablespace_name = a.tablespace_name GROUP BY a.tablespace_name, b.status, b.contents, b.extent_management, d.maxbytes ORDER BY 1 }; } else { $query = q{ SELECT a.tablespace_name "Tablespace", b.status "Status", b.contents "Type", 'DICTIONARY' "Extent Mgmt", a.bytes bytes, a.maxbytes bytes_max, c.bytes_free bytes_free FROM ( -- belegter und maximal verfuegbarer platz pro datafile -- nach tablespacenamen zusammengefasst -- => bytes -- => maxbytes SELECT a.tablespace_name, SUM(a.bytes) bytes, SUM(a.bytes) maxbytes FROM dba_data_files a GROUP BY tablespace_name ) a, sys.dba_tablespaces b, ( -- freier platz pro tablespace -- => bytes_free SELECT a.tablespace_name, SUM(a.bytes) bytes_free FROM dba_free_space a GROUP BY tablespace_name ) c WHERE a.tablespace_name = c.tablespace_name (+) AND a.tablespace_name = b.tablespace_name }; } $self->{sql}->query(query => $query); my $result = $self->{sql}->fetchall_arrayref(); $self->{tablespace} = {}; foreach my $row (@$result) { my ($name, $status, $type, $extentmgmt, $bytes, $bytes_max, $bytes_free) = @$row; if (defined($self->{option_results}->{notemp}) && ($type eq 'UNDO' || $type eq 'TEMPORARY')) { $self->{output}->output_add(long_msg => "skipping '" . $name . "': temporary or undo.", debug => 1); next; } if (defined($self->{option_results}->{filter_tablespace}) && $self->{option_results}->{filter_tablespace} ne '' && $name !~ /$self->{option_results}->{filter_tablespace}/) { $self->{output}->output_add(long_msg => "skipping '" . $name . "': no matching filter.", debug => 1); next; } if (!defined($bytes)) { # seems corrupted, cannot get value $self->{output}->output_add(long_msg => sprintf("tbs '%s' cannot get data", $name), debug => 1); next; } if (defined($self->{option_results}->{skip}) && $status eq 'OFFLINE') { $self->{output}->output_add(long_msg => "skipping '" . $name . "': tbs is offline", debug => 1); next; } my ($percent_used, $percent_free, $used, $free, $size); if ($self->{sql}->is_version_minimum(version => '11')) { $percent_used = $bytes / $bytes_max * 100; $size = $bytes_max; $free = $bytes_max - $bytes; $used = $bytes; } elsif ((!defined($bytes_max)) || ($bytes_max eq '')) { $self->{output}->output_add(long_msg => "skipping '" . $name . "': bytes max not defined.", debug => 1); next; } elsif ($bytes_max > $bytes) { $percent_used = ($bytes - $bytes_free) / $bytes_max * 100; $size = $bytes_max; $free = $bytes_free + ($bytes_max - $bytes); $used = $size - $free; } else { $percent_used = ($bytes - $bytes_free) / $bytes * 100; $size = $bytes; $free = $bytes_free; $used = $size - $free; } $self->{tablespace}->{$name} = { used => $used, free => $free, total => $size, prct_used => $percent_used, display => lc($name) }; } $self->manage_container(); $self->{sql}->disconnect(); if (scalar(keys %{$self->{tablespace}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No tablespaces found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check Oracle tablespaces usage. =over 8 =item B<--warning-tablespace> Threshold warning. =item B<--critical-tablespace> Threshold critical. =item B<--filter-tablespace> Filter tablespace by name. Can be a regex =item B<--units> Default is '%', can be 'B' =item B<--free> Perfdata show free space =item B<--notemp> skip temporary or undo tablespaces. =item B<--add-container> Add tablespaces of container databases. =item B<--skip> Skip offline tablespaces. =back =cut centreon-plugins-20220113/database/oracle/mode/tnsping.pm000066400000000000000000000054201417000230700232120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::oracle::mode::tnsping; use base qw(centreon::plugins::mode); use strict; use warnings; use Time::HiRes; use POSIX; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $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) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; my ($exit, $msg_error) = $self->{sql}->connect(dontquit => 1); if (defined($msg_error) && $msg_error !~ /(ORA-01017|ORA-01004)/i) { $self->{output}->output_add(severity => 'CRITICAL', short_msg => $msg_error); } else { my ($sid) = $self->{sql}->{data_source} =~ /(?:sid|service_name)=(\S+)/; $self->{output}->output_add(severity => 'OK', short_msg => sprintf("Connection established to listener '%s'.", $sid)); } $self->{sql}->disconnect(); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check Oracle listener status. =over 8 =back =cut centreon-plugins-20220113/database/oracle/plugin.pm000066400000000000000000000133771417000230700221140ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::oracle::plugin; use strict; use warnings; use base qw(centreon::plugins::script_sql); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $self->{version} = '0.1'; $self->{modes} = { 'asm-diskgroup-usage' => 'database::oracle::mode::asmdiskgroupusage', 'collection' => 'centreon::common::protocols::sql::mode::collection', 'connection-time' => 'centreon::common::protocols::sql::mode::connectiontime', 'connected-users' => 'database::oracle::mode::connectedusers', 'corrupted-blocks' => 'database::oracle::mode::corruptedblocks', 'dataguard' => 'database::oracle::mode::dataguard', 'data-files-status' => 'database::oracle::mode::datafilesstatus', 'datacache-hitratio' => 'database::oracle::mode::datacachehitratio', 'dictionary-cache-usage' => 'database::oracle::mode::dictionarycacheusage', 'event-waits-usage' => 'database::oracle::mode::eventwaitsusage', 'fra-usage' => 'database::oracle::mode::frausage', 'invalid-object' => 'database::oracle::mode::invalidobject', 'library-cache-usage' => 'database::oracle::mode::librarycacheusage', 'list-asm-diskgroups' => 'database::oracle::mode::listasmdiskgroups', 'list-tablespaces' => 'database::oracle::mode::listtablespaces', 'long-queries' => 'database::oracle::mode::longqueries', 'password-expiration' => 'database::oracle::mode::passwordexpiration', 'process-usage' => 'database::oracle::mode::processusage', 'redolog-usage' => 'database::oracle::mode::redologusage', 'rman-backup-problems' => 'database::oracle::mode::rmanbackupproblems', 'rman-backup-age' => 'database::oracle::mode::rmanbackupage', 'rman-online-backup-age' => 'database::oracle::mode::rmanonlinebackupage', 'rollback-segment-usage' => 'database::oracle::mode::rollbacksegmentusage', 'session-usage' => 'database::oracle::mode::sessionusage', 'sql' => 'centreon::common::protocols::sql::mode::sql', 'sql-string' => 'centreon::common::protocols::sql::mode::sqlstring', 'tablespace-usage' => 'database::oracle::mode::tablespaceusage', 'tnsping' => 'database::oracle::mode::tnsping' }; $self->{sql_modes}->{dbi} = 'database::oracle::dbi'; $self->{sql_modes}->{sqlpluscmd} = 'database::oracle::sqlpluscmd'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options(arguments => { 'hostname:s@' => { name => 'hostname' }, 'port:s@' => { name => 'port' }, 'sid:s' => { name => 'sid' }, 'servicename:s' => { name => 'servicename' }, 'container:s' => { name => 'container' } }); $self->{options}->parse_options(); my $options_result = $self->{options}->get_options(); $self->{options}->clean(); if (defined($options_result->{hostname})) { @{$self->{sqldefault}->{dbi}} = (); @{$self->{sqldefault}->{sqlpluscmd}} = (); for (my $i = 0; $i < scalar(@{$options_result->{hostname}}); $i++) { $self->{sqldefault}->{dbi}[$i] = { data_source => 'Oracle:host=' . $options_result->{hostname}[$i] }; $self->{sqldefault}->{sqlpluscmd}[$i] = { hostname => $options_result->{hostname}[$i] }; if (defined($options_result->{port}[$i])) { $self->{sqldefault}->{dbi}[$i]->{data_source} .= ';port=' . $options_result->{port}[$i]; $self->{sqldefault}->{sqlpluscmd}[$i]->{port} = $options_result->{port}[$i]; } if (defined($options_result->{sid}) && $options_result->{sid} ne '') { $self->{sqldefault}->{dbi}[$i]->{data_source} .= ';sid=' . $options_result->{sid}; $self->{sqldefault}->{sqlpluscmd}[$i]->{sid} = $options_result->{sid}; } if (defined($options_result->{servicename}) && $options_result->{servicename} ne '') { $self->{sqldefault}->{dbi}[$i]->{data_source} .= ';service_name=' . $options_result->{servicename}; $self->{sqldefault}->{sqlpluscmd}[$i]->{service_name} = $options_result->{servicename}; } $self->{sqldefault}->{dbi}[$i]->{container} = $options_result->{container}; $self->{sqldefault}->{sqlpluscmd}[$i]->{container} = $options_result->{container}; } } $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Oracle Server. =over 8 =item B<--hostname> Hostname to query. =item B<--port> Database Server Port. =item B<--sid> Database SID. =item B<--servicename> Database Service Name. =item B<--container> Change container (does an alter session set container command). =back =cut centreon-plugins-20220113/database/oracle/sqlpluscmd.pm000066400000000000000000000401131417000230700227710ustar00rootroot00000000000000# # Copyright 2018 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::oracle::sqlpluscmd; use strict; use warnings; use centreon::plugins::misc; use Digest::MD5 qw(md5_hex); use File::Temp qw(tempfile); use Data::Dumper; sub new { my ($class, %options) = @_; my $self = {}; bless $self, $class; # $options{options} = options object # $options{output} = output object # $options{exit_value} = integer # $options{noptions} = integer if (!defined($options{output})) { print "Class sqlpluscmd: Need to specify 'output' argument.\n"; exit 3; } if (!defined($options{options})) { $options{output}->add_option_msg(short_msg => "Class sqlpluscmd: Need to specify 'options' argument."); $options{output}->option_exit(); } if (!defined($options{noptions})) { $options{options}->add_options(arguments => { 'sqlplus-cmd:s' => { name => 'sqlplus_cmd'}, 'oracle-home:s' => { name => 'oracle_home' }, 'tnsadmin-home:s' => { name => 'tnsadmin_home' }, 'tnsnames-sid:s' => { name => 'tnsnames_sid'}, 'tnsnames-servicename:s' => { name => 'tnsnames_servicename'}, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'local-connexion' => { name => 'local_connexion', default => 0 }, 'sysdba' => { name => 'sysdba', default => 0 }, 'sql-errors-exit:s' => { name => 'sql_errors_exit', default => 'unknown' }, 'tempdir:s' => { name => 'tempdir', default => '/tmp' } } ); } $options{options}->add_help(package => __PACKAGE__, sections => 'sqlpluscmd OPTIONS', once => 1); $self->{output} = $options{output}; $self->{sqlmode_name} = $options{sqlmode_name}; $self->{args} = undef; $self->{stdout} = undef; $self->{columns} = undef; $self->{version} = undef; $self->{sid} = undef; $self->{oracle_home} = undef; $self->{tnsadmin_home} = undef; $self->{local_connexion} = undef; return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults { my ($self, %options) = @_; foreach (keys %{$options{default}}) { if ($_ eq $self->{sqlmode_name}) { 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->{sid} = defined($self->{option_results}->{sid}[0]) ? $self->{option_results}->{sid}[0] : $self->{option_results}->{tnsnames_sid}; $self->{service_name} = defined($self->{option_results}->{service_name}[0]) ? $self->{option_results}->{service_name}[0] : $self->{option_results}->{tnsnames_servicename}; $self->{oracle_home} = defined($self->{option_results}->{oracle_home}) ? $self->{option_results}->{oracle_home} : $ENV{'ORACLE_HOME'}; $self->{tnsadmin_home} = defined($self->{option_results}->{tnsadmin_home}) ? $self->{option_results}->{tnsadmin_home} : $ENV{'TNSADMIN'}; $self->{local_connexion} = $self->{option_results}->{local_connexion}; $self->{sqlplus_cmd} = $self->{option_results}->{sqlplus_cmd}; $self->{container} = defined($self->{option_results}->{container}[0]) ? $self->{option_results}->{container}[0] : undef; $self->{output}->output_add(long_msg => "*** DEBUG MODE****\n", debug => 1); $self->{output}->output_add(long_msg => Data::Dumper::Dumper($self->{option_results}), debug => 1); if ((!defined($self->{sid}) || $self->{sid} eq '') && (!defined($self->{service_name}) || $self->{service_name} eq '')) { $self->{output}->add_option_msg(short_msg => "Need to specify sid or servicename argument."); $self->{output}->option_exit(exit_litteral => $self->{option_results}->{sql_errors_exit}); } # check the ORACLE_HOME variable if (!defined($self->{oracle_home}) || $self->{oracle_home} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify oracle-home argument."); $self->{output}->option_exit(exit_litteral => $self->{option_results}->{sql_errors_exit}); } # construct the TNSADMIN variable if not available if(!defined($self->{tnsadmin_home})) { $self->{tnsadmin_home} = $self->{oracle_home} . "/network/admin"; } # check the SQLPLUS command to use if(!$self->{sqlplus_cmd}) { $self->{sqlplus_cmd} = $self->{oracle_home} . "/bin/sqlplus"; } $self->{args} = ['-L', '-S']; my $connection_string = ""; if ($self->{option_results}->{sysdba} == 1) { $self->{output}->output_add(long_msg => "*** SYDBA MODE****", debug => 1); $connection_string="/ as sysdba"; $self->{local_connexion} = 1; } elsif (defined($self->{option_results}->{username}) && defined($self->{option_results}->{password})) { $connection_string=$self->{option_results}->{username} . "/" . $self->{option_results}->{password}; } else { $self->{output}->add_option_msg(short_msg => "Need to specify username/password arguments or sysdba option."); $self->{output}->option_exit(exit_litteral => $self->{option_results}->{sql_errors_exit}); } if ($self->{local_connexion} == 0) { if (defined($self->{option_results}->{hostname})) { my $port = defined($self->{option_results}->{port}) ? $self->{option_results}->{port}[0] : 1521; $connection_string .= "\@//" . $self->{option_results}->{hostname}[0] . ':' . $port . '/' . ((defined($self->{sid}) && $self->{sid} ne '') ? $self->{sid} : $self->{service_name}); } else { $connection_string .= "\@" . ((defined($self->{sid}) && $self->{sid} ne '') ? $self->{sid} : $self->{service_name}); } } else { $self->{output}->output_add(long_msg => "*** LOCAL CONNEXION MODE****", debug => 1); if (defined($self->{sid}) && $self->{sid} ne '') { $ENV{ORACLE_SID} = $self->{sid}; } else { $ENV{TWO_TASK} = '/' . $self->{service_name}; } } # register a false data_source to be compliant with tnsping mode if (defined($self->{sid}) && $self->{sid} ne '') { $self->{data_source} = "sid=" . $self->{sid}; } else { $self->{data_source} = "service_name=" . $self->{service_name}; } push @{$self->{args}}, $connection_string; # set oracle env variable $ENV{ORACLE_HOME} = $self->{oracle_home}; $ENV{TNSADMIN} = $self->{tnsadmin_home}; if (defined($self->{option_results}->{sid})) { return 0; } return 1; } sub is_version_minimum { my ($self, %options) = @_; # $options{version} = string version to check my @version_src = split /\./, $self->{version}; my @versions = split /\./, $options{version}; for (my $i = 0; $i < scalar(@versions); $i++) { return 1 if ($versions[$i] eq 'x'); return 1 if (!defined($version_src[$i])); $version_src[$i] =~ /^([0-9]*)/; next if ($versions[$i] == int($1)); return 0 if ($versions[$i] > int($1)); return 1 if ($versions[$i] < int($1)); } return 1; } sub get_id { my ($self, %options) = @_; my $msg = $self->{sid}; return $msg; } sub get_unique_id4save { my ($self, %options) = @_; my $msg = $self->{sid}; return md5_hex($msg); } sub quote { my $self = shift; return undef; } sub command_execution { my ($self, %options) = @_; my ($fh, $tempfile) = tempfile(DIR => $self->{option_results}->{tempdir}, SUFFIX => ".sql", UNLINK => 1); print $fh "set echo off -- set heading off set feedback off set linesize 16000 set pagesize 50000 set colsep '#&!#' set numwidth 15 $options{request}; exit;"; $self->{output}->output_add(long_msg => "*** COMMAND: " . $self->{sqlplus_cmd} . ' ' . join(' ', (@{$self->{args}}, '@', $tempfile)), debug => 1); $self->{output}->output_add(long_msg => "*** REQUEST: " . $options{request}, debug => 1); my ($lerror, $stdout, $exit_code) = centreon::plugins::misc::backtick( command => $self->{sqlplus_cmd}, arguments => [@{$self->{args}}, '@', $tempfile], timeout => 30, wait_exit => 1, redirect_stderr => 1 ); $self->{output}->output_add(long_msg => "REQ. STDOUT: '$stdout'", debug => 1); $self->{output}->output_add(long_msg => "REQ. EXIT_CODE: $exit_code", debug => 1); # search oracle error lines $exit_code = -1 if($stdout =~ /^(ORA\-\d+|TNS\-\d+|SP\d\-\d+)/); if ($exit_code <= -1000) { if ($exit_code == -1000) { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => $stdout); } $self->{output}->display(); $self->{output}->exit(); } return ($exit_code, $stdout); } sub disconnect {} # Connection initializer sub connect { my ($self, %options) = @_; my $dontquit = (defined($options{dontquit}) && $options{dontquit} == 1) ? 1 : 0; (my $exit_code, $self->{stdout}) = $self->command_execution(request => "select version from v\$instance"); if ($exit_code != 0) { if ($dontquit == 0) { $self->{output}->add_option_msg(short_msg => "Cannot connect: " . $self->{stdout}); $self->{output}->option_exit(exit_litteral => $self->{option_results}->{sql_errors_exit}); } return (-1, "Cannot connect: " . $self->{stdout}); } $self->{version} = $self->fetchrow_array(); $self->{output}->output_add(long_msg => "VERSION: " . $self->{version}, debug => 1); if (defined($self->{container}) and $self->{container} ne '') { $self->query(query => "alter session set container=$self->{container}"); } return 0; } sub fetchall_arrayref { my ($self, %options) = @_; my $array_ref = []; if($self->{stdout} eq '') { $self->{output}->output_add(long_msg => "fetchall_arrayref: no data returned (no rows selected)", debug => 1); return $array_ref; } if (!defined($self->{columns})) { $self->{stdout} =~ s/^\s*\n(.*?)(\n|$)//; my $line = $1; $self->{output}->output_add(long_msg => "fetchall_arrayref COLUMNS: $line", debug => 1) if(defined($line)); @{$self->{columns}} = split(/#&!#/, $line); map { s/^\s+|\s+$//g; } @{$self->{columns}}; $self->{stdout} =~ s/[\-#&!]+(\n|$)//; } foreach (split /\n/, $self->{stdout}) { my $line = $_; $line =~ s/^\s+|\s+$//g; $line =~ s/#&!#\s+/#&!#/g; $line =~ s/\s+#&!#/#&!#/g; $self->{output}->output_add(long_msg => "fetchall_arrayref VALUE: " . $line, debug => 1); push @$array_ref, [map({ s/\\n/\x{0a}/g; s/\\t/\x{09}/g; s/\\/\x{5c}/g; $_; } split(/#&!#/, $line))]; } return $array_ref; } sub fetchrow_array { my ($self, %options) = @_; my @array_result = (); if($self->{stdout} eq '') { $self->{output}->output_add(long_msg => "fetchrow_array: no data returned (no rows selected)", debug => 1); return @array_result; } if (!defined($self->{columns})) { $self->{stdout} =~ s/^\s*\n(.*?)(\n|$)//; my $line = $1; $self->{output}->output_add(long_msg => "fetchrow_array COLUMNS: $line", debug => 1); @{$self->{columns}} = split(/#&!#/, $line); map { s/^\s+|\s+$//g; } @{$self->{columns}}; $self->{stdout} =~ s/[\-#&!]+(\n|$)//; } $self->{output}->output_add(long_msg => "fetchrow_array STDOUT: '" . $self->{stdout} . "'", debug => 1); if (($self->{stdout} =~ s/^(.*?)(\n|$)//)) { my $line = $1; $self->{output}->output_add(long_msg => "fetchrow_array VALUE: '" . $line . "'", debug => 1); push @array_result, map({ s/\\n/\x{0a}/g; s/\\t/\x{09}/g; s/\\/\x{5c}/g; $_; } split(/#&!#/, $line)); map { s/^\s+|\s+$//g; } @array_result; $self->{output}->output_add(long_msg => "ARRAY: " . Data::Dumper::Dumper(@array_result), debug => 1); } $self->{output}->output_add(long_msg => "RETURN: " . Data::Dumper::Dumper(@array_result), debug => 1); return scalar(@array_result) == 1 ? $array_result[0] : @array_result; } sub fetchrow_hashref { my ($self, %options) = @_; my $array_result = undef; if($self->{stdout} eq '') { $self->{output}->output_add(long_msg => "fetchrow_hashref: no data returned (no rows selected)", debug => 1); return $array_result; } if (!defined($self->{columns})) { $self->{stdout} =~ s/^\s*\n(.*?)(\n|$)//; my $line = $1; $self->{output}->output_add(long_msg => "fetchrow_hashref COLUMNS: $line", debug => 1); @{$self->{columns}} = split(/#&!#/, $line); map { s/^\s+|\s+$//g; } @{$self->{columns}}; $self->{stdout} =~ s/[\-#&!]+(\n|$)//; } if ($self->{stdout} ne '' && $self->{stdout} =~ s/^(.*?)(\n|$)//) { my $line = $1; $self->{output}->output_add(long_msg => "fetchrow_hashref VALUE: " . $line, debug => 1); $array_result = {}; my @values = split(/#&!#/, $line); for (my $i = 0; $i < scalar(@values); $i++) { my $value = $values[$i]; $value =~ s/^\s+|\s+$//g; $value =~ s/\\n/\x{0a}/g; $value =~ s/\\t/\x{09}/g; $value =~ s/\\/\x{5c}/g; $self->{output}->output_add(long_msg => "fetchrow_hashref RES: '" . $self->{columns}[$i] . "' = '$value'", debug => 1); $array_result->{$self->{columns}[$i]} = $value; } } return $array_result; } sub query { my ($self, %options) = @_; $self->{columns} = undef; (my $exit_code, $self->{stdout}) = $self->command_execution(request => $options{query}); if ($exit_code != 0) { $self->{output}->add_option_msg(short_msg => "Cannot execute query: " . $self->{stdout}); $self->{output}->option_exit(exit_litteral => $self->{option_results}->{sql_errors_exit}); } } 1; __END__ =head1 NAME sqlpluscmd global =head1 SYNOPSIS sqlpluscmd class =head1 sqlpluscmd OPTIONS =over 8 =item B<--sqlplus-cmd> sqlplus command (Default: 'sqlplus'). =item B<--oracle-home> Oracle Database Server Home. =item B<--tnsadmin-home> Oracle TNS Admin Home. Where to locate tnsnames.ora file (default: ${ORACLE_HOME}/network/admin) =item B<--tnsnames-sid> Oracle SID defined in tnsnames.ora. =item B<--tnsnames-servicename> Oracle Service Name defined in tnsnames.ora. =item B<--username> Database username. =item B<--password> Database password. =item B<--sysdba> Use a sysdba connexion, need to be execute under the oracle local user on the server, and use a local connexion. =item B<--local-connexion> Use a local connexion, don't need listener. =item B<--sql-errors-exit> Exit code for DB Errors (default: unknown) =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/database/postgres/000077500000000000000000000000001417000230700206465ustar00rootroot00000000000000centreon-plugins-20220113/database/postgres/mode/000077500000000000000000000000001417000230700215725ustar00rootroot00000000000000centreon-plugins-20220113/database/postgres/mode/backends.pm000066400000000000000000000127311417000230700237060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::postgres::mode::backends; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning:s" => { name => 'warning', }, "critical:s" => { name => 'critical', }, "exclude:s" => { name => 'exclude', }, "noidle" => { name => 'noidle', }, }); 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) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); my $noidle = ''; if (defined($self->{option_results}->{noidle})) { if ($self->{sql}->is_version_minimum(version => '9.2')) { $noidle = " AND state <> 'idle'"; } else { $noidle = " AND current_query <> ''"; } } my $query = "SELECT COUNT(datid) AS current, (SELECT setting AS mc FROM pg_settings WHERE name = 'max_connections') AS mc, d.datname FROM pg_database d LEFT JOIN pg_stat_activity s ON (s.datid = d.oid $noidle) GROUP BY d.datname ORDER BY d.datname"; $self->{sql}->query(query => $query); $self->{output}->output_add(severity => 'OK', short_msg => "All client database connections are ok."); my $database_check = 0; my $result = $self->{sql}->fetchall_arrayref(); foreach my $row (@{$result}) { if (defined($self->{option_results}->{exclude}) && $$row[2] !~ /$self->{option_results}->{exclude}/) { $self->{output}->output_add(long_msg => "Skipping database '" . $$row[2] . '"'); next; } $database_check++; my $used = $$row[0]; my $max_connections = $$row[1]; my $database_name = $$row[2]; my $prct_used = ($used * 100) / $max_connections; my $exit_code = $self->{perfdata}->threshold_check(value => $prct_used, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(long_msg => sprintf("Database '%s': %.2f%% client connections limit reached (%d of max. %d)", $database_name, $prct_used, $used, $max_connections)); if (!$self->{output}->is_status(value => $exit_code, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("Database '%s': %.2f%% client connections limit reached (%d of max. %d)", $database_name, $prct_used, $used, $max_connections)); } $self->{output}->perfdata_add(label => 'connections_' . $database_name, value => $used, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning', total => $max_connections, cast_int => 1), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical', total => $max_connections, cast_int => 1), min => 0, max => $max_connections); } if ($database_check == 0) { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => 'No database checked. (permission or a wrong exclude filter)'); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check the current number of connections for one or more databases =over 8 =item B<--warning> Threshold warning in percent. =item B<--critical> Threshold critical in percent. =item B<--exclude> Filter databases. =item B<--noidle> Idle connections are not counted. =back =cut centreon-plugins-20220113/database/postgres/mode/databasesize.pm000066400000000000000000000065001417000230700245700ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::postgres::mode::databasesize; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'databases', type => 1, cb_prefix_output => 'prefix_database_output', message_multiple => 'All databases are ok' }, ]; $self->{maps_counters}->{databases} = [ { label => 'size', set => { key_values => [ { name => 'size' }, { name => 'display' } ], output_template => 'size : %s %s', output_change_bytes => 1, perfdatas => [ { label => 'size', value => 'size', template => '%s', min => 0, unit => 'B', label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub prefix_database_output { my ($self, %options) = @_; return "Database '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-database:s" => { name => 'filter_database' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; $self->{sql} = $options{sql}; $self->{sql}->connect(); $self->{sql}->query(query => "SELECT pg_database.datname, pg_database_size(pg_database.datname) FROM pg_database;"); my $result = $self->{sql}->fetchall_arrayref(); $self->{databases} = {}; foreach my $row (@$result) { next if (defined($self->{option_results}->{filter_database}) && $self->{option_results}->{filter_database} ne '' && $$row[0] !~ /$self->{option_results}->{filter_database}/); $self->{databases}->{$$row[0]}->{display} = $$row[0]; $self->{databases}->{$$row[0]}->{size} = $$row[1]; } if (scalar(keys %{$self->{databases}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No databases found'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check databases size =over 8 =item B<--filter-database> Filter database to checks (Can use regexp). =item B<--warning-size> Threshold warning in bytes, maximum size allowed. =item B<--critical-size> Threshold critical in bytes, maximum size allowed. =back =cut centreon-plugins-20220113/database/postgres/mode/hitratio.pm000066400000000000000000000163471417000230700237660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::postgres::mode::hitratio; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::statefile; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning:s" => { name => 'warning', }, "critical:s" => { name => 'critical', }, "lookback" => { name => 'lookback', }, "exclude:s" => { name => 'exclude', }, }); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); 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(); } $self->{statefile_cache}->check_options(%options); } sub run { my ($self, %options) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); $self->{sql}->query(query => q{ SELECT sd.blks_hit, sd.blks_read, d.datname FROM pg_stat_database sd, pg_database d WHERE d.oid=sd.datid }); $self->{statefile_cache}->read(statefile => 'postgres_' . $self->{mode} . '_' . $self->{sql}->get_unique_id4save()); my $old_timestamp = $self->{statefile_cache}->get(name => 'last_timestamp'); my $database_check = 0; my $new_datas = {}; $new_datas->{last_timestamp} = time(); my $result = $self->{sql}->fetchall_arrayref(); $self->{output}->output_add(severity => 'OK', short_msg => "All databases hitratio are ok."); foreach my $row (@{$result}) { $new_datas->{$$row[2] . '_blks_hit'} = $$row[0]; $new_datas->{$$row[2] . '_blks_read'} = $$row[1]; if (defined($self->{option_results}->{exclude}) && $$row[2] !~ /$self->{option_results}->{exclude}/) { $self->{output}->output_add(long_msg => "Skipping database '" . $$row[2] . '"'); next; } my $old_blks_hit = $self->{statefile_cache}->get(name => $$row[2] . '_blks_hit'); my $old_blks_read = $self->{statefile_cache}->get(name => $$row[2] . '_blks_read'); next if (!defined($old_blks_hit) || !defined($old_blks_read)); $old_blks_hit = 0 if ($$row[0] <= $old_blks_hit); $old_blks_read = 0 if ($$row[1] <= $old_blks_read); $database_check++; my %prcts = (); my $total_read_requests = $new_datas->{$$row[2] . '_blks_hit'} - $old_blks_hit; my $total_read_disk = $new_datas->{$$row[2] . '_blks_read'} - $old_blks_read; $prcts{hitratio_now} = (($total_read_requests + $total_read_disk) == 0) ? 100 : $total_read_requests * 100 / ($total_read_requests + $total_read_disk); $prcts{hitratio} = (($new_datas->{$$row[2] . '_blks_hit'} + + $new_datas->{$$row[2] . '_blks_read'}) == 0) ? 100 : $new_datas->{$$row[2] . '_blks_hit'} * 100 / ($new_datas->{$$row[2] . '_blks_hit'} + $new_datas->{$$row[2] . '_blks_read'}); my $exit_code = $self->{perfdata}->threshold_check(value => $prcts{'hitratio' . ((defined($self->{option_results}->{lookback})) ? '' : '_now' )}, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(long_msg => sprintf("Database '%s' hitratio at %.2f%%", $$row[2], $prcts{'hitratio' . ((defined($self->{option_results}->{lookback})) ? '' : '_now')}) ); if (!$self->{output}->is_status(value => $exit_code, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("Database '%s' hitratio at %.2f%%", $$row[2], $prcts{'hitratio' . ((defined($self->{option_results}->{lookback})) ? '' : '_now')}) ); } $self->{output}->perfdata_add(label => $$row[2] . '_hitratio' . ((defined($self->{option_results}->{lookback})) ? '' : '_now'), unit => '%', value => sprintf("%.2f", $prcts{'hitratio' . ((defined($self->{option_results}->{lookback})) ? '' : '_now')}), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0, max => 100); $self->{output}->perfdata_add(label => $$row[2] . '_hitratio' . ((defined($self->{option_results}->{lookback})) ? '_now' : ''), unit => '%', value => sprintf("%.2f", $prcts{'hitratio' . ((defined($self->{option_results}->{lookback})) ? '_now' : '')}), min => 0, max => 100); } $self->{statefile_cache}->write(data => $new_datas); if (!defined($old_timestamp)) { $self->{output}->output_add(severity => 'OK', short_msg => "Buffer creation..."); } if (defined($old_timestamp) && $database_check == 0) { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => 'No database checked. (permission or a wrong exclude filter)'); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check hitratio (in buffer cache) for databases. =over 8 =item B<--warning> Threshold warning. =item B<--critical> Threshold critical. =item B<--lookback> Threshold isn't on the percent calculated from the difference ('xxx_hitratio_now'). =item B<--exclude> Filter databases. =back =cut centreon-plugins-20220113/database/postgres/mode/listdatabases.pm000066400000000000000000000053561417000230700247640ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::postgres::mode::listdatabases; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "exclude:s" => { name => 'exclude', }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; $self->{sql}->connect(); $self->{sql}->query(query => q{ SELECT datname FROM pg_database } ); $self->{list_db} = []; while ((my $row = $self->{sql}->fetchrow_hashref())) { if (defined($self->{option_results}->{exclude}) && $row->{datname} !~ /$self->{option_results}->{exclude}/) { $self->{output}->output_add(long_msg => "Skipping database '" . $row->{datname} . "': no matching filter name"); next; } push @{$self->{list_db}}, $row->{datname}; } } sub run { my ($self, %options) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->manage_selection(); foreach my $name (sort @{$self->{list_db}}) { $self->{output}->output_add(long_msg => "'" . $name . "'"); } $self->{output}->output_add(severity => 'OK', short_msg => "List of databases:"); $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->{sql} = $options{sql}; $self->manage_selection(); foreach (sort @{$self->{list_db}}) { $self->{output}->add_disco_entry(name => $_); } } 1; __END__ =head1 MODE Display databases =over 8 =item B<--exclude> Filter databases. =back =cut centreon-plugins-20220113/database/postgres/mode/locks.pm000066400000000000000000000131011417000230700232370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::postgres::mode::locks; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning:s" => { name => 'warning', default => ''}, "critical:s" => { name => 'critical', default => ''}, "exclude:s" => { name => 'exclude', }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); my @warns = split /,/, $self->{option_results}->{warning}; my @crits = split /,/, $self->{option_results}->{critical}; foreach my $val (@warns) { next if (!defined($val)); my ($label, $value) = split /=/, $val; next if (!defined($label) || !defined($value)); if (($self->{perfdata}->threshold_validate(label => 'warn-' . $label, value => $value)) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong warning ('$label' locks) threshold '" . $value . "'."); $self->{output}->option_exit(); } } foreach my $val (@crits) { next if (!defined($val)); my ($label, $value) = split /=/, $val; next if (!defined($label) || !defined($value)); if (($self->{perfdata}->threshold_validate(label => 'crit-' . $label, value => $value)) == 0) { $self->{output}->add_option_msg(short_msg => "Critical warning ('$label' locks) threshold '" . $value . "'."); $self->{output}->option_exit(); } } } sub run { my ($self, %options) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); $self->{sql}->query(query => q{ SELECT granted, mode, datname FROM pg_database d LEFT JOIN pg_locks l ON (d.oid=l.database) WHERE d.datallowconn }); $self->{output}->output_add(severity => 'OK', short_msg => "All databases locks are ok."); my $result = $self->{sql}->fetchall_arrayref(); my $dblocks = {}; foreach my $row (@{$result}) { my ($granted, $mode, $dbname) = ($$row[0], $$row[1], $$row[2]); if (defined($self->{option_results}->{exclude}) && $dbname !~ /$self->{option_results}->{exclude}/) { next; } if (!defined($dblocks->{$dbname})) { $dblocks->{$dbname} = {total => 0, waiting => 0}; # Empty. no lock (left join) next if (!defined($mode) || $mode eq ''); } $dblocks->{$dbname}->{total}++; $mode =~ s{lock$}{}; $dblocks->{$dbname}->{lc($mode)}++; $dblocks->{$dbname}->{waiting}++ if (!$granted); } foreach my $dbname (keys %$dblocks) { foreach my $locktype (keys %{$dblocks->{$dbname}}) { $self->{output}->output_add(long_msg => sprintf("Database '%s' lock '%s': %d", $dbname, $locktype, $dblocks->{$dbname}->{$locktype})); my $exit_code = $self->{perfdata}->threshold_check(value => $dblocks->{$dbname}->{$locktype}, threshold => [ { label => 'crit-' . $locktype, 'exit_litteral' => 'critical' }, { label => 'warn-' . $locktype, exit_litteral => 'warning' } ]); if (!$self->{output}->is_status(value => $exit_code, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("Database '%s' lock '%s': %d", $dbname, $locktype, $dblocks->{$dbname}->{$locktype})); } $self->{output}->perfdata_add(label => $dbname . '_' . $locktype, value => $dblocks->{$dbname}->{$locktype}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warn-' . $locktype), critical => $self->{perfdata}->get_perfdata_for_output(label => 'crit-' . $locktype), min => 0); } } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check locks for one or more databases =over 8 =item B<--warning> Threshold warning. (example: "total=250,waiting=5,exclusive=20") 'total', 'waiting', or the name of a lock type used by Postgres. =item B<--critical> Threshold critical. (example: "total=250,waiting=5,exclusive=20") 'total', 'waiting', or the name of a lock type used by Postgres. =item B<--exclude> Filter databases. =back =cut centreon-plugins-20220113/database/postgres/mode/querytime.pm000066400000000000000000000132711417000230700241600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::postgres::mode::querytime; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning:s" => { name => 'warning', }, "critical:s" => { name => 'critical', }, "exclude:s" => { name => 'exclude', }, "exclude-user:s" => { name => 'exclude_user', }, }); 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) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); my $query; if ($self->{sql}->is_version_minimum(version => '9.2')) { $query = q{ SELECT pg_database.datname, pgsa.datid, pgsa.pid, pgsa.usename, pgsa.client_addr, pgsa.query AS current_query, pgsa.state AS state, CASE WHEN pgsa.client_port < 0 THEN 0 ELSE pgsa.client_port END AS client_port, COALESCE(ROUND(EXTRACT(epoch FROM now()-query_start)),0) AS seconds FROM pg_database LEFT JOIN pg_stat_activity pgsa ON pg_database.datname = pgsa.datname AND (pgsa.query_start IS NOT NULL AND (pgsa.state NOT LIKE 'idle%' OR pgsa.state IS NULL)) ORDER BY pgsa.query_start, pgsa.pid DESC }; } else { $query = q{ SELECT pg_database.datname, pgsa.datid, pgsa.procpid, pgsa.usename, pgsa.client_addr, pgsa.current_query AS current_query, '' AS state, CASE WHEN pgsa.client_port < 0 THEN 0 ELSE pgsa.client_port END AS client_port, COALESCE(ROUND(EXTRACT(epoch FROM now()-query_start)),0) AS seconds FROM pg_database LEFT JOIN pg_stat_activity pgsa ON pg_database.datname = pgsa.datname AND (pgsa.query_start IS NOT NULL AND current_query NOT LIKE '%') ORDER BY pgsa.query_start, pgsa.procpid DESC }; } $self->{sql}->query(query => $query); $self->{output}->output_add(severity => 'OK', short_msg => "All databases queries time are ok."); my $dbquery = {}; while ((my $row = $self->{sql}->fetchrow_hashref())) { if (!defined($dbquery->{$row->{datname}})) { $dbquery->{$row->{datname}} = { total => 0, code => {} }; } next if (!defined($row->{datid}) || $row->{datid} eq ''); # No joint if (defined($self->{option_results}->{exclude}) && $row->{datname} !~ /$self->{option_results}->{exclude}/) { next; } if (defined($self->{option_results}->{exclude_user}) && $row->{usename} !~ /$self->{option_results}->{exclude_user}/) { next; } my $exit_code = $self->{perfdata}->threshold_check(value => $row->{seconds}, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); if (!$self->{output}->is_status(value => $exit_code, compare => 'ok', litteral => 1)) { $self->{output}->output_add(long_msg => sprintf("Request from client '%s' too long (%d sec) on database '%s': %s", $row->{client_addr}, $row->{seconds}, $row->{datname}, $row->{current_query})); $dbquery->{$row->{datname}}->{total}++; $dbquery->{$row->{datname}}->{code}->{$exit_code}++; } } foreach my $dbname (keys %$dbquery) { $self->{output}->perfdata_add(label => $dbname . '_qtime_num', value => $dbquery->{$dbname}->{total}, min => 0); foreach my $exit_code (keys %{$dbquery->{$dbname}->{code}}) { $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("%d request exceed " . lc($exit_code) . " threshold on database '%s'", $dbquery->{$dbname}->{code}->{$exit_code}, $dbname)); } } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Checks the time of running queries for one or more databases =over 8 =item B<--warning> Threshold warning in seconds. =item B<--critical> Threshold critical in seconds. =item B<--exclude> Filter databases. =item B<--exclude-user> Filter users. =back =cut centreon-plugins-20220113/database/postgres/mode/statistics.pm000066400000000000000000000201021417000230700243150ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::postgres::mode::statistics; 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 => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } }, { name => 'database', type => 1, cb_prefix_output => 'prefix_database_output', message_multiple => 'All database statistics are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'total-commit', nlabel => 'queries.commit.count', set => { key_values => [ { name => 'commit', diff => 1 } ], output_template => 'Commit : %s', perfdatas => [ { label => 'commit', value => 'commit', template => '%s', min => 0 }, ], } }, { label => 'total-rollback', nlabel => 'queries.rollback.count', set => { key_values => [ { name => 'rollback', diff => 1 } ], output_template => 'Rollback : %s', perfdatas => [ { label => 'rollback', value => 'rollback', template => '%s', min => 0 }, ], } }, { label => 'total-insert', nlabel => 'queries.insert.count', set => { key_values => [ { name => 'insert', diff => 1 } ], output_template => 'Insert : %s', perfdatas => [ { label => 'insert', value => 'insert', template => '%s', min => 0 }, ], } }, { label => 'total-update', nlabel => 'queries.update.count', set => { key_values => [ { name => 'update', diff => 1 } ], output_template => 'Update : %s', perfdatas => [ { label => 'update', value => 'update', template => '%s', min => 0 }, ], } }, { label => 'total-delete', nlabel => 'queries.delete.count', set => { key_values => [ { name => 'delete', diff => 1 } ], output_template => 'Delete : %s', perfdatas => [ { label => 'delete', value => 'delete', template => '%s', min => 0 }, ], } }, ]; $self->{maps_counters}->{database} = [ { label => 'commit', nlabel => 'queries.commit.count', set => { key_values => [ { name => 'commit', diff => 1 }, { name => 'name' }, ], output_template => 'Commit : %s', perfdatas => [ { label => 'commit', value => 'commit', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'name' }, ], } }, { label => 'rollback', nlabel => 'queries.rollback.count', set => { key_values => [ { name => 'rollback', diff => 1 }, { name => 'name' }, ], output_template => 'Rollback : %s', perfdatas => [ { label => 'rollback', value => 'rollback', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'name' }, ], } }, { label => 'insert', nlabel => 'queries.insert.count', set => { key_values => [ { name => 'insert', diff => 1 }, { name => 'name' }, ], output_template => 'Insert : %s', perfdatas => [ { label => 'insert', value => 'insert', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'name' }, ], } }, { label => 'update', nlabel => 'queries.update.count', set => { key_values => [ { name => 'update', diff => 1 }, { name => 'name' }, ], output_template => 'Update : %s', perfdatas => [ { label => 'update', value => 'update', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'name' }, ], } }, { label => 'delete', nlabel => 'queries.delete.count', set => { key_values => [ { name => 'delete', diff => 1 }, { name => 'name' }, ], output_template => 'Delete : %s', perfdatas => [ { label => 'delete', value => 'delete', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'name' }, ], } }, ]; } sub prefix_global_output { my ($self, %options) = @_; return 'Total '; } sub prefix_database_output { my ($self, %options) = @_; return "Database '" . $options{instance_value}->{name} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { "filter-database:s" => { name => 'filter_database' }, }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{database} = {}; $self->{global} = { commit => 0, rollback => 0, insert => 0, update => 0, delete => 0 }; my $query = q{ SELECT d.datname as name, pg_stat_get_db_xact_commit(d.oid) as commit, pg_stat_get_db_xact_rollback(d.oid) as rollback, pg_stat_get_tuples_inserted(d.oid) as insert, pg_stat_get_tuples_updated(d.oid) as update, pg_stat_get_tuples_updated(d.oid) as delete FROM pg_database d; }; $options{sql}->connect(); $options{sql}->query(query => $query); while ((my $row = $options{sql}->fetchrow_hashref())) { if (defined($self->{option_results}->{filter_database}) && $self->{option_results}->{filter_database} ne '' && $row->{name} !~ /$self->{option_results}->{filter_database}/) { $self->{output}->output_add(long_msg => "skipping '" . $row->{name} . "': no matching filter."); next; } $self->{database}->{$row->{name}} = {%$row}; foreach (keys %{$self->{global}}) { $self->{global}->{$_} += $row->{$_}; } } if (scalar(keys %{$self->{database}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No database found."); $self->{output}->option_exit(); } $self->{cache_name} = "postgres_" . $self->{mode} . '_' . $options{sql}->get_unique_id4save() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_database}) ? md5_hex($self->{option_results}->{filter_database}) : md5_hex('all')); } 1; __END__ =head1 MODE Check database statistics: commit, rollback, insert, delete, update. =over 8 =item B<--warning-*> Threshold warning. Can be: 'commit', 'rollback', 'insert', 'delete', 'update', 'total-commit', 'total-rollback', 'total-insert', 'total-delete', 'total-update'. =item B<--critical-*> Threshold critical. Can be: 'commit', 'rollback', 'insert', 'delete', 'update', 'total-commit', 'total-rollback', 'total-insert', 'total-delete', 'total-update'. =item B<--filter-database> Filter database (can be a regexp). =back =cut centreon-plugins-20220113/database/postgres/mode/tablespace.pm000066400000000000000000000065441417000230700242440ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::postgres::mode::tablespace; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_tablespace_output { my ($self, %options) = @_; return "Tablespace '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'tablespaces', type => 1, cb_prefix_output => 'prefix_tablespace_output', message_multiple => 'All tablespaces are ok' } ]; $self->{maps_counters}->{tablespaces} = [ { label => 'space-usage', nlabel => 'tablespace.space.usage.bytes', set => { key_values => [ { name => 'space_used' } ], output_template => 'space used: %s %s', output_change_bytes => 1, perfdatas => [ { template => '%d', min => 0, unit => 'B', label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-sql-name:s' => { name => 'filter_sql_name' }, 'filter-name:s' => { name => 'filter_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); my $query = 'SELECT spcname, pg_tablespace_size(spcname) FROM pg_tablespace'; if (defined($self->{option_results}->{filter_sql_name}) && $self->{option_results}->{filter_sql_name} ne '') { $query .= ' WHERE spcname LIKE ' . $options{sql}->quote($self->{option_results}->{filter_sql_name}); } $options{sql}->query(query => $query); $self->{tablespaces} = {}; while (my @row = $options{sql}->fetchrow_array()) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $row[0] !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping tablespace '" . $row[0] . "': no matching filter.", debug => 1); next; } $self->{tablespaces}->{ $row[0] } = { display => $row[0], space_used => $row[1] }; } } 1; __END__ =head1 MODE Check a tablespaces. =over 8 =item B<--filter-sql-name> Filter tablespace name directly in sql query (LIKE sql syntax used). =item B<--filter-name> Filter tablespace name after getting all tablespaces (can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'space-usage' (B). =back =cut centreon-plugins-20220113/database/postgres/mode/timesync.pm000066400000000000000000000070251417000230700237670ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::postgres::mode::timesync; use base qw(centreon::plugins::mode); use strict; use warnings; use Time::HiRes; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $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) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); $self->{sql}->query(query => q{ SELECT extract(epoch FROM now()) AS epok }); my ($result) = $self->{sql}->fetchrow_array(); my $ltime = Time::HiRes::time(); if (!defined($result)) { $self->{output}->add_option_msg(short_msg => "Cannot get server time."); $self->{output}->option_exit(); } my $diff = $result - $ltime; my $exit_code = $self->{perfdata}->threshold_check(value => $diff, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("%.3fs time diff between servers", $diff)); $self->{output}->perfdata_add(label => 'timediff', unit => 's', value => sprintf("%.3f", $diff), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical')); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Compares the local system time with the time reported by Postgres =over 8 =item B<--warning> Threshold warning in seconds. (use a range. it can be -0.3s or +0.3s.) =item B<--critical> Threshold critical in seconds. (use a range. it can be -0.3s or +0.3s.) =back =cut centreon-plugins-20220113/database/postgres/mode/vacuum.pm000066400000000000000000000074241417000230700234370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::postgres::mode::vacuum; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { '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) = @_; $options{sql}->connect(); my $target_fields = 'last_vacuum'; # Autovacuum feature has only been impleted starting PG 8.2 # (options needed http://www.postgresql.org/docs/8.2/static/runtime-config-autovacuum.html, no need starting 8.3) if ($options{sql}->is_version_minimum(version => '8.2.0')) { $target_fields = 'greatest(last_autovacuum,last_vacuum)'; } my $query = sprintf( 'SELECT ROUND(EXTRACT(EPOCH from (select min (now() - %s) from pg_stat_all_tables where %s is not null)))', $target_fields, $target_fields ); $options{sql}->query(query => $query); my $result = $options{sql}->fetchrow_array(); if (defined($result)) { my $exit_code = $self->{perfdata}->threshold_check(value => $result, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add( severity => $exit_code, short_msg => sprintf('Most recent vacuum dates back from %d seconds', $result) ); $self->{output}->perfdata_add( label => 'last_vacuum', value => $result, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical') ); } else { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => 'No vacuum performed on this BD yet.' ); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check a vacuum (manual or auto) command has been performed on at least one of the tables of the associated DB =over 8 =item B<--warning> Threshold warning in seconds, maximum time interval since last vacuum. =item B<--critical> Threshold critical in seconds, maximum time interval since last vacuum. =back =cut centreon-plugins-20220113/database/postgres/plugin.pm000066400000000000000000000076601417000230700225130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::postgres::plugin; use strict; use warnings; use base qw(centreon::plugins::script_sql); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $self->{version} = '0.1'; $self->{modes} = { 'backends' => 'database::postgres::mode::backends', 'collection' => 'centreon::common::protocols::sql::mode::collection', 'connection-time' => 'centreon::common::protocols::sql::mode::connectiontime', 'database-size' => 'database::postgres::mode::databasesize', 'hitratio' => 'database::postgres::mode::hitratio', 'locks' => 'database::postgres::mode::locks', 'list-databases' => 'database::postgres::mode::listdatabases', 'query-time' => 'database::postgres::mode::querytime', 'sql' => 'centreon::common::protocols::sql::mode::sql', 'sql-string' => 'centreon::common::protocols::sql::mode::sqlstring', 'statistics' => 'database::postgres::mode::statistics', 'tablespace' => 'database::postgres::mode::tablespace', 'timesync' => 'database::postgres::mode::timesync', 'vacuum' => 'database::postgres::mode::vacuum', }; $self->{sql_modes}->{psqlcmd} = 'database::postgres::psqlcmd'; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options( arguments => { 'host:s@' => { name => 'db_host' }, 'port:s@' => { name => 'db_port' }, 'database:s@' => { name => 'db_name' } } ); $self->{options}->parse_options(); my $options_result = $self->{options}->get_options(); $self->{options}->clean(); if (defined($options_result->{db_host})) { @{$self->{sqldefault}->{dbi}} = (); @{$self->{sqldefault}->{psqlcmd}} = (); for (my $i = 0; $i < scalar(@{$options_result->{db_host}}); $i++) { $self->{sqldefault}->{dbi}->[$i] = { data_source => 'Pg:host=' . $options_result->{db_host}->[$i] }; $self->{sqldefault}->{psqlcmd}->[$i] = { host => $options_result->{db_host}->[$i] }; if (defined($options_result->{db_port}->[$i])) { $self->{sqldefault}->{dbi}->[$i]->{data_source} .= ';port=' . $options_result->{db_port}->[$i]; $self->{sqldefault}->{psqlcmd}->[$i]->{port} = $options_result->{db_port}->[$i]; } $options_result->{db_name}->[$i] = (defined($options_result->{db_name}[$i]) && $options_result->{db_name}->[$i] ne '') ? $options_result->{db_name}->[$i] : 'postgres'; $self->{sqldefault}->{dbi}->[$i]->{data_source} .= ';database=' . $options_result->{db_name}->[$i]; $self->{sqldefault}->{psqlcmd}->[$i]->{dbname} = $options_result->{db_name}->[$i]; } } $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Postgres Server. =over 8 You can use following options or options from 'sqlmode' directly. =item B<--host> Hostname to query. =item B<--port> Database Server Port. =item B<--database> Database Name. (default: postgres) =back =cut centreon-plugins-20220113/database/postgres/psqlcmd.pm000066400000000000000000000240171417000230700226530ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::postgres::psqlcmd; use strict; use warnings; use centreon::plugins::misc; use Digest::MD5 qw(md5_hex); sub new { my ($class, %options) = @_; my $self = {}; bless $self, $class; if (!defined($options{output})) { print "Class psqlcmd: Need to specify 'output' argument.\n"; exit 3; } if (!defined($options{options})) { $options{output}->add_option_msg(short_msg => "Class psqlcmd: Need to specify 'options' argument."); $options{output}->option_exit(); } if (!defined($options{noptions})) { $options{options}->add_options(arguments => { 'psql-cmd:s' => { name => 'psql_cmd', default => '/usr/bin/psql' }, 'host:s@' => { name => 'host' }, 'port:s@' => { name => 'port' }, 'username:s@' => { name => 'username' }, 'password:s@' => { name => 'password' }, 'dbname:s@' => { name => 'dbname' }, 'sql-errors-exit:s' => { name => 'sql_errors_exit', default => 'unknown' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'PSQLCMD OPTIONS', once => 1); $self->{output} = $options{output}; $self->{sqlmode_name} = $options{sqlmode_name}; $self->{args} = undef; $self->{stdout} = undef; $self->{columns} = undef; $self->{version} = undef; $self->{host} = undef; $self->{port} = undef; $self->{username} = undef; $self->{password} = undef; $self->{dbname} = undef; $self->{record_separator} = '----====----'; $self->{field_separator} = '-====-'; return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults { my ($self, %options) = @_; foreach (keys %{$options{default}}) { if ($_ eq $self->{sqlmode_name}) { 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->{host} = (defined($self->{option_results}->{host})) ? shift(@{$self->{option_results}->{host}}) : undef; $self->{port} = (defined($self->{option_results}->{port})) ? shift(@{$self->{option_results}->{port}}) : undef; $self->{username} = (defined($self->{option_results}->{username})) ? shift(@{$self->{option_results}->{username}}) : undef; $self->{password} = (defined($self->{option_results}->{password})) ? shift(@{$self->{option_results}->{password}}) : undef; $self->{dbname} = (defined($self->{option_results}->{dbname})) ? shift(@{$self->{option_results}->{dbname}}) : undef; $self->{sql_errors_exit} = $self->{option_results}->{sql_errors_exit}; $self->{psql_cmd} = $self->{option_results}->{psql_cmd}; # If we want a command line: password with variable "PGPASSWORD". # psql -d template1 -A -R "----====-----" -F "-====-" -c "select code from films" if (!defined($self->{host}) || $self->{host} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify host argument."); $self->{output}->option_exit(exit_litteral => $self->{sql_errors_exit}); } $self->{args} = ['-A', '-R', $self->{record_separator}, '-F', $self->{field_separator}, '--pset', 'footer=off', '-h', $self->{host}]; if (defined($self->{port})) { push @{$self->{args}}, "-p", $self->{port}; } if (defined($self->{username})) { push @{$self->{args}}, "-U", $self->{username}; } if (defined($self->{password}) && $self->{password} ne '') { $ENV{PGPASSWORD} = $self->{password}; } if (defined($self->{dbname}) && $self->{dbname} ne '') { push @{$self->{args}}, "-d", $self->{dbname}; } if (scalar(@{$self->{option_results}->{host}}) == 0) { return 0; } return 1; } sub is_version_minimum { my ($self, %options) = @_; # $options{version} = string version to check my @version_src = split /\./, $self->{version}; my @versions = split /\./, $options{version}; for (my $i = 0; $i < scalar(@versions); $i++) { return 1 if ($versions[$i] eq 'x'); return 1 if (!defined($version_src[$i])); $version_src[$i] =~ /^([0-9]*)/; next if ($versions[$i] == int($1)); return 0 if ($versions[$i] > int($1)); return 1 if ($versions[$i] < int($1)); } return 1; } sub get_id { my ($self, %options) = @_; my $msg = $self->{host}; if (defined($self->{port})) { $msg .= ":" . $self->{port}; } return $msg; } sub get_unique_id4save { my ($self, %options) = @_; my $msg = $self->{host}; if (defined($self->{port})) { $msg .= ":" . $self->{port}; } return md5_hex($msg); } sub quote { my $self = shift; return undef; } sub command_execution { my ($self, %options) = @_; my ($stdout, $exit_code) = centreon::plugins::misc::execute( output => $self->{output}, command => $self->{psql_cmd}, command_options => join(' ', @{$self->{args}}) . ' -c "' . $options{request} . '"', wait_exit => 1, redirect_stderr => 1, no_quit => 1, options => { timeout => 30 } ); return ($exit_code, $stdout); } sub disconnect {} # Connection initializer sub connect { my ($self, %options) = @_; my $dontquit = (defined($options{dontquit}) && $options{dontquit} == 1) ? 1 : 0; (my $exit_code, $self->{stdout}) = $self->command_execution(request => "SELECT current_setting('server_version') as version"); if ($exit_code != 0) { if ($dontquit == 0) { $self->{output}->add_option_msg(short_msg => "Cannot connect: " . $self->{stdout}); $self->{output}->option_exit(exit_litteral => $self->{sql_errors_exit}); } return (-1, "Cannot connect: " . $self->{stdout}); } my $row = $self->fetchrow_hashref(); $self->{version} = $row->{version}; return 0; } sub fetchall_arrayref { my ($self, %options) = @_; my $array_ref = []; if (!defined($self->{columns})) { $self->{stdout} =~ s/^(.*?)\Q$self->{record_separator}\E//ms; @{$self->{columns}} = split(/\Q$self->{field_separator}\E/, $1); } foreach (split /\Q$self->{record_separator}\E/, $self->{stdout}) { push @$array_ref, [split(/\Q$self->{field_separator}\E/, $_)]; } return $array_ref; } sub fetchall_hashref { my ($self, %options) = @_; my $array_ref = []; my $array_result = undef; if (!defined($self->{columns})) { $self->{stdout} =~ s/^(.*?)\Q$self->{record_separator}\E//ms; @{$self->{columns}} = split(/\Q$self->{field_separator}\E/, $1); } foreach (split /\Q$self->{record_separator}\E/, $self->{stdout}) { $array_result = {}; my @values = split(/\Q$self->{field_separator}\E/, $_); for (my $i = 0; $i < scalar(@values); $i++) { my $value = $values[$i]; $array_result->{$self->{columns}[$i]} = $value; } push @$array_ref, $array_result; } return $array_ref; } sub fetchrow_array { my ($self, %options) = @_; my @array_result = (); if (!defined($self->{columns})) { $self->{stdout} =~ s/^(.*?)\Q$self->{record_separator}\E//ms; @{$self->{columns}} = split(/\Q$self->{field_separator}\E/, $1); } if (($self->{stdout} =~ s/^(.*?)(\Q$self->{record_separator}\E|\Z)//ms)) { push @array_result, split(/\Q$self->{field_separator}\E/, $1); } return @array_result; } sub fetchrow_hashref { my ($self, %options) = @_; my $array_result = undef; if (!defined($self->{columns})) { $self->{stdout} =~ s/^(.*?)\Q$self->{record_separator}\E//ms; @{$self->{columns}} = split(/\Q$self->{field_separator}\E/, $1); } if ($self->{stdout} ne '' && $self->{stdout} =~ s/^(.*?)(\Q$self->{record_separator}\E|\Z)//ms) { $array_result = {}; my @values = split(/\Q$self->{field_separator}\E/, $1); for (my $i = 0; $i < scalar(@values); $i++) { my $value = $values[$i]; $array_result->{$self->{columns}[$i]} = $value; } } return $array_result; } sub query { my ($self, %options) = @_; $self->{columns} = undef; (my $exit_code, $self->{stdout}) = $self->command_execution(request => $options{query}); if ($exit_code != 0) { $self->{output}->add_option_msg(short_msg => "Cannot execute query: " . $self->{stdout}); $self->{output}->option_exit(exit_litteral => $self->{sql_errors_exit}); } } 1; __END__ =head1 NAME psqlcmd global =head1 SYNOPSIS psqlcmd class =head1 PSQLCMD OPTIONS =over 8 =item B<--psql-cmd> postgres command (Default: '/usr/bin/psql'). =item B<--host> Database hostname. =item B<--port> Database port. =item B<--dbname> Database name to connect (default: postgres). =item B<--username> Database username. =item B<--password> Database password. =item B<--sql-errors-exit> Exit code for DB Errors (default: unknown) =back =head1 DESCRIPTION B<>. =cut centreon-plugins-20220113/database/redis/000077500000000000000000000000001417000230700201065ustar00rootroot00000000000000centreon-plugins-20220113/database/redis/custom/000077500000000000000000000000001417000230700214205ustar00rootroot00000000000000centreon-plugins-20220113/database/redis/custom/cli.pm000066400000000000000000000233531417000230700225330ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::redis::custom::cli; use strict; use warnings; use centreon::plugins::ssh; use centreon::plugins::misc; use Digest::MD5 qw(md5_hex); 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 => { 'ssh-hostname:s' => { name => 'ssh_hostname' }, 'server:s' => { name => 'server' }, 'port:s' => { name => 'port' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'sentinel:s@' => { name => 'sentinel' }, 'sentinel-port:s' => { name => 'sentinel_port' }, 'service:s' => { name => 'service' }, 'tls' => { name => 'tls' }, 'cacert:s' => { name => 'cacert' }, 'insecure' => { name => 'insecure' }, 'timeout:s' => { name => 'timeout' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REDIS OPTIONS', once => 1); $self->{output} = $options{output}; $self->{ssh} = centreon::plugins::ssh->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{ssh_hostname} = defined($self->{option_results}->{ssh_hostname}) && $self->{option_results}->{ssh_hostname} ne '' ? $self->{option_results}->{ssh_hostname} : ''; $self->{server} = defined($self->{option_results}->{server}) && $self->{option_results}->{server} ne '' ? $self->{option_results}->{server} : ''; $self->{port} = defined($self->{option_results}->{port}) && $self->{option_results}->{port} ne '' ? $self->{option_results}->{port} : 6379; $self->{sentinel_port} = defined($self->{option_results}->{sentinel_port}) && $self->{option_results}->{sentinel_port} =~ /(\d+)/ ? $1 : 26379; $self->{username} = defined($self->{option_results}->{password}) && $self->{option_results}->{username} ne '' ? $self->{option_results}->{username} : ''; $self->{password} = defined($self->{option_results}->{password}) && $self->{option_results}->{password} ne '' ? $self->{option_results}->{password} : ''; $self->{timeout} = defined($self->{option_results}->{timeout}) && $self->{option_results}->{timeout} =~ /(\d+)/ ? $1 : 10; $self->{tls} = defined($self->{option_results}->{tls}) ? 1 : 0; $self->{insecure} = defined($self->{option_results}->{insecure}) ? 1 : 0; $self->{cacert} = defined($self->{option_results}->{cacert}) && $self->{option_results}->{cacert} ne '' ? $self->{option_results}->{cacert} : ''; $self->{sentinel} = []; if (defined($self->{option_results}->{sentinel})) { foreach my $addr (@{$self->{option_results}->{sentinel}}) { next if ($addr eq ''); push @{$self->{sentinel}}, $addr . ($self->{sentinel_port} ne '' ? ':' . $self->{sentinel_port} : '') } } $self->{service} = defined($self->{option_results}->{service}) && $self->{option_results}->{service} ne '' ? $self->{option_results}->{service} : ''; if ($self->{server} eq '' && scalar(@{$self->{sentinel}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'Need to specify --server or --sentinel option.'); $self->{output}->option_exit(); } if (scalar(@{$self->{sentinel}}) > 0 && $self->{service} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --service option.'); $self->{output}->option_exit(); } if ($self->{ssh_hostname} ne '') { $self->{option_results}->{hostname} = $self->{ssh_hostname}; $self->{ssh}->check_options(option_results => $self->{option_results}); } if ($self->{username} ne '' && $self->{option_results}->{password} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --password option.'); $self->{output}->option_exit(); } return 0; } sub get_connection_info { my ($self, %options) = @_; my $id = ''; if ($self->{server} ne '') { $id = $self->{server} . ':' . $self->{port}; } else { foreach (@{$self->{sentinel}}) { $id .= $_ . '-'; } } return md5_hex($id); } sub execute_command { my ($self, %options) = @_; my $timeout = $self->{timeout}; if (!defined($timeout)) { $timeout = defined($options{timeout}) ? $options{timeout} : 10; } my ($stdout, $exit_code); if ($self->{ssh_hostname} ne '') { ($stdout, $exit_code) = $self->{ssh}->execute( hostname => $self->{ssh_hostname}, sudo => $self->{option_results}->{sudo}, command => $options{command}, command_path => $options{command_path}, command_options => $options{command_options}, timeout => $timeout, no_quit => $options{no_quit} ); } else { ($stdout, $exit_code) = centreon::plugins::misc::execute( output => $self->{output}, sudo => $self->{option_results}->{sudo}, options => { timeout => $timeout }, command => $options{command}, command_path => $options{command_path}, command_options => $options{command_options}, no_quit => $options{no_quit} ); } $self->{output}->output_add(long_msg => "command response: $stdout", debug => 1); return ($stdout, $exit_code); } sub get_extra_options { my ($self, %options) = @_; my $options = ''; $options .= ' --tls' if ($self->{tls} == 1); $options .= " --cacert '" . $self->{cacert} . "'" if ($self->{cacert} ne ''); $options .= ' --insecure' if ($self->{insecure} == 1); $options .= " --user '" . $self->{username} . "'" if ($self->{username} ne ''); $options .= " -a '" . $self->{password} . "'" if ($self->{password} ne ''); return $options; } sub sentinels_get_master { my ($self, %options) = @_; my ($host, $port); foreach my $addr (@{$self->{sentinel}}) { my ($sentinel_host, $sentinel_port) = split(/:/, $addr); my $command_options = "-h '" . $sentinel_host . "' -p " . (defined($sentinel_port) ? $sentinel_port : 26379); $command_options .= ' --no-raw'; $command_options .= ' sentinel get-master-addr-by-name ' . $self->{service}; my ($stdout, $exit_code) = $self->execute_command( command => 'redis-cli', command_options => $command_options, no_quit => 1 ); next if ($exit_code != 0); $host = $1 if ($stdout =~ /1\) "(.*?)"/m); $port = $1 if ($stdout =~ /2\) "(\d+)"/m); last if (defined($port)); } if (!defined($port)) { $self->{output}->add_option_msg(short_msg => 'Cannot find redis master (sentinels)'); $self->{output}->option_exit(); } return ($host, $port); } sub get_info { my ($self, %options) = @_; my $command_options; if (scalar(@{$self->{sentinel}}) > 0) { my ($host, $port) = $self->sentinels_get_master(); $command_options = "-h '" . $host . "' -p " . $port; } else { $command_options = "-h '" . $self->{server} . "' -p " . $self->{port}; } $command_options .= $self->get_extra_options(); $command_options .= ' info'; my ($stdout) = $self->execute_command( command => 'redis-cli', command_options => $command_options ); if ($stdout =~ /^NOPERM/m) { $self->{output}->add_option_msg(short_msg => 'Permissions issue'); $self->{output}->option_exit(); } my $items = {}; foreach my $line (split /\n/, $stdout) { if ($line =~ /^(.*?):(.*)$/) { $items->{$1} = $2; } } return $items; } 1; __END__ =head1 NAME redis-cli. =head1 SYNOPSIS redis-cli. =head1 REDIS OPTIONS =over 8 =item B<--server> Redis server. =item B<--port> Redis port (Default: 6379). =item B<--tls> Establish a secure TLS connection (redis-cli >= 6.x mandatory). =item B<--cacert> CA Certificate file to verify with (redis-cli >= 6.x mandatory). =item B<--insecure> Allow insecure TLS connection by skipping cert validation (Since redis-cli 6.2.0). =item B<--username> Redis username (redis-cli >= 6.x mandatory). =item B<--password> Redis password. =item B<--sentinel> Sentinel server. Alternative of server option. service option is required. =item B<--sentinel-port> Sentinel port (Default: 26379). =item B<--service> Service parameter. =item B<--ssh-hostname> Remote ssh redis-cli execution. =item B<--timeout> Timeout in seconds for the command (Default: 10). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/database/redis/custom/perlmod.pm000066400000000000000000000122511417000230700234210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::redis::custom::perlmod; use strict; use warnings; use Redis; use Digest::MD5 qw(md5_hex); 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 => { 'server:s' => { name => 'server' }, 'port:s' => { name => 'port' }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'sentinel:s@' => { name => 'sentinel' }, 'sentinel-port:s' => { name => 'sentinel_port' }, 'service:s' => { name => 'service' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REDIS OPTIONS', once => 1); $self->{output} = $options{output}; return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{server} = defined($self->{option_results}->{server}) && $self->{option_results}->{server} ne '' ? $self->{option_results}->{server} : ''; $self->{port} = defined($self->{option_results}->{port}) && $self->{option_results}->{port} =~ /(\d+)/ ? $1 : 6379; $self->{sentinel_port} = defined($self->{option_results}->{sentinel_port}) && $self->{option_results}->{sentinel_port} =~ /(\d+)/ ? $1 : 26379; $self->{username} = defined($self->{option_results}->{username}) && $self->{option_results}->{username} ne '' ? $self->{option_results}->{username} : ''; $self->{password} = defined($self->{option_results}->{password}) && $self->{option_results}->{password} ne '' ? $self->{option_results}->{password} : ''; $self->{sentinel} = []; if (defined($self->{option_results}->{sentinel})) { foreach my $addr (@{$self->{option_results}->{sentinel}}) { next if ($addr eq ''); push @{$self->{sentinel}}, $addr . ($self->{sentinel_port} ne '' ? ':' . $self->{sentinel_port} : '') } } $self->{service} = defined($self->{option_results}->{service}) && $self->{option_results}->{service} ne '' ? $self->{option_results}->{service} : ''; if ($self->{server} eq '' && scalar(@{$self->{sentinel}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'Need to specify --server or --sentinel option.'); $self->{output}->option_exit(); } if (scalar(@{$self->{sentinel}}) > 0 && $self->{service} eq '') { $self->{output}->add_option_msg(short_msg => 'Need to specify --service option.'); $self->{output}->option_exit(); } if ($self->{username} ne '') { $self->{output}->add_option_msg(short_msg => 'Unsupported --username option.'); $self->{output}->option_exit(); } return 0; } sub get_connection_info { my ($self, %options) = @_; my $id = ''; if ($self->{server} ne '') { $id = $self->{server} . ':' . $self->{port}; } else { foreach (@{$self->{sentinel}}) { $id .= $_ . '-'; } } return md5_hex($id); } sub get_info { my ($self, %options) = @_; my $redis; if (scalar(@{$self->{sentinel}}) > 0) { $redis = Redis->new(sentinels => $self->{sentinel}, service => $self->{service}); } else { $redis = Redis->new(server => $self->{server} . ':' . $self->{port}); } if ($self->{password} ne '') { $redis->auth($self->{password}); } my $response = $redis->info(); my $items; foreach my $attributes (keys %$response) { $items->{$attributes} = $response->{$attributes}; } $redis->quit(); return $items; } 1; __END__ =head1 NAME REDIS perlmod =head1 SYNOPSIS Redis perlmod =head1 REDIS OPTIONS =over 8 =item B<--server> Redis server. =item B<--port> Redis port (Default: 6379). =item B<--password> Redis password. =item B<--sentinel> Sentinel server. Alternative of server option. service option is required. =item B<--sentinel-port> Sentinel port (Default: 26379). =item B<--service> Service parameter. =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/database/redis/mode/000077500000000000000000000000001417000230700210325ustar00rootroot00000000000000centreon-plugins-20220113/database/redis/mode/clients.pm000066400000000000000000000102421417000230700230300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::redis::mode::clients; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_output { my ($self, %options) = @_; return 'Clients '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_output', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'connected-clients', nlabel => 'clients.connected.count', set => { key_values => [ { name => 'connected_clients' } ], output_template => 'connected: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'blocked-clients', nlabel => 'clients.blocked.count', set => { key_values => [ { name => 'blocked_clients' } ], output_template => 'blocked: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'client-longest-output-list', nlabel => 'clients.longest_output_list.count', set => { key_values => [ { name => 'client_longest_output_list' } ], output_template => 'longest output list: %s', perfdatas => [ { label => 'client_longest_output_list', template => '%s', min => 0 } ] } }, { label => 'client-biggest-input-buf', nlabel => 'clients.biggest_input_buffer.count', set => { key_values => [ { name => 'client_biggest_input_buf' } ], output_template => 'client biggest input buffer: %s', perfdatas => [ { template => '%s', min => 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 => {}); return $self; } sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->get_info(); $self->{global} = { connected_clients => $results->{connected_clients}, blocked_clients => $results->{blocked_clients}, client_longest_output_list => $results->{client_longest_output_list}, client_biggest_input_buf => $results->{client_biggest_input_buf} }; } 1; __END__ =head1 MODE Check number of connected and blocked clients =over 8 =item B<--warning-connected-clients> Warning threshold for number of connected clients =item B<--critical-connected-clients> Critical threshold for number of connected clients =item B<--warning-blocked-clients> Warning threshold for number of blocked clients =item B<--critical-blocked-clients> Critical threshold for number of blocked clients =item B<--warning-client-longest-output-list> Warning threshold for longest output list among current client connections =item B<--critical-client-longest-output-list> Critical threshold for longest output list among current client connections =item B<--warning-client-biggest-input-buf> Warning threshold for biggest input buffer among current client connections =item B<--critical-client-biggest-input-buf> Critical threshold for biggest input buffer among current client connections =back =cut centreon-plugins-20220113/database/redis/mode/commands.pm000066400000000000000000000062131417000230700231730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::redis::mode::commands; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); sub prefix_output { my ($self, %options) = @_; return 'Number of commands processed: '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, message_separator => ' ', cb_prefix_output => 'prefix_output' } ]; $self->{maps_counters}->{global} = [ { label => 'processed-commands', nlabel => 'commands.processed.count', set => { key_values => [ { name => 'total_commands_processed', diff => 1 } ], output_template => '%s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'ops-per-sec', nlabel => 'commands.processed.persecond', set => { key_values => [ { name => 'instantaneous_ops_per_sec' } ], output_template => '%.2f/s', perfdatas => [ { template => '%.2f', min => 0 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = 'redis_database_' . $self->{mode} . '_' . $options{custom}->get_connection_info() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); my $results = $options{custom}->get_info(); $self->{global} = { total_commands_processed => $results->{total_commands_processed}, instantaneous_ops_per_sec => $results->{instantaneous_ops_per_sec} }; } 1; __END__ =head1 MODE Check commands number =over 8 =item B<--warning-processed-commands> Warning threshold for number of commands processed by the server =item B<--critical-processed-commands> Critical threshold for number of commands processed by the server =item B<--warning-ops-per-sec> Warning threshold for number of commands processed per second =item B<--critical-ops-per-sec> Critical threshold for number of commands processed per second =back =cut centreon-plugins-20220113/database/redis/mode/connections.pm000066400000000000000000000112371417000230700237160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::redis::mode::connections; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); sub prefix_connections_output { my ($self, %options) = @_; return 'Number of connections '; } sub prefix_traffic_output { my ($self, %options) = @_; return 'Network usage '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'connections', type => 0, cb_prefix_output => 'prefix_connections_output' }, { name => 'traffic', type => 0, cb_prefix_output => 'prefix_traffic_output' } ]; $self->{maps_counters}->{connections} = [ { label => 'received-connections', nlabel => 'connections.received.count', set => { key_values => [ { name => 'total_connections_received', diff => 1 } ], output_template => 'received: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'rejected-connections', nlabel => 'connections.rejected.count', set => { key_values => [ { name => 'rejected_connections', diff => 1 } ], output_template => 'rejected: %s', perfdatas => [ { template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{traffic} = [ { label => 'traffic-in', nlabel => 'network.traffic.in.bitspersecond', set => { key_values => [ { name => 'total_net_input_bytes', per_second => 1 } ], output_template => 'traffic in: %s %s/s', output_change_bytes => 2, perfdatas => [ { template => '%d', min => 0, unit => 'b/s' } ] } }, { label => 'traffic-out', nlabel => 'network.traffic.out.bitspersecond', set => { key_values => [ { name => 'total_net_output_bytes', per_second => 1 } ], output_template => 'traffic out: %s %s/s', output_change_bytes => 2, perfdatas => [ { template => '%d', min => 0, unit => 'b/s' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = 'redis_database_' . $self->{mode} . '_' . $options{custom}->get_connection_info() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); my $results = $options{custom}->get_info(); $self->{connections} = { total_connections_received => $results->{total_connections_received}, rejected_connections => $results->{rejected_connections} }; $self->{traffic} = { total_net_input_bytes => $results->{total_net_input_bytes} * 8, total_net_output_bytes => $results->{total_net_output_bytes} * 8 }; } 1; __END__ =head1 MODE Check connections number and network usage =over 8 =item B<--warning-received-connections> Warning threshold for received connections =item B<--critical-received-connections> Critical threshold for received connections =item B<--warning-rejected-connections> Warning threshold for rejected connections =item B<--critical-rejected-connections> Critical threshold for rejected connections =item B<--warning-traffic-in> Warning threshold for inbound traffic (b/s) =item B<--critical-traffic-in> Critical threshold for inbound traffic (b/s) =item B<--warning-traffic-out> Warning threshold for outbound traffic (b/s) =item B<--critical-traffic-out> Critical thresholdfor outbound traffic (b/s) =back =cut centreon-plugins-20220113/database/redis/mode/cpu.pm000066400000000000000000000127051417000230700221640ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::redis::mode::cpu; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); sub prefix_output { my ($self, %options) = @_; return 'CPU usage '; } sub custom_usage_calc { my ($self, %options) = @_; my $delta_total = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{label_ref}} - $options{old_datas}->{$self->{instance} . '_' . $options{extra_options}->{label_ref}}; $self->{result_values}->{used_delta} = 100 * $delta_total / $options{delta_time}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_output' } ]; $self->{maps_counters}->{global} = [ { label => 'sys', nlabel => 'cpu.system.usage.percentage', set => { key_values => [ { name => 'used_cpu_sys', diff => 1 } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { label_ref => 'used_cpu_sys' }, output_template => 'system: %.2f %%', output_use => 'used_delta', threshold_use => 'used_delta', perfdatas => [ { value => 'used_delta', template => '%.2f', min => 0, max => 100, unit => '%' } ] } }, { label => 'user', nlabel => 'cpu.user.usage.percentage', set => { key_values => [ { name => 'used_cpu_user', diff => 1 } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { label_ref => 'used_cpu_user' }, output_template => 'user: %.2f %%', output_use => 'used_delta', threshold_use => 'used_delta', perfdatas => [ { value => 'used_delta', template => '%.2f', min => 0, max => 100, unit => '%' } ] } }, { label => 'sys-children', nlabel => 'cpu.system.children.usage.percentage', set => { key_values => [ { name => 'used_cpu_sys_children', diff => 1 } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { label_ref => 'used_cpu_sys_children' }, output_template => 'system children: %.2f %%', output_use => 'used_delta', threshold_use => 'used_delta', perfdatas => [ { value => 'used_delta', template => '%.2f', min => 0, max => 100, unit => '%' } ] } }, { label => 'user-children', nlabel => 'cpu.user.children.usage.percentage', set => { key_values => [ { name => 'used_cpu_user_children', diff => 1 } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { label_ref => 'used_cpu_user_children' }, output_template => 'user children: %.2f %%', output_use => 'used_delta', threshold_use => 'used_delta', perfdatas => [ { value => 'used_delta', template => '%.2f', min => 0, max => 100, unit => '%' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = 'redis_database_' . $self->{mode} . '_' . $options{custom}->get_connection_info() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); my $results = $options{custom}->get_info(); $self->{global} = { used_cpu_sys => $results->{used_cpu_sys}, used_cpu_user => $results->{used_cpu_user}, used_cpu_sys_children => $results->{used_cpu_sys_children}, used_cpu_user_children => $results->{used_cpu_user_children} }; } 1; __END__ =head1 MODE Check CPU utilization. =over 8 =item B<--warning-sys> Warning threshold for Sys CPU utilization =item B<--critical-sys> Critical threshold for Sys CPU utilization =item B<--warning-user> Warning threshold for User CPU utilization =item B<--critical-user> Critical threshold for User CPU utilization =item B<--warning-sys-children> Warning threshold for Sys Children CPU utilization =item B<--critical-sys-children> Critical threshold for Sys Children CPU utilization =item B<--warning-user-children> Warning threshold for User Children CPU utilization =item B<--critical-user-children> Critical threshold for User Children CPU utilization =back =cut centreon-plugins-20220113/database/redis/mode/memory.pm000066400000000000000000000305541417000230700227070ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::redis::mode::memory; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_usage_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel}, unit => 'B', value => $self->{result_values}->{used}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), min => 0, max => $self->{result_values}->{total} ); } sub custom_usage_threshold { my ($self, %options) = @_; my ($exit, $threshold_value); $threshold_value = $self->{result_values}->{used}; $threshold_value = $self->{result_values}->{free} if (defined($self->{instance_mode}->{option_results}->{free})); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; $threshold_value = $self->{result_values}->{prct_free} if (defined($self->{instance_mode}->{option_results}->{free})); } $exit = $self->{perfdata}->threshold_check( value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ] ); return $exit; } sub custom_usage_output { my ($self, %options) = @_; my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); return sprintf( "%s: %s (%.2f%%)", $self->{result_values}->{display}, $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used} ); } sub custom_usage_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{label} = $options{new_datas}->{$self->{instance} . '_label'}; $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_used'}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_total'}; $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 => 'used', type => 0 }, { name => 'rss', type => 0, skipped_code => { -10 => 1 } }, { name => 'peak', type => 0, skipped_code => { -10 => 1 } }, { name => 'overhead', type => 0, skipped_code => { -10 => 1 } }, { name => 'startup', type => 0, skipped_code => { -10 => 1 } }, { name => 'dataset', type => 0, skipped_code => { -10 => 1 } }, { name => 'lua', type => 0, skipped_code => { -10 => 1 } }, { name => 'stats', type => 0, skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{used} = [ { label => 'used', nlabel => 'memory.usage.bytes', set => { key_values => [ { name => 'display' }, { name => 'label' }, { 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') } } ]; $self->{maps_counters}->{rss} = [ { label => 'rss', nlabel => 'memory.rss.usage.bytes', set => { key_values => [ { name => 'display' }, { name => 'label' }, { 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') } } ]; $self->{maps_counters}->{peak} = [ { label => 'peak', nlabel => 'memory.peak.usage.bytes', set => { key_values => [ { name => 'display' }, { name => 'label' }, { 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') } } ]; $self->{maps_counters}->{overhead} = [ { label => 'overhead', nlabel => 'memory.overhead.usage.bytes', set => { key_values => [ { name => 'display' }, { name => 'label' }, { 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') } } ]; $self->{maps_counters}->{startup} = [ { label => 'startup', nlabel => 'memory.startup.usage.bytes', set => { key_values => [ { name => 'display' }, { name => 'label' }, { 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') } } ]; $self->{maps_counters}->{dataset} = [ { label => 'dataset', nlabel => 'memory.dataset.usage.bytes', set => { key_values => [ { name => 'display' }, { name => 'label' }, { 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') } } ]; $self->{maps_counters}->{lua} = [ { label => 'lua', nlabel => 'memory.lua.usage.bytes', set => { key_values => [ { name => 'display' }, { name => 'label' }, { 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') } } ]; $self->{maps_counters}->{stats} = [ { label => 'fragmentation-ratio', nlabel => 'memory.fragmentation.ratio.count', set => { key_values => [ { name => 'mem_fragmentation_ratio' } ], output_template => 'fragmentation ratio: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'defrag-running', nlabel => 'memory.defragmentation.running.count', set => { key_values => [ { name => 'active_defrag_running' } ], output_template => 'defragmentation running: %s', perfdatas => [ { label => 'defrag_running', template => '%s', min => 0 } ] } }, { label => 'lazyfree-pending-objects', nlabel => 'memory.lazy_pending_objects.count', set => { key_values => [ { name => 'lazyfree_pending_objects' } ], output_template => 'lazyfree pending objects: %s', perfdatas => [ { label => 'lazyfree_pending_objects', template => '%s', min => 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 => { 'units:s' => { name => 'units', default => '%' }, 'free' => { name => 'free' } }); return $self; } my $metrics = { used_memory => { label => 'used', display => 'used' }, used_memory_rss => { label => 'rss', display => 'rss' }, used_memory_peak => { label => 'peak', display => 'peak' }, used_memory_overhead => { label => 'overhead', display => 'overhead' }, used_memory_startup => { label => 'startup', display => 'startup' }, used_memory_dataset => { label => 'dataset', display => 'dataset' }, used_memory_lua => { label => 'lua', display => 'lua' } }; sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->get_info(); foreach my $type (keys %$metrics) { next if (!defined($results->{$type})); $self->{$metrics->{$type}->{label}} = { display => $metrics->{$type}->{display}, label => $metrics->{$type}->{label}, used => $results->{$type}, total => $results->{total_system_memory} }; } $self->{stats} = { mem_fragmentation_ratio => $results->{mem_fragmentation_ratio}, active_defrag_running => $results->{active_defrag_running}, lazyfree_pending_objects => $results->{lazyfree_pending_objects} }; } 1; __END__ =head1 MODE Check memory utilization =over 8 =item B<--units> Units of thresholds (Default: '%') ('%', 'B'). =item B<--free> Thresholds are on free space left. =item B<--warning-used> Warning threshold for Used memory utilization =item B<--critical-used> Critical threshold for Used memory utilization =item B<--warning-rss> Warning threshold for Rss memory utilization =item B<--critical-rss> Critical threshold for Rss memory utilization =item B<--warning-peak> Warning threshold for Peak memory utilization =item B<--critical-peak> Critical threshold for Peak memory utilization =item B<--warning-overhead> Warning threshold for Overhead memory utilization =item B<--critical-overhead> Critical threshold for Overhead memory utilization =item B<--warning-startup> Warning threshold for Startup memory utilization =item B<--critical-startup> Critical threshold for Startup memory utilization =item B<--warning-dataset> Warning threshold for Dataset memory utilization =item B<--critical-dataset> Critical threshold for Dataset memory utilization =item B<--warning-lua> Warning threshold for Lua memory utilization =item B<--critical-lua> Critical threshold for Lua memory utilization =item B<--warning-fragmentation-ratio> Warning threshold for Fragmentation Ratio =item B<--critical-fragmentation-ratio> Critical threshold for Fragmentation Ratio =item B<--warning-defrag-running> Warning threshold for Running Defragmentation =item B<--critical-defrag-running> Critical threshold for Running Defragmentation =item B<--warning-lazyfree-pending-objects> Warning threshold for Lazyfree Pending Objects =item B<--critical-lazyfree-pending-objects> Critical threshold for Lazyfree Pending Objects =back =cut centreon-plugins-20220113/database/redis/mode/persistence.pm000066400000000000000000000130421417000230700237140ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::redis::mode::persistence; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf("RDB save status is '%s' [progress status: %s]", $self->{result_values}->{status}, $self->{result_values}->{progress_status}); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'status', type => 2, warning_default => '%{sync_status} =~ /in progress/i', critical_default => '%{link_status} =~ /down/i', set => { key_values => [ { name => 'status' }, { name => 'progress_status' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'changes', nlabel => 'rdb.changes.since_last_save.count', set => { key_values => [ { name => 'rdb_changes_since_last_save' } ], output_template => 'number of changes since the last dump: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'last-save', nlabel => 'rdb.last_successful_save.seconds',set => { key_values => [ { name => 'rdb_last_save_time' }, { name => 'rdb_last_save_time_sec' } ], output_template => 'time since last successful save: %s', perfdatas => [ { value => 'rdb_last_save_time_sec', template => '%s', min => 0, unit => 's' } ] } }, { label => 'save-size', nlabel => 'rdb.last_save.size.bytes', set => { key_values => [ { name => 'rdb_last_cow_size' } ], output_template => 'size of last save: %s %s', output_change_bytes => 1, perfdatas => [ { template => '%s', min => 0, unit => 'B' } ] } }, { label => 'last-save-duration', nlabel => 'rdb.last_save.duration.seconds', set => { key_values => [ { name => 'rdb_last_bgsave_time' } ], output_template => 'duration of last save: %s s', perfdatas => [ { template => '%s', min => 0, unit => 's' } ] } }, { label => 'current-save-duration', nlabel => 'rdb.current_save.duration.seconds', set => { key_values => [ { name => 'rdb_current_bgsave_time' } ], output_template => 'duration of current save: %s s', perfdatas => [ { template => '%s', min => 0, unit => 's' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } my %map_status = ( 0 => 'stopped', 1 => 'in progress' ); sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->get_info(); $self->{global} = { status => $results->{rdb_last_bgsave_status}, progress_status => $map_status{$results->{rdb_bgsave_in_progress}}, rdb_changes_since_last_save => $results->{rdb_changes_since_last_save}, rdb_last_save_time => centreon::plugins::misc::change_seconds(value => time() - $results->{rdb_last_save_time}), rdb_last_save_time_sec => time() - $results->{rdb_last_save_time}, rdb_last_cow_size => $results->{rdb_last_cow_size}, rdb_last_bgsave_time => $results->{rdb_last_bgsave_time_sec}, rdb_current_bgsave_time => $results->{rdb_current_bgsave_time_sec} }; } 1; __END__ =head1 MODE Check RDB persistence status. =over 8 =item B<--warning-status> Set warning threshold for status (Default: '%{progress_status} =~ /in progress/i'). Can used special variables like: %{progress_status}, %{status} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /fail/i'). Can used special variables like: %{progress_status}, %{status} =item B<--warning-*> Threshold warning. Can be: 'changes', 'last-save', 'save-size', 'last-save-duration', 'current-save-duration'. =item B<--critical-*> Threshold critical. Can be: 'changes', 'last-save', 'save-size', 'last-save-duration', 'current-save-duration'. =back =cut centreon-plugins-20220113/database/redis/mode/replication.pm000066400000000000000000000150211417000230700237000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::redis::mode::replication; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("Node role is '%s' [cluster: %s]", $self->{result_values}->{role}, $self->{result_values}->{cluster_state}); if ($self->{result_values}->{role} eq 'slave') { $msg .= sprintf( " [link status: %s] [sync status: %s]", $self->{result_values}->{link_status}, $self->{result_values}->{sync_status} ); } return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'master', type => 0, skipped_code => { -10 => 1 } }, { name => 'slave', type => 0, skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'status', type => 2, warning_default => '%{sync_status} =~ /in progress/i', critical_default => '%{link_status} =~ /down/i', set => { key_values => [ { name => 'link_status' }, { name => 'sync_status' }, { name => 'role' }, { name => 'cluster_state' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'connected-slaves', nlabel => 'replication.slaves.connected.count', set => { key_values => [ { name => 'connected_slaves' } ], output_template => 'number of connected slaves: %s', perfdatas => [ { template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{master} = [ { label => 'master-repl-offset', nlabel => 'replication.master.offset.count', set => { key_values => [ { name => 'master_repl_offset' } ], output_template => 'master replication offset: %s', perfdatas => [ { template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{slave} = [ { label => 'master-last-io', nlabel => 'replication.master.last_interaction.seconds', set => { key_values => [ { name => 'master_last_io_seconds_ago' } ], output_template => 'last interaction with master: %s s', perfdatas => [ { template => '%s', min => 0, unit => 's' } ] } }, { label => 'slave-repl-offset', nlabel => 'replication.slave.offset.count', set => { key_values => [ { name => 'slave_repl_offset' } ], output_template => 'slave replication offset: %s s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'slave-priority', nlabel => 'replication.slave.priority.count', set => { key_values => [ { name => 'slave_priority' } ], output_template => 'slave replication priority: %s', perfdatas => [ { template => '%s' } ] } }, { label => 'slave-read-only', nlabel => 'replication.slave.readonly.count',set => { key_values => [ { name => 'slave_read_only' } ], output_template => 'slave readonly: %s', perfdatas => [ { template => '%s' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } my %map_sync = ( 0 => 'stopped', 1 => 'in progress' ); my %map_cluster_state = ( 0 => 'disabled', 1 => 'enabled' ); sub manage_selection { my ($self, %options) = @_; my $results = $options{custom}->get_info(); $self->{global} = { connected_slaves => $results->{connected_slaves}, role => $results->{role}, cluster_state => defined($results->{cluster_enabled}) ? $map_cluster_state{$results->{cluster_enabled}} : '-', link_status => defined($results->{master_link_status}) ? $results->{master_link_status} : '-', sync_status => defined($results->{master_sync_in_progress}) ? $map_sync{$results->{master_sync_in_progress}} : '-' }; $self->{master} = { master_repl_offset => $results->{master_repl_offset} }; $self->{slave} = { master_last_io_seconds_ago => $results->{master_last_io_seconds_ago}, slave_repl_offset => $results->{slave_repl_offset}, slave_priority => $results->{slave_priority}, slave_read_only => $results->{slave_read_only} }; } 1; __END__ =head1 MODE Check replication status. =over 8 =item B<--warning-status> Set warning threshold for status (Default: '%{sync_status} =~ /in progress/i'). Can used special variables like: %{sync_status}, %{link_status}, %{cluster_state} =item B<--critical-status> Set critical threshold for status (Default: '%{link_status} =~ /down/i'). Can used special variables like: %{sync_status}, %{link_status}, %{cluster_state} =item B<--warning-*> Threshold warning. Can be: 'connected-slaves', 'master-repl-offset', 'master-last-io', 'slave-priority', 'slave-read-only'. =item B<--critical-*> Threshold critical. Can be: 'connected-slaves', 'master-repl-offset', 'master-last-io', 'slave-priority', 'slave-read-only'. =back =cut centreon-plugins-20220113/database/redis/plugin.pm000066400000000000000000000032651417000230700217500ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::redis::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} = '1.0'; $self->{modes} = { 'clients' => 'database::redis::mode::clients', 'commands' => 'database::redis::mode::commands', 'connections' => 'database::redis::mode::connections', 'cpu' => 'database::redis::mode::cpu', 'memory' => 'database::redis::mode::memory', 'persistence' => 'database::redis::mode::persistence', 'replication' => 'database::redis::mode::replication' }; $self->{custom_modes}->{perlmod} = 'database::redis::custom::perlmod'; $self->{custom_modes}->{cli} = 'database::redis::custom::cli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Redis database. =cut centreon-plugins-20220113/database/rrdtool/000077500000000000000000000000001417000230700204655ustar00rootroot00000000000000centreon-plugins-20220113/database/rrdtool/local/000077500000000000000000000000001417000230700215575ustar00rootroot00000000000000centreon-plugins-20220113/database/rrdtool/local/custom/000077500000000000000000000000001417000230700230715ustar00rootroot00000000000000centreon-plugins-20220113/database/rrdtool/local/custom/cli.pm000066400000000000000000000146101417000230700242000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::rrdtool::local::custom::cli; use strict; use warnings; use centreon::plugins::ssh; use centreon::plugins::misc; use JSON::XS; 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 => { 'hostname:s' => { name => 'hostname' }, 'timeout:s' => { name => 'timeout' }, 'command:s' => { name => 'command' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options' }, 'sudo:s' => { name => 'sudo' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'CLI OPTIONS', once => 1); $self->{output} = $options{output}; $self->{ssh} = centreon::plugins::ssh->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; if (defined($self->{option_results}->{timeout}) && $self->{option_results}->{timeout} =~ /(\d+)/) { $self->{timeout} = $1; } if (defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '') { $self->{ssh}->check_options(option_results => $self->{option_results}); } return 0; } sub get_identifier { my ($self, %options) = @_; my $id = defined($self->{option_results}->{hostname}) ? $self->{option_results}->{hostname} : 'me'; if (defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '') { $id .= ':' . $self->{ssh}->get_port(); } return $id; } sub execute_command { my ($self, %options) = @_; my $timeout = $self->{timeout}; if (!defined($timeout)) { $timeout = defined($options{timeout}) ? $options{timeout} : 45; } my $command_options = defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne '' ? $self->{option_results}->{command_options} : $options{command_options}; my ($stdout, $exit_code); if (defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '') { ($stdout, $exit_code) = $self->{ssh}->execute( hostname => $self->{option_results}->{hostname}, sudo => $self->{option_results}->{sudo}, command => defined($self->{option_results}->{command}) && $self->{option_results}->{command} ne '' ? $self->{option_results}->{command} : $options{command}, command_path => defined($self->{option_results}->{command_path}) && $self->{option_results}->{command_path} ne '' ? $self->{option_results}->{command_path} : $options{command_path}, command_options => $command_options, timeout => $timeout, no_quit => $options{no_quit} ); } else { ($stdout, $exit_code) = centreon::plugins::misc::execute( output => $self->{output}, sudo => $self->{option_results}->{sudo}, options => { timeout => $timeout }, command => defined($self->{option_results}->{command}) && $self->{option_results}->{command} ne '' ? $self->{option_results}->{command} : $options{command}, command_path => defined($self->{option_results}->{command_path}) && $self->{option_results}->{command_path} ne '' ? $self->{option_results}->{command_path} : $options{command_path}, command_options => $command_options, no_quit => $options{no_quit} ); } $self->{output}->output_add(long_msg => "command response: $stdout", debug => 1); return ($stdout, $exit_code); } sub query { my ($self, %options) = @_; my $command_options = 'graph - --start=' . $options{start} . ' --end=' . $options{end} . ' --imgformat=JSON' . ' DEF:v1="' . $options{rrd_file} . ':' . $options{ds_name} . ':AVERAGE"' . ' LINE1:v1#00CC00:v1' . ' VDEF:v1max=v1,MAXIMUM' . ' VDEF:v1min=v1,MINIMUM' . ' VDEF:v1avg=v1,AVERAGE' . ' GPRINT:v1max:"MAX\:%6.2lf"' . ' GPRINT:v1min:"MIN\:%6.2lf"' . ' GPRINT:v1avg:"AVG\:%6.2lf"'; my ($stdout) = $self->execute_command( command => 'rrdtool', command_options => $command_options ); my $decoded; eval { $decoded = JSON::XS->new->decode($stdout); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } my $results = {}; foreach (@{$decoded->{meta}->{gprints}}) { if (defined($_->{gprint}) && $_->{gprint} =~ /(MIN|MAX|AVG):\s*([0-9\.]+)/) { $results->{ lc($1) } = $2; } } return $results; } 1; __END__ =head1 NAME rrdtool command line. =head1 SYNOPSIS rrdtool command line. =head1 CLI OPTIONS =over 8 =item B<--hostname> Hostname to query. =item B<--timeout> Timeout in seconds for the command (Default: 45). Default value can be override by the mode. =item B<--command> Command to get information. Used it you have output in a file. =item B<--command-path> Command path. =item B<--command-options> Command options. =item B<--sudo> sudo command. =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/database/rrdtool/local/custom/perlmod.pm000066400000000000000000000053231417000230700250740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::rrdtool::local::custom::perlmod; use strict; use warnings; use RRDs; 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 => { }); } $options{options}->add_help(package => __PACKAGE__, sections => 'PERLMOD OPTIONS', once => 1); $self->{output} = $options{output}; return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { return 0; } sub get_identifier { my ($self, %options) = @_; return 'none'; } sub query { my ($self, %options) = @_; my ($prints) = RRDs::graph( '/dev/null', '--start=' . $options{start}, '--end=' . $options{end}, '--imgformat=JSON', 'DEF:v1=' . $options{rrd_file} . ':' . $options{ds_name} . ':AVERAGE', 'LINE1:v1#00CC00:v1', 'VDEF:v1max=v1,MAXIMUM', 'VDEF:v1min=v1,MINIMUM', 'VDEF:v1avg=v1,AVERAGE', 'PRINT:v1max:MAX\:%6.2lf', 'PRINT:v1min:MIN\:%6.2lf', 'PRINT:v1avg:AVG\:%6.2lf' ); if (RRDs::error()) { $self->{output}->add_option_msg(short_msg => "rrd graph error: " . RRDs::error()); $self->{output}->option_exit(); } my $results = {}; foreach (@$prints) { if (/(MIN|MAX|AVG):\s*([0-9\.]+)/) { $results->{ lc($1) } = $2; } } return $results; } 1; __END__ =head1 NAME perlmod rrds. =head1 SYNOPSIS perlmod rrds. =head1 PERLMOD OPTIONS no options. =head1 DESCRIPTION B. =cut centreon-plugins-20220113/database/rrdtool/local/mode/000077500000000000000000000000001417000230700225035ustar00rootroot00000000000000centreon-plugins-20220113/database/rrdtool/local/mode/query.pm000066400000000000000000000105521417000230700242110ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::rrdtool::local::mode::query; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_global_output { my ($self, %options) = @_; return "datasource '" . $options{instance_value}->{ds_name} . "': "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'value-minimum', nlabel => 'datasource.value.minimum.count', set => { key_values => [ { name => 'min' }, { name => 'ds_name' } ], output_template => '%s (min)', perfdatas => [ { template => '%s', label_extra_instance => 1, instance_use => 'ds_name' } ] } }, { label => 'value-average', nlabel => 'datasource.value.average.count', set => { key_values => [ { name => 'avg' }, { name => 'ds_name' } ], output_template => '%s (avg)', perfdatas => [ { template => '%s', label_extra_instance => 1, instance_use => 'ds_name' } ] } }, { label => 'value-maximum', nlabel => 'datasource.value.maximum.count', set => { key_values => [ { name => 'max'}, { name => 'ds_name' } ], output_template => '%s (max)', perfdatas => [ { template => '%s', label_extra_instance => 1, instance_use => 'ds_name' } ] } } ]; } 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 => { 'rrd-file:s' => { name => 'rrd_file' }, 'ds-name:s' => { name => 'ds_name', default => 'value' }, 'timeframe:s' => { name => 'timeframe', default => 3600 } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (!defined($self->{option_results}->{rrd_file}) || $self->{option_results}->{rrd_file} eq '') { $self->{output}->add_option_msg(short_msg => 'Please set --rrd-file option.'); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{timeframe}) || $self->{option_results}->{timeframe} eq '') { $self->{output}->add_option_msg(short_msg => 'Please set --timeframe option.'); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{ds_name}) || $self->{option_results}->{ds_name} eq '') { $self->{output}->add_option_msg(short_msg => 'Please set --ds-name option.'); $self->{output}->option_exit(); } } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->query( rrd_file => $self->{option_results}->{rrd_file}, ds_name => $self->{option_results}->{ds_name}, start => time() - $self->{option_results}->{timeframe}, end => time() ); $self->{global} = { ds_name => $self->{option_results}->{ds_name}, %$result }; } 1; __END__ =head1 MODE Query DS min/max/average on a timeframe. =over 8 =item B<--rrd-file> Set rrd file to query. =item B<--ds-name> Set DS name to query (default: 'value'). =item B<--timeframe> Set timeframe in seconds (E.g '3600' to check last 60 minutes). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'value-minimum', 'value-average', 'value-maximum'. =back =cut centreon-plugins-20220113/database/rrdtool/local/plugin.pm000066400000000000000000000025521417000230700234170ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::rrdtool::local::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} = { 'query' => 'database::rrdtool::local::mode::query' }; $self->{custom_modes}->{cli} = 'database::rrdtool::local::custom::cli'; $self->{custom_modes}->{perlmod} = 'database::rrdtool::local::custom::perlmod'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check rrdtool database. =cut centreon-plugins-20220113/database/sap/000077500000000000000000000000001417000230700175635ustar00rootroot00000000000000centreon-plugins-20220113/database/sap/hana/000077500000000000000000000000001417000230700204725ustar00rootroot00000000000000centreon-plugins-20220113/database/sap/hana/mode/000077500000000000000000000000001417000230700214165ustar00rootroot00000000000000centreon-plugins-20220113/database/sap/hana/mode/blockedtransactions.pm000066400000000000000000000046101417000230700260110ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::sap::hana::mode::blockedtransactions; 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 }, ]; $self->{maps_counters}->{global} = [ { label => 'blocked-transactions', nlabel => 'transactions.blocked.count', set => { key_values => [ { name => 'total' } ], output_template => 'Current Total Blocked Transactions : %s', perfdatas => [ { label => 'total_blocked_transactions', value => 'total', template => '%s', min => 0 }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); my $query = q{ SELECT COUNT(*) AS total FROM M_BLOCKED_TRANSACTIONS }; $options{sql}->query(query => $query); $self->{global} = { total => 0 }; if (my $row = $options{sql}->fetchrow_hashref()) { $self->{global}->{total} = $row->{total} if (defined($row->{total})); } } 1; __END__ =head1 MODE Check total blocked transactions. =over 8 =item B<--warning-*> Threshold warning. Can be: 'blocked-transactions'. =item B<--critical-*> Threshold critical. Can be: 'blocked-transactions'. =back =cutcentreon-plugins-20220113/database/sap/hana/mode/connectedusers.pm000066400000000000000000000066351417000230700250120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::sap::hana::mode::connectedusers; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'host', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All connected users are ok' }, ]; $self->{maps_counters}->{host} = [ { label => 'users', nlabel => 'users.count', set => { key_values => [ { name => 'total' }, { name => 'display' } ], output_template => 'Connected Users : %s', perfdatas => [ { label => 'users', value => 'total', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub prefix_output { my ($self, %options) = @_; return "Host '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-username:s" => { name => 'filter_username' }, }); return $self; } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); my $query = q{ SELECT * FROM SYS.M_CONNECTIONS WHERE CONNECTION_TYPE IN ('Remote') }; $options{sql}->query(query => $query); $self->{host} = {}; while ((my $row = $options{sql}->fetchrow_hashref())) { my $name = $row->{HOST} . ':' . $row->{PORT}; $self->{host}->{$name} = { total => 0, display => $name } if (!defined($self->{host}->{$name})); if (defined($self->{option_results}->{filter_username}) && $self->{option_results}->{filter_username} ne '' && $row->{USER_NAME} !~ /$self->{option_results}->{filter_username}/) { $self->{output}->output_add(long_msg => "skipping '" . $name . '/' . $row->{USER_NAME} . "': no matching filter.", debug => 1); next; } $self->{host}->{$name}->{total}++; } if (scalar(keys %{$self->{host}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No host found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check connected users. =over 8 =item B<--filter-username> Filter connected username. (Can be a regex) =item B<--warning-*> Threshold warning. Can be: 'users'. =item B<--critical-*> Threshold critical. Can be: 'users'. =back =cutcentreon-plugins-20220113/database/sap/hana/mode/diskusage.pm000066400000000000000000000153141417000230700237370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::sap::hana::mode::diskusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'disk', type => 1, cb_prefix_output => 'prefix_volume_output', message_multiple => 'All disks are ok' }, ]; $self->{maps_counters}->{disk} = [ { label => 'usage', nlabel => 'disk.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'total' }, { name => 'display' } ], 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 custom_usage_perfdata { my ($self, %options) = @_; my ($label, $nlabel) = ('used', $self->{nlabel}); my $value_perf = $self->{result_values}->{used}; if (defined($self->{instance_mode}->{option_results}->{free})) { ($label, $nlabel) = ('free', 'disk.usage.free.bytes'); $value_perf = $self->{result_values}->{free}; } my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } $self->{output}->perfdata_add( label => $label, unit => 'B', nlabel => $self->{nlabel}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, 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} ); } sub custom_usage_threshold { my ($self, %options) = @_; my ($exit, $threshold_value); $threshold_value = $self->{result_values}->{used}; $threshold_value = $self->{result_values}->{free} if (defined($self->{instance_mode}->{option_results}->{free})); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; $threshold_value = $self->{result_values}->{prct_free} if (defined($self->{instance_mode}->{option_results}->{free})); } $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel}, 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("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 new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "units:s" => { name => 'units', default => '%' }, "free" => { name => 'free' }, }); return $self; } sub prefix_disk_output { my ($self, %options) = @_; return "Disk '" . $options{instance_value}->{display} . "' "; } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); my $query = q{ SELECT * FROM SYS.M_DISKS }; $options{sql}->query(query => $query); $self->{disk} = {}; while ((my $row = $options{sql}->fetchrow_hashref())) { my $name = $row->{HOST} . ':' . $row->{PATH}; 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->{disk}->{$name} = { used => $row->{USED_SIZE}, total => $row->{TOTAL_SIZE}, display => $name }; } 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 usages. =over 8 =item B<--warning-usage> Threshold warning. =item B<--critical-usage> Threshold critical. =item B<--filter-name> Filter disk name. (Can be a regex) =item B<--units> Default is '%', can be 'B' =item B<--free> Thresholds are on free space left. =back =cut centreon-plugins-20220113/database/sap/hana/mode/hostcpu.pm000066400000000000000000000143321417000230700234440ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::sap::hana::mode::hostcpu; 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 => 'cpu', type => 1, cb_prefix_output => 'prefix_cpu_output', message_multiple => 'All cpu usages are ok' }, ]; $self->{maps_counters}->{cpu} = [ { label => 'user', nlabel => 'host.cpu.user.utilization.percentage', set => { key_values => [ { name => 'total', diff => 1 }, { name => 'user', diff => 1 }, { name => 'display' } ], closure_custom_calc => $self->can('custom_data_calc'), closure_custom_calc_extra_options => { label_ref => 'user' }, output_template => 'User %.2f %%', output_use => 'user_prct', threshold_use => 'user_prct', perfdatas => [ { label => 'user', value => 'user_prct', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'sys', nlabel => 'host.cpu.system.utilization.percentage', set => { key_values => [ { name => 'total', diff => 1 }, { name => 'sys', diff => 1 }, { name => 'display' } ], closure_custom_calc => $self->can('custom_data_calc'), closure_custom_calc_extra_options => { label_ref => 'sys' }, output_template => 'System %.2f %%', output_use => 'sys_prct', threshold_use => 'sys_prct', perfdatas => [ { label => 'sys', value => 'sys_prct', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'wait', nlabel => 'host.cpu.wait.utilization.percentage', set => { key_values => [ { name => 'total', diff => 1 }, { name => 'wait', diff => 1 }, { name => 'display' } ], closure_custom_calc => $self->can('custom_data_calc'), closure_custom_calc_extra_options => { label_ref => 'wait' }, output_template => 'Wait %.2f %%', output_use => 'wait_prct', threshold_use => 'wait_prct', perfdatas => [ { label => 'wait', value => 'wait_prct', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'idle', nlabel => 'host.cpu.idle.utilization.percentage', set => { key_values => [ { name => 'total', diff => 1 }, { name => 'idle', diff => 1 }, { name => 'display' } ], closure_custom_calc => $self->can('custom_data_calc'), closure_custom_calc_extra_options => { label_ref => 'idle' }, output_template => 'Idle %.2f %%', output_use => 'idle_prct', threshold_use => 'idle_prct', perfdatas => [ { label => 'idle', value => 'idle_prct', template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub custom_data_calc { my ($self, %options) = @_; my $label = $options{extra_options}->{label_ref}; my $delta_value = $options{new_datas}->{$self->{instance} . '_' . $label} - $options{old_datas}->{$self->{instance} . '_' . $label}; my $delta_total = $options{new_datas}->{$self->{instance} . '_total'} - $options{old_datas}->{$self->{instance} . '_total'}; $self->{result_values}->{$label . '_prct'} = 0; if ($delta_total > 0) { $self->{result_values}->{$label . '_prct'} = $delta_value * 100 / $delta_total; } return 0; } sub prefix_cpu_output { my ($self, %options) = @_; return "CPU '" . $options{instance_value}->{display} . "' Usage : "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); my $query = q{ SELECT * FROM SYS.M_HOST_RESOURCE_UTILIZATION }; $options{sql}->query(query => $query); $self->{cache_name} = "sap_hana_db_" . $self->{mode} . '_' . $options{sql}->get_unique_id4save() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); $self->{cpu} = {}; while ((my $row = $options{sql}->fetchrow_hashref())) { my $name = $row->{HOST}; $self->{cpu}->{$name} = { display => $name, total => $row->{TOTAL_CPU_SYSTEM_TIME} + $row->{TOTAL_CPU_USER_TIME} + $row->{TOTAL_CPU_IDLE_TIME} + $row->{TOTAL_CPU_WIO_TIME}, sys => $row->{TOTAL_CPU_SYSTEM_TIME}, user => $row->{TOTAL_CPU_USER_TIME}, idle => $row->{TOTAL_CPU_IDLE_TIME}, wait => $row->{TOTAL_CPU_WIO_TIME}, }; } } 1; __END__ =head1 MODE Check system CPUs. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example : --filter-counters='^idle$' =item B<--warning-*> Threshold warning. Can be: 'user', 'sys', 'idle', 'wait'. =item B<--critical-*> Threshold critical. Can be: 'user', 'sys', 'idle', 'wait'. =back =cutcentreon-plugins-20220113/database/sap/hana/mode/hostmemory.pm000066400000000000000000000151421417000230700241650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::sap::hana::mode::hostmemory; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_usage_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( label => 'used', unit => 'B', nlabel => $self->{nlabel}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, value => $self->{result_values}->{used}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), min => 0, max => $self->{result_values}->{total} ); } sub custom_usage_threshold { my ($self, %options) = @_; my $exit = $self->{perfdata}->threshold_check(value => $self->{result_values}->{prct_used}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, 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("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}->{label} = $options{extra_options}->{label_ref}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_used'} + $options{new_datas}->{$self->{instance} . '_free'}; $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_used'}; $self->{result_values}->{free} = $options{new_datas}->{$self->{instance} . '_free'}; $self->{result_values}->{prct_free} = $self->{result_values}->{free} * 100 / $self->{result_values}->{total}; $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; 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 physical memories are ok' }, { name => 'swap', type => 1, cb_prefix_output => 'prefix_swap_output', message_multiple => 'All swap memories are ok' }, ]; $self->{maps_counters}->{memory} = [ { label => 'physical-usage', nlabel => 'host.memory.usage.bytes', set => { key_values => [ { name => 'free' }, { name => 'used' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { label_ref => 'physical' }, 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'), } }, ]; $self->{maps_counters}->{swap} = [ { label => 'swap-usage', nlabel => 'host.swap.usage.bytes', set => { key_values => [ { name => 'free' }, { name => 'used' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { label_ref => 'swap' }, 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 prefix_memory_output { my ($self, %options) = @_; return "Physical memory '" . $options{instance_value}->{display} . "' "; } sub prefix_swap_output { my ($self, %options) = @_; return "Swap memory '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); my $query = q{ SELECT * FROM SYS.M_HOST_RESOURCE_UTILIZATION }; $options{sql}->query(query => $query); $self->{swap} = {}; $self->{memory} = {}; while ((my $row = $options{sql}->fetchrow_hashref())) { my $name = $row->{HOST}; $self->{memory}->{$name} = { display => $name, free => $row->{FREE_PHYSICAL_MEMORY}, used => $row->{USED_PHYSICAL_MEMORY}, }; $self->{swap}->{$name} = { display => $name, free => $row->{FREE_SWAP_SPACE}, used => $row->{USED_SWAP_SPACE}, }; } } 1; __END__ =head1 MODE Check memory usages. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example : --filter-counters='^physical-usage$' =item B<--warning-*> Threshold warning. Can be: 'physical-usage' (%), 'swap-usage' (%). =item B<--critical-*> Threshold critical. Can be: 'physical-usage' (%), 'swap-usage' (%). =back =cut centreon-plugins-20220113/database/sap/hana/mode/volumeusage.pm000066400000000000000000000154721417000230700243210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::sap::hana::mode::volumeusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'volume', type => 1, cb_prefix_output => 'prefix_volume_output', message_multiple => 'All data volumes are ok' }, ]; $self->{maps_counters}->{volume} = [ { label => 'usage', nlabel => 'volume.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'total' }, { name => 'display' } ], 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 custom_usage_perfdata { my ($self, %options) = @_; my ($label, $nlabel) = ('used', $self->{nlabel}); my $value_perf = $self->{result_values}->{used}; if (defined($self->{instance_mode}->{option_results}->{free})) { ($label, $nlabel) = ('free', 'volume.free.usage.bytes'); $value_perf = $self->{result_values}->{free}; } my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } $self->{output}->perfdata_add( label => $label, unit => 'B', nlabel => $self->{nlabel}, instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, 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} ); } sub custom_usage_threshold { my ($self, %options) = @_; my ($exit, $threshold_value); $threshold_value = $self->{result_values}->{used}; $threshold_value = $self->{result_values}->{free} if (defined($self->{instance_mode}->{option_results}->{free})); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; $threshold_value = $self->{result_values}->{prct_free} if (defined($self->{instance_mode}->{option_results}->{free})); } $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel}, 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("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 new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "units:s" => { name => 'units', default => '%' }, "free" => { name => 'free' }, }); return $self; } sub prefix_volume_output { my ($self, %options) = @_; return "Volume '" . $options{instance_value}->{display} . "' "; } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); my $query = q{ SELECT * FROM SYS.M_VOLUME_FILES WHERE FILE_TYPE = 'DATA' }; $options{sql}->query(query => $query); $self->{volume} = {}; while ((my $row = $options{sql}->fetchrow_hashref())) { my $volume_name = $row->{HOST} . ':' . $row->{FILE_NAME}; if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $volume_name !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $volume_name . "': no matching filter.", debug => 1); next; } $self->{volume}->{$volume_name} = { used => $row->{USED_SIZE}, total => $row->{TOTAL_SIZE}, display => $volume_name }; } if (scalar(keys %{$self->{volume}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No volume found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check data volume usages. =over 8 =item B<--warning-usage> Threshold warning. =item B<--critical-usage> Threshold critical. =item B<--filter-name> Filter volume name. (Can be a regex) =item B<--units> Default is '%', can be 'B' =item B<--free> Thresholds are on free space left. =back =cut centreon-plugins-20220113/database/sap/hana/plugin.pm000066400000000000000000000070631417000230700223340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::sap::hana::plugin; use strict; use warnings; use base qw(centreon::plugins::script_sql); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $self->{version} = '0.1'; $self->{modes} = { 'blocked-transactions' => 'database::sap::hana::mode::blockedtransactions', 'collection' => 'centreon::common::protocols::sql::mode::collection', 'connected-users' => 'database::sap::hana::mode::connectedusers', 'connection-time' => 'centreon::common::protocols::sql::mode::connectiontime', 'disk-usage' => 'database::sap::hana::mode::diskusage', 'host-memory' => 'database::sap::hana::mode::hostmemory', 'host-cpu' => 'database::sap::hana::mode::hostcpu', 'sql' => 'centreon::common::protocols::sql::mode::sql', 'volume-usage' => 'database::sap::hana::mode::volumeusage' }; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options( arguments => { 'servernode:s@' => { name => 'servernode' }, 'port:s@' => { name => 'port' }, 'database:s' => { name => 'database' } } ); $self->{options}->parse_options(); my $options_result = $self->{options}->get_options(); $self->{options}->clean(); if (defined($options_result->{servernode})) { @{$self->{sqldefault}->{dbi}} = (); for (my $i = 0; $i < scalar(@{$options_result->{servernode}}); $i++) { $self->{sqldefault}->{dbi}[$i] = { data_source => 'ODBC:DRIVER={HDBODBC};SERVERNODE=' . $options_result->{servernode}[$i] }; if (defined($options_result->{port}[$i])) { $self->{sqldefault}->{dbi}[$i]->{data_source} .= ':' . $options_result->{port}[$i]; } else { $self->{sqldefault}->{dbi}[$i]->{data_source} .= ':30013'; } if ((defined($options_result->{database})) && ($options_result->{database} ne '')) { $self->{sqldefault}->{dbi}[$i]->{data_source} .= ';DATABASENAME=' . $options_result->{database}; } } } $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check SAP Hana DB Server. Prerequisite on the system: =over 8 =item * SAP Hana client for Linux/Unix =item * unixODBC and perl DBD::ODBC =item * Add in file /etc/odbcinst.ini [HDBODBC] Description = "SmartCloudPT HANA" Driver=/usr/sap/hdbclient/libodbcHDB.so =item * Use option --connect-options="LongReadLen=1000000,LongTruncOk=1" =back =over 8 =item B<--servernode> Hostname to query. =item B<--port> Database Server Port (default: 30013). =item B<--database> Database name to connect. =back =cut centreon-plugins-20220113/database/sybase/000077500000000000000000000000001417000230700202665ustar00rootroot00000000000000centreon-plugins-20220113/database/sybase/mode/000077500000000000000000000000001417000230700212125ustar00rootroot00000000000000centreon-plugins-20220113/database/sybase/mode/blockedprocesses.pm000066400000000000000000000062761417000230700251150ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::sybase::mode::blockedprocesses; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "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) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); $self->{sql}->query(query => q{SELECT count(*) FROM master.dbo.sysprocesses WHERE blocked <> 0}); my $blocked = $self->{sql}->fetchrow_array(); my $exit_code = $self->{perfdata}->threshold_check(value => $blocked, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("%i blocked process(es).", $blocked)); $self->{output}->perfdata_add(label => 'blocked_processes', value => $blocked, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check MSSQL blocked processes. =over 8 =item B<--warning> Threshold warning. =item B<--critical> Threshold critical. =back =cut centreon-plugins-20220113/database/sybase/mode/connectedusers.pm000066400000000000000000000062511417000230700246000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::sybase::mode::connectedusers; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "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) = @_; # $options{sql} = sqlmode object $self->{sql} = $options{sql}; $self->{sql}->connect(); $self->{sql}->query(query => q{SELECT count(*) FROM master..sysprocesses WHERE spid >= 51}); my $users = $self->{sql}->fetchrow_array(); my $exit_code = $self->{perfdata}->threshold_check(value => $users, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("%i Connected user(s).", $users)); $self->{output}->perfdata_add(label => 'connected_users', value => $users, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check MSSQL connected users. =over 8 =item B<--warning> Threshold warning. =item B<--critical> Threshold critical. =back =cut centreon-plugins-20220113/database/sybase/mode/databasessize.pm000066400000000000000000000200141417000230700243670ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::sybase::mode::databasessize; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'database', type => 1, cb_prefix_output => 'prefix_database_output', message_multiple => 'All databases are OK', message_separator => ' - ' }, ]; $self->{maps_counters}->{database} = [ { label => 'data', set => { key_values => [ { name => 'data_used' }, { name => 'data_size' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { label_ref => 'data' }, 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 => 'log', set => { key_values => [ { name => 'log_used' }, { name => 'log_size' }, { name => 'display' } ], closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { label_ref => 'log' }, 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 custom_usage_perfdata { my ($self, %options) = @_; my $label = $self->{result_values}->{label} . '_used'; my $value_perf = $self->{result_values}->{used}; if (defined($self->{instance_mode}->{option_results}->{free})) { $label = $self->{result_values}->{label} . '_free'; $value_perf = $self->{result_values}->{free}; } my %total_options = (); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $total_options{total} = $self->{result_values}->{total}; $total_options{cast_int} = 1; } $self->{output}->perfdata_add( label => $label, unit => 'B', instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, 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} ); } sub custom_usage_threshold { my ($self, %options) = @_; my ($exit, $threshold_value); $threshold_value = $self->{result_values}->{used}; $threshold_value = $self->{result_values}->{free} if (defined($self->{instance_mode}->{option_results}->{free})); if ($self->{instance_mode}->{option_results}->{units} eq '%') { $threshold_value = $self->{result_values}->{prct_used}; $threshold_value = $self->{result_values}->{prct_free} if (defined($self->{instance_mode}->{option_results}->{free})); } $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel}, 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("Total %s: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", ucfirst($self->{result_values}->{label}), $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) = @_; my $label = $options{extra_options}->{label_ref}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_' . $label . '_size'}; $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_' . $label . '_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}; $self->{result_values}->{label} = $label; return 0; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-database:s" => { name => 'filter_database' }, "units:s" => { name => 'units', default => '%' }, "free" => { name => 'free' }, }); return $self; } sub prefix_database_output { my ($self, %options) = @_; return "Database '" . $options{instance_value}->{display} . "' "; } sub manage_selection { my ($self, %options) = @_; $options{sql}->connect(); $options{sql}->query(query => q{ select db_name(d.dbid) as db_name, ceiling(sum(case when u.segmap != 4 then u.size/1.*@@maxpagesize end )) as data_size, ceiling(sum(case when u.segmap != 4 then size - curunreservedpgs(u.dbid, u.lstart, u.unreservedpgs) end)/1.*@@maxpagesize) as data_used, ceiling(sum(case when u.segmap in (4, 7) then u.size/1.*@@maxpagesize end)) as log_size, ceiling(sum(case when u.segmap in (4, 7) then u.size/1.*@@maxpagesize end) - lct_admin("logsegment_freepages",d.dbid)/1.*@@maxpagesize) as log_used from master..sysdatabases d, master..sysusages u where u.dbid = d.dbid and d.status not in (256,4096) group by d.dbid order by db_name(d.dbid) }); my $result = $options{sql}->fetchall_arrayref(); foreach my $row (@$result) { if (defined($self->{option_results}->{filter_database}) && $self->{option_results}->{filter_database} ne '' && $$row[0] !~ /$self->{option_results}->{filter_database}/) { $self->{output}->output_add(long_msg => "skipping '" . $$row[0] . "': no matching filter.", debug => 1); next; } $self->{database}->{$$row[0]} = { data_size => $$row[1], data_used => $$row[2], log_size => $$row[3], log_used => $$row[4], display => lc($$row[0]) }; } } 1; __END__ =head1 MODE Check MSSQL Database usage =over 8 =item B<--warning-*> Threshold warning. Can be: 'data', 'log'. =item B<--critical-*> Threshold warning. Can be: 'data', 'log'. =item B<--filter-database> Filter database by name. Can be a regex =item B<--units> Units of thresholds (Default: '%') ('%', 'B'). =item B<--free> Thresholds are on free space left. =back =cut centreon-plugins-20220113/database/sybase/plugin.pm000066400000000000000000000064601417000230700221300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::sybase::plugin; use strict; use warnings; use base qw(centreon::plugins::script_sql); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $self->{version} = '0.1'; $self->{modes} = { 'blocked-processes' => 'database::sybase::mode::blockedprocesses', 'collection' => 'centreon::common::protocols::sql::mode::collection', 'connected-users' => 'database::sybase::mode::connectedusers', 'connection-time' => 'centreon::common::protocols::sql::mode::connectiontime', 'databases-size' => 'database::sybase::mode::databasessize', 'sql' => 'centreon::common::protocols::sql::mode::sql' }; return $self; } sub init { my ($self, %options) = @_; $self->{options}->add_options( arguments => { 'hostname:s@' => { name => 'hostname' }, 'port:s@' => { name => 'port' }, 'tds-level:s@' => { name => 'tds_level' }, 'database:s' => { name => 'database' } } ); $self->{options}->parse_options(); my $options_result = $self->{options}->get_options(); $self->{options}->clean(); if (defined($options_result->{hostname})) { @{$self->{sqldefault}->{dbi}} = (); for (my $i = 0; $i < scalar(@{$options_result->{hostname}}); $i++) { $self->{sqldefault}->{dbi}[$i] = { data_source => 'Sybase:host=' . $options_result->{hostname}[$i] }; my $port = defined($options_result->{port}[$i]) && $options_result->{port}[$i] ne '' ? $options_result->{port}[$i] : 2638; $self->{sqldefault}->{dbi}[$i]->{data_source} .= ';port=' . $port; my $tds_level = defined($options_result->{tds_level}[$i]) && $options_result->{tds_level}[$i] ne '' ? $options_result->{tds_level}[$i] : 'CS_TDS_50'; $self->{sqldefault}->{dbi}[$i]->{data_source} .= ';tdsLevel=' . $tds_level; if ((defined($options_result->{database})) && ($options_result->{database} ne '')) { $self->{sqldefault}->{dbi}[$i]->{data_source} .= ';database=' . $options_result->{database}; } } } $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Sybase Server. =over 8 =item B<--hostname> Hostname to query. =item B<--port> Database Server Port (Default: 2638). =item B<--tds-level> TDS protocol level to use (Default: 'CS_TDS_50') =back =cut centreon-plugins-20220113/database/warp10/000077500000000000000000000000001417000230700201125ustar00rootroot00000000000000centreon-plugins-20220113/database/warp10/sensision/000077500000000000000000000000001417000230700221245ustar00rootroot00000000000000centreon-plugins-20220113/database/warp10/sensision/mode/000077500000000000000000000000001417000230700230505ustar00rootroot00000000000000centreon-plugins-20220113/database/warp10/sensision/mode/fetchstatistics.pm000066400000000000000000000171751417000230700266250ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::warp10::sensision::mode::fetchstatistics; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::common::monitoring::openmetrics::scrape; use Digest::MD5 qw(md5_hex); sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'fetchs', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All fetchs statistics are ok' }, ]; $self->{maps_counters}->{fetchs} = [ { label => 'calls-count', nlabel => 'fetch.calls.count', set => { key_values => [ { name => 'calls', diff => 1 }, { name => 'display' } ], output_template => 'Calls: %d', perfdatas => [ { template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'calls-persecond', nlabel => 'fetch.calls.persecond', set => { key_values => [ { name => 'calls', per_second => 1 }, { name => 'display' } ], output_template => 'Calls (per second): %.2f', perfdatas => [ { template => '%.2f', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'bytes-values-count', nlabel => 'fetch.bytes.values.bytes', set => { key_values => [ { name => 'bytes_values', diff => 1 }, { name => 'display' } ], output_template => 'Bytes Values: %s%s', output_change_bytes => 1, perfdatas => [ { template => '%s', min => 0, unit => 'B', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'bytes-values-persecond', nlabel => 'fetch.bytes.values.bytespersecond', set => { key_values => [ { name => 'bytes_values', per_second => 1 }, { name => 'display' } ], output_change_bytes => 1, output_template => 'Bytes Values (per second): %s%s/s', perfdatas => [ { template => '%s', min => 0, unit => 'B/s', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'bytes-keys-count', nlabel => 'fetch.bytes.keys.bytes', set => { key_values => [ { name => 'bytes_keys', diff => 1 }, { name => 'display' } ], output_template => 'Bytes Keys: %s%s', output_change_bytes => 1, perfdatas => [ { template => '%s', min => 0, unit => 'B', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'bytes-keys-persecond', nlabel => 'fetch.bytes.keys.bytespersecond', set => { key_values => [ { name => 'bytes_keys', per_second => 1 }, { name => 'display' } ], output_change_bytes => 1, output_template => 'Bytes Keys (per second): %s%s/s', perfdatas => [ { template => '%s', min => 0, unit => 'B/s', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'datapoints-count', nlabel => 'fetch.datapoints.count', set => { key_values => [ { name => 'datapoints', diff => 1 }, { name => 'display' } ], output_template => 'Datapoints: %d', perfdatas => [ { template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'datapoints-persecond', nlabel => 'fetch.datapoints.persecond', set => { key_values => [ { name => 'datapoints', per_second => 1 }, { name => 'display' } ], output_template => 'Datapoints (per second): %.2f', perfdatas => [ { template => '%.2f', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub prefix_output { my ($self, %options) = @_; return "Fetch '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = "warp10_" . $self->{mode} . '_' . (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); $self->{metrics} = centreon::common::monitoring::openmetrics::scrape::parse(%options); foreach my $fetch (@{$self->{metrics}->{'warp.fetch.count'}->{data}}) { $self->{fetchs}->{$fetch->{dimensions}->{app}}->{calls} = $fetch->{value}; $self->{fetchs}->{$fetch->{dimensions}->{app}}->{display} = $fetch->{dimensions}->{app}; } foreach my $fetch (@{$self->{metrics}->{'warp.fetch.bytes.values'}->{data}}) { $self->{fetchs}->{$fetch->{dimensions}->{app}}->{bytes_values} = $fetch->{value}; $self->{fetchs}->{$fetch->{dimensions}->{app}}->{display} = $fetch->{dimensions}->{app}; } foreach my $fetch (@{$self->{metrics}->{'warp.fetch.bytes.keys'}->{data}}) { $self->{fetchs}->{$fetch->{dimensions}->{app}}->{bytes_keys} = $fetch->{value}; $self->{fetchs}->{$fetch->{dimensions}->{app}}->{display} = $fetch->{dimensions}->{app}; } foreach my $fetch (@{$self->{metrics}->{'warp.fetch.datapoints'}->{data}}) { $self->{fetchs}->{$fetch->{dimensions}->{app}}->{datapoints} = $fetch->{value}; $self->{fetchs}->{$fetch->{dimensions}->{app}}->{display} = $fetch->{dimensions}->{app}; } foreach (keys %{$self->{fetchs}}) { delete $self->{fetchs}->{$_} if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $_ !~ /$self->{option_results}->{filter_name}/); } if (scalar(keys %{$self->{fetchs}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No fetchs found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check fetchs statistics. =over 8 =item B<--filter-name> Filter app name (can be a regexp). =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='calls' =item B<--warning-*-count/persecond> Threshold warning. Can be: 'calls', 'bytes-values', 'bytes-keys'. =item B<--critical-*-count/persecond> Threshold critical. Can be: 'calls', 'bytes-values', 'bytes-keys'. =back =cut centreon-plugins-20220113/database/warp10/sensision/mode/scriptstatistics.pm000066400000000000000000000207711417000230700270340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::warp10::sensision::mode::scriptstatistics; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::common::monitoring::openmetrics::scrape; use Digest::MD5 qw(md5_hex); sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'functions', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All functions statistics are ok' }, ]; $self->{maps_counters}->{global} = [ { label => 'time-total', nlabel => 'time.total.microseconds', set => { key_values => [ { name => 'time', diff => 1 } ], output_template => 'Time Spent: %d us', perfdatas => [ { template => '%d', min => 0, unit => 'us' }, ], } }, { label => 'requests-count', nlabel => 'requests.count', set => { key_values => [ { name => 'requests', diff => 1 } ], output_template => 'Requests: %d', perfdatas => [ { template => '%d', min => 0 }, ], } }, { label => 'requests-persecond', nlabel => 'requests.persecond', set => { key_values => [ { name => 'requests', per_second => 1 } ], output_template => 'Requests (per second): %.2f', perfdatas => [ { template => '%.2f', min => 0 }, ], } }, { label => 'ops-count', nlabel => 'ops.count', set => { key_values => [ { name => 'ops', diff => 1 } ], output_template => 'Ops: %d', perfdatas => [ { template => '%d', min => 0 }, ], } }, { label => 'ops-persecond', nlabel => 'ops.persecond', set => { key_values => [ { name => 'ops', per_second => 1 } ], output_template => 'Ops (per second): %.2f', perfdatas => [ { template => '%.2f', min => 0 }, ], } }, { label => 'errors-count', nlabel => 'errors.count', set => { key_values => [ { name => 'errors', diff => 1 } ], output_template => 'Errors: %d', perfdatas => [ { template => '%d', min => 0 }, ], } }, { label => 'errors-persecond', nlabel => 'errors.persecond', set => { key_values => [ { name => 'errors', per_second => 1 } ], output_template => 'Errors (per second): %.2f', perfdatas => [ { template => '%.2f', min => 0 }, ], } }, { label => 'bootstrap-loads-count', nlabel => 'bootstrap.loads.count', set => { key_values => [ { name => 'bootstrap_loads', diff => 1 } ], output_template => 'Bootstrap Loads: %d', perfdatas => [ { template => '%d', min => 0 }, ], } }, { label => 'bootstrap-loads-persecond', nlabel => 'bootstrap.loads.persecond', set => { key_values => [ { name => 'bootstrap_loads', per_second => 1 } ], output_template => 'Bootstrap Loads (per second): %.2f', perfdatas => [ { template => '%.2f', min => 0 }, ], } }, ]; $self->{maps_counters}->{functions} = [ { label => 'time', nlabel => 'function.time.microseconds', set => { key_values => [ { name => 'time', diff => 1 }, { name => 'display' } ], output_template => 'Time Spent: %d us', perfdatas => [ { template => '%d', min => 0, unit => 'us', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'uses-count', nlabel => 'function.uses.count', set => { key_values => [ { name => 'count', diff => 1 }, { name => 'display' } ], output_template => 'Uses: %d', perfdatas => [ { template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'uses-persecond', nlabel => 'function.uses.persecond', set => { key_values => [ { name => 'count', per_second => 1 }, { name => 'display' } ], output_template => 'Uses (per second): %.2f', perfdatas => [ { template => '%.2f', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } } ]; } sub prefix_output { my ($self, %options) = @_; return "Function '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = "warp10_" . $self->{mode} . '_' . (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); $self->{functions} = {}; $self->{metrics} = centreon::common::monitoring::openmetrics::scrape::parse(%options); $self->{global} = { time => $self->{metrics}->{'warp.script.time.us'}->{data}[0]->{value}, requests => $self->{metrics}->{'warp.script.requests'}->{data}[0]->{value}, ops => $self->{metrics}->{'warp.script.ops'}->{data}[0]->{value}, errors => $self->{metrics}->{'warp.script.errors'}->{data}[0]->{value}, bootstrap_loads => $self->{metrics}->{'warp.script.bootstrap.loads'}->{data}[0]->{value}, }; foreach my $function (@{$self->{metrics}->{'warp.script.function.count'}->{data}}) { $self->{functions}->{$function->{dimensions}->{function}}->{count} = $function->{value}; $self->{functions}->{$function->{dimensions}->{function}}->{display} = $function->{dimensions}->{function}; } foreach my $function (@{$self->{metrics}->{'warp.script.function.time.us'}->{data}}) { $self->{functions}->{$function->{dimensions}->{function}}->{time} = $function->{value}; $self->{functions}->{$function->{dimensions}->{function}}->{display} = $function->{dimensions}->{function}; } foreach (keys %{$self->{functions}}) { delete $self->{functions}->{$_} if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $_ !~ /$self->{option_results}->{filter_name}/); } if (scalar(keys %{$self->{functions}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No functions found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check script and functions statistics. =over 8 =item B<--filter-name> Filter function name (can be a regexp). =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^time$|uses' =item B<--warning-*-count/persecond> Threshold warning. Can be: 'time-total' (delta), 'requests', 'ops', 'errors', 'bootstrap-loads', 'time' (delta), 'uses'. =item B<--critical-*-count/persecond> Threshold critical. Can be: 'time-total' (delta), 'requests', 'ops', 'errors', 'bootstrap-loads', 'time' (delta), 'uses'. =back =cut centreon-plugins-20220113/database/warp10/sensision/plugin.pm000066400000000000000000000030051417000230700237560ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package database::warp10::sensision::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}} = ( 'fetch-statistics' => 'database::warp10::sensision::mode::fetchstatistics', 'script-statistics' => 'database::warp10::sensision::mode::scriptstatistics', ); $self->{custom_modes}{web} = 'centreon::common::monitoring::openmetrics::custom::web'; $self->{custom_modes}{file} = 'centreon::common::monitoring::openmetrics::custom::file'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Warp10 using Sensision metrics. =cut centreon-plugins-20220113/doc/000077500000000000000000000000001417000230700160015ustar00rootroot00000000000000centreon-plugins-20220113/doc/en/000077500000000000000000000000001417000230700164035ustar00rootroot00000000000000centreon-plugins-20220113/doc/en/Makefile000066400000000000000000000127041417000230700200470ustar00rootroot00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " text to make text files" @echo " man to make manual pages" @echo " texinfo to make Texinfo files" @echo " info to make Texinfo files and run them through makeinfo" @echo " gettext to make PO message catalogs" @echo " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: -rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Centreon.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Centreon.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/Centreon" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Centreon" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." texinfo: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." @echo "Run \`make' in that directory to run these through makeinfo" \ "(use \`make info' here to do that automatically)." info: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo "Running Texinfo files through makeinfo..." make -C $(BUILDDIR)/texinfo info @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." gettext: $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale @echo @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." centreon-plugins-20220113/doc/en/conf.py000066400000000000000000000202641417000230700177060ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # Centreon documentation build configuration file, created by # sphinx-quickstart on Wed Nov 7 16:30:34 2012. # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys, os on_centreon_rtd = os.environ.get('CENTREON_RTD', None) == 'True' # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. #sys.path.insert(0, os.path.abspath('.')) # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ['sphinx.ext.todo', 'sphinx.ext.intersphinx'] intersphinx_mapping = { 'centreon-engine': ('http://documentation.centreon.com/docs/centreon-engine/en/latest', None), 'centreon-broker': ('http://documentation.centreon.com/docs/centreon-broker/en/latest', None), 'centreon-clib': ('http://documentation.centreon.com/docs/centreon-clib/en/latest', None), 'ces': ('http://documentation.centreon.com/docs/centreon-enterprise-server/en/latest', None), } # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] todo_include_todos = True # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = u'Centreon Plugins' copyright = u'2007-2020 Centreon' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = 'latest' # The full version, including alpha/beta/rc tags. release = 'latest' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ['_build'] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- if on_centreon_rtd: # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'centreon' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. #html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. html_theme_path = ['/srv/themes'] else: html_theme = 'default' # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_domain_indices = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'Centreondoc' # -- Options for LaTeX output -------------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). #'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). #'pointsize': '10pt', # Additional stuff for the LaTeX preamble. #'preamble': '', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('index', 'Centreon.tex', u'Centreon Plugins Documentation', u'Merethis', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # If true, show page references after internal links. #latex_show_pagerefs = False # If true, show URL addresses after external links. #latex_show_urls = False # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_domain_indices = True # -- Options for manual page output -------------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'centreon', u'Centreon Plugins Documentation', [u'Merethis'], 1) ] # If true, show URL addresses after external links. #man_show_urls = False # -- Options for Texinfo output ------------------------------------------------ # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ ('index', 'Centreon', u'Centreon Documentation', u'Merethis', 'Centreon', 'One line description of project.', 'Miscellaneous'), ] # Documents to append as an appendix to all manuals. #texinfo_appendices = [] # If false, no module index is generated. #texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. #texinfo_show_urls = 'footnote' centreon-plugins-20220113/doc/en/developer/000077500000000000000000000000001417000230700203705ustar00rootroot00000000000000centreon-plugins-20220113/doc/en/developer/guide.rst000066400000000000000000002240171417000230700222250ustar00rootroot00000000000000*********** Description *********** This document introduces the best practices in the development of "centreon-plugins". As all plugins are written in Perl, “there is more than one way to do it”. But to avoid reinventing the wheel, you should first take a look at the “example” directory, you will get an overview of how to build your own plugin and associated modes. There are 3 chapters: * :ref:`Quick Start `: Howto create file structure. * :ref:`Libraries Reference `: API description. * :ref:`Code Style Guidelines `: Follow it. * :ref:`Model Classes Usage `: description of classes you should use for your plugin. The lastest version is available on following git repository: https://github.com/centreon/centreon-plugins.git .. _quick-start: *********** Quick Start *********** ------------------ Directory creation ------------------ First of all, you need to create a directory on the git to store the new plugin. Root directories are organized by section: * Application : apps * Database : database * Hardware : hardware * network equipment : network * Operating System : os * Storage equipment : storage According to the monitored object, it exists an organization which can use: * Type * Constructor * Model * Monitoring Protocol For example, if you want to add a plugin to monitor Linux by SNMP, you need to create this directory: :: $ mkdir -p os/linux/snmp You also need to create a "mode" directory for futures modes: :: $ mkdir os/linux/snmp/mode --------------- Plugin creation --------------- Once the directory is created, create the plugin file inside it: :: $ touch plugin.pm Then, edit plugin.pm to add **license terms** by copying it from an other plugin. Don't forget to put your name at the end of it: .. code-block:: perl # ... # Authors : <> Next, describe your **package** name : it matches your plugin directory. .. code-block:: perl package path::to::plugin; Declare used libraries (**strict** and **warnings** are mandatory). Centreon libraries are described later: .. code-block:: perl use strict; use warnings; use base qw(**centreon_library**); The plugin need a **new** constructor to instantiate the object: .. code-block:: perl sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; ... return $self; } Plugin version must be declared in the **new** constructor: .. code-block:: perl $self->{version} = '0.1'; Several modes can be declared in the **new** constructor: .. code-block:: perl $self->{modes} = { 'mode1' => '::mode::mode1', 'mode2' => '::mode::mode2', ... }; Then, declare the module: .. code-block:: perl 1; A description of the plugin is needed to generate the documentation: .. code-block:: perl __END__ =head1 PLUGIN DESCRIPTION . =cut .. tip:: You can copy-paste an other plugin.pm and adapt some lines (package, arguments...). .. tip:: The plugin has ".pm" extension because it's a Perl module. So don't forget to add **1;** at the end of the file. ------------- Mode creation ------------- Once **plugin.pm** is created and modes are declared in it, create modes in the **mode** directory: :: cd mode touch mode1.pm Then, edit mode1.pm to add **license terms** by copying it from an other mode. Don't forget to put your name at the end of it: .. code-block:: perl # ... # Authors : <> Next, describe your **package** name: it matches your mode directory. .. code-block:: perl package path::to::plugin::mode::mode1; Declare used libraries (always the same): .. code-block:: perl use strict; use warnings; use base qw(centreon::plugins::mode); The mode needs a **new** constructor to instantiate the object: .. code-block:: perl sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; ... return $self; } Mode version must be declared in the **new** constructor: .. code-block:: perl $self->{version} = '1.0'; Several options can be declared in the **new** constructor: .. code-block:: perl $options{options}->add_options(arguments => { "option1:s" => { name => 'option1' }, "option2:s" => { name => 'option2', default => 'value1' }, "option3" => { name => 'option3' }, }); Here is the description of arguments used in this example: * option1 : String value * option2 : String value with default value "value1" * option3 : Boolean value .. tip:: You can have more informations about options format here: http://perldoc.perl.org/Getopt/Long.html The mode need a **check_options** method to validate options: .. code-block:: perl sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); ... } For example, Warning and Critical thresholds must be validate in **check_options** method: .. code-block:: perl 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(); } In this example, help is printed if thresholds do not have a correct format. Then comes the **run** method, where you perform measurement, check thresholds, display output and format performance datas. This is an example to check a SNMP value: .. code-block:: perl sub run { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{hostname} = $self->{snmp}->get_hostname(); my $result = $self->{snmp}->get_leef(oids => [$self->{option_results}->{oid}], nothing_quit => 1); my $value = $result->{$self->{option_results}->{oid}}; 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("SNMP Value is %s.", $value)); $self->{output}->perfdata_add(label => 'value', unit => undef, value => $value, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => undef, max => undef); $self->{output}->display(); $self->{output}->exit(); } In this example, we check a SNMP OID that we compare to warning and critical thresholds. There are the methods which we use: * get_leef : get a SNMP value from an OID * threshold_check : compare SNMP value to warning and critical thresholds * output_add : add output * perfdata_add : add perfdata to output * display : display output * exit : exit Then, declare the module: .. code-block:: perl 1; A description of the mode and its arguments is needed to generate the documentation: .. code-block:: perl __END__ =head1 PLUGIN DESCRIPTION . =cut --------------- Commit and push --------------- Before committing the plugin, you need to create an **enhancement ticket** on the centreon-plugins forge : http://forge.centreon.com/projects/centreon-plugins Once plugin and modes are developed, you can commit (commit messages in english) and push your work: :: git add path/to/plugin git commit -m "Add new plugin for XXXX refs #" git push .. _libraries_reference: ******************* Libraries reference ******************* This chapter describes Centreon libraries which you can use in your development. ------ Output ------ This library allows you to build output of your plugin. output_add ---------- Description ^^^^^^^^^^^ Add string to output (print it with **display** method). If status is different than 'ok', output associated with 'ok' status is not printed. Parameters ^^^^^^^^^^ +-----------------+-----------------+-------------+---------------------------------------------------------+ | Parameter | Type | Default | Description | +=================+=================+=============+=========================================================+ | severity | String | OK | Status of the output. | +-----------------+-----------------+-------------+---------------------------------------------------------+ | separator | String | \- | Separator between status and output string. | +-----------------+-----------------+-------------+---------------------------------------------------------+ | short_msg | String | | Short output (first line). | +-----------------+-----------------+-------------+---------------------------------------------------------+ | long_msg | String | | Long output (used with --verbose option). | +-----------------+-----------------+-------------+---------------------------------------------------------+ Example ^^^^^^^ This is an example of how to manage output: .. code-block:: perl $self->{output}->output_add(severity => 'OK', short_msg => 'All is ok'); $self->{output}->output_add(severity => 'Critical', short_msg => 'There is a critical problem'); $self->{output}->output_add(long_msg => 'Port 1 is disconnected'); $self->{output}->display(); Output displays : :: CRITICAL - There is a critical problem Port 1 is disconnected perfdata_add ------------ Description ^^^^^^^^^^^ Add performance data to output (print it with **display** method). Performance data are displayed after '|'. Parameters ^^^^^^^^^^ +-----------------+-----------------+-------------+---------------------------------------------------------+ | Parameter | Type | Default | Description | +=================+=================+=============+=========================================================+ | label | String | | Label of the performance data. | +-----------------+-----------------+-------------+---------------------------------------------------------+ | value | Int | | Value of the performance data. | +-----------------+-----------------+-------------+---------------------------------------------------------+ | unit | String | | Unit of the performance data. | +-----------------+-----------------+-------------+---------------------------------------------------------+ | warning | String | | Warning threshold. | +-----------------+-----------------+-------------+---------------------------------------------------------+ | critical | String | | Critical threshold. | +-----------------+-----------------+-------------+---------------------------------------------------------+ | min | Int | | Minimum value of the performance data. | +-----------------+-----------------+-------------+---------------------------------------------------------+ | max | Int | | Maximum value of the performance data. | +-----------------+-----------------+-------------+---------------------------------------------------------+ Example ^^^^^^^ This is an example of how to add performance data: .. code-block:: perl $self->{output}->output_add(severity => 'OK', short_msg => 'Memory is ok'); $self->{output}->perfdata_add(label => 'memory_used', value => 30000000, unit => 'B', warning => '80000000', critical => '90000000', min => 0, max => 100000000); $self->{output}->display(); Output displays: :: OK - Memory is ok | 'memory_used'=30000000B;80000000;90000000;0;100000000 -------- Perfdata -------- This library allows you to manage performance data. get_perfdata_for_output ----------------------- Description ^^^^^^^^^^^ Manage thresholds of performance data for output. Parameters ^^^^^^^^^^ +-----------------+-----------------+-------------+-----------------------------------------------------------+ | Parameter | Type | Default | Description | +=================+=================+=============+===========================================================+ | **label** | String | | Threshold label. | +-----------------+-----------------+-------------+-----------------------------------------------------------+ | total | Int | | Percent threshold to transform in global. | +-----------------+-----------------+-------------+-----------------------------------------------------------+ | cast_int | Int (0 or 1) | | Cast absolute to int. | +-----------------+-----------------+-------------+-----------------------------------------------------------+ | op | String | | Operator to apply to start/end value (uses with 'value'). | +-----------------+-----------------+-------------+-----------------------------------------------------------+ | value | Int | | Value to apply with 'op' option. | +-----------------+-----------------+-------------+-----------------------------------------------------------+ Example ^^^^^^^ This is an example of how to manage performance data for output: .. code-block:: perl my $format_warning_perfdata = $self->{perfdata}->get_perfdata_for_output(label => 'warning', total => 1000000000, cast_int => 1); my $format_critical_perfdata = $self->{perfdata}->get_perfdata_for_output(label => 'critical', total => 1000000000, cast_int => 1); $self->{output}->perfdata_add(label => 'memory_used', value => 30000000, unit => 'B', warning => $format_warning_perfdata, critical => $format_critical_perfdata, min => 0, max => 1000000000); .. tip:: In this example, instead of print warning and critical thresholds in 'percent', the function calculates and prints these in 'bytes'. threshold_validate ------------------ Description ^^^^^^^^^^^ Validate and affect threshold to a label. Parameters ^^^^^^^^^^ +-----------------+-----------------+-------------+---------------------------------------------------------+ | Parameter | Type | Default | Description | +=================+=================+=============+=========================================================+ | label | String | | Threshold label. | +-----------------+-----------------+-------------+---------------------------------------------------------+ | value | String | | Threshold value. | +-----------------+-----------------+-------------+---------------------------------------------------------+ Example ^^^^^^^ This example checks if warning threshold is correct: .. code-block:: perl 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(); } .. tip:: You can see the correct threshold format here: https://nagios-plugins.org/doc/guidelines.html#THRESHOLDFORMAT threshold_check --------------- Description ^^^^^^^^^^^ Check performance data value with threshold to determine status. Parameters ^^^^^^^^^^ +-----------------+-----------------+-------------+---------------------------------------------------------+ | Parameter | Type | Default | Description | +=================+=================+=============+=========================================================+ | value | Int | | Performance data value to compare. | +-----------------+-----------------+-------------+---------------------------------------------------------+ | threshold | String array | | Threshold label to compare and exit status if reached. | +-----------------+-----------------+-------------+---------------------------------------------------------+ Example ^^^^^^^ This example checks if performance data reached thresholds: .. code-block:: perl $self->{perfdata}->threshold_validate(label => 'warning', value => 80); $self->{perfdata}->threshold_validate(label => 'critical', value => 90); my $prct_used = 85; my $exit = $self->{perfdata}->threshold_check(value => $prct_used, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit, short_msg => sprint("Used memory is %i%%", $prct_used)); $self->{output}->display(); Output displays: :: WARNING - Used memory is 85% | change_bytes ------------ Description ^^^^^^^^^^^ Convert bytes to human readable unit. Return value and unit. Parameters ^^^^^^^^^^ +-----------------+-----------------+-------------+---------------------------------------------------------+ | Parameter | Type | Default | Description | +=================+=================+=============+=========================================================+ | value | Int | | Performance data value to convert. | +-----------------+-----------------+-------------+---------------------------------------------------------+ | network | | 1024 | Unit to divide (1000 if defined). | +-----------------+-----------------+-------------+---------------------------------------------------------+ Example ^^^^^^^ This example change bytes to human readable unit: .. code-block:: perl my ($value, $unit) = $self->{perfdata}->change_bytes(value => 100000); print $value.' '.$unit."\n"; Output displays: :: 100 KB ---- Snmp ---- This library allows you to use SNMP protocol in your plugin. To use it, add the following line at the beginning of your **plugin.pm**: .. code-block:: perl use base qw(centreon::plugins::script_snmp); get_leef -------- Description ^^^^^^^^^^^ Return hash table table of SNMP values for multiple OIDs (do not work with SNMP table). Parameters ^^^^^^^^^^ +-----------------+-----------------+-------------+---------------------------------------------------------+ | Parameter | Type | Default | Description | +=================+=================+=============+=========================================================+ | **oids** | String array | | Array of OIDs to check (Can be set by 'load' method). | +-----------------+-----------------+-------------+---------------------------------------------------------+ | dont_quit | Int (0 or 1) | 0 | Don't quit even if an snmp error occured. | +-----------------+-----------------+-------------+---------------------------------------------------------+ | nothing_quit | Int (0 or 1) | 0 | Quit if no value is returned. | +-----------------+-----------------+-------------+---------------------------------------------------------+ Example ^^^^^^^ This is an example of how to get 2 SNMP values: .. code-block:: perl my $oid_hrSystemUptime = '.1.3.6.1.2.1.25.1.1.0'; my $oid_sysUpTime = '.1.3.6.1.2.1.1.3.0'; my $result = $self->{snmp}->get_leef(oids => [ $oid_hrSystemUptime, $oid_sysUpTime ], nothing_quit => 1); print $result->{$oid_hrSystemUptime}."\n"; print $result->{$oid_sysUpTime}."\n"; load ---- Description ^^^^^^^^^^^ Load a range of OIDs to use with **get_leef** method. Parameters ^^^^^^^^^^ +-----------------+----------------------+--------------+----------------------------------------------------------------+ | Parameter | Type | Default | Description | +=================+======================+==============+================================================================+ | **oids** | String array | | Array of OIDs to check. | +-----------------+----------------------+--------------+----------------------------------------------------------------+ | instances | Int array | | Array of OID instances to check. | +-----------------+----------------------+--------------+----------------------------------------------------------------+ | instance_regexp | String | | Regular expression to get instances from **instances** option. | +-----------------+----------------------+--------------+----------------------------------------------------------------+ | begin | Int | | Instance to begin | +-----------------+----------------------+--------------+----------------------------------------------------------------+ | end | Int | | Instance to end | +-----------------+----------------------+--------------+----------------------------------------------------------------+ Example ^^^^^^^ This is an example of how to get 4 instances of a SNMP table by using **load** method: .. code-block:: perl my $oid_dskPath = '.1.3.6.1.4.1.2021.9.1.2'; $self->{snmp}->load(oids => [$oid_dskPercentNode], instances => [1,2,3,4]); my $result = $self->{snmp}->get_leef(nothing_quit => 1); use Data::Dumper; print Dumper($result); This is an example of how to get multiple instances dynamically (memory modules of Dell hardware) by using **load** method: .. code-block:: perl my $oid_memoryDeviceStatus = '.1.3.6.1.4.1.674.10892.1.1100.50.1.5'; my $oid_memoryDeviceLocationName = '.1.3.6.1.4.1.674.10892.1.1100.50.1.8'; my $oid_memoryDeviceSize = '.1.3.6.1.4.1.674.10892.1.1100.50.1.14'; my $oid_memoryDeviceFailureModes = '.1.3.6.1.4.1.674.10892.1.1100.50.1.20'; my $result = $self->{snmp}->get_table(oid => $oid_memoryDeviceStatus); $self->{snmp}->load(oids => [$oid_memoryDeviceLocationName, $oid_memoryDeviceSize, $oid_memoryDeviceFailureModes], instances => [keys %$result], instance_regexp => '(\d+\.\d+)$'); my $result2 = $self->{snmp}->get_leef(); use Data::Dumper; print Dumper($result2); get_table --------- Description ^^^^^^^^^^^ Return hash table of SNMP values for SNMP table. Parameters ^^^^^^^^^^ +-----------------+----------------------+----------------+--------------------------------------------------------------+ | Parameter | Type | Default | Description | +=================+======================+================+==============================================================+ | **oid** | String | | OID of the snmp table to check. | +-----------------+----------------------+----------------+--------------------------------------------------------------+ | start | Int | | First OID to check. | +-----------------+----------------------+----------------+--------------------------------------------------------------+ | end | Int | | Last OID to check. | +-----------------+----------------------+----------------+--------------------------------------------------------------+ | dont_quit | Int (0 or 1) | 0 | Don't quit even if an SNMP error occured. | +-----------------+----------------------+----------------+--------------------------------------------------------------+ | nothing_quit | Int (0 or 1) | 0 | Quit if no value is returned. | +-----------------+----------------------+----------------+--------------------------------------------------------------+ | return_type | Int (0 or 1) | 0 | Return a hash table with one level instead of multiple. | +-----------------+----------------------+----------------+--------------------------------------------------------------+ Example ^^^^^^^ This is an example of how to get a SNMP table: .. code-block:: perl my $oid_rcDeviceError = '.1.3.6.1.4.1.15004.4.2.1'; my $oid_rcDeviceErrWatchdogReset = '.1.3.6.1.4.1.15004.4.2.1.2.0'; my $results = $self->{snmp}->get_table(oid => $oid_rcDeviceError, start => $oid_rcDeviceErrWatchdogReset); use Data::Dumper; print Dumper($results); get_multiple_table ------------------ Description ^^^^^^^^^^^ Return hash table of SNMP values for multiple SNMP tables. Parameters ^^^^^^^^^^ +-----------------+----------------------+----------------+--------------------------------------------------------------+ | Parameter | Type | Default | Description | +=================+======================+================+==============================================================+ | **oids** | Hash table | | Hash table of OIDs to check (Can be set by 'load' method). | | | | | Keys can be: "oid", "start", "end". | +-----------------+----------------------+----------------+--------------------------------------------------------------+ | dont_quit | Int (0 or 1) | 0 | Don't quit even if an SNMP error occured. | +-----------------+----------------------+----------------+--------------------------------------------------------------+ | nothing_quit | Int (0 or 1) | 0 | Quit if no value is returned. | +-----------------+----------------------+----------------+--------------------------------------------------------------+ | return_type | Int (0 or 1) | 0 | Return a hash table with one level instead of multiple. | +-----------------+----------------------+----------------+--------------------------------------------------------------+ Example ^^^^^^^ This is an example of how to get 2 SNMP tables: .. code-block:: perl my $oid_sysDescr = ".1.3.6.1.2.1.1.1"; my $aix_swap_pool = ".1.3.6.1.4.1.2.6.191.2.4.2.1"; my $results = $self->{snmp}->get_multiple_table(oids => [ { oid => $aix_swap_pool, start => 1 }, { oid => $oid_sysDescr }, ]); use Data::Dumper; print Dumper($results); get_hostname ------------ Description ^^^^^^^^^^^ Get hostname parameter (useful to get hostname in mode). Parameters ^^^^^^^^^^ None. Example ^^^^^^^ This is an example of how to get hostname parameter: .. code-block:: perl my $hostname = $self->{snmp}->get_hostname(); get_port -------- Description ^^^^^^^^^^^ Get port parameter (useful to get port in mode). Parameters ^^^^^^^^^^ None. Example ^^^^^^^ This is an example of how to get port parameter: .. code-block:: perl my $port = $self->{snmp}->get_port(); oid_lex_sort ------------ Description ^^^^^^^^^^^ Return sorted OIDs. Parameters ^^^^^^^^^^ +-----------------+-------------------+-------------+---------------------------------------------------------+ | Parameter | Type | Default | Description | +=================+===================+=============+=========================================================+ | **-** | String array | | Array of OIDs to sort. | +-----------------+-------------------+-------------+---------------------------------------------------------+ Example ^^^^^^^ This example prints sorted OIDs: .. code-block:: perl foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$my_oid}})) { print $oid; } ---- Misc ---- This library provides a set of miscellaneous methods. To use it, you can directly use the path of the method: .. code-block:: perl centreon::plugins::misc::; trim ---- Description ^^^^^^^^^^^ Strip whitespace from the beginning and end of a string. Parameters ^^^^^^^^^^ +-----------------+-----------------+-------------+---------------------------------------------------------+ | Parameter | Type | Default | Description | +=================+=================+=============+=========================================================+ | **-** | String | | String to strip. | +-----------------+-----------------+-------------+---------------------------------------------------------+ Example ^^^^^^^ This is an example of how to use **trim** method: .. code-block:: perl my $word = ' Hello world ! '; my $trim_word = centreon::plugins::misc::trim($word); print $word."\n"; print $trim_word."\n"; Output displays : :: Hello world ! change_seconds -------------- Description ^^^^^^^^^^^ Convert seconds to human readable text. Parameters ^^^^^^^^^^ +-----------------+-----------------+-------------+---------------------------------------------------------+ | Parameter | Type | Default | Description | +=================+=================+=============+=========================================================+ | **-** | Int | | Number of seconds to convert. | +-----------------+-----------------+-------------+---------------------------------------------------------+ Example ^^^^^^^ This is an example of how to use **change_seconds** method: .. code-block:: perl my $seconds = 3750; my $human_readable_time = centreon::plugins::misc::change_seconds($seconds); print 'Human readable time : '.$human_readable_time."\n"; Output displays: :: Human readable time : 1h 2m 30s backtick -------- Description ^^^^^^^^^^^ Execute system command. Parameters ^^^^^^^^^^ +-----------------+-----------------+-------------+---------------------------------------------------------+ | Parameter | Type | Default | Description | +=================+=================+=============+=========================================================+ | **command** | String | | Command to execute. | +-----------------+-----------------+-------------+---------------------------------------------------------+ | arguments | String array | | Command arguments. | +-----------------+-----------------+-------------+---------------------------------------------------------+ | timeout | Int | 30 | Command timeout. | +-----------------+-----------------+-------------+---------------------------------------------------------+ | wait_exit | Int (0 or 1) | 0 | Command process ignore SIGCHLD signals. | +-----------------+-----------------+-------------+---------------------------------------------------------+ | redirect_stderr | Int (0 or 1) | 0 | Print errors in output. | +-----------------+-----------------+-------------+---------------------------------------------------------+ Example ^^^^^^^ This is an example of how to use **backtick** method: .. code-block:: perl my ($error, $stdout, $exit_code) = centreon::plugins::misc::backtick( command => 'ls /home', timeout => 5, wait_exit => 1 ); print $stdout."\n"; Output displays files in '/home' directory. execute ------- Description ^^^^^^^^^^^ Execute command remotely. Parameters ^^^^^^^^^^ +------------------+-----------------+-------------+-----------------------------------------------------------------+ | Parameter | Type | Default | Description | +==================+=================+=============+=================================================================+ | **output** | Object | | Plugin output ($self->{output}). | +------------------+-----------------+-------------+-----------------------------------------------------------------+ | **options** | Object | | Plugin options ($self->{option_results}) to get remote options. | +------------------+-----------------+-------------+-----------------------------------------------------------------+ | sudo | String | | Use sudo command. | +------------------+-----------------+-------------+-----------------------------------------------------------------+ | **command** | String | | Command to execute. | +------------------+-----------------+-------------+-----------------------------------------------------------------+ | command_path | String | | Command path. | +------------------+-----------------+-------------+-----------------------------------------------------------------+ | command_options | String | | Command arguments. | +------------------+-----------------+-------------+-----------------------------------------------------------------+ Example ^^^^^^^ This is an example of how to use **execute** method. We suppose ``--remote`` option is enabled: .. code-block:: perl my $stdout = centreon::plugins::misc::execute(output => $self->{output}, options => $self->{option_results}, sudo => 1, command => 'ls /home', command_path => '/bin/', command_options => '-l'); Output displays files in /home using ssh on a remote host. windows_execute --------------- Description ^^^^^^^^^^^ Execute command on Windows. Parameters ^^^^^^^^^^ +------------------+-----------------+-------------+-----------------------------------------------------------------+ | Parameter | Type | Default | Description | +==================+=================+=============+=================================================================+ | **output** | Object | | Plugin output ($self->{output}). | +------------------+-----------------+-------------+-----------------------------------------------------------------+ | **command** | String | | Command to execute. | +------------------+-----------------+-------------+-----------------------------------------------------------------+ | command_path | String | | Command path. | +------------------+-----------------+-------------+-----------------------------------------------------------------+ | command_options | String | | Command arguments. | +------------------+-----------------+-------------+-----------------------------------------------------------------+ | timeout | Int | | Command timeout. | +------------------+-----------------+-------------+-----------------------------------------------------------------+ | no_quit | Int | | Don't quit even if an error occured. | +------------------+-----------------+-------------+-----------------------------------------------------------------+ Example ^^^^^^^ This is an example of how to use **windows_execute** method. .. code-block:: perl my $stdout = centreon::plugins::misc::windows_execute(output => $self->{output}, timeout => 10, command => 'ipconfig', command_path => '', command_options => '/all'); Output displays IP configuration on a Windows host. --------- Statefile --------- This library provides a set of methods to use a cache file. To use it, add the following line at the beginning of your **mode**: .. code-block:: perl use centreon::plugins::statefile; read ---- Description ^^^^^^^^^^^ Read cache file. Parameters ^^^^^^^^^^ +-------------------+-----------------+-------------+---------------------------------------------------------+ | Parameter | Type | Default | Description | +===================+=================+=============+=========================================================+ | **statefile** | String | | Name of the cache file. | +-------------------+-----------------+-------------+---------------------------------------------------------+ | **statefile_dir** | String | | Directory of the cache file. | +-------------------+-----------------+-------------+---------------------------------------------------------+ | memcached | String | | Memcached server to use. | +-------------------+-----------------+-------------+---------------------------------------------------------+ Example ^^^^^^^ This is an example of how to use **read** method: .. code-block:: perl $self->{statefile_value} = centreon::plugins::statefile->new(%options); $self->{statefile_value}->check_options(%options); $self->{statefile_value}->read(statefile => 'my_cache_file', statefile_dir => '/var/lib/centreon/centplugins' ); use Data::Dumper; print Dumper($self->{statefile_value}); Output displays cache file and its parameters. get --- Description ^^^^^^^^^^^ Get data from cache file. Parameters ^^^^^^^^^^ +-------------------+-----------------+-------------+---------------------------------------------------------+ | Parameter | Type | Default | Description | +===================+=================+=============+=========================================================+ | name | String | | Get a value from cache file. | +-------------------+-----------------+-------------+---------------------------------------------------------+ Example ^^^^^^^ This is an example of how to use **get** method: .. code-block:: perl $self->{statefile_value} = centreon::plugins::statefile->new(%options); $self->{statefile_value}->check_options(%options); $self->{statefile_value}->read(statefile => 'my_cache_file', statefile_dir => '/var/lib/centreon/centplugins' ); my $value = $self->{statefile_value}->get(name => 'property1'); print $value."\n"; Output displays value for 'property1' of the cache file. write ----- Description ^^^^^^^^^^^ Write data to cache file. Parameters ^^^^^^^^^^ +-------------------+-----------------+-------------+---------------------------------------------------------+ | Parameter | Type | Default | Description | +===================+=================+=============+=========================================================+ | data | String | | Data to write in cache file. | +-------------------+-----------------+-------------+---------------------------------------------------------+ Example ^^^^^^^ This is an example of how to use **write** method: .. code-block:: perl $self->{statefile_value} = centreon::plugins::statefile->new(%options); $self->{statefile_value}->check_options(%options); $self->{statefile_value}->read(statefile => 'my_cache_file', statefile_dir => '/var/lib/centreon/centplugins' ); my $new_datas = {}; $new_datas->{last_timestamp} = time(); $self->{statefile_value}->write(data => $new_datas); Then, you can read the result in '/var/lib/centreon/centplugins/my_cache_file', timestamp is written in it. ---- HTTP ---- This library provides a set of methodss to use HTTP protocol. To use it, add the following line at the beginning of your **mode**: .. code-block:: perl use centreon::plugins::http; Some options must be set in **plugin.pm**: +-----------------+-----------------+---------------------------------------------------------+ | Option | Type | Description | +=================+=================+=========================================================+ | **hostname** | String | IP Addr/FQDN of the webserver host. | +-----------------+-----------------+---------------------------------------------------------+ | **port** | String | HTTP port. | +-----------------+-----------------+---------------------------------------------------------+ | **proto** | String | Used protocol ('http' or 'https'). | +-----------------+-----------------+---------------------------------------------------------+ | credentials | | Use credentials. | +-----------------+-----------------+---------------------------------------------------------+ | ntlm | | Use NTLM authentication (if ``--credentials`` is used). | +-----------------+-----------------+---------------------------------------------------------+ | username | String | Username (if ``--credentials`` is used). | +-----------------+-----------------+---------------------------------------------------------+ | password | String | User password (if ``--credentials`` is used). | +-----------------+-----------------+---------------------------------------------------------+ | proxyurl | String | Proxy to use. | +-----------------+-----------------+---------------------------------------------------------+ | url_path | String | URL to connect (start to '/'). | +-----------------+-----------------+---------------------------------------------------------+ connect ------- Description ^^^^^^^^^^^ Test a connection to an HTTP url. Return content of the webpage. Parameters ^^^^^^^^^^ This method use plugin options previously defined. Example ^^^^^^^ This is an example of how to use **connect** method. We suppose these options are defined : * --hostname = 'google.com' * --urlpath = '/' * --proto = 'http' * --port = 80 .. code-block:: perl $self->{http} = centreon::plugins::http->new(output => $self->{output}, options => $self->{options}); $self->{http}->set_options(%{$self->{option_results}}); my $webcontent = $self->{http}->request(); print $webcontent; Output displays content of the webpage '\http://google.com/'. --- DBI --- This library allows you to connect to databases. To use it, add the following line at the beginning of your **plugin.pm**: .. code-block:: perl use base qw(centreon::plugins::script_sql); connect ------- Description ^^^^^^^^^^^ Connect to databases. Parameters ^^^^^^^^^^ +-------------------+-----------------+-------------+---------------------------------------------------------+ | Parameter | Type | Default | Description | +===================+=================+=============+=========================================================+ | dontquit | Int (0 or 1) | 0 | Don't quit even if errors occured. | +-------------------+-----------------+-------------+---------------------------------------------------------+ Example ^^^^^^^ This is an example of how to use **connect** method. The format of the connection string can have the following forms: :: DriverName:database_name DriverName:database_name@hostname:port DriverName:database=database_name;host=hostname;port=port In plugin.pm: .. code-block:: perl $self->{sqldefault}->{dbi} = (); $self->{sqldefault}->{dbi} = { data_source => 'mysql:host=127.0.0.1;port=3306' }; In your mode: .. code-block:: perl $self->{sql} = $options{sql}; my ($exit, $msg_error) = $self->{sql}->connect(dontquit => 1); Then, you are connected to the MySQL database. query ----- Description ^^^^^^^^^^^ Send query to database. Parameters ^^^^^^^^^^ +-------------------+-----------------+-------------+---------------------------------------------------------+ | Parameter | Type | Default | Description | +===================+=================+=============+=========================================================+ | query | String | | SQL query to send. | +-------------------+-----------------+-------------+---------------------------------------------------------+ Example ^^^^^^^ This is an example of how to use **query** method: .. code-block:: perl $self->{sql}->query(query => q{SHOW /*!50000 global */ STATUS LIKE 'Slow_queries'}); my ($name, $result) = $self->{sql}->fetchrow_array(); print 'Name : '.$name."\n"; print 'Value : '.$value."\n"; Output displays count of MySQL slow queries. fetchrow_array -------------- Description ^^^^^^^^^^^ Return Array from sql query. Parameters ^^^^^^^^^^ None. Example ^^^^^^^ This is an example of how to use **fetchrow_array** method: .. code-block:: perl $self->{sql}->query(query => q{SHOW /*!50000 global */ STATUS LIKE 'Uptime'}); my ($dummy, $result) = $self->{sql}->fetchrow_array(); print 'Uptime : '.$result."\n"; Output displays MySQL uptime. fetchall_arrayref ----------------- Description ^^^^^^^^^^^ Return Array from SQL query. Parameters ^^^^^^^^^^ None. Example ^^^^^^^ This is an example of how to use **fetchrow_array** method: .. code-block:: perl $self->{sql}->query(query => q{ SELECT SUM(DECODE(name, 'physical reads', value, 0)), SUM(DECODE(name, 'physical reads direct', value, 0)), SUM(DECODE(name, 'physical reads direct (lob)', value, 0)), SUM(DECODE(name, 'session logical reads', value, 0)) FROM sys.v_$sysstat }); my $result = $self->{sql}->fetchall_arrayref(); my $physical_reads = @$result[0]->[0]; my $physical_reads_direct = @$result[0]->[1]; my $physical_reads_direct_lob = @$result[0]->[2]; my $session_logical_reads = @$result[0]->[3]; print $physical_reads."\n"; Output displays physical reads on Oracle database. fetchrow_hashref ---------------- Description ^^^^^^^^^^^ Return Hash table from SQL query. Parameters ^^^^^^^^^^ None. Example ^^^^^^^ This is an example of how to use **fetchrow_hashref** method: .. code-block:: perl $self->{sql}->query(query => q{ SELECT datname FROM pg_database }); while ((my $row = $self->{sql}->fetchrow_hashref())) { print $row->{datname}."\n"; } Output displays Postgres databases. ***************** Complete examples ***************** ------------------- Simple SNMP request ------------------- Description ----------- | This example explains how to check a single SNMP value on a PfSense firewall (memory dropped packets). | We use cache file because it's a SNMP counter. So we need to get the value between 2 checks. | We get the value and compare it to warning and critical thresholds. Plugin file ----------- First, create the plugin directory and the plugin file: :: $ mkdir -p apps/pfsense/snmp $ touch apps/pfsense/snmp/plugin.pm .. tip:: PfSense is a firewall application and we check it using SNMP protocol Then, edit **plugin.pm** and add the following lines: .. code-block:: perl # # Copyright 2018 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. # # Path to the plugin package apps::pfsense::snmp::plugin; # Needed libraries use strict; use warnings; # Use this library to check using SNMP protocol use base qw(centreon::plugins::script_snmp); .. tip:: Don't forget to edit 'Authors' line. Add **new** method to instantiate the plugin: .. code-block:: perl sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; # $options->{options} = options object # Plugin version $self->{version} = '0.1'; # Modes association %{$self->{modes}} = ( # Mode name => path to the mode 'memory-dropped-packets' => 'apps::pfsense::snmp::mode::memorydroppedpackets', ); return $self; } Declare this plugin as a perl module: .. code-block:: perl 1; Add a description to the plugin: .. code-block:: perl __END__ =head1 PLUGIN DESCRIPTION Check pfSense in SNMP. =cut .. tip:: This description is printed with '--help' option. Mode file --------- Then, create the mode directory and the mode file: :: $ mkdir apps/pfsense/snmp/mode $ touch apps/pfsense/snmp/mode/memorydroppedpackets.pm Edit **memorydroppedpackets.pm** and add the following lines: .. code-block:: perl # # Copyright 2018 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. # # Path to the plugin package apps::pfsense::snmp::mode::memorydroppedpackets; # Needed library for modes use base qw(centreon::plugins::mode); # Needed libraries use strict; use warnings; # Custom library use POSIX; # Needed library to use cache file use centreon::plugins::statefile; Add **new** method to instantiate the mode: .. code-block:: perl sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; # Mode version $self->{version} = '1.0'; # Declare options $options{options}->add_options(arguments => { # option name => variable name "warning:s" => { name => 'warning', }, "critical:s" => { name => 'critical', }, }); # Instantiate cache file $self->{statefile_value} = centreon::plugins::statefile->new(%options); return $self; } .. tip:: A default value can be added to options. Example : "warning:s" => { name => 'warning', default => '80'}, Add **check_options** method to validate options: .. code-block:: perl sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); # Validate threshold options with threshold_validate method 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(); } # Validate cache file options using check_options method of statefile library $self->{statefile_value}->check_options(%options); } Add **run** method to execute mode: .. code-block:: perl sub run { my ($self, %options) = @_; # $options{snmp} = snmp object # Get SNMP options $self->{snmp} = $options{snmp}; $self->{hostname} = $self->{snmp}->get_hostname(); $self->{snmp_port} = $self->{snmp}->get_port(); # SNMP oid to request my $oid_pfsenseMemDropPackets = '.1.3.6.1.4.1.12325.1.200.1.2.6.0'; my ($result, $value); # Get SNMP value for oid previsouly defined $result = $self->{snmp}->get_leef(oids => [ $oid_pfsenseMemDropPackets ], nothing_quit => 1); # $result is a hash table where keys are oids $value = $result->{$oid_pfsenseMemDropPackets}; # Read the cache file $self->{statefile_value}->read(statefile => 'pfsense_' . $self->{hostname} . '_' . $self->{snmp_port} . '_' . $self->{mode}); # Get cache file values my $old_timestamp = $self->{statefile_value}->get(name => 'last_timestamp'); my $old_memDropPackets = $self->{statefile_value}->get(name => 'memDropPackets'); # Create a hash table with new values that will be write to cache file my $new_datas = {}; $new_datas->{last_timestamp} = time(); $new_datas->{memDropPackets} = $value; # Write new values to cache file $self->{statefile_value}->write(data => $new_datas); # If cache file didn't have any values, create it and wait another check to calculate value if (!defined($old_timestamp) || !defined($old_memDropPackets)) { $self->{output}->output_add(severity => 'OK', short_msg => "Buffer creation..."); $self->{output}->display(); $self->{output}->exit(); } # Fix when PfSense reboot (snmp counters initialize to 0) $old_memDropPackets = 0 if ($old_memDropPackets > $new_datas->{memDropPackets}); # Calculate time between 2 checks my $delta_time = $new_datas->{last_timestamp} - $old_timestamp; $delta_time = 1 if ($delta_time == 0); # Calculate value per second my $memDropPacketsPerSec = ($new_datas->{memDropPackets} - $old_memDropPackets) / $delta_time; # Calculate exit code by comparing value to thresholds # Exit code can be : 'OK', 'WARNING', 'CRITICAL', 'UNKNOWN' my $exit_code = $self->{perfdata}->threshold_check(value => $memDropPacketsPerSec, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); # Add a performance data $self->{output}->perfdata_add(label => 'dropped_packets_Per_Sec', value => sprintf("%.2f", $memDropPacketsPerSec), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0); # Add output $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("Dropped packets due to memory limitations : %.2f /s", $memDropPacketsPerSec)); # Display output $self->{output}->display(); $self->{output}->exit(); } Declare this plugin as a perl module: .. code-block:: perl 1; Add a description of the mode options: .. code-block:: perl __END__ =head1 MODE Check number of packets per second dropped due to memory limitations. =over 8 =item B<--warning> Threshold warning for dropped packets in packets per second. =item B<--critical> Threshold critical for dropped packets in packets per second. =back =cut Command line ------------ This is an example of command line: :: $ perl centreon_plugins.pl --plugin apps::pfsense::snmp::plugin --mode memory-dropped-packets --hostname 192.168.0.1 --snmp-community 'public' --snmp-version '2c' --warning '1' --critical '2' Output may display: :: OK: Dropped packets due to memory limitations : 0.00 /s | dropped_packets_Per_Sec=0.00;0;;1;2 .. _code_style_guidelines: ********************* Code Style Guidelines ********************* ------------ Introduction ------------ Perl code from Pull-request must conform to the following style guidelines. If you find any code which doesn't conform, please fix it. ----------- Indentation ----------- Space should be used to indent all code blocks. Tabs should never be used to indent code blocks. Mixing tabs and spaces results in misaligned code blocks for other developers who prefer different indentation settings. Please use 4 for indentation space width. .. code-block:: perl if ($1 > 1) { ....return 1; } else { if ($i == -1) { ....return 0; } return -1 } -------- Comments -------- There should always be at least 1 space between the # character and the beginning of the comment. This makes it a little easier to read multi-line comments: .. code-block:: perl # Good comment #Wrong comment --------------------------- Subroutine & Variable Names --------------------------- Whenever possible, use underscore to seperator words and don't use uppercase characters: .. code-block:: perl sub get_logs {} my $start_time; Keys of hash table should be used alphanumeric and underscore characters only (and no quote!): .. code-block:: perl $dogs->{meapolitan_mastiff} = 10; --------------------------- Curly Brackets, Parenthesis --------------------------- There should be a space between every control/loop keyword and the opening parenthesis: .. code-block:: perl if ($i == 1) { ... } while ($i == 2) { ... } ------------------ If/Else Statements ------------------ 'else', 'elsif' should be on the same line after the previous closing curly brace: .. code-block:: perl if ($i == 1) { ... } else { ... } You can use single line if conditional: .. code-block:: perl next if ($i == 1); .. _model_classes_usage: ******************* Model Classes Usage ******************* ------------ Introduction ------------ With the experience of plugin development, we have created two classes: * centreon::plugins::templates::counter * centreon::plugins::templates::hardware It was developed to have a more consistent code and less redundant code. According to context, you should use one of two classes for modes. Following classes can be used for whatever plugin type (SNMP, Custom, DBI,...). ------------- Class counter ------------- When to use it ? ---------------- If you have some counters (CPU Usage, Memory, Session...), you should use that class. If you have only one global counter to check, it's maybe not useful to use it (but only for these case). Class methods ------------- List of methods: * **new**: class constructor. Overload if you need to add some specific options or to use a statefile. * **check_options**: overload if you need to check your specific options. * **manage_selection**: overload if *mandatory*. Method to get informations for the equipment. * **set_counters**: overload if **mandatory**. Method to configure counters. Examples -------- Example 1 ^^^^^^^^^ We want to develop the following SNMP plugin: * measure the current sessions and current SSL sessions usages. .. code-block:: perl package my::module::name; 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 => 'sessions', set => { key_values => [ { name => 'sessions' } ], output_template => 'Current sessions : %s', perfdatas => [ { label => 'sessions', template => '%s', min => 0 }, ], } }, { label => 'sessions-ssl', set => { key_values => [ { name => 'sessions_ssl' } ], output_template => 'Current ssl sessions : %s', perfdatas => [ { label => 'sessions_ssl', template => '%s', min => 0 }, ], } }, ]; } sub manage_selection { my ($self, %options) = @_; # OIDs are fake. Only for the example. my ($oid_sessions, $oid_sessions_ssl) = ('.1.2.3.4.0', '.1.2.3.5.0'); my $result = $options{snmp}->get_leef( oids => [ $oid_sessions, $oid_sessions_ssl ], nothing_quit => 1 ); $self->{global} = { sessions => $result->{$oid_sessions}, sessions_ssl => $result->{$oid_sessions_ssl} }; } Output may display: :: OK: Current sessions : 24 - Current ssl sessions : 150 | sessions=24;;;0; sessions_ssl=150;;;0; As you can see, we create two arrays of hash tables in **set_counters** method. We use arrays to order the output. * **maps_counters_type**: global configuration. Attributes list: * *name*: the name is really important. It will be used in hash **map_counters** and also in **manage_selection** as you can see. * *type*: 0 or 1. With 0 value, the output will be written in the short output. With the value 1, it depends if we have one or multiple instances. * *message_multiple*: only useful with *type* 1 value. The message will be displayed in short ouput if we have multiple instances selected. * *message_separator*: the string displayed between counters (Default: ', '). * *cb_prefix_output*, *cb_suffix_output*: name of a method (in a string) to callback. Methods will return a string to be displayed before or after **all** counters. * *cb_init*: name of a method (in a string) to callback. Method will return 0 or 1. With 1 value, counters are not checked. * **maps_counters**: complex structure to configure counters. Attributes list: * *label*: name used for threshold options. * *threshold*: if we set the value to 0. There is no threshold check options (can be used if you want to set and check option yourself). * *set*: hash table: * *keys_values*: array of hashes. Set values used for the counter. Order is important (by default, the first value is used to check). * *name*: attribute name. Need to match with attributes in **manage_selection** method! * *diff*: if we set the value to 1, we'll have the difference between two checks (need a statefile!). * *per_second*: if we set the value to 1, the *diff* values will be calculated per seconds (need a statefile!). No need to add diff attribute. * *output_template*: string to display. '%s' will be replaced by the first value of *keys_values*. * *output_use*: which value to be used in *output_template* (If not set, we use the first value of *keys_values*). * *output_change_bytes*: if we set the value to 1 or 2, we can use a second '%s' in *output_template* to display the unit. 1 = divide by 1024 (Bytes), 2 = divide by 1000 (bits). * *perfdata*: array of hashes. To configure perfdatas * *label*: name displayed. * *value*: value to used. It's the name from *keys_values*. * *template*: value format (could be for example: '%.3f'). * *unit*: unit displayed. * *min*, *max*: min and max displayed. You can use a value from *keys_values*. * *label_extra_instance*: if we set the value to 1, perhaps we'll have a suffix concat with *label*. * *instance_use*: which value from *keys_values* to be used. To be used if *label_extra_instance* is 1. Example 2 ^^^^^^^^^ We want to add the current number of sessions by virtual servers. .. code-block:: perl package my::module::name; 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, cb_prefix_output => 'prefix_global_output' }, { name => 'vs', type => 1, cb_prefix_output => 'prefix_vs_output', message_multiple => 'All Virtual servers are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'total-sessions', set => { key_values => [ { name => 'sessions' } ], output_template => 'current sessions : %s', perfdatas => [ { label => 'total_sessions', template => '%s', min => 0 }, ], } }, { label => 'total-sessions-ssl', set => { key_values => [ { name => 'sessions_ssl' } ], output_template => 'current ssl sessions : %s', perfdatas => [ { label => 'total_sessions_ssl', template => '%s', min => 0 }, ], } }, ]; $self->{maps_counters}->{vs} = [ { label => 'sessions', set => { key_values => [ { name => 'sessions' }, { name => 'display' } ], output_template => 'current sessions : %s', perfdatas => [ { label => 'sessions', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'sessions-ssl', set => { key_values => [ { name => 'sessions_ssl' }, { name => 'display' } ], output_template => 'current ssl sessions : %s', perfdatas => [ { label => 'sessions_ssl', template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub prefix_vs_output { my ($self, %options) = @_; return "Virtual server '" . $options{instance_value}->{display} . "' "; } sub prefix_global_output { my ($self, %options) = @_; return "Total "; } sub manage_selection { my ($self, %options) = @_; # OIDs are fake. Only for the example. my ($oid_sessions, $oid_sessions_ssl) = ('.1.2.3.4.0', '.1.2.3.5.0'); my $result = $options{snmp}->get_leef(oids => [ $oid_sessions, $oid_sessions_ssl ], nothing_quit => 1); $self->{global} = { sessions => $result->{$oid_sessions}, sessions_ssl => $result->{$oid_sessions_ssl} }; my $oid_table_vs = '.1.2.3.10'; my $mapping = { vsName => { oid => '.1.2.3.10.1' }, vsSessions => { oid => '.1.2.3.10.2' }, vsSessionsSsl => { oid => '.1.2.3.10.3' }, }; $self->{vs} = {}; $result = $options{snmp}->get_table(oid => $oid_table_vs, nothing_quit => 1); foreach my $oid (keys %{$result->{ $oid_table_vs }}) { next if ($oid !~ /^$mapping->{vsName}->{oid}\.(.*)$/; my $instance = $1; my $data = $options{snmp}->map_instance(mapping => $mapping, results => $result->{$oid_table_vs}, instance => $instance); $self->{vs}->{$instance} = { display => $data->{vsName}, sessions => $data->{vsSessions}, sessions_ssl => $data->{vsSessionsSsl}}; } } If we have at least 2 virtual servers: :: OK: Total current sessions : 24, current ssl sessions : 150 - All Virtual servers are ok | total_sessions=24;;;0; total_sessions_ssl=150;;;0; sessions_foo1=11;;;0; sessions_ssl_foo1=70;;;0; sessions_foo2=13;;;0; sessions_ssl_foo2=80;;;0; Virtual server 'foo1' current sessions : 11, current ssl sessions : 70 Virtual server 'foo2' current sessions : 13, current ssl sessions : 80 Example 3 ^^^^^^^^^ The model can also be used to check strings (not only counters). So we want to check the status of a virtualserver. .. code-block:: perl package my::module::name; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'vs', type => 1, cb_prefix_output => 'prefix_vs_output', message_multiple => 'All Virtual server status are ok' } ]; $self->{maps_counters}->{vs} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { 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 custom_threshold_output { my ($self, %options) = @_; my $status = 'ok'; if ($self->{result_values}->{status} =~ /problem/) { $status = 'critical'; } return $status; } sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("status is '%s'", $self->{result_values}->{status}); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub prefix_vs_output { my ($self, %options) = @_; return "Virtual server '" . $options{instance_value}->{display} . "' "; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } sub manage_selection { my ($self, %options) = @_; my $oid_table_vs = '.1.2.3.10'; my $mapping = { vsName => { oid => '.1.2.3.10.1' }, vsStatus => { oid => '.1.2.3.10.4' }, }; $self->{vs} = {}; my $result = $options{snmp}->get_table(oid => $oid_table_vs, nothing_quit => 1); foreach my $oid (keys %{$result->{ $oid_table_vs }}) { next if ($oid !~ /^$mapping->{vsName}->{oid}\.(.*)$/; my $instance = $1; my $data = $options{snmp}->map_instance(mapping => $mapping, results => $result->{$oid_table_vs}, instance => $instance); $self->{vs}->{$instance} = { display => $data->{vsName}, status => $data->{vsStatus} }; } } The following example show 4 new attributes: * *closure_custom_calc*: should be used to do more complex calculation. * *closure_custom_output*: should be used to have a more complex output (An example: want to display the total, free and used value at the same time). * *closure_custom_perfdata*: should be used to manage yourself the perfdata. * *closure_custom_threshold_check*: should be used to manage yourself the threshold check. -------------- Class hardware -------------- TODO centreon-plugins-20220113/doc/en/developer/index.rst000066400000000000000000000001461417000230700222320ustar00rootroot00000000000000############### Developer guide ############### .. toctree:: :maxdepth: 3 :glob: guide centreon-plugins-20220113/doc/en/index.rst000066400000000000000000000006151417000230700202460ustar00rootroot00000000000000Welcome to Centreon Plugins documentation! ========================================== Centreon Plugins is a common monitoring library and plugins written in Perl. It is licensed under the terms of the `Apache License Version 2 `_ as published by the Free Software Foundation. Contents: .. toctree:: :maxdepth: 2 user/index developer/index centreon-plugins-20220113/doc/en/user/000077500000000000000000000000001417000230700173615ustar00rootroot00000000000000centreon-plugins-20220113/doc/en/user/guide.rst000066400000000000000000003265111417000230700212200ustar00rootroot00000000000000*********** Description *********** "centreon-plugins" is a free and open source project to monitor systems. The project can be used with Centreon, Icinga and all monitoring softwares compatible Nagios plugins. The lastest version is available on following git repository: https://github.com/centreon/centreon-plugins.git ************ Installation ************ ------------- Debian Wheezy ------------- Get the last version of "centreon-plugins" from the repository: :: # aptitude install git # git clone https://github.com/centreon/centreon-plugins.git To monitor SNMP systems, you need to install the following packages: :: # aptitude install perl libsnmp-perl You can install other packages to use more plugins: :: # aptitude install libxml-libxml-perl libjson-perl libwww-perl libxml-xpath-perl libnet-telnet-perl libnet-ntp-perl libnet-dns-perl libdbi-perl libdbd-mysql-perl libdbd-pg-perl To use 'memcached' functionality, you need to install the following CPAN module (no debian package): http://search.cpan.org/~wolfsage/Memcached-libmemcached-1.001702/libmemcached.pm ------------- Centos/Rhel 6 ------------- Get the last version of "centreon-plugins" from the repository: :: # yum install git # git clone https://github.com/centreon/centreon-plugins.git To monitor SNMP systems, you need to install the following packages: :: # yum install perl net-snmp-perl You can install other packages to use more plugins: :: # yum install perl-XML-LibXML perl-JSON perl-libwww-perl perl-XML-XPath perl-Net-Telnet perl-Net-DNS perl-DBI perl-DBD-MySQL perl-DBD-Pg To use 'memcached' functionality, you need to install the following CPAN module (package available in 'rpmforge'): http://search.cpan.org/~wolfsage/Memcached-libmemcached-1.001702/libmemcached.pm *********** Basic Usage *********** We'll use a basic example to show you how to monitor a system. I have finished the install section and I want to monitor a Linux in SNMP. First, I need to find the plugin to use in the list: :: $ perl centreon_plugins.pl --list-plugin | grep -i linux | grep 'PLUGIN' PLUGIN: os::linux::local::plugin PLUGIN: os::linux::snmp::plugin It seems that 'os::linux::snmp::plugin' is the good one. So I verify with the option ``--help`` to be sure: :: $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --help ... Plugin Description: Check Linux operating systems in SNMP. It's exactly what I need. Now I'll the option ``--list-mode`` to know what can I do with it: :: $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --list-mode ... Modes Available: cpu cpu-detailed disk-usage diskio inodes interfaces list-diskspath list-interfaces list-storages load memory processcount storage swap tcpcon time uptime I would like to test the 'load' mode: :: $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --mode=load UNKNOWN: Missing parameter --hostname. It's not working because some options are missing. I can have a description of the mode and options with the option ``--help``: :: $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --mode=load --help Eventually, I have to configure some SNMP options: :: $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --mode=load --hostname=127.0.0.1 --snmp-version=2c --snmp-community=public OK: Load average: 0.00, 0.00, 0.00 | 'load1'=0.00;;;0; 'load5'=0.00;;;0; 'load15'=0.00;;;0; I can set threshold with options ``--warning`` and ``--critical``: :: $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --mode=load --hostname=127.0.0.1 --snmp-version=2c --snmp-community=public --warning=1,2,3 --critical=2,3,4 OK: Load average: 0.00, 0.00, 0.00 | 'load1'=0.00;0:1;0:2;0; 'load5'=0.00;0:2;0:3;0; 'load15'=0.00;0:3;0:4;0; *** FAQ *** -------------------- What can I monitor ? -------------------- The option ``--list-plugin`` can be used to get the list of plugins and a short description. Headers of the table mean: * Transport: The check has internal options for the transport. * Protocol: what is used to get the monitoring datas. * Experimental: The check is still in development. +-------------+--------------------+----------------------------+--------------------------------------------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | | Transport | Protocol | | | | | Category | Check +-------+----------+---------+--------+--------+-------+-------+----------+ Experimental | Comment | Perl dependencies | | | | SSH | TELNET | WSMAN | SNMP | HTTP | WMI | JMX | custom | | | | +=============+====================+=======+==========+=========+========+========+=======+=======+==========+==============+=============================================================+========================================================================+ | | Active Directory | | | | | | | | * | | Use 'dcdiag' command. Must be installed on Windows. | Win32::Job | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Apache | | | | | * | | | | | Need Apache 'mod_status' module. | LWP::UserAgent, URI, HTTP::Cookies | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Apc | | | | | * | | | | | | LWP::UserAgent, URI, HTTP::Cookies | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Apcupsd | * | | | | | | | * | | Use 'apcupsd' commands. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Bluemind | | | | | * | | | | | Use 'influxdb' API. | JSON, LWP::UserAgent, URI, HTTP::Cookies | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Checkmyws | | | | | * | | | | | | JSON, LWP::UserAgent, URI, HTTP::Cookies | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Elasticsearch | | | | | * | | | | | | JSON, LWP::UserAgent, URI, HTTP::Cookies | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Exchange | | | | | | | | * | | Use powershell script. Must be installed on Windows. | Win32::Job | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Github | | | | | * | | | | | Use 'github' API. | JSON, LWP::UserAgent, URI, HTTP::Cookies, DateTime | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Hddtemp | | | | | | | | * | | Open a TCP custom communication | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | | | | | | | * | | | | Must be installed on Windows. | Win32::OLE | | | IIS +-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | Application | | | | * | | | * | | | * | | openwsman, MIME::Base64 | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Jenkins | | | | | * | | | | | | JSON, LWP::UserAgent, URI, HTTP::Cookies | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Kayako | | | | | * | | | | | Use 'kayako' API. | XML::XPath, Digest::SHA, LWP::UserAgent, URI, HTTP::Cookies | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Lmsensors | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Msmq | | | | | | | | * | * | Must be installed on Windows. Not developed yet. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Nginx | | | | | * | | | | | Need 'HttpStubStatusModule' module. | LWP::UserAgent, URI, HTTP::Cookies | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Pacemaker | * | | | | | | | * | | Use 'crm_mon' command. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Pfsense | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Selenium | | | | | | | | * | | Connect to a selenium server to play a scenario. | XML::XPath, WWW::Selenium | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Tomcat | | | | | * | | | | | Need tomcat webmanager. | XML::XPath, LWP::UserAgent, URI, HTTP::Cookies | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Varnish | * | | | | | | | * | | Use varnish commands. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | VMWare | | | | | | | | * | | Need 'centreon-vmware' connector from Centreon. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Pfsense | | | | * | | | | | | | | +-------------+--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Bgp | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Dhcp | | | | | | | | * | | | Net::DHCP::Packet, Net::Subnet | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Dns | | | | | | | | * | | | Net::DNS | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Ftp | | | | | | | | * | | | Net::FTP, Net::FTPSSL | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Http | | | | | * | | | | | | LWP::UserAgent, URI, HTTP::Cookies, JSON, JSON::Path, XML::XPath | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Ftp | | | | | | | | * | | | Net::FTP, Net::FTPSSL | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Imap | | | | | | | | * | | | Net::IMAP::Simple | | Protocols +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Jmx | | | | | | | * | | | | JSON::Path, JMX::Jmx4Perl | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Ldap | | | | | | | | * | | | Net::LDAP | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Ntp | | | | | | | | * | | | Net::NTP | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Radius | | | | | | | | * | | | Authen::Radius | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Smtp | | | | | | | | * | | | Email::Send::SMTP::Gmail | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Tcp | | | | | | | | * | | | IO::Socket::SSL | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Udp | | | | | | | | * | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | x509 | | | | | | | | * | | | IO::Socket::SSL | +-------------+--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Informix | | | | | | | | * | | | DBI, DBD::Informix | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Firebird | | | | | | | | * | | | DBI, DBD::Firebird | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | MS SQL | | | | | | | | * | | | DBI, DBD::Sybase | | Database +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | MySQL | | | | | | | | * | | | DBI, DBD::mysql | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Oracle | | | | | | | | * | | | DBI, DBD::oracle, DateTime | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Postgres | | | | | | | | * | | | DBI, DBD::Pg | +-------------+--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | ATS Apc | | | | * | | | | | * | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | PDU Apc | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | PDU Eaton | | | | * | | | | | * | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | PDU Raritan | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Standard Printers | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Hwgste | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Sensorip | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Sensormetrix Em01 | | | | | * | | | | | | LWP::UserAgent, URI, HTTP::Cookies | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Serverscheck | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Cisco UCS | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Dell CMC | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Dell iDrac | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | Hardware | Dell Openmanage | | | | * | | | | | | Need 'openmanage agent' on the operating system. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | HP Proliant | | | | * | | | | | | Need 'HP Insight agent' on the operating system. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | HP Blade Chassis | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | IBM BladeCenter | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | IBM HMC | * | | | | | | | * | * | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | IBM IMM | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Sun hardware | * | * | | * | | | | * | | Can monitor many sun hardware. | Net::Telnet, SNMP | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | UPS APC | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | UPS Mge | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | UPS Standard | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | UPS Powerware | | | | * | | | | | | | | +-------------+--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | 3com | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Alcatel Omniswitch | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Arkoon | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Aruba | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Bluecoat | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Brocade | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Checkpoint | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Cisco | | | | * | | | | | | Many cisco (2800, Nexus, Wlc, Ironport,...) | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Citrix Netscaler | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Dell Powerconnect | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Dlink | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Extreme | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | Network | F5 Big-Ip | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Fortinet Fortigate | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Fritzbox | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | H3C | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Hirschmann | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | HP Procurve | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | HP Virtual Connect | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Juniper | | | | * | | | | | | Can monitor 'SSG', 'SA', 'SRX', 'MAG', 'EX', 'Ggsn'. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Netasq | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Oneaccess | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Palo Alto | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Radware Alteon | | | | * | | | | | * | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Redback | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Riverbed | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Ruggedcom | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Securactive | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Stonesoft | | | | * | | | | | | | | +-------------+--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | | * | | | | | | | * | | Use AIX commands. | | | | AIX +-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | | | | | | | * | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Freebsd | | | | * | | | | | | Need 'bsnmpd' agent. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | Operating | | * | | | | | | | * | | Use Linux commands. | | | System | Linux +-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | | * | | | | | | | * | | Use Solaris commands. | | | | Solaris +-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | | | | | | | * | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | | | | | * | | | | | | | | | | Windows +-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | | | | * | | | * | | | * | | | +-------------+--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Dell EqualLogic | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Dell MD3000 | | | | | | | | * | | Need 'SMcli' command. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Dell TL2000 | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Dell ML6000 | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | EMC Celerra | * | | | | | | | * | | Use appliance commands. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | EMC Clariion | | | | | | | | * | | Need 'navisphere' command. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | EMC DataDomain | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | EMC Recoverypoint | * | | | | | | | * | | Use appliance commands. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | EMC Vplex | | | | | | * | | | | Use the JSON API. | JSON, LWP::UserAgent, URI, HTTP::Cookies | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | EMC Xtremio | | | | | | * | | | | Use the JSON API. | JSON, LWP::UserAgent, URI, HTTP::Cookies | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Fujitsu Eternus DX | * | | | | | | | * | | Use appliance commands. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | HP 3par | * | | | | | | | * | | Use appliance commands. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | HP Lefthand | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | HP MSA2000 | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | Storage | HP p2000 | | | | | | * | | | | Use the XML API. | XML::XPath, LWP::UserAgent, URI, HTTP::Cookies | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | IBM DS3000 | | | | | | | | * | | Use 'SMcli' command. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | IBM DS4000 | | | | | | | | * | | Use 'SMcli' command. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | IBM DS5000 | | | | | | | | * | | Use 'SMcli' command. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | IBM TS3100 | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | IBM TS3200 | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Netapp | | | | * | | | | | | | DateTime | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Nimble | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Panzura | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Qnap | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Synology | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ | | Violin 3000 | | | | * | | | | | | | | +-------------+--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+-------------------------------------------------------------+------------------------------------------------------------------------+ ---------------------------- How can I remove perfdatas ? ---------------------------- For example, I check TCP connections from a linux in SNMP with following command: :: $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --mode=tcpcon --hostname=127.0.0.1 --snmp-version=2c --snmp-community=public OK: Total connections: 1 | 'total'=1;;;0; 'con_closed'=0;;;0; 'con_closeWait'=0;;;0; ' con_synSent'=0;;;0; 'con_established'=1;;;0; 'con_timeWait'=0;;;0; 'con_lastAck'=0;;;0 ; 'con_listen'=5;;;0; 'con_synReceived'=0;;;0; 'con_finWait1'=0;;;0; 'con_finWait2'=0; ;;0; 'con_closing'=0;;;0; There are too many perfdatas and I want to keep 'total' perfdata only. I use the option ``--filter-perfdata='total'``: :: $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --mode=tcpcon --hostname=127.0.0.1 --snmp-version=2c --snmp-community=public --filter-perfdata='total' OK: Total connections: 1 | 'total'=1;;;0; I can use regexp in ``--filter-perfdata`` option. So, I can exclude perfdata beginning by 'total': :: $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --mode=tcpcon --hostname=127.0.0.1 --snmp-version=2c --snmp-community=public --filter-perfdata='^(?!(total))' OK: Total connections: 1 | 'con_closed'=0;;;0; 'con_closeWait'=0;;;0; 'con_synSent'=0;;;0; 'con_established'=1;;;0; 'con_timeWait'=0;;;0; 'con_lastAck'=0;;;0; 'con_listen'=5;;;0; 'con_synReceived'=0;;;0; 'con_finWait1'=0;;;0; 'con_finWait2'=0;;;0; 'con_closing'=0;;;0; ------------------------------------------------ How can I set threshold: critical if value < X ? ------------------------------------------------ "centreon-plugins" can manage Nagios threshold ranges: https://nagios-plugins.org/doc/guidelines.html#THRESHOLDFORMAT For example, I want to check that 'crond' is running (if there is less than 1 process, critical). I have two ways: :: $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --mode=processcount --hostname=127.0.0.1 --snmp-version=2c --snmp-community=public --process-name=crond --critical=1: CRITICAL: Number of current processes running: 0 | 'nbproc'=0;;1:;0; $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --mode=processcount --hostname=127.0.0.1 --snmp-version=2c --snmp-community=public --process-name=crond --critical=@0:0 CRITICAL: Number of current processes running: 0 | 'nbproc'=0;;@0:0;0; ------------------------------------------ How can I check a generic SNMP OID value ? ------------------------------------------ There is a generic SNMP plugin to check it. An example to get 'SysUptime' SNMP OID: :: $ perl centreon_plugins.pl --plugin=apps::protocols::snmp::plugin --mode=numeric-value --oid='.1.3.6.1.2.1.1.3.0' --hostname=127.0.0.1 --snmp-version=2c --snmp-community=public ---------------------------------------- How can I check ipv6 equipment in SNMP ? ---------------------------------------- To check ipv6 equipment, use the following syntax (``udp6:[xxxx]``): :: $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --hostname='udp6:[fe80::250:56ff:feb5:6ae0]' --mode=storage --snmp-version=2c --snmp-community=public ------------------------------------------------- How to use memcached server for retention datas ? ------------------------------------------------- Some plugins need to store datas. Two ways to store it: * File on a disk (by default). * Memcached server. To use 'memcached', you must have a memcached server and the CPAN 'Memcached::libmemcached' module installed. You can set the memcached server with the option ``--memcached``: :: $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --mode=interfaces --hostname=127.0.0.1 --snmp-version=2c --snmp-community=public --verbose --add-traffic --memcached=127.0.0.1 OK: All traffic are ok | 'traffic_in_lo'=197.40b/s;;;0;10000000 'traffic_out_lo'=197.40b/s;;;0;10000000 'traffic_in_eth0'=14539.11b/s;;;0;1000000000 'traffic_out_eth0'=399.59b/s;;;0;1000000000 'traffic_in_eth1'=13883.82b/s;;;0;1000000000 'traffic_out_eth1'=1688.66b/s;;;0;1000000000 Interface 'lo' Traffic In : 197.40b/s (0.00 %), Out : 197.40b/s (0.00 %) Interface 'eth0' Traffic In : 14.54Kb/s (0.00 %), Out : 399.59b/s (0.00 %) Interface 'eth1' Traffic In : 13.88Kb/s (0.00 %), Out : 1.69Kb/s (0.00 %) .. tip:: Local file is used if the memcached server is not responding. ------------------------------------ What does ``--dyn-mode`` option do ? ------------------------------------ With the option, you can used a mode with a plugin. It commonly used for database checks. For example, I have an application which stores some monitoring information on a database. The developer can use another plugin to create the check (no need to do the SQL connections,... It saves time): :: $ perl centreon_plugins.pl --plugin=database::mysql::plugin --dyn-mode=apps::centreon::mysql::mode::pollerdelay --host=10.30.3.75 --username='test' --password='testpw' --verbose OK: All poller delay for last update are ok | 'delay_Central'=2s;0:300;0:600;0; 'delay_Poller-Engine'=2s;0:300;0:600;0; Delay for last update of Central is 2 seconds Delay for last update of Poller-Engine is 2 seconds .. warning:: A mode using the following system must notice it (in the help description). So you should open the file with an editor and read at the end the description. ------------------------------------ How can I check the plugin version ? ------------------------------------ You can check the version of plugins and modes with option ``--version``: :: $ perl centreon_plugins.pl --version Global Version: 20160524 $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --version Plugin Version: 0.1 $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --mode=storage --version Mode Version: 1.0 You can also use the option ``--mode-version`` to execute the mode only if there is the good version. For example, we want to execute the mode only if the version >= 2.x: :: $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --mode=storage --hostname=127.0.0.1 --snmp-version=2c --snmp-community=public --verbose --mode-version='2.x' UNKNOWN: Not good version for plugin mode. Excepted at least: 2.x. Get: 1.0 ------------------------------------- Can I have one standalone Perl file ? ------------------------------------- We have done some tests and it will cost around 4% more of execution time. We are going to create a standalone Linux SNMP plugin. Download the Perl module ``App::FatPacker`` on metacpan: :: # tar zxvf App-FatPacker-0.010005.tar.gz # cd App-FatPacker-0.010005 # perl Makefile.PL && make && make install Create a directory to build it: :: # mkdir -p build/plugin # cd build Clone ``centreon-plugins``: :: # git clone https://github.com/centreon/centreon-plugins.git ``fatpack`` includes ``pm`` files under the directory ``lib``: :: # mkdir plugin/lib && cd centreon-plugins Copy the common files for all plugins: :: # find . -name "*.pm" -exec sed -i ' /__END__/d' \{\} \; # cp -R --parent centreon/plugins/{misc,mode,options,output,perfdata,script,statefile,values}.pm centreon/plugins/templates/ centreon/plugins/alternative/ ../plugin/lib/ # cp centreon_plugins.pl ../plugin # sed -i 's/alternative_fatpacker = 0/alternative_fatpacker = 1/' ../plugin/lib/centreon/plugins/script.pm Copy files for Linux SNMP plugin: :: # cp -R --parent centreon/plugins/{script_snmp,snmp}.pm os/linux/snmp/ snmp_standard/mode/{cpu,cpudetailed,diskio,diskusage,inodes,interfaces,loadaverage,listdiskspath,listinterfaces,liststorages,memory,processcount,storage,swap,ntp,tcpcon,uptime}.pm ../plugin/lib/ Build the standalone Perl file: :: # cd ../plugin # fatpack file centreon_plugins.pl > centreon_linux_snmp.pl The plugin works in the same way: :: # perl centreon_linux_snmp.pl --plugin=os::linux::snmp::plugin --mode=processcount --snmp-community public --snmp-version 2c --hostname=127.0.0.1 --process-name='' --process-status='' --process-args='' --------------------------------------------- Howto build a standalone Windows executable ? --------------------------------------------- This is only useful if you want to compile your own ``centreon_plugins.exe``. You won't need to install Perl on your windows server. * Install on Windows Strawberry Perl 5.24.x (Download on http://strawberryperl.com/) * Trunk of centreon-plugins repository (Download on https://github.com/centreon/centreon-plugins/archive/master.zip) Once everything is installed, install CPAN Module ``PAR::Packer`` (replace ````): :: cmd> \perl\bin\cpan.bat cpan> install PAR::Packer It can take several minutes to install the CPAN Module. In the parent directory containing the directory ``centreon-plugins``, create a ``build.bat`` file (replace ````). We exclude the module ``IO::Socket::INET6`` (Perl 5.14 has the full set of IPv6 functions as part of its core Socket module). :: set PERL_INSTALL_DIR= chdir /d %~dp0 set PAR_VERBATIM=1 cmd /C %PERL_INSTALL_DIR%\perl\site\bin\pp --lib=centreon-plugins\ -o centreon_plugins.exe centreon-plugins\centreon_plugins.pl ^ --unicode ^ -X IO::Socket::INET6 ^ --link=%PERL_INSTALL_DIR%\c\bin\libxml2-2__.dll ^ --link=%PERL_INSTALL_DIR%\c\bin\libiconv-2__.dll ^ --link=%PERL_INSTALL_DIR%\c\bin\liblzma-5__.dll ^ --link=%PERL_INSTALL_DIR%\c\bin\zlib1__.dll ^ --link=%PERL_INSTALL_DIR%\c\bin\libcrypto-1_1-x64__.dll ^ --link=%PERL_INSTALL_DIR%\c\bin\libssl-1_1-x64__.dll ^ -M IO::Socket::SSL ^ -M Win32::Job ^ -M Email::Send::SMTP::Gmail ^ -M HTTP::ProxyPAC ^ -M JE ^ -M Tie::RefHash::Weak ^ -M XML::LibXML::SAX ^ -M Net::FTPSSL ^ -M Authen::NTLM ^ -M JSON::XS ^ -M apps::backup::netbackup::local::plugin ^ -M apps::backup::netbackup::local::mode::dedupstatus ^ -M apps::backup::netbackup::local::mode::drivecleaning ^ -M apps::backup::netbackup::local::mode::drivestatus ^ -M apps::backup::netbackup::local::mode::jobstatus ^ -M apps::backup::netbackup::local::mode::listpolicies ^ -M apps::backup::netbackup::local::mode::tapeusage ^ -M apps::backup::veeam::local::plugin ^ -M apps::backup::veeam::local::mode::jobstatus ^ -M apps::backup::veeam::local::mode::listjobs ^ -M apps::backup::veeam::local::mode::tapejobs ^ -M apps::centreon::local::plugin ^ -M apps::centreon::local::mode::downtimetrap ^ -M apps::centreon::local::mode::centreonpluginsversion ^ -M apps::citrix::local::plugin ^ -M apps::citrix::local::mode::license ^ -M apps::citrix::local::mode::session ^ -M apps::citrix::local::mode::zone ^ -M apps::citrix::local::mode::folder ^ -M apps::microsoft::activedirectory::local::plugin ^ -M apps::microsoft::activedirectory::local::mode::dcdiag ^ -M apps::microsoft::activedirectory::local::mode::dfsrbacklog ^ -M apps::microsoft::activedirectory::local::mode::netdom ^ -M apps::microsoft::exchange::local::plugin ^ -M apps::microsoft::exchange::local::mode::activesyncmailbox ^ -M apps::microsoft::exchange::local::mode::databases ^ -M apps::microsoft::exchange::local::mode::listdatabases ^ -M apps::microsoft::exchange::local::mode::imapmailbox ^ -M apps::microsoft::exchange::local::mode::mapimailbox ^ -M apps::microsoft::exchange::local::mode::outlookwebservices ^ -M apps::microsoft::exchange::local::mode::owamailbox ^ -M apps::microsoft::exchange::local::mode::queues ^ -M apps::microsoft::exchange::local::mode::replicationhealth ^ -M apps::microsoft::exchange::local::mode::services ^ -M apps::microsoft::hyperv::2012::local::plugin ^ -M apps::microsoft::hyperv::2012::local::mode::listnodevms ^ -M apps::microsoft::hyperv::2012::local::mode::scvmmintegrationservice ^ -M apps::microsoft::hyperv::2012::local::mode::scvmmsnapshot ^ -M apps::microsoft::hyperv::2012::local::mode::scvmmvmstatus ^ -M apps::microsoft::hyperv::2012::local::mode::nodeintegrationservice ^ -M apps::microsoft::hyperv::2012::local::mode::nodereplication ^ -M apps::microsoft::hyperv::2012::local::mode::nodesnapshot ^ -M apps::microsoft::hyperv::2012::local::mode::nodevmstatus ^ -M apps::microsoft::iis::local::plugin ^ -M apps::microsoft::iis::local::mode::listapplicationpools ^ -M apps::microsoft::iis::local::mode::applicationpoolstate ^ -M apps::microsoft::iis::local::mode::listsites ^ -M apps::microsoft::iis::local::mode::webservicestatistics ^ -M apps::microsoft::mscs::local::plugin ^ -M apps::microsoft::mscs::local::mode::listnodes ^ -M apps::microsoft::mscs::local::mode::listresources ^ -M apps::microsoft::mscs::local::mode::networkstatus ^ -M apps::microsoft::mscs::local::mode::nodestatus ^ -M apps::microsoft::mscs::local::mode::resourcestatus ^ -M apps::microsoft::mscs::local::mode::resourcegroupstatus ^ -M apps::microsoft::sccm::local::plugin ^ -M apps::microsoft::sccm::local::mode::databasereplicationstatus ^ -M apps::microsoft::sccm::local::mode::sitestatus ^ -M apps::microsoft::wsus::local::plugin ^ -M apps::microsoft::wsus::local::mode::computersstatus ^ -M apps::microsoft::wsus::local::mode::updatesstatus ^ -M apps::microsoft::wsus::local::mode::synchronisationstatus ^ -M apps::microsoft::wsus::local::mode::serverstatistics ^ -M apps::protocols::ldap::plugin ^ -M apps::protocols::ldap::mode::login ^ -M apps::protocols::ldap::mode::search ^ -M apps::protocols::ftp::plugin ^ -M apps::protocols::ftp::mode::commands ^ -M apps::protocols::ftp::mode::date ^ -M apps::protocols::ftp::mode::filescount ^ -M apps::protocols::ftp::mode::login ^ -M apps::protocols::http::plugin ^ -M apps::protocols::http::mode::expectedcontent ^ -M apps::protocols::http::mode::response ^ -M apps::protocols::tcp::plugin ^ -M apps::protocols::tcp::mode::responsetime ^ -M apps::protocols::x509::plugin ^ -M apps::protocols::x509::mode::certificate ^ -M apps::protocols::x509::mode::validity ^ -M centreon::common::protocols::ldap::lib::ldap ^ -M centreon::common::powershell::exchange::powershell ^ -M centreon::common::powershell::functions ^ -M centreon::common::powershell::hyperv::2012::listnodevms ^ -M centreon::common::powershell::hyperv::2012::nodeintegrationservice ^ -M centreon::common::powershell::hyperv::2012::nodereplication ^ -M centreon::common::powershell::hyperv::2012::nodesnapshot ^ -M centreon::common::powershell::hyperv::2012::nodevmstatus ^ -M centreon::common::powershell::hyperv::2012::scvmmintegrationservice ^ -M centreon::common::powershell::hyperv::2012::scvmmsnapshot ^ -M centreon::common::powershell::hyperv::2012::scvmmvmstatus ^ -M centreon::common::powershell::sccm::databasereplicationstatus ^ -M centreon::common::powershell::sccm::sitestatus ^ -M centreon::common::powershell::veeam::jobstatus ^ -M centreon::common::powershell::veeam::listjobs ^ -M centreon::common::powershell::veeam::tapejobs ^ -M centreon::common::powershell::windows::liststorages ^ -M centreon::common::powershell::wsus::computersstatus ^ -M centreon::common::powershell::wsus::updatesstatus ^ -M centreon::common::powershell::wsus::synchronisationstatus ^ -M centreon::common::powershell::wsus::serverstatistics ^ -M centreon::plugins::alternative::Getopt ^ -M centreon::plugins::backend::http::lwp ^ -M centreon::plugins::backend::http::curl ^ -M centreon::plugins::backend::http::curlconstants ^ -M centreon::plugins::script ^ -M hardware::devices::safenet::hsm::protecttoolkit::plugin ^ -M hardware::devices::safenet::hsm::protecttoolkit::mode::hardware ^ -M hardware::devices::safenet::hsm::protecttoolkit::mode::components::temperature ^ -M hardware::devices::safenet::hsm::protecttoolkit::mode::components::hwstatus ^ -M hardware::devices::safenet::hsm::protecttoolkit::mode::components::memory ^ -M os::windows::local::plugin ^ -M os::windows::local::mode::cmdreturn ^ -M os::windows::local::mode::ntp ^ -M os::windows::local::mode::pendingreboot ^ -M os::windows::local::mode::sessions ^ -M os::windows::local::mode::liststorages ^ -M storage::dell::compellent::local::plugin ^ -M storage::dell::compellent::local::mode::hbausage ^ -M storage::dell::compellent::local::mode::volumeusage ^ --verbose pause Add plugins and modes you need in ``centreon_plugins.exe`` (the example add some plugins). Eventually, execute ``build.bat`` file to create executable ``centreon_plugins.exe``. If you want to change the executable version and ico file, add following code after ``PERL_INSTALL_DIR`` first line: :: set ICO_FILE=centreon.ico set RC_FILE=centreon.rc chdir /d %~dp0 for /f "tokens=4 delims= " %%i in ('type centreon-plugins\centreon\plugins\script.pm ^| findstr global_version ^| findstr my') do set "VERSION_PLUGIN=%%i" set VERSION_PLUGIN=%VERSION_PLUGIN:~1,8% ( echo #define PP_MANIFEST_FILEFLAGS 0 echo #include ^ echo. echo CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "winres\\pp.manifest" echo. echo VS_VERSION_INFO VERSIONINFO echo FILEVERSION 0,0,0,0 echo PRODUCTVERSION 0,0,0,0 echo FILEFLAGSMASK VS_FFI_FILEFLAGSMASK echo FILEFLAGS PP_MANIFEST_FILEFLAGS echo FILEOS VOS_NT_WINDOWS32 echo FILETYPE VFT_APP echo FILESUBTYPE VFT2_UNKNOWN echo BEGIN echo BLOCK "StringFileInfo" echo BEGIN echo BLOCK "000004B0" echo BEGIN echo VALUE "CompanyName", "Centreon\0" echo VALUE "FileDescription", " \0" echo VALUE "FileVersion", "1.0.0.0\0" echo VALUE "InternalName", " \0" echo VALUE "LegalCopyright", " \0" echo VALUE "LegalTrademarks", " \0" echo VALUE "OriginalFilename", " \0" echo VALUE "ProductName", "centreon-plugins\0" echo VALUE "ProductVersion", "%VERSION_PLUGIN%.0\0" echo END echo END echo BLOCK "VarFileInfo" echo BEGIN echo VALUE "Translation", 0x00, 0x04B0 echo END echo END echo. echo WINEXE ICON winres\\pp.ico )> %RC_FILE% for /f "delims=" %%i in ('dir /ad /B %PERL_INSTALL_DIR%\cpan\build\PAR-Packer-*') do set "PAR_PACKER_DIRNAME=%%i" SET PAR_PACKER_SRC=%PERL_INSTALL_DIR%\cpan\build\%PAR_PACKER_DIRNAME% copy /Y %ICO_FILE% %PAR_PACKER_SRC%\myldr\winres\pp.ico copy /Y centreon.rc %PAR_PACKER_SRC%\myldr\winres\pp.rc del %PAR_PACKER_SRC%\myldr\ppresource.coff cd /D %PAR_PACKER_SRC%\myldr\ && perl Makefile.PL cd /D %PAR_PACKER_SRC%\myldr\ && dmake boot.exe cd /D %PAR_PACKER_SRC%\myldr\ && dmake Static.pm attrib -R %PERL_INSTALL_DIR%\perl\site\lib\PAR\StrippedPARL\Static.pm copy /Y %PAR_PACKER_SRC%\myldr\Static.pm %PERL_INSTALL_DIR%\perl\site\lib\PAR\StrippedPARL\Static.pm You can build a 32 bits binary from a Windows 64 bits: * Install Strawberry Perl 5.24.x 32 bits on Windows (Download on http://strawberryperl.com/) * Install cpan module ``PAR::Packer`` * Add following line in the build script : PATH=%PERL_INSTALL_DIR%\c\bin;%PERL_INSTALL_DIR%\perl\bin;C:\Windows\System32 *************** Troubleshooting *************** ---- SNMP ---- I get the SNMP error: 'UNKNOWN:.* (tooBig).*' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The following error can happened with some equipments. You can resolve it if you set following options: * ``--subsetleef=20`` ``--maxrepetitions=20`` I get the SNMP error: 'UNKNOWN:.*Timeout' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The following error means: * Don't have network access to the target SNMP Server (a firewall can block UDP 161). * Wrong SNMP community name or SNMP version set. I get the SNMP error: 'UNKNOWN:.*Cant get a single value' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The following error means: SNMP access is working but you can't retrieve SNMP values. Very possible reasons: * SNMP value is not set yet (can be happened when a SNMP server is just started). * SNMP value is not implemented by the constructor. * SNMP value is set on a specific firmware or OS. Seems that process check is not working well for some arguments filter ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ In SNMP, there is a limit in argument length of 128 characters. So, if you try to filter with an argument after 128 characters, it won't work. It can happen with Java arguments. To solve the problem, you should prefer a NRPE check. Can't access in SNMP v3 ^^^^^^^^^^^^^^^^^^^^^^^ First, you need to validate SNMP v3 connection with snmpwalk. When it's working, you set SNMP v3 options in command line. The mapping between 'snmpwalk' options and "centreon-plugins" options: * -a => ``--authprotocol`` * -A => ``--authpassphrase`` * -u => ``--snmp-username`` * -x => ``--privprotocol`` * -X => ``--privpassphrase`` * -l => not needed (automatic) * -e => ``--securityengineid`` * -E => ``--contextengineid`` ------------- Miscellaneous ------------- I get the error: "UNKNOWN: Need to specify '--custommode'." ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Some plugins need to set the option ``--custommode``. You can know the value to set with the option ``--list-custommode``. An example:: $ perl centreon_plugins.pl --plugin=storage::ibm::DS3000::cli::plugin --list-custommode ... Custom Modes Available: smcli $ perl centreon_plugins.pl --plugin=storage::ibm::DS3000::cli::plugin --custommode=smcli --list-mode I get the error: "UNKNOWN: Cannot write statefile .*" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ You must create the directory (with write permissions) to let the plugin stores some datas on disk. I get the error: "UNKNOWN: Cannot load module 'xxx'." ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The problem can be: * A prerequisite CPAN module is missing. You need to install it. * The CPAN module cannot be loaded because of its path. Perl modules must be installed on some specific paths. I can't see help messages ^^^^^^^^^^^^^^^^^^^^^^^^^ "centreon-plugins" files must Unix format (no Windows carriage returns). You can change it with the following command: :: $ find . -name "*.p[ml]" -type f -exec dos2unix \{\} \; .. Warning:: Execute the command in "centreon-plugins" directory. *************** Command Samples *************** ------- Windows ------- Check all disks in SNMP ^^^^^^^^^^^^^^^^^^^^^^^ Warning if space used > 80% and critical if space used > 90%: :: $ perl centreon_plugins.pl --plugin=os::windows::snmp::plugin --mode=storage --hostname=xxx.xxx.xxx.xxx --snmp-version=2c --snmp-public=community --verbose --storage='.*' --name --regexp --display-transform-src='(..).*' --display-transform-dst='$1' --warning=80 --critical=90 OK: All storages are ok. | used_C:'=38623698944B;0:108796887040;0:122396497920;0;135996108800 used_D:'=38623698944B;0:108796887040;0:122396497920;0;135996108800 Storage 'C:' Total: 126.66 GB Used: 35.97 GB (28.40%) Free: 90.69 GB (71.60%) Storage 'D:' Total: 126.66 GB Used: 35.97 GB (28.40%) Free: 90.69 GB (71.60%) Warning if space free < 5G and critical if space free < 2G: :: $ perl centreon_plugins.pl --plugin=os::windows::snmp::plugin --mode=storage --hostname=xxx.xxx.xxx.xxx --snmp-version=2c --snmp-public=community --verbose --storage='.*' --name --regexp --display-transform-src='(..).*' --display-transform-dst='$1' --warning=5497558138880: --critical=2199023255552: --units='B' --free OK: All storages are ok. | 'free_C:'=97372344320B;0:5497558138880;0:2199023255552;0;135996108800 'free_D:'=97372344320B;0:5497558138880;0:2199023255552;0;135996108800 Storage 'C:' Total: 126.66 GB Used: 35.97 GB (28.40%) Free: 90.69 GB (71.60%) Storage 'D:' Total: 126.66 GB Used: 35.97 GB (28.40%) Free: 90.69 GB (71.60%) ----- Linux ----- Check all interface traffics in SNMP ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning if traffic in/out used > 80% and critical if traffic in/out used > 90%: :: $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --mode=interfaces --hostname=127.0.0.1 --snmp-version=2c --snmp-community=public --verbose --interface='.*' --name --add-traffic --warning-in-traffic=80 --critical-in-traffic=90 --warning-out-traffic=80 --critical-out-traffic=90 OK: All traffic are ok | 'traffic_in_lo'=126.58b/s;0.00:8000000.00;0.00:9000000.00;0;10000000 'traffic_out_lo'=126.58b/s;0.00:8000000.00;0.00:9000000.00;0;10000000 'traffic_in_eth0'=1872.00b/s;0.00:800000000.00;0.00:900000000.00;0;1000000000 'traffic_out_eth0'=266.32b/s;0.00:800000000.00;0.00:900000000.00;0;1000000000 'traffic_in_eth1'=976.65b/s;0.00:800000000.00;0.00:900000000.00;0;1000000000 'traffic_out_eth1'=1021.68b/s;0.00:800000000.00;0.00:900000000.00;0;1000000000 Interface 'lo' Traffic In : 126.58b/s (0.00 %), Out : 126.58b/s (0.00 %) Interface 'eth0' Traffic In : 1.87Kb/s (0.00 %), Out : 266.32b/s (0.00 %) Interface 'eth1' Traffic In : 976.65b/s (0.00 %), Out : 1.02Kb/s (0.00 %) ------------- HTTP Protocol ------------- Check authentification of an application (POST request) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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' -------------------- Multi-service plugin -------------------- This mode allow you to concatenate several result of host and/or service check into one check. Can be used to make some aggregation into logical group or gather information from one Centreon to display in another without checking resources twice. Design of configuration file ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: { "mode":"sqlmatching", "selection":{ "ESX":{ "host_name_filter":"%clus-esx-n%", "service_name_filter":"Esx-Status" }, "XIVO":{ "host_name_filter":"%xivo%", "service_name_filter":"Ping" } }, "counters":{ "totalservices":true, "totalhosts":true, "groups":true }, "formatting":{ "groups_global_msg":"Nothing special on groups", "host_service_separator":"/", "display_details":true } } * mode (mandatory) : can be 'sqlmatching' or 'exactmatch'. Linked to the layout of "selection" bloc * selection (mandatory) : if we use sqlmatching, we define filters like above, if we use exact match, need to pass a key/value pair corresponding to host/service (example below with two "groups" esx-status/load) :: "selection":{ "esx-status":{ "esx-n1":"Esx-Status", "esx-n2":"Esx-Status", "esx-n3":"Esx-Status" }, "esx-load":{ "esx-n1":"Esx-Memory", "esx-n2":"Esx-Memory", "esx-n3":"Esx-Memory", "esx-n1":"Esx-Cpu", "esx-n2":"Esx-Cpu", "esx-n3":"Esx-Cpu" } }, * counters (optionnal) : Contains three keys to choose which counters we should use and consider (totalservices, totalhosts, groups) * formatting (optionnal) : Contains three keys, 'groups_global_msg' to define a global OK status message, 'host_service_separator' to define separator used between host and service name in output, 'display_details' to config if plugin should display details of host/service name in the verbose output. Command line, output, threshold ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Sample command: :: /usr/lib/nagios/plugins/centreon_plugins.pl --plugin database::mysql::plugin --dyn-mode apps::centreon::sql::mode::multiservices --host localhost --username centreon --password c3ntreon --config-file '/root/global-services.json' --verbose Sample output: :: OK: Hosts state summary [up:4][down:2][unreachable:0] - Services state summary [ok:4][warning:0][critical:2][unknown:0] - Nothing special on groups | Perfdatas: :: 'total_host_up'=4;;;0; 'total_host_down'=2;;;0; 'total_host_unreachable'=0;;;0; 'total_host_ok'=4;;;0; 'total_host_warning'=0;;;0; 'total_host_critical'=2;;;0; 'total_host_unknown'=0;;;0; 'host_up_ESX'=4;;;0; 'host_down_ESX'=0;;;0; 'host_unreachable_ESX'=0;;;0; 'service_ok_ESX'=4;;;0; 'service_warning_ESX'=0;;;0; 'service_critical_ESX'=0;;;0; 'service_unknown_ESX'=0;;;0; 'host_up_XIVO'=0;;;0; 'host_down_XIVO'=2;;;0; 'host_unreachable_XIVO'=0;;;0; 'service_ok_XIVO'=0;;;0; 'service_warning_XIVO'=0;;;0; 'service_critical_XIVO'=2;;;0; 'service_unknown_XIVO'=0;;;0; Verbose mode (with display details set as true): :: Group 'ESX': HOSTS: [up: 4 (clus-esx-n1.com - clus-esx-n2.com - clus-esx-n3.com - clus-esx-n4.com)][down: 0][unreachable: 0] - SERVICES: [ok: 4 (clus-esx-n1.com/Esx-Status - clus-esx-n2.com/Esx-Status - clus-esx-n3.com/Esx-Status - clus-esx-n4.com/Esx-Status)][warning: 0][critical: 0][unknown: 0] Group 'XIVO': HOSTS: [up: 0][down: 2 (srvi-xivo-n1 - srvi-xivo-n2)][unreachable: 0] - SERVICES: [ok: 0][warning: 0][critical: 2 (srvi-xivo-n1/Ping - srvi-xivo-n2/Ping)][unknown: 0] Concerning the threshold, you can use some example below: :: --critical-total '%{total_down} > 4' --critical-groups '%{instance} eq 'ESX' && %{unknown} > 5' -------- NSClient -------- You can monitor Windows/Linux system with the Rest API of NSClient. Commands and arguments are the same than NRPE (look the NSClient documentation for more informations): :: $ perl centreon_plugins.pl --plugin=apps::nsclient::restapi::plugin --mode=query --hostname="10.30.2.10" --port=443 --legacy-password=centreon --command=check_drivesize --arg="drive=*" --arg="perf-config=used(unit:B)used %(ignored:true)" --arg="filter=type = 'fixed' and name not regexp '.*yst.*'" --arg="warning=total_used>80%" --arg="critical=total_used>90%" OK All 2 drive(s) are ok | '\\?\Volume{7cd2d555-9868-11e7-8199-806e6f6e6963}\ used'=289468416.000B;293598003.000;330297753.000;0.000;366997504.000 'C:\ used'=23285907456.000B;42654390681.000;47986189516.000;0.000;53317988352.000 centreon-plugins-20220113/doc/en/user/index.rst000066400000000000000000000001241417000230700212170ustar00rootroot00000000000000########## User guide ########## .. toctree:: :maxdepth: 2 :glob: guide centreon-plugins-20220113/doc/fr/000077500000000000000000000000001417000230700164105ustar00rootroot00000000000000centreon-plugins-20220113/doc/fr/Makefile000066400000000000000000000127041417000230700200540ustar00rootroot00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " text to make text files" @echo " man to make manual pages" @echo " texinfo to make Texinfo files" @echo " info to make Texinfo files and run them through makeinfo" @echo " gettext to make PO message catalogs" @echo " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: -rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Centreon.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Centreon.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/Centreon" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Centreon" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." texinfo: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." @echo "Run \`make' in that directory to run these through makeinfo" \ "(use \`make info' here to do that automatically)." info: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo "Running Texinfo files through makeinfo..." make -C $(BUILDDIR)/texinfo info @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." gettext: $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale @echo @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." centreon-plugins-20220113/doc/fr/conf.py000066400000000000000000000202641417000230700177130ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # Centreon documentation build configuration file, created by # sphinx-quickstart on Wed Nov 7 16:30:34 2012. # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys, os on_centreon_rtd = os.environ.get('CENTREON_RTD', None) == 'True' # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. #sys.path.insert(0, os.path.abspath('.')) # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ['sphinx.ext.todo', 'sphinx.ext.intersphinx'] intersphinx_mapping = { 'centreon-engine': ('http://documentation.centreon.com/docs/centreon-engine/en/latest', None), 'centreon-broker': ('http://documentation.centreon.com/docs/centreon-broker/en/latest', None), 'centreon-clib': ('http://documentation.centreon.com/docs/centreon-clib/en/latest', None), 'ces': ('http://documentation.centreon.com/docs/centreon-enterprise-server/en/latest', None), } # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] todo_include_todos = True # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = u'Centreon Plugins' copyright = u'2007-2020 Centreon' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = 'latest' # The full version, including alpha/beta/rc tags. release = 'latest' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ['_build'] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- if on_centreon_rtd: # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'centreon' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. #html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. html_theme_path = ['/srv/themes'] else: html_theme = 'default' # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_domain_indices = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'Centreondoc' # -- Options for LaTeX output -------------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). #'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). #'pointsize': '10pt', # Additional stuff for the LaTeX preamble. #'preamble': '', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('index', 'Centreon.tex', u'Centreon Plugins Documentation', u'Merethis', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # If true, show page references after internal links. #latex_show_pagerefs = False # If true, show URL addresses after external links. #latex_show_urls = False # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_domain_indices = True # -- Options for manual page output -------------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'centreon', u'Centreon Plugins Documentation', [u'Merethis'], 1) ] # If true, show URL addresses after external links. #man_show_urls = False # -- Options for Texinfo output ------------------------------------------------ # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ ('index', 'Centreon', u'Centreon Documentation', u'Merethis', 'Centreon', 'One line description of project.', 'Miscellaneous'), ] # Documents to append as an appendix to all manuals. #texinfo_appendices = [] # If false, no module index is generated. #texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. #texinfo_show_urls = 'footnote' centreon-plugins-20220113/doc/fr/developer/000077500000000000000000000000001417000230700203755ustar00rootroot00000000000000centreon-plugins-20220113/doc/fr/developer/guide.rst000066400000000000000000002000151417000230700222220ustar00rootroot00000000000000*********** Description *********** Ce document présente les bonnes pratiques pour le développement de "centreon-plugins". Comme tous les plugins sont écrits en Perl, "There's more than one way to do it". Afin de ne pas réinventer la roue, vous devriez d'abord regarder le dossier “example”. Vous aurez alors un aperçu de la méthodologie pour construire votre propre plugin ainsi que ses modes associés. La dernière version est disponible sur le dépôt git suivant: https://github.com/centreon/centreon-plugins.git **************** Démarrage rapide **************** ------------------- Création du dossier ------------------- Premièrement, vous avez besoin de créer un dossier sur le git afin de stocker le nouveau plugin. Les répertoires racines sont oganisés par catégorie: * Application : apps * Base de données : database * Matériel : hardware * Equipement réseau : network * Système d'exploitation : os * Equipement de stockage : storage Selon l'objet supervisé, il existe une organisation qui peut être utilisée : * Type * Constructeur * Modèle * Protocole de supervision Par exemple, si vous voulez ajouter un plugin pour superviser Linux par SNMP, vous devez créer ce dossier : :: $ mkdir -p os/linux/snmp Vous avez également besoin de créer une répertoire "mode" pour les futurs modes créés : :: $ mkdir os/linux/snmp/mode ------------------ Création du plugin ------------------ Une fois le dossier créé, ajouter le fichier du plugin à l'intérieur de celui-ci : :: $ touch plugin.pm Ensuite, éditer le fichier plugin.pm pour ajouter les **conditions de licence** en les copiant à partir d'un autre plugin. N'oubliez pas d'ajouter votre nom à la fin de celles-ci : .. code-block:: perl # ... # Authors : <> Renseigner votre nom de **package** : il correspond au dossier de votre plugin. .. code-block:: perl package path::to::plugin; Déclarer les bibliothèques utilisées (**strict** et **warnings** sont obligatoires). Les bibliothèques Centreon sont décrites par la suite : .. code-block:: perl use strict; use warnings; use base qw(**centreon_library**); Le plugin a besoin d'un constructeur **new** pour instancier l'objet : .. code-block:: perl sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; ... return $self; } La version du plugin doit être déclarée dans le constructeur **new** : .. code-block:: perl $self->{version} = '0.1'; Plusieurs modes peuvent être déclarés dans le constructeur **new** : .. code-block:: perl %{$self->{modes}} = ( 'mode1' => '::mode::mode1', 'mode2' => '::mode::mode2', ... ); Ensuite, déclarer le module : .. code-block:: perl 1; Une description du plugin est nécessaire pour générer la documentation : .. code-block:: perl __END__ =head1 PLUGIN DESCRIPTION . =cut .. tip:: Vous pouvez copier/coller les éléments d'un autre plugin et adapter les lignes (paquets, arguments, ...). .. tip:: Le plugin possède une extension ".pm" car c'est un module PERL. Par conséquent, ne pas oublier d'ajouter un **1;**. ---------------- Création du mode ---------------- Une fois que le fichier **plugin.pm** existe et que ses modes sont déclarés, créer les modes dans le dossier **mode** : :: cd mode touch mode1.pm Ensuite, éditer mode1.pm pour ajouter les **conditions de licence** en les copiant à partir d'un autre mode. Ne pas oublier pas d'ajouter votre nom à la fin de celles-ci : .. code-block:: perl # ... # Authors : <> Décrire votre nom de **package** : il correspond au dossier de votre mode. .. code-block:: perl package path::to::plugin::mode::mode1; Déclarer les bibliothèques utilisées (toujours les mêmes) : .. code-block:: perl use strict; use warnings; use base qw(centreon::plugins::mode); Le mode nécessite un constructeur **new** pour instancier l'objet : .. code-block:: perl sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; ... return $self; } La version du mode doit être déclarée dans le constructeur **new** : .. code-block:: perl $self->{version} = '1.0'; Plusieurs options peuvent être déclarées dans le constructeur **new** : .. code-block:: perl $options{options}->add_options(arguments => { "option1:s" => { name => 'option1' }, "option2:s" => { name => 'option2', default => 'value1' }, "option3" => { name => 'option3' }, }); Voici la description des arguments de cet exemple : * option1 : Chaîne de caractères * option2 : Chaîne de caractères avec "value1" comme valeur par défaut * option3 : Booléen .. tip:: Vous pouvez obtenir plus d'informations sur les formats des options ici : http://perldoc.perl.org/Getopt/Long.html Le mode nécessite une méthode **check_options** pour valider les options : .. code-block:: perl sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); ... } Par exemple, les seuils Dégradé (Warning) et Critique (Critical) doivent être validés dans la méthode **check_options** : .. code-block:: perl 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(); } Dans cet exemple, l'aide est affichée si les seuils spécifiés ne sont pas au bon format. Ensuite vient la méthode **run** où le traitement sera effectué, où les seuils seront vérifiés et où le message de sortie et les données de performance seront affichés. Voici un exemple pour vérifier une valeur SNMP : .. code-block:: perl sub run { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{hostname} = $self->{snmp}->get_hostname(); my $result = $self->{snmp}->get_leef(oids => [$self->{option_results}->{oid}], nothing_quit => 1); my $value = $result->{$self->{option_results}->{oid}}; 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("SNMP Value is %s.", $value)); $self->{output}->perfdata_add(label => 'value', unit => undef, value => $value, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => undef, max => undef); $self->{output}->display(); $self->{output}->exit(); } Dans cet exemple, un OID SNMP sera vérifié et comparé aux seuils Dégradé et Critique. Voici les méthodes utilisées : * get_leef : pour obtenir une valeur snmp à partir d'un OID * threshold_check : pour comparer une valeur snmp à des seuils dégradé et critique * output_add : pour ajouter des informations au message de sortie * perfdata_add : pour ajouter des données de performance au message de sortie * display : pour afficher le message de sortie * exit : pour sortir du programme Ensuite, déclarer le module : .. code-block:: perl 1; Une description du mode et de ses arguments est nécessaire pour générer la documentation : .. code-block:: perl __END__ =head1 PLUGIN DESCRIPTION . =cut -------------- Commit et push -------------- Avant de commiter le plugin, vous devez créer un **ticket amélioration** (enhancement) dans la forge centreon-plugins : http://forge.centreon.com/projects/centreon-plugins Une fois que le plugin et ses modes sont développés, vous pouvez commiter (messages de commit en anglais) et envoyer votre travail : :: git add path/to/plugin git commit -m "Add new plugin for XXXX refs #" git push ***************************** Référentiel des bibliothèques ***************************** Ce chapitre décrit les bibliothèques Centreon qui peuvent être utilisées dans votre développement. ------ Output ------ Cette bibliothèque vous permet de construire la sortie de votre plugin. output_add ---------- Description ^^^^^^^^^^^ Ajouter une chaîne de caractères à la sortie (affichée avec la méthode **display**). Si le statut est différent de 'OK', le message de sortie associé à 'OK' ne sera pas affiché. Paramètres ^^^^^^^^^^ +------------+---------+----------+---------------------------------------------------------------+ | Paramètre | Type | Défaut | Description | +============+=========+==========+===============================================================+ | severity | String | OK | Statut du message de sortie. | +------------+---------+----------+---------------------------------------------------------------+ | separator | String | \- | Séparateur entre le statut et le message de sortie. | +------------+---------+----------+---------------------------------------------------------------+ | short_msg | String | | Message de sortie court (première ligne). | +------------+---------+----------+---------------------------------------------------------------+ | long_msg | String | | Message de sortie long (utilisé avec l'option ``--verbose``). | +------------+---------+----------+---------------------------------------------------------------+ Exemple ^^^^^^^ Voici un exemple de gestion de la sortie du plugin : .. code-block:: perl $self->{output}->output_add(severity => 'OK', short_msg => 'All is ok'); $self->{output}->output_add(severity => 'Critical', short_msg => 'There is a critical problem'); $self->{output}->output_add(long_msg => 'Port 1 is disconnected'); $self->{output}->display(); La sortie affichera : :: CRITICAL - There is a critical problem Port 1 is disconnected perfdata_add ------------ Description ^^^^^^^^^^^ Ajouter une donnée de performance à la sortie (affichée avec la méthode **display**). Les données de performance sont affichées après le symbole '|'. Paramètres ^^^^^^^^^^ +-----------------+-----------------+-------------+---------------------------------------------------------+ | Paramètre | Type | Défaut | Description | +=================+=================+=============+=========================================================+ | label | String | | Label de la donnée de performance. | +-----------------+-----------------+-------------+---------------------------------------------------------+ | value | Int | | Valeur de la donnée de performance. | +-----------------+-----------------+-------------+---------------------------------------------------------+ | unit | String | | Unité de la donnée de performance. | +-----------------+-----------------+-------------+---------------------------------------------------------+ | warning | String | | Seuil Dégradé. | +-----------------+-----------------+-------------+---------------------------------------------------------+ | critical | String | | Seuil Critique. | +-----------------+-----------------+-------------+---------------------------------------------------------+ | min | Int | | Valeur minimum de la donnée de performance. | +-----------------+-----------------+-------------+---------------------------------------------------------+ | max | Int | | Valeur maximum de la donnée de performance. | +-----------------+-----------------+-------------+---------------------------------------------------------+ Exemple ^^^^^^^ Voici un exemple d'ajout d'une donnée de performance : .. code-block:: perl $self->{output}->output_add(severity => 'OK', short_msg => 'Memory is ok'); $self->{output}->perfdata_add(label => 'memory_used', value => 30000000, unit => 'B', warning => '80000000', critical => '90000000', min => 0, max => 100000000); $self->{output}->display(); La sortie affichera : :: OK - Memory is ok | 'memory_used'=30000000B;80000000;90000000;0;100000000 -------- Perfdata -------- Cette bibliothèque vous permet de gérer les données de performance. get_perfdata_for_output ----------------------- Description ^^^^^^^^^^^ Gérer les seuils des données de performance pour la sortie. Paramètres ^^^^^^^^^^ +-----------------+-----------------+-------------+--------------------------------------------------------------------------+ | Paramètre | Type | Défaut | Description | +=================+=================+=============+==========================================================================+ | **label** | String | | Label du seuil. | +-----------------+-----------------+-------------+--------------------------------------------------------------------------+ | total | Int | | Seuil en pourcentage à transformer en valeur globale. | +-----------------+-----------------+-------------+--------------------------------------------------------------------------+ | cast_int | Int (0 or 1) | | Cast une valeur absolue en entier. | +-----------------+-----------------+-------------+--------------------------------------------------------------------------+ | op | String | | Opérateur à appliquer à la valeur de début/fin (utilisé avec ``value``). | +-----------------+-----------------+-------------+--------------------------------------------------------------------------+ | value | Int | | Valeur à appliquer avec l'option ``op``. | +-----------------+-----------------+-------------+--------------------------------------------------------------------------+ Exemple ^^^^^^^ Voici un exemple de gestion des données de performance pour la sortie : .. code-block:: perl my $format_warning_perfdata = $self->{perfdata}->get_perfdata_for_output(label => 'warning', total => 1000000000, cast_int => 1); my $format_critical_perfdata = $self->{perfdata}->get_perfdata_for_output(label => 'critical', total => 1000000000, cast_int => 1); $self->{output}->perfdata_add(label => 'memory_used', value => 30000000, unit => 'B', warning => $format_warning_perfdata, critical => $format_critical_perfdata, min => 0, max => 1000000000); .. tip:: Dans cet exemple, au lieu d'afficher les seuils Dégradé et Critique en 'pourcentage', la fonction calculera et affichera ceux-ci en 'bytes'. threshold_validate ------------------ Description ^^^^^^^^^^^ Valider et associer un seuil à un label. Paramètres ^^^^^^^^^^ +-----------------+-----------------+-------------+---------------------------------------------------------+ | Paramètre | Type | Défaut | Description | +=================+=================+=============+=========================================================+ | label | String | | Label du seuil. | +-----------------+-----------------+-------------+---------------------------------------------------------+ | value | String | | Valeur du seuil. | +-----------------+-----------------+-------------+---------------------------------------------------------+ Exemple ^^^^^^^ Voici un exemple vérifiant si le seuil dégradé est correct : .. code-block:: perl 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(); } .. tip:: Les bon formats de seuils sont consultables ici : https://nagios-plugins.org/doc/guidelines.html#THRESHOLDFORMAT threshold_check --------------- Description ^^^^^^^^^^^ Vérifier la valeur d'une donnée de performance avec un seuil pour déterminer son statut. Paramètres ^^^^^^^^^^ +-----------------+-----------------+-------------+-------------------------------------------------------------------------+ | Paramètre | Type | Défaut | Description | +=================+=================+=============+=========================================================================+ | value | Int | | Valeur de la donnée de performance à comparer. | +-----------------+-----------------+-------------+-------------------------------------------------------------------------+ | threshold | String array | | Label du seuil à comparer et statut de sortie si celui-ci est atteint. | +-----------------+-----------------+-------------+-------------------------------------------------------------------------+ Exemple ^^^^^^^ Voici un exemple vérifiant si une donnée de performance a atteint certains seuils : .. code-block:: perl $self->{perfdata}->threshold_validate(label => 'warning', value => 80); $self->{perfdata}->threshold_validate(label => 'critical', value => 90); my $prct_used = 85; my $exit = $self->{perfdata}->threshold_check(value => $prct_used, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit, short_msg => sprint("Used memory is %i%%", $prct_used)); $self->{output}->display(); La sortie affichera : :: WARNING - Used memory is 85% | change_bytes ------------ Description ^^^^^^^^^^^ Convertir des bytes en unité de mesure lisible. Retourner une valeur et une unité. Paramètres ^^^^^^^^^^ +-----------------+-----------------+-------------+---------------------------------------------------------+ | Paramètre | Type | Défaut | Description | +=================+=================+=============+=========================================================+ | value | Int | | Valeur de données de performance à convertir. | +-----------------+-----------------+-------------+---------------------------------------------------------+ | network | | 1024 | Unité de division (1000 si définie). | +-----------------+-----------------+-------------+---------------------------------------------------------+ Exemple ^^^^^^^ Voici un exemple de conversion des bytes en unité de mesure lisible : .. code-block:: perl my ($value, $unit) = $self->{perfdata}->change_bytes(value => 100000); print $value.' '.$unit."\n"; La sortie affichera : :: 100 KB ---- SNMP ---- Cette bibliothèque vous permet d'utiliser le protocole SNMP dans votre plugin. Pour l'utiliser, vous devez ajouter la ligne suivant au début de votre fichier **plugin.pm** : .. code-block:: perl use base qw(centreon::plugins::script_snmp); get_leef -------- Description ^^^^^^^^^^^ Retourne une table de hashage de valeurs SNMP pour plusieurs OIDs (ne fonctionne pas avec les tables SNMP). Paramètres ^^^^^^^^^^ +--------------+--------------+----------+----------------------------------------------------------------------------+ | Paramètre | Type | Défaut | Description | +==============+==============+==========+============================================================================+ | **oids** | String array | | Tableau d'OIDs à contrôler (Peut être spécifié avec la méthode ``load``). | +--------------+--------------+----------+----------------------------------------------------------------------------+ | dont_quit | Int (0 or 1) | 0 | Ne pas quitter pas même si une erreur SNMP se produit. | +--------------+--------------+----------+----------------------------------------------------------------------------+ | nothing_quit | Int (0 or 1) | 0 | Quitter si aucune valeur n'est retournée. | +--------------+--------------+----------+----------------------------------------------------------------------------+ Exemple ^^^^^^^ Voici un exemple pour récupérer 2 valeurs SNMP : .. code-block:: perl my $oid_hrSystemUptime = '.1.3.6.1.2.1.25.1.1.0'; my $oid_sysUpTime = '.1.3.6.1.2.1.1.3.0'; my $result = $self->{snmp}->get_leef(oids => [ $oid_hrSystemUptime, $oid_sysUpTime ], nothing_quit => 1); print $result->{$oid_hrSystemUptime}."\n"; print $result->{$oid_sysUpTime}."\n"; load ---- Description ^^^^^^^^^^^ Charger une liste d'OIDs à utiliser avec la méthode **get_leef**. Paramètres ^^^^^^^^^^ +-----------------+----------------------+--------------+----------------------------------------------------------------------------+ | Paramètre | Type | Défaut | Description | +=================+======================+==============+============================================================================+ | **oids** | String array | | Tableau d'OIDs à vérifier. | +-----------------+----------------------+--------------+----------------------------------------------------------------------------+ | instances | Int array | | Tableau d'instances d'OIDs à vérifier. | +-----------------+----------------------+--------------+----------------------------------------------------------------------------+ | instance_regexp | String | | Expression régulière pour obtenir les instances de l'option **instances**. | +-----------------+----------------------+--------------+----------------------------------------------------------------------------+ | begin | Int | | Instance de début. | +-----------------+----------------------+--------------+----------------------------------------------------------------------------+ | end | Int | | Instance de fin. | +-----------------+----------------------+--------------+----------------------------------------------------------------------------+ Exemple ^^^^^^^ Voici un exemple pour obtenir les 4 premières instances d'une table SNMP en utilisant la méthode **load** : .. code-block:: perl my $oid_dskPath = '.1.3.6.1.4.1.2021.9.1.2'; $self->{snmp}->load(oids => [$oid_dskPercentNode], instances => [1,2,3,4]); my $result = $self->{snmp}->get_leef(nothing_quit => 1); use Data::Dumper; print Dumper($result); Voici un exemple pour obtenir plusieurs instances dynamiquement (modules mémoire de matériel Dell) en utilisant la méthode **load** : .. code-block:: perl my $oid_memoryDeviceStatus = '.1.3.6.1.4.1.674.10892.1.1100.50.1.5'; my $oid_memoryDeviceLocationName = '.1.3.6.1.4.1.674.10892.1.1100.50.1.8'; my $oid_memoryDeviceSize = '.1.3.6.1.4.1.674.10892.1.1100.50.1.14'; my $oid_memoryDeviceFailureModes = '.1.3.6.1.4.1.674.10892.1.1100.50.1.20'; my $result = $self->{snmp}->get_table(oid => $oid_memoryDeviceStatus); $self->{snmp}->load(oids => [$oid_memoryDeviceLocationName, $oid_memoryDeviceSize, $oid_memoryDeviceFailureModes], instances => [keys %$result], instance_regexp => '(\d+\.\d+)$'); my $result2 = $self->{snmp}->get_leef(); use Data::Dumper; print Dumper($result2); get_table --------- Description ^^^^^^^^^^^ Retourner une table de hashage de valeurs SNMP pour une table SNMP. Paramètres ^^^^^^^^^^ +-----------------+----------------------+----------------+-----------------------------------------------------------------+ | Paramètre | Type | Défaut | Description | +=================+======================+================+=================================================================+ | **oid** | String | | OID de la table SNMP à récupérer. | +-----------------+----------------------+----------------+-----------------------------------------------------------------+ | start | Int | | Premier OID à récupérer. | +-----------------+----------------------+----------------+-----------------------------------------------------------------+ | end | Int | | Dernier OID à récupérer. | +-----------------+----------------------+----------------+-----------------------------------------------------------------+ | dont_quit | Int (0 or 1) | 0 | Ne pas quitter même si une erreur SNMP se produit. | +-----------------+----------------------+----------------+-----------------------------------------------------------------+ | nothing_quit | Int (0 or 1) | 0 | Quitter si aucune valeur n'est retournée. | +-----------------+----------------------+----------------+-----------------------------------------------------------------+ | return_type | Int (0 or 1) | 0 | Retourner une table de hashage à un niveau au lieu de plusieurs.| +-----------------+----------------------+----------------+-----------------------------------------------------------------+ Exemple ^^^^^^^ Voici un exemple pour récupérer une table SNMP : .. code-block:: perl my $oid_rcDeviceError = '.1.3.6.1.4.1.15004.4.2.1'; my $oid_rcDeviceErrWatchdogReset = '.1.3.6.1.4.1.15004.4.2.1.2.0'; my $results = $self->{snmp}->get_table(oid => $oid_rcDeviceError, start => $oid_rcDeviceErrWatchdogReset); use Data::Dumper; print Dumper($results); get_multiple_table ------------------ Description ^^^^^^^^^^^ Retourner une table de hashage de valeurs SNMP pour plusieurs tables SNMP. Paramètres ^^^^^^^^^^ +-----------------+----------------------+----------------+---------------------------------------------------------------------------------------+ | Paramètre | Type | Défaut | Description | +=================+======================+================+=======================================================================================+ | **oids** | Hash table | | Table de hashage des OIDs à récupérer (Peut être spécifié avec la méthode ``load``). | | | | | Les clés peuvent être : "oid", "start", "end". | +-----------------+----------------------+----------------+---------------------------------------------------------------------------------------+ | dont_quit | Int (0 or 1) | 0 | Ne pas quitter même si une erreur snmp se produit. | +-----------------+----------------------+----------------+---------------------------------------------------------------------------------------+ | nothing_quit | Int (0 or 1) | 0 | Quitter si aucune valeur n'est retournée. | +-----------------+----------------------+----------------+---------------------------------------------------------------------------------------+ | return_type | Int (0 or 1) | 0 | Retourner une table de hashage à un niveau au lieu de plusieurs. | +-----------------+----------------------+----------------+---------------------------------------------------------------------------------------+ Exemple ^^^^^^^ Voici un exemple pour récupérer 2 tables SNMP : .. code-block:: perl my $oid_sysDescr = ".1.3.6.1.2.1.1.1"; my $aix_swap_pool = ".1.3.6.1.4.1.2.6.191.2.4.2.1"; my $results = $self->{snmp}->get_multiple_table(oids => [ { oid => $aix_swap_pool, start => 1 }, { oid => $oid_sysDescr }, ]); use Data::Dumper; print Dumper($results); get_hostname ------------ Description ^^^^^^^^^^^ Récupérer le nom d'hôte en paramètre (utile pour obtenir le nom d'hôte dans un mode). Paramètres ^^^^^^^^^^ Aucun. Exemple ^^^^^^^ Voici un exemple pour obtenir le nom d'hôte en paramètre : .. code-block:: perl my $hostname = $self->{snmp}->get_hostname(); get_port -------- Description ^^^^^^^^^^^ Récupérer le port en paramètre (utile pour obtenir le port dans un mode). Parameters ^^^^^^^^^^ Aucun. Exemple ^^^^^^^ Voici un exemple pour obtenir le port en paramètre : .. code-block:: perl my $port = $self->{snmp}->get_port(); oid_lex_sort ------------ Description ^^^^^^^^^^^ Retourner des OIDs triés. Paramètres ^^^^^^^^^^ +-----------------+-------------------+-------------+---------------------------------------------------------+ | Paramètre | Type | Défaut | Description | +=================+===================+=============+=========================================================+ | **-** | String array | | Tableau d'OIDs à trier. | +-----------------+-------------------+-------------+---------------------------------------------------------+ Exemple ^^^^^^^ Cet exemple afichera des OIDs triés : .. code-block:: perl foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$my_oid}})) { print $oid; } ---- Misc ---- Cette bibliothèque fournit un ensemble de méthodes diverses. Pour l'utiliser, vous pouvez directement utiliser le chemin de la méthode : .. code-block:: perl centreon::plugins::misc::; trim ---- Description ^^^^^^^^^^^ Enlever les espaces de début et de fin d'une chaîne de caractères. Paramètres ^^^^^^^^^^ +-----------------+-----------------+-------------+---------------------------------------------------------+ | Paramètre | Type | Défaut | Description | +=================+=================+=============+=========================================================+ | **-** | String | | Chaîne à modifier. | +-----------------+-----------------+-------------+---------------------------------------------------------+ Exemple ^^^^^^^ Voici un exemple d'utilisation de la méthode **trim** : .. code-block:: perl my $word = ' Hello world ! '; my $trim_word = centreon::plugins::misc::trim($word); print $word."\n"; print $trim_word."\n"; La sortie affichera : :: Hello world ! change_seconds -------------- Description ^^^^^^^^^^^ Convertir des secondes en unité de mesure lisible. Paramètres ^^^^^^^^^^ +-----------------+-----------------+-------------+---------------------------------------------------------+ | Paramètre | Type | Défaut | Description | +=================+=================+=============+=========================================================+ | **-** | Int | | Nombre de secondes à convertir. | +-----------------+-----------------+-------------+---------------------------------------------------------+ Exemple ^^^^^^^ Voici un exemple d'utilisation de la méthode **change_seconds** : .. code-block:: perl my $seconds = 3750; my $human_readable_time = centreon::plugins::misc::change_seconds($seconds); print 'Human readable time : '.$human_readable_time."\n"; La sortie affichera : :: Human readable time : 1h 2m 30s backtick -------- Description ^^^^^^^^^^^ Exécuter une commande système. Paramètres ^^^^^^^^^^ +-----------------+-----------------+-------------+---------------------------------------------------------+ | Paramètre | Type | Défaut | Description | +=================+=================+=============+=========================================================+ | **command** | String | | Commande à exécuter. | +-----------------+-----------------+-------------+---------------------------------------------------------+ | arguments | String array | | Arguments de la commande. | +-----------------+-----------------+-------------+---------------------------------------------------------+ | timeout | Int | 30 | Timeout de la commande. | +-----------------+-----------------+-------------+---------------------------------------------------------+ | wait_exit | Int (0 or 1) | 0 | Le processus de la commande ignore les signaux SIGCHLD. | +-----------------+-----------------+-------------+---------------------------------------------------------+ | redirect_stderr | Int (0 or 1) | 0 | Afficher les erreurs dans la sortie. | +-----------------+-----------------+-------------+---------------------------------------------------------+ Exemple ^^^^^^^ Voici un exemple d'utilisation de la méthode **backtick** : .. code-block:: perl my ($error, $stdout, $exit_code) = centreon::plugins::misc::backtick( command => 'ls /home', timeout => 5, wait_exit => 1 ); print $stdout."\n"; La sortie affichera les fichiers du répertoire '/home'. execute ------- Description ^^^^^^^^^^^ Exécuter une commande à distance. Paramètres ^^^^^^^^^^ +------------------+-----------------+-------------+----------------------------------------------------------------------------------------------------+ | Paramètre | Type | Défaut | Description | +==================+=================+=============+====================================================================================================+ | **output** | Object | | Sortie du plugin ($self->{output}). | +------------------+-----------------+-------------+----------------------------------------------------------------------------------------------------+ | **options** | Object | | Options du plugin ($self->{option_results}) pour obtenir les informations de connexion à distance. | +------------------+-----------------+-------------+----------------------------------------------------------------------------------------------------+ | sudo | String | | Utiliser la commande sudo. | +------------------+-----------------+-------------+----------------------------------------------------------------------------------------------------+ | **command** | String | | Commande à exécuter. | +------------------+-----------------+-------------+----------------------------------------------------------------------------------------------------+ | command_path | String | | Chemin de la commande. | +------------------+-----------------+-------------+----------------------------------------------------------------------------------------------------+ | command_options | String | | Arguments de la commande. | +------------------+-----------------+-------------+----------------------------------------------------------------------------------------------------+ Exemple ^^^^^^^ Voici un exemple d'utilisation de la méthode **execute**. Nous supposons que l'option ``--remote`` soit activée : .. code-block:: perl my $stdout = centreon::plugins::misc::execute(output => $self->{output}, options => $self->{option_results}, sudo => 1, command => 'ls /home', command_path => '/bin/', command_options => '-l'); La sortie affichera les fichier du répertoire /home d'un hôte distant à travers une connexion SSH. windows_execute --------------- Description ^^^^^^^^^^^ Exécuter une commande sur Windows. Paramètres ^^^^^^^^^^ +------------------+-----------------+-------------+-----------------------------------------------------------------+ | Paramètre | Type | Défaut | Description | +==================+=================+=============+=================================================================+ | **output** | Object | | Sortie du plugin ($self->{output}). | +------------------+-----------------+-------------+-----------------------------------------------------------------+ | **command** | String | | Commande à exécuter. | +------------------+-----------------+-------------+-----------------------------------------------------------------+ | command_path | String | | Chemin de la commande. | +------------------+-----------------+-------------+-----------------------------------------------------------------+ | command_options | String | | Arguments de la commande. | +------------------+-----------------+-------------+-----------------------------------------------------------------+ | timeout | Int | | Timeout de la commande. | +------------------+-----------------+-------------+-----------------------------------------------------------------+ | no_quit | Int | | Ne pas quitter même si une erreur SNMP se produit. | +------------------+-----------------+-------------+-----------------------------------------------------------------+ Exemple ^^^^^^^ Voici un exemple d'utilisation de la méthode **windows_execute**. .. code-block:: perl my $stdout = centreon::plugins::misc::windows_execute(output => $self->{output}, timeout => 10, command => 'ipconfig', command_path => '', command_options => '/all'); La sortie affichera la configuration IP d'un hôte Windows. --------- Statefile --------- Cette bibliothèque fournit un ensemble de méthodes pour utiliser un fichier de cache. Pour l'utiliser, ajouter la ligne suivante au début de votre **mode** : .. code-block:: perl use centreon::plugins::statefile; read ---- Description ^^^^^^^^^^^ Lire un fichier de cache. Paramètres ^^^^^^^^^^ +-------------------+-----------------+-------------+---------------------------------------------------------+ | Paramètre | Type | Défaut | Description | +===================+=================+=============+=========================================================+ | **statefile** | String | | Nom du fichier de cache. | +-------------------+-----------------+-------------+---------------------------------------------------------+ | **statefile_dir** | String | | Répertoire du fichier de cache. | +-------------------+-----------------+-------------+---------------------------------------------------------+ | memcached | String | | Serveur memcached à utiliser. | +-------------------+-----------------+-------------+---------------------------------------------------------+ Exemple ^^^^^^^ Voici un exemple d'utilisation de la méthode **read** : .. code-block:: perl $self->{statefile_value} = centreon::plugins::statefile->new(%options); $self->{statefile_value}->check_options(%options); $self->{statefile_value}->read(statefile => 'my_cache_file', statefile_dir => '/var/lib/centreon/centplugins' ); use Data::Dumper; print Dumper($self->{statefile_value}); La sortie affichera le fichier de cache et ses paramètres. get --- Description ^^^^^^^^^^^ Récupérer les données d'un fichier de cache. Paramètres ^^^^^^^^^^ +-------------------+-----------------+-------------+---------------------------------------------------------+ | Paramètre | Type | Défaut | Description | +===================+=================+=============+=========================================================+ | name | String | | Récupérer une valeur du fichier de cache. | +-------------------+-----------------+-------------+---------------------------------------------------------+ Exemple ^^^^^^^ Voici un exemple d'utilisation de la méthode **get** : .. code-block:: perl $self->{statefile_value} = centreon::plugins::statefile->new(%options); $self->{statefile_value}->check_options(%options); $self->{statefile_value}->read(statefile => 'my_cache_file', statefile_dir => '/var/lib/centreon/centplugins' ); my $value = $self->{statefile_value}->get(name => 'property1'); print $value."\n"; La sortie affichera la valeur associée à 'property1' du fichier de cache. write ----- Description ^^^^^^^^^^^ Ecrire des données dans le fichier de cache. Paramètres ^^^^^^^^^^ +-------------------+-----------------+-------------+---------------------------------------------------------+ | Paramètre | Type | Défaut | Description | +===================+=================+=============+=========================================================+ | data | String | | Données à écrire dans le fichier de cache. | +-------------------+-----------------+-------------+---------------------------------------------------------+ Exemple ^^^^^^^ Voici un exemple d'utilisation de la méthode **write** : .. code-block:: perl $self->{statefile_value} = centreon::plugins::statefile->new(%options); $self->{statefile_value}->check_options(%options); $self->{statefile_value}->read(statefile => 'my_cache_file', statefile_dir => '/var/lib/centreon/centplugins' ); my $new_datas = {}; $new_datas->{last_timestamp} = time(); $self->{statefile_value}->write(data => $new_datas); Ensuite, vous pouvez voir le résultat dans le fichier '/var/lib/centreon/centplugins/my_cache_file', le timestamp y est écrit. ---- HTTP ---- Cette bibliothèque fournit un ensemble de méthodes pour utiliser le protocole HTTP. Pour l'utiliser, ajouter la ligne suivante au début de votre **mode** : .. code-block:: perl use centreon::plugins::http; Certaines options doivent être spécifiées dans **plugin.pm** : +-----------------+-----------------+----------------------------------------------------------------------+ | Option | Type | Description | +=================+=================+======================================================================+ | **hostname** | String | Adresse IP/FQDN du serveur web. | +-----------------+-----------------+----------------------------------------------------------------------+ | **port** | String | Port HTTP. | +-----------------+-----------------+----------------------------------------------------------------------+ | **proto** | String | Protocole utilisé ('HTTP' ou 'HTTPS'). | +-----------------+-----------------+----------------------------------------------------------------------+ | credentials | | Utiliser les informations d'authentification. | +-----------------+-----------------+----------------------------------------------------------------------+ | ntlm | | Utiliser l'authentification NTLM (si ``--credentials`` est utilisée).| +-----------------+-----------------+----------------------------------------------------------------------+ | username | String | Nom d'utilisateur (si ``--credentials`` est utilisée). | +-----------------+-----------------+----------------------------------------------------------------------+ | password | String | Mot de passe (si ``--credentials`` est utilisée). | +-----------------+-----------------+----------------------------------------------------------------------+ | proxyurl | String | Proxy à utiliser. | +-----------------+-----------------+----------------------------------------------------------------------+ | url_path | String | URL à se connecter (commence par '/'). | +-----------------+-----------------+----------------------------------------------------------------------+ connect ------- Description ^^^^^^^^^^^ Tester la connexion vers une url HTTP. Retourner le contenu de la page web. Paramètres ^^^^^^^^^^ Cette méthode utilise les options du plugin précédemment définies. Exemple ^^^^^^^ Voici un exemple d'utilisation de la méthode **connect**. Nous supposons que ces options sont définies : * --hostname = 'google.com' * --urlpath = '/' * --proto = 'http' * --port = 80 .. code-block:: perl $self->{http} = centreon::plugins::http->new(output => $self->{output}, options => $self->{options}); $self->{http}->set_options(%{$self->{option_results}}); my $webcontent = $self->{http}->request(); print $webcontent; La sortie affichera le contenu de la page web '\http://google.com/'. --- DBI --- Cette bibliothèque vous permet de vous connecter à une ou plusieurs bases de données. Pour l'utiliser, ajouter la ligne suivante au début de votre fichier **plugin.pm** : .. code-block:: perl use base qw(centreon::plugins::script_sql); connect ------- Description ^^^^^^^^^^^ Se connecter à une ou plusieurs bases de données. Paramètres ^^^^^^^^^^ +------------+--------------+----------+-----------------------------------------------------------+ | Paramètre | Type | Défaut | Description | +============+==============+==========+===========================================================+ | dontquit | Int (0 or 1) | 0 | Ne pas quitter même si une erreur de connexion se produit.| +------------+--------------+----------+-----------------------------------------------------------+ Exemple ^^^^^^^ Voici un exemple d'utilisation de la méthode **connect**. Le format de la chaîne de connexion peut avoir les formes suivantes : :: DriverName:database_name DriverName:database_name@hostname:port DriverName:database=database_name;host=hostname;port=port Dans plugin.pm : .. code-block:: perl $self->{sqldefault}->{dbi} = (); $self->{sqldefault}->{dbi} = { data_source => 'mysql:host=127.0.0.1;port=3306' }; Dans votre mode : .. code-block:: perl $self->{sql} = $options{sql}; my ($exit, $msg_error) = $self->{sql}->connect(dontquit => 1); Vous êtes alors connecté à la base de données MySQL. query ----- Description ^^^^^^^^^^^ Exécuter une requête SQL sur la base de données. Paramètres ^^^^^^^^^^ +-------------------+-----------------+-------------+---------------------------------------------------------+ | Paramètre | Type | Défaut | Description | +===================+=================+=============+=========================================================+ | query | String | | Requête SQL à exécuter. | +-------------------+-----------------+-------------+---------------------------------------------------------+ Exemple ^^^^^^^ Voici un exemple d'utilisation de la méthode **query** : .. code-block:: perl $self->{sql}->query(query => q{SHOW /*!50000 global */ STATUS LIKE 'Slow_queries'}); my ($name, $result) = $self->{sql}->fetchrow_array(); print 'Name : '.$name."\n"; print 'Value : '.$value."\n"; La sortie affichera le nombre de requêtes MySQL lentes. fetchrow_array -------------- Description ^^^^^^^^^^^ Retourner une tableau à partir d'une requête SQL. Paramètres ^^^^^^^^^^ Aucun. Exemple ^^^^^^^ Voici un exemple d'utilisation de la méthode **fetchrow_array** : .. code-block:: perl $self->{sql}->query(query => q{SHOW /*!50000 global */ STATUS LIKE 'Uptime'}); my ($dummy, $result) = $self->{sql}->fetchrow_array(); print 'Uptime : '.$result."\n"; La sortie affichera l'uptime MySQL. fetchall_arrayref ----------------- Description ^^^^^^^^^^^ Retourner un tableau à partir d'une requête SQL. Paramètres ^^^^^^^^^^ Aucun. Exemple ^^^^^^^ Voici un exemple d'utilisation de la méthode **fetchrow_array** : .. code-block:: perl $self->{sql}->query(query => q{ SELECT SUM(DECODE(name, 'physical reads', value, 0)), SUM(DECODE(name, 'physical reads direct', value, 0)), SUM(DECODE(name, 'physical reads direct (lob)', value, 0)), SUM(DECODE(name, 'session logical reads', value, 0)) FROM sys.v_$sysstat }); my $result = $self->{sql}->fetchall_arrayref(); my $physical_reads = @$result[0]->[0]; my $physical_reads_direct = @$result[0]->[1]; my $physical_reads_direct_lob = @$result[0]->[2]; my $session_logical_reads = @$result[0]->[3]; print $physical_reads."\n"; La sortie affichera les lectures physiques sur une base de données Oracle. fetchrow_hashref ---------------- Description ^^^^^^^^^^^ Retourner une table de hashage à partir d'une requête SQL. Paramètres ^^^^^^^^^^ Aucun. Exemple ^^^^^^^ Voici un exemple d'utilisation de la méthode **fetchrow_hashref** : .. code-block:: perl $self->{sql}->query(query => q{ SELECT datname FROM pg_database }); while ((my $row = $self->{sql}->fetchrow_hashref())) { print $row->{datname}."\n"; } La sortie affichera la liste des bases de données PostgreSQL. ***************** Exemples complets ***************** ------------------- Requête SNMP simple ------------------- Description ----------- | Cet exemple explique comment vérifier une valeur SNMP unique sur un pare-feu PfSense (paquets supprimés pour cause de surcharge mémoire). | Un fichier de cache sera utilisé car c'est un compteur SNMP. Il est nécessaire d'obtenir la valeur différentielle entre 2 contrôles. | La valeur récupérée sera comparée aux seuils Dégradé et Critique. Fichier du plugin ----------------- Tout d'abord, créer le dossier du plugin, ainsi que le fichier du plugin : :: $ mkdir -p apps/pfsense/snmp $ touch apps/pfsense/snmp/plugin.pm .. tip:: PfSense est un pare-feu applicatif et il sera contrôlé en utilisant le protocole SNMP Ensuite, éditer le fichier **plugin.pm** et ajouter les lignes suivantes : .. code-block:: perl # # Copyright 2018 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. # # Chemin vers le plugin package apps::pfsense::snmp::plugin; # Bibliothèques nécessaires use strict; use warnings; # Utiliser cette bibliothèque pour contrôle en utilisant le protocole SNMP use base qw(centreon::plugins::script_snmp); .. tip:: N'oublier pas de modifier la ligne 'Authors'. Ajouter la méthode **new** pour instancier le plugin : .. code-block:: perl sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; # $options->{options} = options object # Version du plugin $self->{version} = '0.1'; # Association des modes %{$self->{modes}} = ( # Nom du mode => Chemin vers le mode 'memory-dropped-packets' => 'apps::pfsense::snmp::mode::memorydroppedpackets', ); return $self; } Déclarer ce plugin en tant que module perl : .. code-block:: perl 1; Ajouter une description au plugin : .. code-block:: perl __END__ =head1 PLUGIN DESCRIPTION Check pfSense in SNMP. =cut .. tip:: Cette description est affichée avec l'option ``--help``. Fichier du mode --------------- Ensuite, créer le répertoire du mode, ainsi que le fichier du mode : :: $ mkdir apps/pfsense/snmp/mode $ touch apps/pfsense/snmp/mode/memorydroppedpackets.pm Editer le fichier **memorydroppedpackets.pm** et ajouter les lignes suivantes : .. code-block:: perl # # Copyright 2018 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. # # Chemin vers le mode package apps::pfsense::snmp::mode::memorydroppedpackets; # Bibliothèque nécessaire pour le mode use base qw(centreon::plugins::mode); # Bibliothèques nécessaires use strict; use warnings; # Bibliothèque nécessaire pour certaines fonctions use POSIX; # Bibliothèque nécessaire pour utiliser un fichier de cache use centreon::plugins::statefile; Ajouter la méthode **new** pour instancier le mode : .. code-block:: perl sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; # Version du mode $self->{version} = '1.0'; # Declaration des options $options{options}->add_options(arguments => { # nom de l'option => nom de la variable "warning:s" => { name => 'warning', }, "critical:s" => { name => 'critical', }, }); # Instanciation du fichier de cache $self->{statefile_value} = centreon::plugins::statefile->new(%options); return $self; } .. tip:: Une valeur par défaut peut être ajoutée aux options. Exemple : "warning:s" => { name => 'warning', default => '80'}, Ajouter la méthode **check_options** pour valider les options : .. code-block:: perl sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); # Validation des options de seuil avec la méthode threshold_validate 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(); } # Validation des options de fichier de cache en utilisant la méthode check_options de la bibliothèque statefile $self->{statefile_value}->check_options(%options); } Ajouter la méthode **run** pour exécuter le mode : .. code-block:: perl sub run { my ($self, %options) = @_; # $options{snmp} = snmp object # Récupération des options SNMP $self->{snmp} = $options{snmp}; $self->{hostname} = $self->{snmp}->get_hostname(); $self->{snmp_port} = $self->{snmp}->get_port(); # oid SNMP à requêter my $oid_pfsenseMemDropPackets = '.1.3.6.1.4.1.12325.1.200.1.2.6.0'; my ($result, $value); # Récupération de la valeur SNMP pour l'oid précédemment défini $result = $self->{snmp}->get_leef(oids => [ $oid_pfsenseMemDropPackets ], nothing_quit => 1); # $result est une table de hashage où les clés sont les oids $value = $result->{$oid_pfsenseMemDropPackets}; # Lecture du fichier de cache $self->{statefile_value}->read(statefile => 'pfsense_' . $self->{hostname} . '_' . $self->{snmp_port} . '_' . $self->{mode}); # Lecture des valeurs du fichier de cache my $old_timestamp = $self->{statefile_value}->get(name => 'last_timestamp'); my $old_memDropPackets = $self->{statefile_value}->get(name => 'memDropPackets'); # Création d'une table de hashage avec les nouvelles valeurs qui seront écrites dans le fichier de cache my $new_datas = {}; $new_datas->{last_timestamp} = time(); $new_datas->{memDropPackets} = $value; # Ecriture des nouvelles valeurs dans le fichier de cache $self->{statefile_value}->write(data => $new_datas); # Si le fichier de cache ne possède aucune valeur, nous les créons et attendons un nouveau contrôle pour calculer la valeur if (!defined($old_timestamp) || !defined($old_memDropPackets)) { $self->{output}->output_add(severity => 'OK', short_msg => "Buffer creation..."); $self->{output}->display(); $self->{output}->exit(); } # Correctif lorsque PfSense redémarre (les compteurs snmp sont réinitialisés à 0) $old_memDropPackets = 0 if ($old_memDropPackets > $new_datas->{memDropPackets}); # Calcul de l'intervalle de temps entre 2 contrôles my $delta_time = $new_datas->{last_timestamp} - $old_timestamp; $delta_time = 1 if ($delta_time == 0); # Calcul de la valeur par seconde my $memDropPacketsPerSec = ($new_datas->{memDropPackets} - $old_memDropPackets) / $delta_time; # Calcul le code de retour en comparant la valeur aux seuils # Le code de retour peut être : 'OK', 'WARNING', 'CRITICAL', 'UNKNOWN' my $exit_code = $self->{perfdata}->threshold_check(value => $memDropPacketsPerSec, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); # Ajout d'une donnée de performance $self->{output}->perfdata_add(label => 'dropped_packets_Per_Sec', value => sprintf("%.2f", $memDropPacketsPerSec), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0); # Ajout du message de sortie $self->{output}->output_add(severity => $exit_code, short_msg => sprintf("Dropped packets due to memory limitations : %.2f /s", $memDropPacketsPerSec)); # Affichage du message de sortie $self->{output}->display(); $self->{output}->exit(); } Déclarer ce mode comme un module perl : .. code-block:: perl 1; Ajouter une description aux options du mode : .. code-block:: perl __END__ =head1 MODE Check number of packets per second dropped due to memory limitations. =over 8 =item B<--warning> Threshold warning for dropped packets in packets per second. =item B<--critical> Threshold critical for dropped packets in packets per second. =back =cut Ligne de commande ----------------- Voici un exemple de ligne de commande : :: $ perl centreon_plugins.pl --plugin apps::pfsense::snmp::plugin --mode memory-dropped-packets --hostname 192.168.0.1 --snmp-community 'public' --snmp-version '2c' --warning '1' --critical '2' La sortie pourrait afficher : :: OK: Dropped packets due to memory limitations : 0.00 /s | dropped_packets_Per_Sec=0.00;0;;1;2 centreon-plugins-20220113/doc/fr/developer/index.rst000066400000000000000000000001631417000230700222360ustar00rootroot00000000000000#################### Guide de développeur #################### .. toctree:: :maxdepth: 3 :glob: guide centreon-plugins-20220113/doc/fr/index.rst000066400000000000000000000006701417000230700202540ustar00rootroot00000000000000Bienvenue dans la documentation Centreon Plugins! ================================================= Centreon Plugins est un ensemble de bibliothèques et plugins de supervision écrits en Perl. Cet ensemble est licencié sous les termes de `Apache License Version 2 ` tel que publié par la "Free Software Fondation". Sommaire : .. toctree:: :maxdepth: 2 user/index developer/index centreon-plugins-20220113/doc/fr/user/000077500000000000000000000000001417000230700173665ustar00rootroot00000000000000centreon-plugins-20220113/doc/fr/user/guide.rst000066400000000000000000003363111417000230700212240ustar00rootroot00000000000000*********** Description *********** "centreon-plugins" est un projet gratuit et open source de supervision des systèmes. Ce projet peut être utilisé avec Centreon, Icinga et tout autre logiciel de supervision compatible avec les plugins Nagios. La dernière version est disponible sur le dépôt git suivant: https://github.com/centreon/centreon-plugins.git ************ Installation ************ ------------- Debian Wheezy ------------- Télécharger la dernière version de "centreon-plugins" depuis le dépôt : :: # aptitude install git # git clone https://github.com/centreon/centreon-plugins.git Pour superviser les systèmes SNMP, vous devez installer les paquets suivants : :: # aptitude install perl libsnmp-perl Vous pouvez installer d'autres paquets pour utiliser plus de plugins : :: # aptitude install libxml-libxml-perl libjson-perl libwww-perl libxml-xpath-perl libnet-telnet-perl libnet-ntp-perl libnet-dns-perl libdbi-perl libdbd-mysql-perl libdbd-pg-perl Pour utiliser la fonctionnalité 'memcached', vous devez installer le module CPAN suivant (pas de paquet debian): http://search.cpan.org/~wolfsage/Memcached-libmemcached-1.001702/libmemcached.pm ------------- Centos/Rhel 6 ------------- Télécharger la dernière version de "centreon-plugins" depuis le dépôt : :: # yum install git # git clone https://github.com/centreon/centreon-plugins.git Pour superviser les systèmes SNMP, vous devez installer les paquets suivants : :: # yum install perl net-snmp-perl Vous pouvez installer d'autres paquets pour utiliser plus de plugins : :: # yum install perl-XML-LibXML perl-JSON perl-libwww-perl perl-XML-XPath perl-Net-Telnet perl-Net-DNS perl-DBI perl-DBD-MySQL perl-DBD-Pg Pour utiliser la fonctionnalité 'memcached', vous devez installer le module CPAN suivant (paquet disponible dans 'rpmforge'): http://search.cpan.org/~wolfsage/Memcached-libmemcached-1.001702/libmemcached.pm ******************* Utilisation basique ******************* Nous allons utiliser un exemple basique pour montrer comment superviser un système. J'ai terminé la partie installation et je veux superviser un système Linux par SNMP. Tout d'abord, j'ai besoin de trouver le plugin à utiliser dans la liste : :: $ perl centreon_plugins.pl --list-plugin | grep -i linux | grep 'PLUGIN' PLUGIN: os::linux::local::plugin PLUGIN: os::linux::snmp::plugin Il semblerait que 'os::linux::snmp::plugin' est le bon donc je vérifie avec l'option ``--help`` pour être sûr : :: $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --help ... Plugin Description: Check Linux operating systems in SNMP. C'est exactement ce dont j'ai besoin. Maintenant je vais utiliser l'option ``--list-mode`` pour connaître ce que je peux faire avec celui-ci : :: $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --list-mode ... Modes Available: cpu cpu-detailed disk-usage diskio inodes interfaces list-diskspath list-interfaces list-storages load memory processcount storage swap tcpcon time uptime J'aimerais tester le mode 'load': :: $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --mode=load UNKNOWN: Missing parameter --hostname. Il ne fonctionne pas car certaines options sont manquantes. Je peux avoir une description du mode et ses options avec l'option ``--help`` : :: $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --mode=load --help Je dois éventuellement configurer certaines options SNMP : :: $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --mode=load --hostname=127.0.0.1 --snmp-version=2c --snmp-community=public OK: Load average: 0.00, 0.00, 0.00 | 'load1'=0.00;;;0; 'load5'=0.00;;;0; 'load15'=0.00;;;0; Je peux spécifier des seuils avec les options ``--warning`` et ``--critical``: :: $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --mode=load --hostname=127.0.0.1 --snmp-version=2c --snmp-community=public --warning=1,2,3 --critical=2,3,4 OK: Load average: 0.00, 0.00, 0.00 | 'load1'=0.00;0:1;0:2;0; 'load5'=0.00;0:2;0:3;0; 'load15'=0.00;0:3;0:4;0; *** FAQ *** ---------------------------------- Qu'est ce que je peux superviser ? ---------------------------------- L'option ``--list-plugin`` peut être utilisée pour obtenir la liste des plugins, ainsi qu'une courte description. Les en-têtes du tableau signifient : * Transport : Le point de contrôle a des options internes pour le transport. * Protocole : qu'est-ce qui est utilisé pour obtenir les informations de supervision ? * Expérimental : Le point de contrôle est en cours de développement. +----------------+--------------------+----------------------------+--------------------------------------------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | | Transport | Protocole | | | | | Categorie | Contrôle +-------+----------+---------+--------+--------+-------+-------+----------+ Experimental | Comment | Dépendances Perl | | | | SSH | TELNET | WSMAN | SNMP | HTTP | WMI | JMX | custom | | | | +================+====================+=======+==========+=========+========+========+=======+=======+==========+==============+===============================================================+========================================================================+ | | Active Directory | | | | | | | | * | | Utilise la commande 'dcdiag'. Doit être installée sur Windows.| Win32::Job | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Apache | | | | | * | | | | | Requiert le module Apache 'mod_status'. | LWP::UserAgent, URI, HTTP::Cookies | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Apc | | | | | * | | | | | | LWP::UserAgent, URI, HTTP::Cookies | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Apcupsd | * | | | | | | | * | | UUtilise les commandes 'apcupsd'. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Bluemind | | | | | * | | | | | Utilise l'API 'influxdb'. | JSON, LWP::UserAgent, URI, HTTP::Cookies | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Checkmyws | | | | | * | | | | | | JSON, LWP::UserAgent, URI, HTTP::Cookies | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Elasticsearch | | | | | * | | | | | | JSON, LWP::UserAgent, URI, HTTP::Cookies | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Exchange | | | | | | | | * | | Utilise un script powershell. Doit être installé sur Windows. | Win32::Job | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Github | | | | | * | | | | | Utilise l'API 'github'. | JSON, LWP::UserAgent, URI, HTTP::Cookies, DateTime | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Hddtemp | | | | | | | | * | | Ouvre une connexion TCP personnalisée. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | | | | | | | * | | | | Doit être installé sur Windows. | Win32::OLE | | | IIS +-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | Application | | | | * | | | * | | | * | | openwsman, MIME::Base64 | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Jenkins | | | | | * | | | | | | JSON, LWP::UserAgent, URI, HTTP::Cookies | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Kayako | | | | | * | | | | | Utilise l'API 'kayako'. | XML::XPath, Digest::SHA, LWP::UserAgent, URI, HTTP::Cookies | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Lmsensors | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Msmq | | | | | | | | * | * | Doit être installé sur Windows. Pas encore développé. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Nginx | | | | | * | | | | | Requiert le module 'HttpStubStatusModule'. | LWP::UserAgent, URI, HTTP::Cookies | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Pacemaker | * | | | | | | | * | | Utilise la commande 'crm_mon'. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Pfsense | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Selenium | | | | | | | | * | | Se connecte à un serveur Selenium pour jouer un scenario. | XML::XPath, WWW::Selenium | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Tomcat | | | | | * | | | | | Requiert tomcat webmanager. | XML::XPath, LWP::UserAgent, URI, HTTP::Cookies | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Varnish | * | | | | | | | * | | Utilise les commandes varnish. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | VMWare | | | | | | | | * | | Requiert le connecteur 'centreon-vmware' de Centreon. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Pfsense | | | | * | | | | | | | | +----------------+--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Bgp | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Dhcp | | | | | | | | * | | | Net::DHCP::Packet, Net::Subnet | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Dns | | | | | | | | * | | | Net::DNS | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Ftp | | | | | | | | * | | | Net::FTP, Net::FTPSSL | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Http | | | | | * | | | | | | LWP::UserAgent, URI, HTTP::Cookies, JSON, JSON::Path, XML::XPath | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Ftp | | | | | | | | * | | | Net::FTP, Net::FTPSSL | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Imap | | | | | | | | * | | | Net::IMAP::Simple | | Protocoles +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Jmx | | | | | | | * | | | | JSON::Path, JMX::Jmx4Perl | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Ldap | | | | | | | | * | | | Net::LDAP | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Ntp | | | | | | | | * | | | Net::NTP | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Radius | | | | | | | | * | | | Authen::Radius | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Smtp | | | | | | | | * | | | Email::Send::SMTP::Gmail | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Tcp | | | | | | | | * | | | IO::Socket::SSL | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Udp | | | | | | | | * | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | x509 | | | | | | | | * | | | IO::Socket::SSL | +----------------+--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Informix | | | | | | | | * | | | DBI, DBD::Informix | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Firebird | | | | | | | | * | | | DBI, DBD::Firebird | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | MS SQL | | | | | | | | * | | | DBI, DBD::Sybase | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | Bases de | MySQL | | | | | | | | * | | | DBI, DBD::mysql | | données +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Oracle | | | | | | | | * | | | DBI, DBD::oracle, DateTime | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Postgres | | | | | | | | * | | | DBI, DBD::Pg | +----------------+--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | ATS Apc | | | | * | | | | | * | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | PDU Apc | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | PDU Eaton | | | | * | | | | | * | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | PDU Raritan | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Standard Printers | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Hwgste | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Sensorip | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Sensormetrix Em01 | | | | | * | | | | | | LWP::UserAgent, URI, HTTP::Cookies | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Serverscheck | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Cisco UCS | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Dell CMC | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Dell iDrac | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | Matériel | Dell Openmanage | | | | * | | | | | | Requiert "l'agent openmanage" sur le système d'exploitation. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | HP Proliant | | | | * | | | | | | Requiert "l'agent HP Insight" sur le système d'exploitation. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | HP Blade Chassis | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | IBM BladeCenter | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | IBM HMC | * | | | | | | | * | * | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | IBM IMM | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Sun hardware | * | * | | * | | | | * | | Peut superviser plusieurs types de matériel Sun. | Net::Telnet, SNMP | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | UPS APC | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | UPS Mge | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | UPS Standard | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | UPS Powerware | | | | * | | | | | | | | +----------------+--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | 3com | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Alcatel Omniswitch | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Arkoon | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Aruba | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Bluecoat | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Brocade | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Checkpoint | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Cisco | | | | * | | | | | | Many cisco (2800, Nexus, Wlc, Ironport,...) | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Citrix Netscaler | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Dell Powerconnect | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Dlink | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Extreme | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | F5 Big-Ip | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Fortinet Fortigate | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Fritzbox | | | | * | | | | | | | | | Réseau +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | H3C | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Hirschmann | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | HP Procurve | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | HP Virtual Connect | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Juniper | | | | * | | | | | | Peut superviser: 'SSG', 'SA', 'SRX', 'MAG', 'EX', 'Ggsn'. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Palo Alto | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Netasq | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Oneaccess | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Radware Alteon | | | | * | | | | | * | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Redback | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Riverbed | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Ruggedcom | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Securactive | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Stonesoft | | | | * | | | | | | | | +----------------+--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | | * | | | | | | | * | | Utilise les commandes AIX. | | | | AIX +-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | | | | | | | * | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Freebsd | | | | * | | | | | | Utilise l'agent 'bsnmpd'. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | | * | | | | | | | * | | Utilise les commandes Linux. | | | Systèmes | Linux +-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | | * | | | | | | | * | | Utilise les commandes Solaris. | | | | Solaris +-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | | | | | | | * | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | | | | | * | | | | | | | | | | Windows +-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | | | | * | | | * | | | * | | | +----------------+--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Dell EqualLogic | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Dell MD3000 | | | | | | | | * | | Requiert la commande 'SMcli'. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Dell TL2000 | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Dell ML6000 | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | EMC Celerra | * | | | | | | | * | | Utilise les commandes de l'appliance. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | EMC Clariion | | | | | | | | * | | Requiert la commande 'navisphere'. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | EMC DataDomain | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | EMC Recoverypoint | * | | | | | | | * | | Utilise les commandes de l'appliance. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | EMC Vplex | | | | | | * | | | | Utilise l'API JSON. | JSON, LWP::UserAgent, URI, HTTP::Cookies | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | EMC Xtremio | | | | | | * | | | | Utilise l'API JSON. | JSON, LWP::UserAgent, URI, HTTP::Cookies | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Fujitsu Eternus DX | * | | | | | | | * | | Utilise les commandes de l'appliance. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | HP 3par | * | | | | | | | * | | Utilise les commandes de l'appliance. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | HP Lefthand | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | HP MSA2000 | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | Stockage | HP p2000 | | | | | | * | | | | Utilise l'API XML. | XML::XPath, LWP::UserAgent, URI, HTTP::Cookies | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | IBM DS3000 | | | | | | | | * | | Utilise la commande 'SMcli'. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | IBM DS4000 | | | | | | | | * | | Utilise la commande 'SMcli'. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | IBM DS5000 | | | | | | | | * | | Utilise la commande 'SMcli'. | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | IBM TS3100 | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | IBM TS3200 | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Netapp | | | | * | | | | | | | DateTime | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Nimble | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Panzura | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Qnap | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Synology | | | | * | | | | | | | | | +--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ | | Violin 3000 | | | | * | | | | | | | | +----------------+--------------------+-------+----------+---------+--------+--------+-------+-------+----------+--------------+---------------------------------------------------------------+------------------------------------------------------------------------+ ------------------------------------------------------ Comment puis-je supprimer les données de performance ? ------------------------------------------------------ Par exemple, je vérifie les connexions TCP d'un serveur Linux par SNMP avec la commande suivante : :: $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --mode=tcpcon --hostname=127.0.0.1 --snmp-version=2c --snmp-community=public OK: Total connections: 1 | 'total'=1;;;0; 'con_closed'=0;;;0; 'con_closeWait'=0;;;0; ' con_synSent'=0;;;0; 'con_established'=1;;;0; 'con_timeWait'=0;;;0; 'con_lastAck'=0;;;0 ; 'con_listen'=5;;;0; 'con_synReceived'=0;;;0; 'con_finWait1'=0;;;0; 'con_finWait2'=0; ;;0; 'con_closing'=0;;;0; Il y a trop de données de performances et je veux seulement garder la donnée de performance 'total'. J'utilise l'option ``--filter-perfdata='total'`` : :: $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --mode=tcpcon --hostname=127.0.0.1 --snmp-version=2c --snmp-community=public --filter-perfdata='total' OK: Total connections: 1 | 'total'=1;;;0; Je peux utiliser une expression régulière dans l'option ``--filter-perfdata``. Donc je peux exclure les données de performance commençant par 'total' : :: $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --mode=tcpcon --hostname=127.0.0.1 --snmp-version=2c --snmp-community=public --filter-perfdata='^(?!(total))' OK: Total connections: 1 | 'con_closed'=0;;;0; 'con_closeWait'=0;;;0; 'con_synSent'=0;;;0; 'con_established'=1;;;0; 'con_timeWait'=0;;;0; 'con_lastAck'=0;;;0; 'con_listen'=5;;;0; 'con_synReceived'=0;;;0; 'con_finWait1'=0;;;0; 'con_finWait2'=0;;;0; 'con_closing'=0;;;0; ---------------------------------------------------------- Comment puis-je ajuster un seuil: critique si valeur < X ? ---------------------------------------------------------- "centreon-plugins" gère les seuils Nagios : https://nagios-plugins.org/doc/guidelines.html#THRESHOLDFORMAT Par exemple, je veux vérifier que 'crond' fonctionne (s'il y a moins de 1 processus, critique). J'ai deux solutions : :: $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --mode=processcount --hostname=127.0.0.1 --snmp-version=2c --snmp-community=public --process-name=crond --critical=1: CRITICAL: Number of current processes running: 0 | 'nbproc'=0;;1:;0; $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --mode=processcount --hostname=127.0.0.1 --snmp-version=2c --snmp-community=public --process-name=crond --critical=@0:0 CRITICAL: Number of current processes running: 0 | 'nbproc'=0;;@0:0;0; ------------------------------------------------------- Comment puis-je vérifier des équipements ipv6 en SNMP ? ------------------------------------------------------- Vous pouvez vérifier des équipements ipv6 en SNMP via la syntaxe suivante (``udp6:[xxxx]``): :: $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --hostname='udp6:[fe80::250:56ff:feb5:6ae0]' --mode=storage --snmp-version=2c --snmp-community=public ------------------------------------------------------------ Comment puis-je vérifier la valeur d'un OID SNMP générique ? ------------------------------------------------------------ Il y a un plugin SNMP générique pour vérifier cela. Voici un exemple pour obtenir l'OID SNMP 'SysUptime' : :: $ perl centreon_plugins.pl --plugin=apps::protocols::snmp::plugin --mode=numeric-value --oid='.1.3.6.1.2.1.1.3.0' --hostname=127.0.0.1 --snmp-version=2c --snmp-community=public --------------------------------------------------------------------- Comment utiliser un serveur memcached pour la rétention des données ? --------------------------------------------------------------------- Quelques plugins ont besoin de stocker des données. Il y a deux solutions pour cela : * Un fichier sur le disque (par defaut). * Un serveur memcached. Pour utiliser 'memcached', vous devez avoir un serveur memcached et le module CPAN 'Memcached::libmemcached' installé. Vous pouvez renseigner le serveur memcached avec l'option ``--memcached``: :: $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --mode=interfaces --hostname=127.0.0.1 --snmp-version=2c --snmp-community=public --verbose --add-traffic --memcached=127.0.0.1 OK: All traffic are ok | 'traffic_in_lo'=197.40b/s;;;0;10000000 'traffic_out_lo'=197.40b/s;;;0;10000000 'traffic_in_eth0'=14539.11b/s;;;0;1000000000 'traffic_out_eth0'=399.59b/s;;;0;1000000000 'traffic_in_eth1'=13883.82b/s;;;0;1000000000 'traffic_out_eth1'=1688.66b/s;;;0;1000000000 Interface 'lo' Traffic In : 197.40b/s (0.00 %), Out : 197.40b/s (0.00 %) Interface 'eth0' Traffic In : 14.54Kb/s (0.00 %), Out : 399.59b/s (0.00 %) Interface 'eth1' Traffic In : 13.88Kb/s (0.00 %), Out : 1.69Kb/s (0.00 %) .. tip:: Un fichier local est utilisé si le serveur memcached ne répond pas. -------------------------------------------- Quel est l'usage de l'option ``--dyn-mode`` ? -------------------------------------------- Avec cette option, vous pouvez utiliser un mode avec un plugin. Cela est couramment utilisé pour les bases de données. Par exemple, j'ai une application qui stocke des informations de supervision dans une base de données. Le développeur peut utiliser un autre plugin pour créer le point de contrôle (pas besoin de faire les connexions SQL,... cela fait gagner du temps) : :: $ perl centreon_plugins.pl --plugin=database::mysql::plugin --dyn-mode=apps::centreon::mysql::mode::pollerdelay --host=10.30.3.75 --username='test' --password='testpw' --verbose OK: All poller delay for last update are ok | 'delay_Central'=2s;0:300;0:600;0; 'delay_Poller-Engine'=2s;0:300;0:600;0; Delay for last update of Central is 2 seconds Delay for last update of Poller-Engine is 2 seconds .. warning:: Un mode utilisant le système suivant doit le notifier (dans l'aide associée). Donc vous devriez ouvrir un fichier dans éditeur et lire à la fin de la description. ----------------------------------------------- Comment puis-je vérifier la version du plugin ? ----------------------------------------------- Vous pouvez vérifier la version des plugins et des modes avec l'option ``--version`` : :: $ perl centreon_plugins.pl --version Global Version: 20160524 $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --version Plugin Version: 0.1 $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --mode=storage --version Mode Version: 1.0 Vous pouvez également utiliser l'option ``--mode-version`` pour exécuter le mode seulement s'il est dans la bonne version. Par exemple, nous voulons exécuter le mode seulement si sa version >= 2.x : :: $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --mode=storage --hostname=127.0.0.1 --snmp-version=2c --snmp-community=public --verbose --mode-version='2.x' UNKNOWN: Not good version for plugin mode. Excepted at least: 2.x. Get: 1.0 -------------------------------------------- Comment puis-je avoir un seul fichier Perl ? -------------------------------------------- Nous avons réalisé des tests et le temps d'éxecution est augmenté d'environ 4%. Nous allons créer un fichier unique pour la sonde Linux SNMP. Télécharger le module Perl ``App::FatPacker`` sur metacpan: :: # tar zxvf App-FatPacker-0.010005.tar.gz # cd App-FatPacker-0.010005 # perl Makefile.PL && make && make install Créer un répertoire de construction: :: # mkdir -p build/plugin # cd build Cloner ``centreon-plugins``: :: # git clone https://github.com/centreon/centreon-plugins.git ``fatpack`` inclut les fichiers ``pm`` présent dans le répertoire ``lib``: :: # mkdir plugin/lib && cd centreon-plugins Copier les fichiers communs à l'ensemble des sondes: :: # find . -name "*.pm" -exec sed -i ' /__END__/d' \{\} \; # cp -R --parent centreon/plugins/{misc,mode,options,output,perfdata,script,statefile,values}.pm centreon/plugins/templates/ centreon/plugins/alternative/ ../plugin/lib/ # cp centreon_plugins.pl ../plugin # sed -i 's/alternative_fatpacker = 0/alternative_fatpacker = 1/' ../plugin/lib/centreon/plugins/script.pm Copier les fichiers pour la sonde Linux SNMP: :: # cp -R --parent centreon/plugins/{script_snmp,snmp}.pm os/linux/snmp/ snmp_standard/mode/{cpu,cpudetailed,diskio,diskusage,inodes,interfaces,loadaverage,listdiskspath,listinterfaces,liststorages,memory,processcount,storage,swap,ntp,tcpcon,uptime}.pm ../plugin/lib/ Construire le fichier Perl unique: :: # cd ../plugin # fatpack file centreon_plugins.pl > centreon_linux_snmp.pl La sonde fonctionne de la même façon: :: # perl centreon_linux_snmp.pl --plugin os::linux::snmp::plugin --mode=processcount --snmp-community public --snmp-version 2c --hostname=127.0.0.1 --process-name='' --process-status='' --process-args='' ------------------------------------------ Comment puis-je créer un binaire Windows ? ------------------------------------------ Cette procédure permet d'utiliser les sondes sans installer installer Perl sur le système Windows. * Installer Strawberry Perl 5.24.x sur un Windows (Télécharger sur http://strawberryperl.com/) * Récupérer la dernière version des centreon-plugins (Télécharger https://github.com/centreon/centreon-plugins/archive/master.zip) Après les installations, installer le module ``PAR::Packer`` (remplacer ````): :: cmd> \perl\bin\cpan.bat cpan> install PAR::Packer L'installation peut prendre plusieurs minutes. Dans un dossier contenant le répertoire ``centreon-plugins``, créer un fichier ``build.bat`` (remplacer ````). Nous excluons le module ``IO::Socket::INET6`` (Perl 5.14 intègre la fonctionnalité IPv6 en natif). :: set PERL_INSTALL_DIR= chdir /d %~dp0 set PAR_VERBATIM=1 cmd /C %PERL_INSTALL_DIR%\perl\site\bin\pp --lib=centreon-plugins\ -o centreon_plugins.exe centreon-plugins\centreon_plugins.pl ^ --unicode ^ -X IO::Socket::INET6 ^ --link=%PERL_INSTALL_DIR%\c\bin\libxml2-2__.dll ^ --link=%PERL_INSTALL_DIR%\c\bin\libiconv-2__.dll ^ --link=%PERL_INSTALL_DIR%\c\bin\liblzma-5__.dll ^ --link=%PERL_INSTALL_DIR%\c\bin\zlib1__.dll ^ --link=%PERL_INSTALL_DIR%\c\bin\libcrypto-1_1-x64__.dll ^ --link=%PERL_INSTALL_DIR%\c\bin\libssl-1_1-x64__.dll ^ -M IO::Socket::SSL ^ -M Win32::Job ^ -M Email::Send::SMTP::Gmail ^ -M HTTP::ProxyPAC ^ -M JE ^ -M Tie::RefHash::Weak ^ -M XML::LibXML::SAX ^ -M Net::FTPSSL ^ -M Authen::NTLM ^ -M JSON::XS ^ -M apps::backup::netbackup::local::plugin ^ -M apps::backup::netbackup::local::mode::dedupstatus ^ -M apps::backup::netbackup::local::mode::drivecleaning ^ -M apps::backup::netbackup::local::mode::drivestatus ^ -M apps::backup::netbackup::local::mode::jobstatus ^ -M apps::backup::netbackup::local::mode::listpolicies ^ -M apps::backup::netbackup::local::mode::tapeusage ^ -M apps::backup::veeam::local::plugin ^ -M apps::backup::veeam::local::mode::jobstatus ^ -M apps::backup::veeam::local::mode::listjobs ^ -M apps::backup::veeam::local::mode::tapejobs ^ -M apps::centreon::local::plugin ^ -M apps::centreon::local::mode::downtimetrap ^ -M apps::centreon::local::mode::centreonpluginsversion ^ -M apps::citrix::local::plugin ^ -M apps::citrix::local::mode::license ^ -M apps::citrix::local::mode::session ^ -M apps::citrix::local::mode::zone ^ -M apps::citrix::local::mode::folder ^ -M apps::microsoft::activedirectory::local::plugin ^ -M apps::microsoft::activedirectory::local::mode::dcdiag ^ -M apps::microsoft::activedirectory::local::mode::dfsrbacklog ^ -M apps::microsoft::activedirectory::local::mode::netdom ^ -M apps::microsoft::exchange::local::plugin ^ -M apps::microsoft::exchange::local::mode::activesyncmailbox ^ -M apps::microsoft::exchange::local::mode::databases ^ -M apps::microsoft::exchange::local::mode::listdatabases ^ -M apps::microsoft::exchange::local::mode::imapmailbox ^ -M apps::microsoft::exchange::local::mode::mapimailbox ^ -M apps::microsoft::exchange::local::mode::outlookwebservices ^ -M apps::microsoft::exchange::local::mode::owamailbox ^ -M apps::microsoft::exchange::local::mode::queues ^ -M apps::microsoft::exchange::local::mode::replicationhealth ^ -M apps::microsoft::exchange::local::mode::services ^ -M apps::microsoft::hyperv::2012::local::plugin ^ -M apps::microsoft::hyperv::2012::local::mode::listnodevms ^ -M apps::microsoft::hyperv::2012::local::mode::scvmmintegrationservice ^ -M apps::microsoft::hyperv::2012::local::mode::scvmmsnapshot ^ -M apps::microsoft::hyperv::2012::local::mode::scvmmvmstatus ^ -M apps::microsoft::hyperv::2012::local::mode::nodeintegrationservice ^ -M apps::microsoft::hyperv::2012::local::mode::nodereplication ^ -M apps::microsoft::hyperv::2012::local::mode::nodesnapshot ^ -M apps::microsoft::hyperv::2012::local::mode::nodevmstatus ^ -M apps::microsoft::iis::local::plugin ^ -M apps::microsoft::iis::local::mode::listapplicationpools ^ -M apps::microsoft::iis::local::mode::applicationpoolstate ^ -M apps::microsoft::iis::local::mode::listsites ^ -M apps::microsoft::iis::local::mode::webservicestatistics ^ -M apps::microsoft::mscs::local::plugin ^ -M apps::microsoft::mscs::local::mode::listnodes ^ -M apps::microsoft::mscs::local::mode::listresources ^ -M apps::microsoft::mscs::local::mode::networkstatus ^ -M apps::microsoft::mscs::local::mode::nodestatus ^ -M apps::microsoft::mscs::local::mode::resourcestatus ^ -M apps::microsoft::mscs::local::mode::resourcegroupstatus ^ -M apps::microsoft::sccm::local::plugin ^ -M apps::microsoft::sccm::local::mode::databasereplicationstatus ^ -M apps::microsoft::sccm::local::mode::sitestatus ^ -M apps::microsoft::wsus::local::plugin ^ -M apps::microsoft::wsus::local::mode::computersstatus ^ -M apps::microsoft::wsus::local::mode::updatesstatus ^ -M apps::microsoft::wsus::local::mode::synchronisationstatus ^ -M apps::microsoft::wsus::local::mode::serverstatistics ^ -M apps::protocols::ldap::plugin ^ -M apps::protocols::ldap::mode::login ^ -M apps::protocols::ldap::mode::search ^ -M apps::protocols::ftp::plugin ^ -M apps::protocols::ftp::mode::commands ^ -M apps::protocols::ftp::mode::date ^ -M apps::protocols::ftp::mode::filescount ^ -M apps::protocols::ftp::mode::login ^ -M apps::protocols::http::plugin ^ -M apps::protocols::http::mode::expectedcontent ^ -M apps::protocols::http::mode::response ^ -M apps::protocols::tcp::plugin ^ -M apps::protocols::tcp::mode::responsetime ^ -M apps::protocols::x509::plugin ^ -M apps::protocols::x509::mode::certificate ^ -M apps::protocols::x509::mode::validity ^ -M centreon::common::protocols::ldap::lib::ldap ^ -M centreon::common::powershell::exchange::powershell ^ -M centreon::common::powershell::functions ^ -M centreon::common::powershell::hyperv::2012::listnodevms ^ -M centreon::common::powershell::hyperv::2012::nodeintegrationservice ^ -M centreon::common::powershell::hyperv::2012::nodereplication ^ -M centreon::common::powershell::hyperv::2012::nodesnapshot ^ -M centreon::common::powershell::hyperv::2012::nodevmstatus ^ -M centreon::common::powershell::hyperv::2012::scvmmintegrationservice ^ -M centreon::common::powershell::hyperv::2012::scvmmsnapshot ^ -M centreon::common::powershell::hyperv::2012::scvmmvmstatus ^ -M centreon::common::powershell::sccm::databasereplicationstatus ^ -M centreon::common::powershell::sccm::sitestatus ^ -M centreon::common::powershell::veeam::jobstatus ^ -M centreon::common::powershell::veeam::listjobs ^ -M centreon::common::powershell::veeam::tapejobs ^ -M centreon::common::powershell::windows::liststorages ^ -M centreon::common::powershell::wsus::computersstatus ^ -M centreon::common::powershell::wsus::updatesstatus ^ -M centreon::common::powershell::wsus::synchronisationstatus ^ -M centreon::common::powershell::wsus::serverstatistics ^ -M centreon::plugins::alternative::Getopt ^ -M centreon::plugins::backend::http::lwp ^ -M centreon::plugins::backend::http::curl ^ -M centreon::plugins::backend::http::curlconstants ^ -M centreon::plugins::script ^ -M hardware::devices::safenet::hsm::protecttoolkit::plugin ^ -M hardware::devices::safenet::hsm::protecttoolkit::mode::hardware ^ -M hardware::devices::safenet::hsm::protecttoolkit::mode::components::temperature ^ -M hardware::devices::safenet::hsm::protecttoolkit::mode::components::hwstatus ^ -M hardware::devices::safenet::hsm::protecttoolkit::mode::components::memory ^ -M os::windows::local::plugin ^ -M os::windows::local::mode::cmdreturn ^ -M os::windows::local::mode::ntp ^ -M os::windows::local::mode::pendingreboot ^ -M os::windows::local::mode::sessions ^ -M os::windows::local::mode::liststorages ^ -M storage::dell::compellent::local::plugin ^ -M storage::dell::compellent::local::mode::hbausage ^ -M storage::dell::compellent::local::mode::volumeusage ^ --verbose pause Lancer le fichier "build.bat" pour créer le binaire "centreon_plugins.exe". Pour changer la version et l'icône du binaire, ajouter le code suivant après ``PERL_INSTALL_DIR`` (première ligne) : :: set ICO_FILE=centreon.ico set RC_FILE=centreon.rc chdir /d %~dp0 for /f "tokens=4 delims= " %%i in ('type centreon-plugins\centreon\plugins\script.pm ^| findstr global_version ^| findstr my') do set "VERSION_PLUGIN=%%i" set VERSION_PLUGIN=%VERSION_PLUGIN:~1,8% ( echo #define PP_MANIFEST_FILEFLAGS 0 echo #include ^ echo. echo CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "winres\\pp.manifest" echo. echo VS_VERSION_INFO VERSIONINFO echo FILEVERSION 0,0,0,0 echo PRODUCTVERSION 0,0,0,0 echo FILEFLAGSMASK VS_FFI_FILEFLAGSMASK echo FILEFLAGS PP_MANIFEST_FILEFLAGS echo FILEOS VOS_NT_WINDOWS32 echo FILETYPE VFT_APP echo FILESUBTYPE VFT2_UNKNOWN echo BEGIN echo BLOCK "StringFileInfo" echo BEGIN echo BLOCK "000004B0" echo BEGIN echo VALUE "CompanyName", "Centreon\0" echo VALUE "FileDescription", " \0" echo VALUE "FileVersion", "1.0.0.0\0" echo VALUE "InternalName", " \0" echo VALUE "LegalCopyright", " \0" echo VALUE "LegalTrademarks", " \0" echo VALUE "OriginalFilename", " \0" echo VALUE "ProductName", "centreon-plugins\0" echo VALUE "ProductVersion", "%VERSION_PLUGIN%.0\0" echo END echo END echo BLOCK "VarFileInfo" echo BEGIN echo VALUE "Translation", 0x00, 0x04B0 echo END echo END echo. echo WINEXE ICON winres\\pp.ico )> %RC_FILE% for /f "delims=" %%i in ('dir /ad /B %PERL_INSTALL_DIR%\cpan\build\PAR-Packer-*') do set "PAR_PACKER_DIRNAME=%%i" SET PAR_PACKER_SRC=%PERL_INSTALL_DIR%\cpan\build\%PAR_PACKER_DIRNAME% copy /Y %ICO_FILE% %PAR_PACKER_SRC%\myldr\winres\pp.ico copy /Y centreon.rc %PAR_PACKER_SRC%\myldr\winres\pp.rc del %PAR_PACKER_SRC%\myldr\ppresource.coff cd /D %PAR_PACKER_SRC%\myldr\ && perl Makefile.PL cd /D %PAR_PACKER_SRC%\myldr\ && dmake boot.exe cd /D %PAR_PACKER_SRC%\myldr\ && dmake Static.pm attrib -R %PERL_INSTALL_DIR%\perl\site\lib\PAR\StrippedPARL\Static.pm copy /Y %PAR_PACKER_SRC%\myldr\Static.pm %PERL_INSTALL_DIR%\perl\site\lib\PAR\StrippedPARL\Static.pm Il est possible de compiler un binaire 32 bits depuis une version 64 bits Windows : * Installer Strawberry Perl 5.24.x version 32 bits sur un Windows (Télécharger sur http://strawberryperl.com/) * Installer le module cpan "PAR::Packer" * Ajouter la ligne suivante au début du script : PATH=%PERL_INSTALL_DIR%\c\bin;%PERL_INSTALL_DIR%\perl\bin;C:\Windows\System32 ********* Dépannage ********* ---- SNMP ---- J'ai l'erreur SNMP: 'UNKNOWN:.* (tooBig).*' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ L'erreur suivante peut se produire avec certains équipements. Vous pouvez la résoudre si vous paramétrez les options suivantes : * ``--subsetleef=20`` ``--maxrepetitions=20`` J'ai l'erreur SNMP: 'UNKNOWN:.*Timeout' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ L'erreur suivante signifie : * Pas d'accès réseau vers le serveur SNMP cible (un pare-feu peut bloquer le port UDP 161). * La communauté ou la version SNMP paramétrées n'est pas correcte. J'ai l'erreur SNMP: 'UNKNOWN:.*Cant get a single value' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ L'erreur suivante signifie: l'accès SNMP fonctionne mais vous ne pouvez pas récupérer les valeurs SNMP. Plusieurs raisons possibles : * La valeur SNMP n'est pas encore renseignée (peut se produire lorsqu'un serveur SNMP vient juste de démarrer). * La valeur SNMP n'est pas implémentée par le constructeur. * La valeur SNMP est renseignée sur un firmware ou OS spécifique. Il semblerait que le contrôle de processus ne fonctionne pas avec certains filtres sur les arguments ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Avec le SNMP, il y a une limite pour la longueur des arguments qui est fixée à 128 caractères. Donc, si vous essayez de filtrer avec un argument après 128 caractères, cela ne fonctionnera pas. Cela peut arriver avec les arguments Java. Pour résoudre le problème, vous devez privilégier le contrôle via NRPE. Pas d'accès en SNMP v3 ^^^^^^^^^^^^^^^^^^^^^^ Tout d'abord, vous devez valider la connexion SNMP v3 avec snmpwalk. Lorsque cela fonctionne, renseignez alors les options SNMP v3 en ligne de commande. L'association entre les options 'snmpwalk' et les options "centreon-plugins" : * -a => ``--authprotocol`` * -A => ``--authpassphrase`` * -u => ``--snmp-username`` * -x => ``--privprotocol`` * -X => ``--privpassphrase`` * -l => non nécessaire (automatique) * -e => ``--securityengineid`` * -E => ``--contextengineid`` ------ Divers ------ J'ai l'erreur: "UNKNOWN: Need to specify '--custommode'." ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Certains plugins ont besoin de renseigner l'option ``--custommode``. Vous pouvez connaître la valeur à renseigner avec l'option ``--list-custommode``. Un exemple : :: $ perl centreon_plugins.pl --plugin=storage::ibm::DS3000::cli::plugin --list-custommode ... Custom Modes Available: smcli $ perl centreon_plugins.pl --plugin=storage::ibm::DS3000::cli::plugin --custommode=smcli --list-mode J'ai l'erreur: "UNKNOWN: Cannot write statefile .*" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Vous devez créer le dossier (avec les droits d'écriture) pour autoriser le plugin à stocker certaines données sur le disque. J'ai l'erreur: "UNKNOWN: Cannot load module 'xxx'." ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Le problème peut être: * Un module CPAN prérequis est manquant. Vous devez l'installer. * Le module CPAN ne peut pas être chargé en raison de son chemin d'accès. Les modules Perl doivent être installés dans des chemins spécifiques. Je ne peux pas voir les messages d'aide ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Les fichiers "centreon-plugins" doivent être sous format Unix (pas de retour à la ligne Windows). Vous pouvez les modifier avec la commande suivante : :: $ find . -name "*.p[ml]" -type f -exec dos2unix \{\} \; .. Warning:: Exécuter cette commande dans le dossier "centreon-plugins". ********************* Examples de commandes ********************* ------- Windows ------- Contrôler tous les disques en SNMP ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Dégradé si l'espace utilisé > 80% et critique sur l'espace utilisé > 90% : :: $ perl centreon_plugins.pl --plugin=os::windows::snmp::plugin --mode=storage --hostname=xxx.xxx.xxx.xxx --snmp-version=2c --snmp-public=community --verbose --storage='.*' --name --regexp --display-transform-src='(..).*' --display-transform-dst='$1' --warning=80 --critical=90 OK: All storages are ok. | used_C:'=38623698944B;0:108796887040;0:122396497920;0;135996108800 used_D:'=38623698944B;0:108796887040;0:122396497920;0;135996108800 Storage 'C:' Total: 126.66 GB Used: 35.97 GB (28.40%) Free: 90.69 GB (71.60%) Storage 'D:' Total: 126.66 GB Used: 35.97 GB (28.40%) Free: 90.69 GB (71.60%) Dégradé si l'espace disponible < 5G et critique si l'espace disponible < 2G : :: $ perl centreon_plugins.pl --plugin=os::windows::snmp::plugin --mode=storage --hostname=xxx.xxx.xxx.xxx --snmp-version=2c --snmp-public=community --verbose --storage='.*' --name --regexp --display-transform-src='(..).*' --display-transform-dst='$1' --warning=5497558138880: --critical=2199023255552: --units='B' --free OK: All storages are ok. | 'free_C:'=97372344320B;0:5497558138880;0:2199023255552;0;135996108800 'free_D:'=97372344320B;0:5497558138880;0:2199023255552;0;135996108800 Storage 'C:' Total: 126.66 GB Used: 35.97 GB (28.40%) Free: 90.69 GB (71.60%) Storage 'D:' Total: 126.66 GB Used: 35.97 GB (28.40%) Free: 90.69 GB (71.60%) ----- Linux ----- Contrôler le trafic de toutes les interfaces en SNMP ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Dégradé si le trafic entrant/sortant utilisé > 80% et critique si le trafic entrant/sortant utilisé > 90% : :: $ perl centreon_plugins.pl --plugin=os::linux::snmp::plugin --mode=interfaces --hostname=127.0.0.1 --snmp-version=2c --snmp-community=public --verbose --interface='.*' --name --add-traffic --warning-in-traffic=80 --critical-in-traffic=90 --warning-out-traffic=80 --critical-out-traffic=90 OK: All traffic are ok | 'traffic_in_lo'=126.58b/s;0.00:8000000.00;0.00:9000000.00;0;10000000 'traffic_out_lo'=126.58b/s;0.00:8000000.00;0.00:9000000.00;0;10000000 'traffic_in_eth0'=1872.00b/s;0.00:800000000.00;0.00:900000000.00;0;1000000000 'traffic_out_eth0'=266.32b/s;0.00:800000000.00;0.00:900000000.00;0;1000000000 'traffic_in_eth1'=976.65b/s;0.00:800000000.00;0.00:900000000.00;0;1000000000 'traffic_out_eth1'=1021.68b/s;0.00:800000000.00;0.00:900000000.00;0;1000000000 Interface 'lo' Traffic In : 126.58b/s (0.00 %), Out : 126.58b/s (0.00 %) Interface 'eth0' Traffic In : 1.87Kb/s (0.00 %), Out : 266.32b/s (0.00 %) Interface 'eth1' Traffic In : 976.65b/s (0.00 %), Out : 1.02Kb/s (0.00 %) -------------- Protocole HTTP -------------- Contrôler l'authentification à une application (requête POST) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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 de manière globale. 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' -------------------- Multi-service plugin -------------------- Ce mode permet de compiler/aggréger le résultat de plusieurs checks dans un seul. Il peut aussi être utilisé pour réaliser des aggregations dans des groupes logiques, il a été pensé pour récupérer au travers de réseaux bas débit des résultats de contrôle sur des Centreon distants, mais il peut aussi permettre d'éviter de vérifier deux fois les ressources dans deux Centreon différents. Format du fichier de configuration ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: { "mode":"sqlmatching", "selection":{ "ESX":{ "host_name_filter":"%clus-esx-n%", "service_name_filter":"Esx-Status" }, "XIVO":{ "host_name_filter":"%xivo%", "service_name_filter":"Ping" } }, "counters":{ "totalservices":true, "totalhosts":true, "groups":true }, "formatting":{ "groups_global_msg":"Nothing special on groups", "host_service_separator":"/", "display_details":true } } * mode (obligatoire) : valeurs possibles: 'sqlmatching' or 'exactmatch'. Liés au format du bloc "selection" ; * selection (obligatoire) : Lorsque le mode 'sqlmatching' est choisi, on va alors définir les filtres comme ci-dessus (host/service_name_filter). Au contraire, si l'on utilise le mode "exactmatch", alors on passe des clés valeurs correspondant à host/service. (Exemple avec deux aggregations logiques "groups" esx-status/load ci-dessous) :: "selection":{ "esx-status":{ "esx-n1":"Esx-Status", "esx-n2":"Esx-Status", "esx-n3":"Esx-Status" }, "esx-load":{ "esx-n1":"Esx-Memory", "esx-n2":"Esx-Memory", "esx-n3":"Esx-Memory", "esx-n1":"Esx-Cpu", "esx-n2":"Esx-Cpu", "esx-n3":"Esx-Cpu" } }, * counters (optionnel) : Contiens trois booléens, à configurer en 'true' ou 'false' selon les compteurs que l'on veut utiliser et considérer (totalservices, totalhosts, groups). * formatting (optionnel) : Contient trois clés/valeurs, 'groups_global_msg' pour définir un statut global lorsque tout va bien, 'host_service_separator' pour choisir le séparateur entre le nom de l'hôte et celui du service dans les éléments de l'output, 'display_details' afin de définir si le plugin doit détailler les hôtes et/ou services en erreur dans l'output étendu (mode verbose) Ligne de commande, output, seuils ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Exemple de commande : :: /usr/lib/nagios/plugins/centreon_plugins.pl --plugin database::mysql::plugin --dyn-mode apps::centreon::sql::mode::multiservices --host localhost --username centreon --password c3ntreon --config-file '/root/global-services.json' --verbose Example de sortie : :: OK: Hosts state summary [up:4][down:2][unreachable:0] - Services state summary [ok:4][warning:0][critical:2][unknown:0] - Nothing special on groups | Données de performance : :: 'total_host_up'=4;;;0; 'total_host_down'=2;;;0; 'total_host_unreachable'=0;;;0; 'total_host_ok'=4;;;0; 'total_host_warning'=0;;;0; 'total_host_critical'=2;;;0; 'total_host_unknown'=0;;;0; 'host_up_ESX'=4;;;0; 'host_down_ESX'=0;;;0; 'host_unreachable_ESX'=0;;;0; 'service_ok_ESX'=4;;;0; 'service_warning_ESX'=0;;;0; 'service_critical_ESX'=0;;;0; 'service_unknown_ESX'=0;;;0; 'host_up_XIVO'=0;;;0; 'host_down_XIVO'=2;;;0; 'host_unreachable_XIVO'=0;;;0; 'service_ok_XIVO'=0;;;0; 'service_warning_XIVO'=0;;;0; 'service_critical_XIVO'=2;;;0; 'service_unknown_XIVO'=0;;;0; Mode verbeux (avec l'affichage détaillé d'activé) : :: Group 'ESX': HOSTS: [up: 4 (clus-esx-n1.com - clus-esx-n2.com - clus-esx-n3.com - clus-esx-n4.com)][down: 0][unreachable: 0] - SERVICES: [ok: 4 (clus-esx-n1.com/Esx-Status - clus-esx-n2.com/Esx-Status - clus-esx-n3.com/Esx-Status - clus-esx-n4.com/Esx-Status)][warning: 0][critical: 0][unknown: 0] Group 'XIVO': HOSTS: [up: 0][down: 2 (srvi-xivo-n1 - srvi-xivo-n2)][unreachable: 0] - SERVICES: [ok: 0][warning: 0][critical: 2 (srvi-xivo-n1/Ping - srvi-xivo-n2/Ping)][unknown: 0] Voici la manière de définir les seuils (total_statut pour les warning/critical-total et définition de l'instance et du décompte du nombre de statut pour les seuils par "groupes logiques") : :: --critical-total '%{total_down} > 4' --critical-groups '%{instance} eq 'ESX' && %{unknown} > 5' -------- NSClient -------- Vous pouvez superviser des systèmes Windows/Linux via l'API Rest de NSClient. Les commandes et arguments sont les mêmes que via NRPE (veuillez lire la documentation NSClient pour plus d'informations) : :: $ perl centreon_plugins.pl --plugin=apps::nsclient::restapi::plugin --mode=query --hostname="10.30.2.10" --port=443 --legacy-password=centreon --command=check_drivesize --arg="drive=*" --arg="perf-config=used(unit:B)used %(ignored:true)" --arg="filter=type = 'fixed' and name not regexp '.*yst.*'" --arg="warning=total_used>80%" --arg="critical=total_used>90%" OK All 2 drive(s) are ok | '\\?\Volume{7cd2d555-9868-11e7-8199-806e6f6e6963}\ used'=289468416.000B;293598003.000;330297753.000;0.000;366997504.000 'C:\ used'=23285907456.000B;42654390681.000;47986189516.000;0.000;53317988352.000 centreon-plugins-20220113/doc/fr/user/index.rst000066400000000000000000000001511417000230700212240ustar00rootroot00000000000000################# Guide utilisateur ################# .. toctree:: :maxdepth: 2 :glob: guide centreon-plugins-20220113/example/000077500000000000000000000000001417000230700166675ustar00rootroot00000000000000centreon-plugins-20220113/example/custommode/000077500000000000000000000000001417000230700210465ustar00rootroot00000000000000centreon-plugins-20220113/example/custommode/simple.pm000066400000000000000000000064621417000230700227050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package example::custommode::simple; use strict; use warnings; sub new { my ($class, %options) = @_; my $self = {}; bless $self, $class; # $options{options} = options object # $options{output} = output object # $options{exit_value} = integer # $options{noptions} = integer 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 => { "customarg:s@" => { name => 'customarg' }, }); } $options{options}->add_help(package => __PACKAGE__, sections => 'CUSTOM OPTIONS', once => 1); $self->{output} = $options{output}; $self->{custommode_name} = $options{custommode_name}; $self->{customarg} = undef; return $self; } # Method to manage multiples sub set_options { my ($self, %options) = @_; # options{options_result} $self->{option_results} = $options{option_results}; } # Method to manage multiples sub set_defaults { my ($self, %options) = @_; # options{default} # Manage default value foreach (keys %{$options{default}}) { if ($_ eq $self->{custommode_name}) { 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) = @_; # return 1 = ok still customarg # return 0 = no customarg left $self->{customarg} = (defined($self->{option_results}->{customarg})) ? shift(@{$self->{option_results}->{customarg}}) : undef; if (!defined($self->{customarg}) || scalar(@{$self->{option_results}->{customarg}}) == 0) { return 0; } return 1; } ############## # Specific methods ############## sub test { my ($self, %options) = @_; use Data::Dumper; print Data::Dumper::Dumper($self); } 1; __END__ =head1 NAME My Custom global =head1 SYNOPSIS my custom class example =head1 CUSTOM OPTIONS =over 8 =item B<--customarg> Argument test. =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/example/mode/000077500000000000000000000000001417000230700176135ustar00rootroot00000000000000centreon-plugins-20220113/example/mode/getvalue.pm000066400000000000000000000070051417000230700217670ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package example::mode::getvalue; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "oid:s" => { name => 'oid' }, "warning:s" => { name => 'warning' }, "critical:s" => { name => 'critical' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{oid})) { $self->{output}->add_option_msg(short_msg => "Need to specify an OID."); $self->{output}->option_exit(); } 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) = @_; $self->{snmp} = $options{snmp}; $self->{hostname} = $self->{snmp}->get_hostname(); my $result = $self->{snmp}->get_leef(oids => [$self->{option_results}->{oid}], nothing_quit => 1); my $value = $result->{$self->{option_results}->{oid}}; 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("SNMP Value is %s.", $value)); $self->{output}->perfdata_add(label => 'value', unit => undef, value => $value, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => undef, max => undef); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check an SNMP Integer value. =over 8 =item B<--oid> Check OID Integer value. =item B<--warning> Threshold warning. =item B<--critical> Threshold critical. =back =cut centreon-plugins-20220113/example/mode/launchcmd.pm000066400000000000000000000057711417000230700221210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package example::mode::launchcmd; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::misc; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "cmd:s" => { name => 'cmd' }, "timeout:s" => { name => 'timeout', default => 30 } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); if (!defined($self->{option_results}->{cmd})) { $self->{output}->add_option_msg(short_msg => "Need to specify a command."); $self->{output}->option_exit(); } } sub run { my ($self, %options) = @_; my ($lerror, $stdout, $exit_code) = centreon::plugins::misc::backtick( command => $self->{option_results}->{cmd}, timeout => $self->{option_results}->{timeout}, wait_exit => 1 ); $stdout =~ s/\r//g; if ($exit_code <= -1000) { if ($exit_code == -1000) { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => $stdout); } $self->{output}->display(); $self->{output}->exit(); } if ($exit_code != 0) { $stdout =~ s/\n/ - /g; $self->{output}->output_add(severity => 'UNKNOWN', short_msg => "Command error: $stdout"); $self->{output}->display(); $self->{output}->exit(); } $self->{output}->output_add(severity => 'OK', short_msg => 'Command executed with no errors.'); $self->{output}->output_add(long_msg => $stdout); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Launch a local command. Use --verbose to see the command output. =over 8 =item B<--cmd> Command to execute. =item B<--timeout> Timeout in seconds for the command (Default: 30). =back =cut centreon-plugins-20220113/example/mode/testcustom.pm000066400000000000000000000031121417000230700223600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package example::mode::testcustom; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "timeout:s" => { name => 'timeout', default => 30 } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my $custom = $options{custom}; $custom->test(); #$self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE For custom mode example test. =over 8 =item B<--timeout> Timeout in seconds. =back =cut centreon-plugins-20220113/example/plugin_command.pm000066400000000000000000000023541417000230700222250ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package example::plugin_command; 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} = '0.1'; %{$self->{modes}} = ( 'launchcmd' => 'example::mode::launchcmd' ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION An example of local command plugin. =cut centreon-plugins-20220113/example/plugin_custom.pm000066400000000000000000000027141417000230700221210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package example::plugin_custom; 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}} = ( 'testcustom' => 'example::mode::testcustom', ); $self->{custom_modes}{mycustommodetest} = 'example::custommode::simple'; return $self; } sub init { my ($self, %options) = @_; $self->SUPER::init(%options); } 1; __END__ =head1 PLUGIN DESCRIPTION Check Custom mode (an example for creating test with a same line argument). =over 8 =back =cut centreon-plugins-20220113/example/plugin_snmp.pm000066400000000000000000000023411417000230700215600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package example::plugin_snmp; 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}} = ( 'getvalue' => 'example::mode::getvalue' ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION An example of SNMP plugin type. =cut centreon-plugins-20220113/hardware/000077500000000000000000000000001417000230700170315ustar00rootroot00000000000000centreon-plugins-20220113/hardware/ats/000077500000000000000000000000001417000230700176205ustar00rootroot00000000000000centreon-plugins-20220113/hardware/ats/apc/000077500000000000000000000000001417000230700203635ustar00rootroot00000000000000centreon-plugins-20220113/hardware/ats/apc/snmp/000077500000000000000000000000001417000230700213405ustar00rootroot00000000000000centreon-plugins-20220113/hardware/ats/apc/snmp/mode/000077500000000000000000000000001417000230700222645ustar00rootroot00000000000000centreon-plugins-20220113/hardware/ats/apc/snmp/mode/components/000077500000000000000000000000001417000230700244515ustar00rootroot00000000000000centreon-plugins-20220113/hardware/ats/apc/snmp/mode/components/entity.pm000066400000000000000000000117361417000230700263330ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::ats::apc::snmp::mode::components::entity; use strict; use warnings; my %map_com = (1 => 'atsNeverDiscovered', 2 => 'atsCommEstablished', 3 => 'atsCommLost'); my %map_redunt = (1 => 'atsRedundancyLost', 2 => 'atsFullyRedundant'); my %map_current = (1 => 'atsOverCurrent', 2 => 'atsCurrentOK'); my %map_power = (1 => 'atsPowerSupplyFailure', 2 => 'atsPowerSupplyOK'); my %map_fail = (1 => 'fail', 2 => 'ok'); my %map_sync = (1 => 'inSync', 2 => 'outOfSync'); my $mapping = { atsStatusCommStatus => { oid => '.1.3.6.1.4.1.318.1.1.8.5.1.1', map => \%map_com, label => 'CommStatus' }, atsStatusRedundancyState => { oid => '.1.3.6.1.4.1.318.1.1.8.5.1.3', map => \%map_redunt, label => 'RedundancyState' }, atsStatusOverCurrentState => { oid => '.1.3.6.1.4.1.318.1.1.8.5.1.4', map => \%map_current, label => 'OverCurrentState' }, atsStatus5VPowerSupply => { oid => '.1.3.6.1.4.1.318.1.1.8.5.1.5', map => \%map_power, label => '5VPowerSupply' }, atsStatus24VPowerSupply => { oid => '.1.3.6.1.4.1.318.1.1.8.5.1.6', map => \%map_power, label => '24VPowerSupply' }, atsStatus24VSourceBPowerSupply => { oid => '.1.3.6.1.4.1.318.1.1.8.5.1.7', map => \%map_power, label => '24VSourceBPowerSupply' }, atsStatusPlus12VPowerSupply => { oid => '.1.3.6.1.4.1.318.1.1.8.5.1.8', map => \%map_power, label => 'Plus12VPowerSupply' }, atsStatusMinus12VPowerSupply => { oid => '.1.3.6.1.4.1.318.1.1.8.5.1.9', map => \%map_power, label => 'Minus12VPowerSupply' }, atsStatusSwitchStatus => { oid => '.1.3.6.1.4.1.318.1.1.8.5.1.10', map => \%map_fail, label => 'SwitchStatus' }, atsStatusSourceAStatus => { oid => '.1.3.6.1.4.1.318.1.1.8.5.1.12', map => \%map_fail, label => 'SourceAStatus' }, atsStatusSourceBStatus => { oid => '.1.3.6.1.4.1.318.1.1.8.5.1.13', map => \%map_fail, label => 'SourceBStatus' }, atsStatusPhaseSyncStatus => { oid => '.1.3.6.1.4.1.318.1.1.8.5.1.14', map => \%map_sync, label => 'PhaseSyncStatus' }, atsStatusVoltageOutStatus => { oid => '.1.3.6.1.4.1.318.1.1.8.5.1.15', map => \%map_fail, label => 'VoltageOutStatus' }, atsStatusHardwareStatus => { oid => '.1.3.6.1.4.1.318.1.1.8.5.1.16', map => \%map_fail, label => 'HardwareStatus' }, atsStatus3dot3VPowerSupply => { oid => '.1.3.6.1.4.1.318.1.1.8.5.1.17', map => \%map_power, label => '3dot3VPowerSupply' }, atsStatus1Dot0VPowerSupply => { oid => '.1.3.6.1.4.1.318.1.1.8.5.1.18', map => \%map_power, label => '1Dot0VPowerSupply' }, atsStatusVBoostSourceA => { oid => '.1.3.6.1.4.1.318.1.1.8.5.1.19', map => \%map_power, label => 'VBoostSourceA' }, atsStatusVBoostSourceB => { oid => '.1.3.6.1.4.1.318.1.1.8.5.1.20', map => \%map_power, label => 'VBoostSourceB' } }; my $oid_atsStatusDeviceStatus = '.1.3.6.1.4.1.318.1.1.8.5.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_atsStatusDeviceStatus }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking entities"); $self->{components}->{entity} = {name => 'entities', total => 0, skip => 0}; return if ($self->check_filter(section => 'entity')); my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_atsStatusDeviceStatus}, instance => '0'); foreach (sort keys %{$mapping}) { next if ($self->check_filter(section => 'entity', instance => $mapping->{$_}->{label})); $self->{components}->{entity}->{total}++; $self->{output}->output_add(long_msg => sprintf("entity '%s' status is '%s' [instance = %s]", $mapping->{$_}->{label}, defined($result->{$_}) ? $result->{$_} : 'n/a', $mapping->{$_}->{label})); next if (!defined($result->{$_})); my $exit = $self->get_severity(section => 'entity', instance => $mapping->{$_}->{label}, value => $result->{$_}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Entity '%s' status is '%s'", $mapping->{$_}->{label}, $result->{$_})); } } } 1;centreon-plugins-20220113/hardware/ats/apc/snmp/mode/devicestatus.pm000066400000000000000000000053501417000230700253300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::ats::apc::snmp::mode::devicestatus; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { entity => [ ['atsPowerSupplyFailure', 'CRITICAL'], ['atsPowerSupplyOK', 'OK'], ['atsOverCurrent', 'CRITICAL'], ['atsCurrentOK', 'OK'], ['atsRedundancyLost', 'CRITICAL'], ['atsFullyRedundant', 'OK'], ['atsNeverDiscovered', 'OK'], ['atsCommEstablished', 'OK'], ['atsCommLost', 'CRITICAL'], ['fail', 'CRITICAL'], ['ok', 'OK'], ['inSync', 'OK'], ['outOfSync', 'CRITICAL'] ] }; $self->{components_path} = 'hardware::ats::apc::snmp::mode::components'; $self->{components_module} = ['entity']; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $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, no_performance => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } 1; __END__ =head1 MODE Check device status. =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'entity'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=entity) Can also exclude specific instance: --filter=entity,CommStatus =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='entity,SourceBStatus,WARNING,fail' =back =cut centreon-plugins-20220113/hardware/ats/apc/snmp/mode/inputlines.pm000066400000000000000000000120371417000230700250170ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::ats::apc::snmp::mode::inputlines; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'input', type => 1, cb_prefix_output => 'prefix_line_output', message_multiple => 'All input lines are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{input} = [ { label => 'voltage', set => { key_values => [ { name => 'atsInputVoltage' }, { name => 'display' } ], output_template => 'Voltage : %.2f V', perfdatas => [ { label => 'voltage', value => 'atsInputVoltage', template => '%s', unit => 'V', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'current', set => { key_values => [ { name => 'atsInputCurrent' }, { name => 'display' } ], output_template => 'Current : %.2f A', perfdatas => [ { label => 'current', value => 'atsInputCurrent', template => '%s', unit => 'A', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'power', set => { key_values => [ { name => 'atsInputPower' }, { name => 'display' } ], output_template => 'Power : %.2f W', perfdatas => [ { label => 'power', value => 'atsInputPower', template => '%s', unit => 'W', label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub prefix_line_output { my ($self, %options) = @_; return "Input Line '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my $mapping = { atsInputVoltage => { oid => '.1.3.6.1.4.1.318.1.1.8.5.3.3.1.3' }, atsInputCurrent => { oid => '.1.3.6.1.4.1.318.1.1.8.5.3.3.1.6' }, atsInputPower => { oid => '.1.3.6.1.4.1.318.1.1.8.5.3.3.1.9' }, }; my $mapping2 = { atsInputName => { oid => '.1.3.6.1.4.1.318.1.1.8.5.3.2.1.6' }, }; my $oid_atsInputPhaseEntry = '.1.3.6.1.4.1.318.1.1.8.5.3.3.1'; sub manage_selection { my ($self, %options) = @_; my $results = $options{snmp}->get_multiple_table(oids => [ { oid => $oid_atsInputPhaseEntry }, { oid => $mapping2->{atsInputName}->{oid} }, ], nothing_quit => 1); $self->{input} = {}; foreach my $oid (keys %{$results->{$oid_atsInputPhaseEntry}}) { next if ($oid !~ /^$mapping->{atsInputVoltage}->{oid}\.(\d+)\.(.*)$/); my ($input_index, $phase_index) = ($1, $2); my $result = $options{snmp}->map_instance(mapping => $mapping, results => $results->{$oid_atsInputPhaseEntry}, instance => $input_index . '.' . $phase_index); my $result2 = $options{snmp}->map_instance(mapping => $mapping2, results => $results->{$mapping2->{atsInputName}->{oid}}, instance => $input_index); my $name = defined($result2->{atsInputName}) && $result2->{atsInputName} ne '' ? $result2->{atsInputName} : $input_index; $name .= '.' . $phase_index; $self->{input}->{$name} = { display => $name }; foreach (keys %{$mapping}) { $result->{$_} = undef if (defined($result->{$_}) && $result->{$_} == -1); $self->{input}->{$name}->{$_} = $result->{$_}; } } } 1; __END__ =head1 MODE Check input phase metrics (voltage, current and power). =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^power$' =item B<--warning-*> Threshold warning. Can be: 'voltage', 'current', 'power'. =item B<--critical-*> Threshold critical. Can be: 'voltage', 'current', 'power'. =back =cut centreon-plugins-20220113/hardware/ats/apc/snmp/mode/ntp.pm000066400000000000000000000040311417000230700234210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::ats::apc::snmp::mode::ntp; use base qw(snmp_standard::mode::ntp); use strict; use warnings; use Date::Parse; sub get_target_time { my ($self, %options) = @_; my $oid_mconfigClockDate = '.1.3.6.1.4.1.318.2.1.6.1.0'; my $oid_mconfigClockTime = '.1.3.6.1.4.1.318.2.1.6.2.0'; my $snmp_result = $options{snmp}->get_leef(oids => [ $oid_mconfigClockDate, $oid_mconfigClockTime ], nothing_quit => 1); my $epoch = Date::Parse::str2time($snmp_result->{$oid_mconfigClockDate} . ' ' . $snmp_result->{$oid_mconfigClockTime}); return $self->get_from_epoch(date => $epoch); } 1; __END__ =head1 MODE Check time offset of server with ntp server. Use local time if ntp-host option is not set. SNMP gives a date with second precision (no milliseconds). Time precision is not very accurate. Use threshold with (+-) 2 seconds offset (minimum). =over 8 =item B<--warning-offset> Time offset warning threshold (in seconds). =item B<--critical-offset> Time offset critical Threshold (in seconds). =item B<--ntp-hostname> Set the ntp hostname (if not set, localtime is used). =item B<--ntp-port> Set the ntp port (Default: 123). =item B<--timezone> Set the timezone of distant server. For Windows, you need to set it. Can use format: 'Europe/London' or '+0100'. =back =cut centreon-plugins-20220113/hardware/ats/apc/snmp/mode/outputlines.pm000066400000000000000000000174221417000230700252230ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::ats::apc::snmp::mode::outputlines; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'oline', type => 1, cb_prefix_output => 'prefix_line_output', message_multiple => 'All output lines are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{oline} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'atsOutputPhaseState' }, { 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 => \&catalog_status_threshold, } }, { label => 'voltage', set => { key_values => [ { name => 'atsOutputVoltage' }, { name => 'display' } ], output_template => 'Voltage : %.2f V', perfdatas => [ { label => 'voltage', value => 'atsOutputVoltage', template => '%s', unit => 'V', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'current', set => { key_values => [ { name => 'atsOutputCurrent' }, { name => 'display' } ], output_template => 'Current : %.2f A', perfdatas => [ { label => 'current', value => 'atsOutputCurrent', template => '%s', unit => 'A', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'power', set => { key_values => [ { name => 'atsOutputPower' }, { name => 'display' } ], output_template => 'Power : %.2f W', perfdatas => [ { label => 'power', value => 'atsOutputPower', template => '%s', unit => 'W', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'load', set => { key_values => [ { name => 'atsOutputLoad' }, { name => 'display' } ], output_template => 'Load : %.2f VA', perfdatas => [ { label => 'load', value => 'atsOutputLoad', template => '%s', unit => 'VA', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'load-capacity', set => { key_values => [ { name => 'atsOutputPercentLoad' }, { name => 'display' } ], output_template => 'Load capacity : %.2f %%', perfdatas => [ { label => 'load_capacity', value => 'atsOutputPercentLoad', template => '%s', unit => '%', label_extra_instance => 1, instance_use => 'display', min => 0, max => 100 }, ], } }, ]; } 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} . '_atsOutputPhaseState'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub prefix_line_output { my ($self, %options) = @_; return "Output Line '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning-status:s" => { name => 'warning_status', default => '%{status} =~ /nearoverload/' }, "critical-status:s" => { name => 'critical_status', default => '%{status} =~ /^(lowload|overload)$/' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } my %map_state = (1 => 'normal', 2 => 'lowload', 3 => 'nearoverload', 4 => 'overload'); my $mapping = { atsOutputVoltage => { oid => '.1.3.6.1.4.1.318.1.1.8.5.4.3.1.3', factor => 1 }, atsOutputCurrent => { oid => '.1.3.6.1.4.1.318.1.1.8.5.4.3.1.4', factor => 0.1 }, atsOutputLoad => { oid => '.1.3.6.1.4.1.318.1.1.8.5.4.3.1.7', factor => 1 }, atsOutputPercentLoad => { oid => '.1.3.6.1.4.1.318.1.1.8.5.4.3.1.10', factor => 1 }, atsOutputPower => { oid => '.1.3.6.1.4.1.318.1.1.8.5.4.3.1.13', factor => 1 }, atsOutputPhaseState => { oid => '.1.3.6.1.4.1.318.1.1.8.5.4.3.1.19', map => \%map_state }, }; my $oid_atsOutputPhaseEntry = '.1.3.6.1.4.1.318.1.1.8.5.4.3.1'; sub manage_selection { my ($self, %options) = @_; my $results = $options{snmp}->get_multiple_table(oids => [ { oid => $oid_atsOutputPhaseEntry }, ], nothing_quit => 1); $self->{oline} = {}; foreach my $oid (keys %{$results->{$oid_atsOutputPhaseEntry}}) { next if ($oid !~ /^$mapping->{atsOutputVoltage}->{oid}\.(\d+)\.(.*)$/); my ($output_index, $phase_index) = ($1, $2); my $result = $options{snmp}->map_instance(mapping => $mapping, results => $results->{$oid_atsOutputPhaseEntry}, instance => $output_index . '.' . $phase_index); my $name = $output_index . '.' . $phase_index; $self->{oline}->{$name} = { display => $name }; foreach (keys %{$mapping}) { if (defined($mapping->{$_}->{factor})) { $result->{$_} = undef if (defined($result->{$_}) && $result->{$_} == -1); $result->{$_} *= $mapping->{$_}->{factor} if (defined($result->{$_})); } $self->{oline}->{$name}->{$_} = $result->{$_}; } } } 1; __END__ =head1 MODE Check output phase metrics. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^power$' =item B<--warning-*> Threshold warning. Can be: 'voltage', 'current', 'power', 'load', 'load-capacity'. =item B<--critical-*> Threshold critical. Can be: 'voltage', 'current', 'power', 'load', 'load-capacity'. =item B<--warning-status> Set warning threshold for status (Default: '%{status} =~ /nearoverload/'). Can used special variables like: %{status}, %{display} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /^(lowload|overload)$/'). Can used special variables like: %{status}, %{display} =back =cut centreon-plugins-20220113/hardware/ats/apc/snmp/plugin.pm000066400000000000000000000027441417000230700232030ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::ats::apc::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} = { 'device-status' => 'hardware::ats::apc::snmp::mode::devicestatus', 'input-lines' => 'hardware::ats::apc::snmp::mode::inputlines', 'output-lines' => 'hardware::ats::apc::snmp::mode::outputlines', 'time' => 'hardware::ats::apc::snmp::mode::ntp', 'uptime' => 'snmp_standard::mode::uptime' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check APC ATS in SNMP. =cut centreon-plugins-20220113/hardware/ats/eaton/000077500000000000000000000000001417000230700207265ustar00rootroot00000000000000centreon-plugins-20220113/hardware/ats/eaton/snmp/000077500000000000000000000000001417000230700217035ustar00rootroot00000000000000centreon-plugins-20220113/hardware/ats/eaton/snmp/mode/000077500000000000000000000000001417000230700226275ustar00rootroot00000000000000centreon-plugins-20220113/hardware/ats/eaton/snmp/mode/inputlines.pm000066400000000000000000000117711417000230700253660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::ats::eaton::snmp::mode::inputlines; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'line', type => 1, cb_prefix_output => 'prefix_line_output', message_multiple => 'All input lines are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{line} = [ { label => 'voltage', nlabel => 'line.input.voltage.volt', set => { key_values => [ { name => 'voltage' }, { name => 'display' } ], output_template => 'Voltage : %.2f V', perfdatas => [ { value => 'voltage', template => '%s', unit => 'V', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'frequence', nlabel => 'line.input.frequence.hertz', set => { key_values => [ { name => 'frequency', no_value => -1 } ], output_template => 'Frequence : %.2f Hz', perfdatas => [ { value => 'frequency', template => '%.2f', unit => 'Hz', label_extra_instance => 1 }, ], } }, ]; } sub prefix_line_output { my ($self, %options) = @_; return "Input Line '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my $map_input_name = { 1 => 'source-1', 2 => 'source-2', }; sub check_ats { my ($self, %options) = @_; return if (scalar(keys %{$self->{line}}) > 0); my $mapping = { atsInputIndex => { oid => '.1.3.6.1.4.1.534.10.1.3.1.1.1', map => $map_input_name }, atsInputVoltage => { oid => '.1.3.6.1.4.1.534.10.1.3.1.1.2' }, atsInputFrequency => { oid => '.1.3.6.1.4.1.534.10.1.3.1.1.3' }, }; my $oid_atsInputEntry = '.1.3.6.1.4.1.534.10.1.3.1.1'; my $snmp_result = $options{snmp}->get_table(oid => $oid_atsInputEntry, nothing_quit => 1); foreach my $oid (keys %{$snmp_result}) { next if ($oid !~ /^$mapping->{atsInputIndex}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); $self->{line}->{$result->{atsInputIndex}} = { display => $result->{atsInputIndex}, voltage => $result->{atsInputVoltage} * 0.1, frequency => $result->{atsInputFrequency} * 0.1, }; } } sub check_ats2 { my ($self, %options) = @_; my $mapping = { ats2InputIndex => { oid => '.1.3.6.1.4.1.534.10.2.2.2.1.1', map => $map_input_name }, ats2InputVoltage => { oid => '.1.3.6.1.4.1.534.10.2.2.2.1.2' }, ats2InputFrequency => { oid => '.1.3.6.1.4.1.534.10.2.2.2.1.3' }, }; my $oid_ats2InputEntry = '.1.3.6.1.4.1.534.10.2.2.2.1'; my $snmp_result = $options{snmp}->get_table(oid => $oid_ats2InputEntry); foreach my $oid (keys %{$snmp_result}) { next if ($oid !~ /^$mapping->{ats2InputIndex}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); $self->{line}->{$result->{ats2InputIndex}} = { display => $result->{ats2InputIndex}, voltage => $result->{ats2InputVoltage} * 0.1, frequency => $result->{ats2InputFrequency} * 0.1, }; } } sub manage_selection { my ($self, %options) = @_; $self->{line} = {}; $self->check_ats2(%options); $self->check_ats(%options); if (scalar(keys %{$self->{line}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No line found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check input lines. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^voltage$' =item B<--warning-*> B<--critical-*> Threshold warning. Can be: 'voltage', 'frequence'. =back =cut centreon-plugins-20220113/hardware/ats/eaton/snmp/mode/outputline.pm000066400000000000000000000070631417000230700254030ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::ats::eaton::snmp::mode::outputline; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'oline', type => 0, cb_prefix_output => 'prefix_line_output', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{oline} = [ { label => 'voltage', nlabel => 'line.output.voltage.volt', set => { key_values => [ { name => 'voltage' } ], output_template => 'Voltage : %.2f V', perfdatas => [ { value => 'voltage', template => '%s', unit => 'V' }, ], } }, { label => 'current', nlabel => 'line.current.ampere', set => { key_values => [ { name => 'current' } ], output_template => 'current : %s A', perfdatas => [ { template => '%s', value => 'current', unit => 'A', min => 0 }, ], } }, ]; } sub prefix_line_output { my ($self, %options) = @_; return "Output line "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my $oid_atsOutputVoltage = '.1.3.6.1.4.1.534.10.1.3.2.1.0'; my $oid_atsOutputCurrent = '.1.3.6.1.4.1.534.10.1.3.2.2.0'; my $oid_ats2OutputVoltage = '.1.3.6.1.4.1.534.10.2.2.3.1.0'; my $oid_ats2OutputCurrent = '.1.3.6.1.4.1.534.10.2.2.3.2.0'; sub check_ats2 { my ($self, %options) = @_; return if (!defined($options{result}->{$oid_ats2OutputVoltage})); $self->{oline} = { voltage => $options{result}->{$oid_ats2OutputVoltage} * 0.1, current => $options{result}->{$oid_ats2OutputCurrent} * 0.1 }; } sub check_ats { my ($self, %options) = @_; return if (defined($self->{oline})); $self->{oline} = { voltage => $options{result}->{$oid_atsOutputVoltage} * 0.1, current => $options{result}->{$oid_atsOutputCurrent} * 0.1 }; } sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_leef(oids => [ $oid_atsOutputVoltage, $oid_atsOutputCurrent, $oid_ats2OutputVoltage, $oid_ats2OutputCurrent, ], nothing_quit => 1); $self->check_ats2(result => $snmp_result); $self->check_ats(result => $snmp_result); } 1; __END__ =head1 MODE Check output line. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^voltage$' =item B<--warning-*> B<--critical-*> Threshold warning. Can be: 'voltage', 'current'. =back =cut centreon-plugins-20220113/hardware/ats/eaton/snmp/mode/system.pm000066400000000000000000000132721417000230700245160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::ats::eaton::snmp::mode::system; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = 'operation mode : ' . $self->{result_values}->{operation_mode}; return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{operation_mode} = $options{new_datas}->{$self->{instance} . '_operation_mode'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, message_separator => ' - ', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'operation_mode' } ], 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 => \&catalog_status_threshold, } }, { label => 'temperature', nlabel => 'system.temperature.celsius', set => { key_values => [ { name => 'temperature' } ], output_template => 'temperature : %s C', perfdatas => [ { label => 'temperature', value => 'temperature', template => '%s', unit => 'C' }, ], } }, { label => 'humidity', nlabel => 'system.humidity.percentage', set => { key_values => [ { name => 'humidity' } ], output_template => 'humidity : %s %%', perfdatas => [ { label => 'humidity', value => 'humidity', template => '%s', unit => '%', min => 9, max => 100 }, ], } }, ]; } 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 => { "unknown-status:s" => { name => 'unknown_status', default => '' }, "warning-status:s" => { name => 'warning_status', default => '' }, "critical-status:s" => { name => 'critical_status', default => '%{operation_mode} !~ /source1|source2/i' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status', 'unknown_status']); } my $map_opmode = { 1 => 'initialization', 2 => 'diagnosis', 3 => 'off', 4 => 'source1', 5 => 'source2', 6 => 'safe', 7 => 'fault', }; my $oid_ats2OperationMode = '.1.3.6.1.4.1.534.10.2.2.4.0'; my $oid_ats2EnvRemoteTemp = '.1.3.6.1.4.1.534.10.2.5.1.0'; my $oid_ats2EnvRemoteHumidity = '.1.3.6.1.4.1.534.10.2.5.2.0'; my $oid_atsMeasureTemperatureC = '.1.3.6.1.4.1.534.10.1.3.3.0'; my $oid_atsMessureOperationMode = '.1.3.6.1.4.1.534.10.1.3.7.0'; sub check_ats2 { my ($self, %options) = @_; return if (!defined($options{result}->{$oid_ats2OperationMode})); $self->{global} = { operation_mode => $map_opmode->{$options{result}->{$oid_ats2OperationMode}}, temperature => $options{result}->{$oid_ats2EnvRemoteTemp}, humidity => $options{result}->{$oid_ats2EnvRemoteHumidity} }; } sub check_ats { my ($self, %options) = @_; return if (defined($self->{global})); $self->{global} = { operation_mode => $map_opmode->{$options{result}->{$oid_atsMessureOperationMode}}, temperature => $options{result}->{$oid_atsMeasureTemperatureC}, }; } sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_leef(oids => [ $oid_ats2OperationMode, $oid_ats2EnvRemoteTemp, $oid_ats2EnvRemoteHumidity, $oid_atsMeasureTemperatureC, $oid_atsMessureOperationMode, ], nothing_quit => 1); $self->check_ats2(result => $snmp_result); $self->check_ats(result => $snmp_result); } 1; __END__ =head1 MODE Check system (operation mode, temperature). =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^status$' =item B<--unknown-status> Set warning threshold for status (Default: ''). Can used special variables like: operation_mode =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: operation_mode =item B<--critical-status> Set critical threshold for status (Default: '%{operation_mode} !~ /source1|source2/i'). Can used special variables like: %{operation_mode} =item B<--warning-*> Threshold warning. Can be: 'temperature', 'humidity'. =item B<--critical-*> Threshold critical. Can be: 'temperature', 'humidity'. =back =cut centreon-plugins-20220113/hardware/ats/eaton/snmp/plugin.pm000066400000000000000000000025631417000230700235450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::ats::eaton::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}} = ( 'input-lines' => 'hardware::ats::eaton::snmp::mode::inputlines', 'system' => 'hardware::ats::eaton::snmp::mode::system', 'output-line' => 'hardware::ats::eaton::snmp::mode::outputline', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Eaton ATS in SNMP. =cut centreon-plugins-20220113/hardware/devices/000077500000000000000000000000001417000230700204535ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/abb/000077500000000000000000000000001417000230700211775ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/abb/cms700/000077500000000000000000000000001417000230700222105ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/abb/cms700/snmp/000077500000000000000000000000001417000230700231655ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/abb/cms700/snmp/mode/000077500000000000000000000000001417000230700241115ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/abb/cms700/snmp/mode/listsensors.pm000066400000000000000000000110021417000230700270310ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::abb::cms700::snmp::mode::listsensors; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } my $oid_GroupName = '.1.3.6.1.4.1.51055.1.20'; my $oid_BranchNamesens = '.1.3.6.1.4.1.51055.1.19'; my $mapping = { Phasesens => { oid => '.1.3.6.1.4.1.51055.1.21' }, Groupsens => { oid => '.1.3.6.1.4.1.51055.1.22' }, }; sub manage_selection { my ($self, %options) = @_; my %groups; my $snmp_result = $options{snmp}->get_table(oid => $oid_GroupName); foreach my $oid (keys %$snmp_result) { next if ($oid !~ /^$oid_GroupName\.(.*)/); next if ($snmp_result->{$oid} eq ''); $groups{$1} = $snmp_result->{$oid}; } my %sensors; $snmp_result = $options{snmp}->get_table(oid => $oid_BranchNamesens); foreach my $oid (keys %$snmp_result) { next if ($oid !~ /^$oid_BranchNamesens\.(.*)/); next if ($snmp_result->{$oid} eq ''); 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 sensor '" . $snmp_result->{$oid} . "'.", debug => 1); next; } $sensors{$instance} = $snmp_result->{$oid}; } $options{snmp}->load( oids => [ $mapping->{Phasesens}->{oid}, $mapping->{Groupsens}->{oid}, ], instances => [ keys %sensors ], instance_regexp => '^(.*)$' ); my $snmp_result_data = $options{snmp}->get_leef(nothing_quit => 1); foreach my $oid (keys %$snmp_result_data) { next if ($oid !~ /^$mapping->{Phasesens}->{oid}\.(.*)/); my $instance = $1; my $result = $options{snmp}->map_instance( mapping => $mapping, results => $snmp_result_data, instance => $instance ); $self->{sensors}->{$instance}->{name} = $sensors{$instance}; $self->{sensors}->{$instance}->{phase} = ($result->{Phasesens} != 0) ? $result->{Phasesens} : '-'; $self->{sensors}->{$instance}->{group} = (defined($groups{$result->{Groupsens}})) ? $groups{$result->{Groupsens}} : '-'; } } sub run { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $instance (sort keys %{$self->{sensors}}) { $self->{output}->output_add( long_msg => sprintf("[name = %s] [group = %s] [phase = %s]", $self->{sensors}->{$instance}->{name}, $self->{sensors}->{$instance}->{group}, $self->{sensors}->{$instance}->{phase}) ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List sensors:' ); $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', 'group', 'phase']); } sub disco_show { my ($self, %options) = @_; $self->manage_selection(%options); foreach my $instance (sort keys %{$self->{sensors}}) { $self->{output}->add_disco_entry( name => $self->{sensors}->{$instance}->{name}, group => $self->{sensors}->{$instance}->{group}, phase => $self->{sensors}->{$instance}->{phase}, ); } } 1; __END__ =head1 MODE List sensors. =over 8 =back =cut centreon-plugins-20220113/hardware/devices/abb/cms700/snmp/mode/mainsmeasurements.pm000066400000000000000000000275231417000230700302200ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::abb::cms700::snmp::mode::mainsmeasurements; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_output { my ($self, %options) = @_; return "Phase '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_init => 'skip_global' }, { name => 'phases', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All mains phases are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ { label => 'power-active-total', nlabel => 'power.active.watt', set => { key_values => [ { name => 'p3' } ], output_template => 'Active Power: %.2f W', perfdatas => [ { value => 'p3', template => '%.2f', unit => 'W', min => 0 }, ], } }, { label => 'power-reactive-total', nlabel => 'power.reactive.voltamperereactive', set => { key_values => [ { name => 'q3' } ], output_template => 'Reactive Power: %.2f VAR', perfdatas => [ { value => 'q3', template => '%.2f', unit => 'VAR', min => 0 }, ], } }, { label => 'power-apparent-total', nlabel => 'power.apparent.voltampere', set => { key_values => [ { name => 's3' } ], output_template => 'Apparent Power: %.2f VA', perfdatas => [ { value => 's3', template => '%.2f', unit => 'VA', min => 0 }, ], } }, ]; $self->{maps_counters}->{phases} = [ { label => 'voltage', nlabel => 'phase.voltage.volt', set => { key_values => [ { name => 'uL' }, { name => 'display' } ], output_template => 'Voltage: %.2f V', perfdatas => [ { value => 'uL', template => '%.2f', unit => 'V', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'current', nlabel => 'phase.current.ampere', set => { key_values => [ { name => 'iL' }, { name => 'display' } ], output_template => 'Current: %.2f A', perfdatas => [ { value => 'iL', template => '%.2f', unit => 'A', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'power-factor', nlabel => 'phase.power.factor.ratio', set => { key_values => [ { name => 'pfL' }, { name => 'display' } ], output_template => 'Power Factor: %.2f', perfdatas => [ { value => 'pfL', template => '%.2f', min => 0, max => 1, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'cosphi', nlabel => 'phase.cosphi.ratio', set => { key_values => [ { name => 'cosP' }, { name => 'display' } ], output_template => 'Cos Phi: %.2f', perfdatas => [ { value => 'cosP', template => '%.2f', min => 0, max => 1, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'power-active', nlabel => 'phase.power.active.watt', set => { key_values => [ { name => 'pL' }, { name => 'display' } ], output_template => 'Active Power: %.2f W', perfdatas => [ { value => 'pL', template => '%.2f', unit => 'W', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'power-reactive', nlabel => 'phase.power.reactive.voltamperereactive', set => { key_values => [ { name => 'qL' }, { name => 'display' } ], output_template => 'Reactive Power: %.2f VAR', perfdatas => [ { value => 'qL', template => '%.2f', unit => 'VAR', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'power-apparent', nlabel => 'phase.power.apparent.voltampere', set => { key_values => [ { name => 'sL' }, { name => 'display' } ], output_template => 'Apparent Power: %.2f VA', perfdatas => [ { value => 'sL', template => '%.2f', unit => 'VA', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'energy-active', nlabel => 'phase.energy.active.watthours', set => { key_values => [ { name => 'whL' }, { name => 'display' } ], output_template => 'Active Energy: %.2f Wh', perfdatas => [ { value => 'whL', template => '%.2f', unit => 'Wh', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'energy-reactive', nlabel => 'phase.energy.reactive.voltamperereactivehours', set => { key_values => [ { name => 'qhL' }, { name => 'display' } ], output_template => 'Reactive Energy: %.2f VARh', perfdatas => [ { value => 'qhL', template => '%.2f', unit => 'VARh', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'energy-apparent', nlabel => 'phase.energy.apparent.voltamperehours', set => { key_values => [ { name => 'shL' }, { name => 'display' } ], output_template => 'Apparent Energy: %.2f VAh', perfdatas => [ { value => 'shL', template => '%.2f', unit => 'VAh', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'voltage-thd', nlabel => 'phase.voltage.thd.percentage', set => { key_values => [ { name => 'thdUL' }, { name => 'display' } ], output_template => 'Voltage THD: %.2f %%', perfdatas => [ { value => 'thdUL', template => '%.2f', unit => '%', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'current-thd', nlabel => 'phase.current.thd.percentage', set => { key_values => [ { name => 'thdIL' }, { name => 'display' } ], output_template => 'Current THD: %.2f %%', perfdatas => [ { value => 'thdIL', template => '%.2f', unit => '%', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub skip_global { my ($self, %options) = @_; scalar(keys %{$self->{phases}}) > 1 ? return(0) : return(1); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { "filter-phase:s" => { name => 'filter_phase' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } my $mapping = { uL => { oid => '.1.3.6.1.4.1.51055.1.24' }, # PHASE VOLTAGE (0.01V) iL => { oid => '.1.3.6.1.4.1.51055.1.25' }, # LINE CURRENT (0.01A) pfL => { oid => '.1.3.6.1.4.1.51055.1.26' }, # POWER FACTOR (0.01) cosP => { oid => '.1.3.6.1.4.1.51055.1.27' }, # COSPHI sL => { oid => '.1.3.6.1.4.1.51055.1.29' }, # APPARENT POWER (VA) pL => { oid => '.1.3.6.1.4.1.51055.1.31' }, # ACTIVE POWER (W) qL => { oid => '.1.3.6.1.4.1.51055.1.33' }, # REACTIVE POWER (VAr) whL => { oid => '.1.3.6.1.4.1.51055.1.36' }, # ACTIVE ENERGY (0.01Wh) qhL => { oid => '.1.3.6.1.4.1.51055.1.37' }, # REACTIVE ENERGY (0.01Varh) thdUL => { oid => '.1.3.6.1.4.1.51055.1.38' }, # VOLTAGE THD (%) thdIL => { oid => '.1.3.6.1.4.1.51055.1.39' }, # CURRENT THD (%) shL => { oid => '.1.3.6.1.4.1.51055.1.41' }, # APPARENT ENERGY (0.01Vah) }; my $oid_main = '.1.3.6.1.4.1.51055.1'; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_table( oid => $oid_main, start => $mapping->{uL}->{oid}, end => $mapping->{shL}->{oid}, ); $self->{global} = { s3 => 0, p3 => 0, q3 => 0 }; $self->{phases} = {}; foreach my $oid (keys %$snmp_result) { next if ($oid !~ /^$mapping->{uL}->{oid}\.(.*)/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); if (defined($self->{option_results}->{filter_phase}) && $self->{option_results}->{filter_phase} ne '' && $instance !~ /$self->{option_results}->{filter_phase}/) { $self->{output}->output_add(long_msg => "skipping sensor '" . $snmp_result->{$oid} . "'.", debug => 1); next; } $self->{phases}->{$instance}->{display} = 'L' . $instance; $self->{phases}->{$instance}->{uL} = $result->{uL} / 100; $self->{phases}->{$instance}->{iL} = $result->{iL} / 100; $self->{phases}->{$instance}->{pfL} = $result->{pfL} / 100; $self->{phases}->{$instance}->{cosP} = $result->{cosP}; $self->{phases}->{$instance}->{sL} = $result->{sL}; $self->{phases}->{$instance}->{pL} = $result->{pL}; $self->{phases}->{$instance}->{qL} = $result->{qL}; $self->{phases}->{$instance}->{shL} = $result->{shL} / 100; $self->{phases}->{$instance}->{whL} = $result->{whL} / 100; $self->{phases}->{$instance}->{qhL} = $result->{qhL} / 100; $self->{phases}->{$instance}->{thdUL} = $result->{thdUL} / 100; $self->{phases}->{$instance}->{thdIL} = $result->{thdIL} / 100; $self->{global}->{s3} += $result->{sL}; $self->{global}->{p3} += $result->{pL}; $self->{global}->{q3} += $result->{qL}; } if (scalar(keys %{$self->{phases}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No phases found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check mains phases measurements. =over 8 =item B<--filter-phase> Filter by phase (can be a regexp). =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^power|energy$' =item B<--warning-*> B<--critical-*> Threshold warning. Can be: 'power-apparent-total', 'power-active-total', 'power-reactive-total', 'voltage', 'current', 'power-factor', 'cosphi', 'power-apparent', 'power-active', 'power-reactive', 'energy-apparent', 'energy-active', 'energy-reactive', 'voltage-thd', 'current-thd'. =back =cut centreon-plugins-20220113/hardware/devices/abb/cms700/snmp/mode/sensorsmeasurements.pm000066400000000000000000000230321417000230700305740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::abb::cms700::snmp::mode::sensorsmeasurements; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_output { my ($self, %options) = @_; my $output = sprintf("Sensor '%s' [Group: %s] [Phase: %s] ", $options{instance_value}->{display}, $options{instance_value}->{Groupsens}, $options{instance_value}->{Phasesens} ); return $output; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'sensors', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All sensors are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{sensors} = [ { label => 'current-mixte', nlabel => 'sensor.current.mixte.ampere', set => { key_values => [ { name => 'TRMSsens' }, { name => 'display' } ], output_template => 'Mixte Current: %.2f A', perfdatas => [ { value => 'TRMSsens', template => '%.2f', unit => 'A', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'current-alternative', nlabel => 'sensor.current.alternative.ampere', set => { key_values => [ { name => 'ACsens' }, { name => 'display' } ], output_template => 'Alternative Current: %.2f A', perfdatas => [ { value => 'ACsens', template => '%.2f', unit => 'A', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'current-direct', nlabel => 'sensor.current.direct.ampere', set => { key_values => [ { name => 'DCsens' }, { name => 'display' } ], output_template => 'Direct Current: %.2f A', perfdatas => [ { value => 'DCsens', template => '%.2f', unit => 'A', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'power-active', nlabel => 'sensor.power.active.watt', set => { key_values => [ { name => 'Psens' }, { name => 'display' } ], output_template => 'Active Power: %.2f W', perfdatas => [ { value => 'Psens', template => '%.2f', unit => 'W', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'energy-active', nlabel => 'sensor.energy.active.watthours', set => { key_values => [ { name => 'Whsens' }, { name => 'display' } ], output_template => 'Active Energy: %.2f Wh', perfdatas => [ { value => 'Whsens', template => '%.2f', unit => 'Wh', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'power-factor', nlabel => 'sensor.power.factor.ratio', set => { key_values => [ { name => 'PowerFactorsens' }, { name => 'display' } ], output_template => 'Power Factor: %.2f', perfdatas => [ { value => 'PowerFactorsens', template => '%.2f', min => 0, max => 1, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "filter-group:s" => { name => 'filter_group' }, "filter-phase:s" => { name => 'filter_phase' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } my $oid_GroupName = '.1.3.6.1.4.1.51055.1.20'; my $oid_BranchNamesens = '.1.3.6.1.4.1.51055.1.19'; my $mapping = { TRMSsens => { oid => '.1.3.6.1.4.1.51055.1.1' }, ACsens => { oid => '.1.3.6.1.4.1.51055.1.2' }, DCsens => { oid => '.1.3.6.1.4.1.51055.1.3' }, POLsens => { oid => '.1.3.6.1.4.1.51055.1.14' }, Psens => { oid => '.1.3.6.1.4.1.51055.1.15' }, Whsens => { oid => '.1.3.6.1.4.1.51055.1.16' }, Phasesens => { oid => '.1.3.6.1.4.1.51055.1.21' }, Groupsens => { oid => '.1.3.6.1.4.1.51055.1.22' }, PowerFactorsens => { oid => '.1.3.6.1.4.1.51055.1.23' }, }; sub manage_selection { my ($self, %options) = @_; my %groups; my $snmp_result = $options{snmp}->get_table(oid => $oid_GroupName); foreach my $oid (keys %$snmp_result) { next if ($oid !~ /^$oid_GroupName\.(.*)/); next if ($snmp_result->{$oid} eq ''); $groups{$1} = $snmp_result->{$oid}; } my %sensors; $snmp_result = $options{snmp}->get_table(oid => $oid_BranchNamesens); foreach my $oid (keys %$snmp_result) { next if ($oid !~ /^$oid_BranchNamesens\.(.*)/); next if ($snmp_result->{$oid} eq ''); 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 sensor '" . $snmp_result->{$oid} . "'.", debug => 1); next; } $sensors{$instance} = $snmp_result->{$oid}; } $options{snmp}->load( oids => [ $mapping->{TRMSsens}->{oid}, $mapping->{ACsens}->{oid}, $mapping->{DCsens}->{oid}, $mapping->{POLsens}->{oid}, $mapping->{Psens}->{oid}, $mapping->{Whsens}->{oid}, $mapping->{Phasesens}->{oid}, $mapping->{Groupsens}->{oid}, $mapping->{PowerFactorsens}->{oid}, ], instances => [ keys %sensors ], instance_regexp => '^(.*)$' ); my $snmp_result_data = $options{snmp}->get_leef(nothing_quit => 1); $self->{sensors} = {}; foreach my $oid (keys %$snmp_result_data) { next if ($oid !~ /^$mapping->{TRMSsens}->{oid}\.(.*)/); my $instance = $1; my $result = $options{snmp}->map_instance( mapping => $mapping, results => $snmp_result_data, instance => $instance ); if (defined($self->{option_results}->{filter_group}) && $self->{option_results}->{filter_group} ne '' && (!defined($groups{$result->{Groupsens}}) || ($groups{$result->{Groupsens}} !~ /$self->{option_results}->{filter_group}/))) { $self->{output}->output_add(long_msg => "skipping sensor '" . $sensors{$instance} . "'.", debug => 1); next; } if (defined($self->{option_results}->{filter_phase}) && $self->{option_results}->{filter_phase} ne '' && $result->{Phasesens} !~ /$self->{option_results}->{filter_phase}/) { $self->{output}->output_add(long_msg => "skipping sensor '" . $sensors{$instance} . "'.", debug => 1); next; } $self->{sensors}->{$instance}->{display} = $sensors{$instance}; $self->{sensors}->{$instance}->{TRMSsens} = $result->{TRMSsens} / 100; $self->{sensors}->{$instance}->{ACsens} = $result->{ACsens} / 100; $self->{sensors}->{$instance}->{DCsens} = $result->{DCsens} / 100; $self->{sensors}->{$instance}->{POLsens} = $result->{POLsens}; $self->{sensors}->{$instance}->{Psens} = $result->{Psens}; $self->{sensors}->{$instance}->{Whsens} = $result->{Whsens} / 10; $self->{sensors}->{$instance}->{PowerFactorsens} = $result->{PowerFactorsens} / 100; $self->{sensors}->{$instance}->{Phasesens} = $result->{Phasesens}; $self->{sensors}->{$instance}->{Groupsens} = (defined($groups{$result->{Groupsens}})) ? $groups{$result->{Groupsens}} : '-'; } if (scalar(keys %{$self->{sensors}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No sensors found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check sensors measurements. =over 8 =item B<--filter-name> Filter by sensor name (can be a regexp). =item B<--filter-group> Filter by sensor group name (can be a regexp). =item B<--filter-phase> Filter by sensor phase (can be a regexp). =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^current$' =item B<--warning-*> B<--critical-*> Threshold warning. Can be: 'current-mixte', 'current-alternative', 'current-direct', 'power-active', 'energy-active', 'power-factor'. =back =cut centreon-plugins-20220113/hardware/devices/abb/cms700/snmp/plugin.pm000066400000000000000000000027271417000230700250310ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::abb::cms700::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}} = ( 'mains-measurements' => 'hardware::devices::abb::cms700::snmp::mode::mainsmeasurements', 'sensors-measurements' => 'hardware::devices::abb::cms700::snmp::mode::sensorsmeasurements', 'list-sensors' => 'hardware::devices::abb::cms700::snmp::mode::listsensors', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check ABB CMS-700 measurements in SNMP. =cut centreon-plugins-20220113/hardware/devices/aeg/000077500000000000000000000000001417000230700212075ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/aeg/acm/000077500000000000000000000000001417000230700217475ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/aeg/acm/snmp/000077500000000000000000000000001417000230700227245ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/aeg/acm/snmp/mode/000077500000000000000000000000001417000230700236505ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/aeg/acm/snmp/mode/acstatus.pm000066400000000000000000000102171417000230700260360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::aeg::acm::snmp::mode::acstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("AC plant fail status is '%s'", $self->{result_values}->{status}); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_acFail'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'acFail' } ], 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 => \&catalog_status_threshold, } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning-status:s" => { name => 'warning_status', default => '' }, "critical-status:s" => { name => 'critical_status', default => '%{status} =~ /true/i' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } my %map_status = ( 0 => 'false', 1 => 'true', ); my $mapping_acm1000 = { acFail => { oid => '.1.3.6.1.4.1.15416.37.4.1', map => \%map_status }, }; my $mapping_acmi1000 = { acFail => { oid => '.1.3.6.1.4.1.15416.38.4.1', map => \%map_status }, }; my $oid_acm1000AcPlant = '.1.3.6.1.4.1.15416.37.4'; my $oid_acmi1000AcPlant = '.1.3.6.1.4.1.15416.38.4'; sub manage_selection { my ($self, %options) = @_; $self->{global} = {}; $self->{results} = $options{snmp}->get_multiple_table( oids => [ { oid => $oid_acm1000AcPlant }, { oid => $oid_acmi1000AcPlant }, ], nothing_quit => 1 ); my $result_acm1000 = $options{snmp}->map_instance(mapping => $mapping_acm1000, results => $self->{results}->{$oid_acm1000AcPlant}, instance => '0'); my $result_acmi1000 = $options{snmp}->map_instance(mapping => $mapping_acmi1000, results => $self->{results}->{$oid_acmi1000AcPlant}, instance => '0'); foreach my $name (keys %{$mapping_acm1000}) { if (defined($result_acm1000->{$name})) { $self->{global}->{$name} = $result_acm1000->{$name}; } } foreach my $name (keys %{$mapping_acmi1000}) { if (defined($result_acmi1000->{$name})) { $self->{global}->{$name} = $result_acmi1000->{$name}; } } } 1; __END__ =head1 MODE Check AC plant status. =over 8 =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /true/i'). Can used special variables like: %{status} =back =cut centreon-plugins-20220113/hardware/devices/aeg/acm/snmp/mode/alarmsstatus.pm000066400000000000000000000047051417000230700267370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::aeg::acm::snmp::mode::alarmsstatus; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { simple => [ ['true', 'CRITICAL'], ['false', 'OK'], ['on', 'CRITICAL'], ['off', 'OK'] ], multiple => [ ['true', 'CRITICAL'], ['false', 'OK'] ] }; $self->{components_path} = 'hardware::devices::aeg::acm::snmp::mode::components'; $self->{components_module} = ['simple', 'multiple']; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $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, no_performance => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } 1; __END__ =head1 MODE Check alarms status. =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'alarm'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=simple) Can also exclude specific instance: --filter=simple,3 =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='multiple,2,OK,true' =back =cut centreon-plugins-20220113/hardware/devices/aeg/acm/snmp/mode/batterystatus.pm000066400000000000000000000232511417000230700271270ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::aeg::acm::snmp::mode::batterystatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("Battery charging mode is '%s'", $self->{result_values}->{status}); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_battChargeMode'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'battChargeMode' } ], 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 => \&catalog_status_threshold, } }, { label => 'voltage', set => { key_values => [ { name => 'battVoltage' } ], output_template => 'Voltage : %s V', perfdatas => [ { label => 'voltage', value => 'battVoltage', template => '%s', unit => 'V' }, ], } }, { label => 'current', set => { key_values => [ { name => 'battCurrent' } ], output_template => 'Current : %s A', perfdatas => [ { label => 'current', value => 'battCurrent', template => '%s', min => 0, unit => 'A' }, ], } }, { label => 'current1', set => { key_values => [ { name => 'battCurrent1' } ], output_template => 'Current 1 : %s A', perfdatas => [ { label => 'current1', value => 'battCurrent1', template => '%s', min => 0, unit => 'A' }, ], } }, { label => 'current2', set => { key_values => [ { name => 'battCurrent2' } ], output_template => 'Current 2 : %s A', perfdatas => [ { label => 'current2', value => 'battCurrent2', template => '%s', min => 0, unit => 'A' }, ], } }, { label => 'temperature', set => { key_values => [ { name => 'battTemp' } ], output_template => 'Temperature : %s C', perfdatas => [ { label => 'temperature', value => 'battTemp', template => '%s', unit => 'C'}, ], } }, { label => 'temperature1', set => { key_values => [ { name => 'battTemp1' } ], output_template => 'Temperature 1 : %s C', perfdatas => [ { label => 'temperature1', value => 'battTemp1', template => '%s', unit => 'C'}, ], } }, { label => 'temperature2', set => { key_values => [ { name => 'battTemp2' } ], output_template => 'Temperature 2 : %s C', perfdatas => [ { label => 'temperature2', value => 'battTemp2', template => '%s', unit => 'C'}, ], } }, { label => 'amphourmeter', set => { key_values => [ { name => 'battAmpHMeter' } ], output_template => 'Amp Hour Meter : %s %%', perfdatas => [ { label => 'amphourmeter', value => 'battAmpHMeter', template => '%s', unit => '%'}, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning-status:s" => { name => 'warning_status', default => '%{status} =~ /onBattery/i' }, "critical-status:s" => { name => 'critical_status', default => '%{status} =~ /disconnected/i || %{status} =~ /shutdown/i' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } my %map_battery_mode = ( 0 => 'initial', 1 => 'float', 2 => 'highRate', 3 => 'dischargeTest', 4 => 'presenceTest', 5 => 'disconnected', 6 => 'onBattery', 7 => 'shutdown', 8 => 'fallback', 9 => 'inhibited', ); my $mapping_acm1000 = { battChargeMode => { oid => '.1.3.6.1.4.1.15416.37.1.1', map => \%map_battery_mode }, battVoltage => { oid => '.1.3.6.1.4.1.15416.37.1.2', divider => '100' }, battCurrent => { oid => '.1.3.6.1.4.1.15416.37.1.3', divider => '100' }, battTemp => { oid => '.1.3.6.1.4.1.15416.37.1.4', divider => '100' }, battAmpHMeter => { oid => '.1.3.6.1.4.1.15416.37.1.5' }, }; my $mapping_acmi1000 = { battChargeMode => { oid => '.1.3.6.1.4.1.15416.38.1.1', map => \%map_battery_mode }, battVoltage => { oid => '.1.3.6.1.4.1.15416.38.1.2', divider => '100' }, battCurrent1 => { oid => '.1.3.6.1.4.1.15416.38.1.4', divider => '100' }, battCurrent2 => { oid => '.1.3.6.1.4.1.15416.38.1.5', divider => '100' }, battTemp1 => { oid => '.1.3.6.1.4.1.15416.38.1.7', divider => '100' }, battTemp2 => { oid => '.1.3.6.1.4.1.15416.38.1.8', divider => '100' }, battAmpHMeter => { oid => '.1.3.6.1.4.1.15416.38.1.9' }, }; my $mapping_acm1d = { battVoltage => { oid => '.1.3.6.1.4.1.15416.29.1.1' }, battCurrent => { oid => '.1.3.6.1.4.1.15416.29.1.2' }, battTemp => { oid => '.1.3.6.1.4.1.15416.29.1.3' }, }; my $oid_acm1000Battery = '.1.3.6.1.4.1.15416.37.1'; my $oid_acmi1000Battery = '.1.3.6.1.4.1.15416.38.1'; my $oid_acm1dBattery = '.1.3.6.1.4.1.15416.29.1'; sub manage_selection { my ($self, %options) = @_; $self->{global} = {}; $self->{results} = $options{snmp}->get_multiple_table(oids => [ { oid => $oid_acm1000Battery }, { oid => $oid_acmi1000Battery }, { oid => $oid_acm1dBattery }, ], nothing_quit => 1); my $result_acm1000 = $options{snmp}->map_instance(mapping => $mapping_acm1000, results => $self->{results}->{$oid_acm1000Battery}, instance => '0'); my $result_acmi1000 = $options{snmp}->map_instance(mapping => $mapping_acmi1000, results => $self->{results}->{$oid_acmi1000Battery}, instance => '0'); my $result_acm1d = $options{snmp}->map_instance(mapping => $mapping_acm1d, results => $self->{results}->{$oid_acm1dBattery}, instance => '0'); foreach my $name (keys %{$mapping_acm1000}) { if (defined($result_acm1000->{$name})) { $self->{global}->{$name} = $result_acm1000->{$name}; $self->{global}->{$name} = $result_acm1000->{$name} / $mapping_acm1000->{$name}->{divider} if defined($mapping_acm1000->{$name}->{divider}); } } foreach my $name (keys %{$mapping_acmi1000}) { if (defined($result_acmi1000->{$name})) { $self->{global}->{$name} = $result_acmi1000->{$name}; $self->{global}->{$name} = $result_acmi1000->{$name} / $mapping_acmi1000->{$name}->{divider} if defined($mapping_acmi1000->{$name}->{divider}); } } foreach my $name (keys %{$mapping_acm1d}) { $self->{global}->{$name} = $result_acm1d->{$name} unless (!defined($result_acm1d->{$name})); } } 1; __END__ =head1 MODE Check battery charging mode and power statistics. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^status|current$' =item B<--warning-status> Set warning threshold for status (Default: '%{status} =~ /onBattery/i'). Can used special variables like: %{status} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /disconnected/i || %{status} =~ /shutdown/i'). Can used special variables like: %{status} =item B<--warning-*> Threshold warning. Can be: 'voltage', 'current', 'current1', 'current2', 'temperature', 'temperature2', 'temperature2', 'amphourmeter'. =item B<--critical-*> Threshold critical. Can be: 'voltage', 'current', 'current1', 'current2', 'temperature', 'temperature2', 'temperature2', 'amphourmeter'. =back =cut centreon-plugins-20220113/hardware/devices/aeg/acm/snmp/mode/components/000077500000000000000000000000001417000230700260355ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/aeg/acm/snmp/mode/components/multiple.pm000066400000000000000000000065511417000230700302350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::aeg::acm::snmp::mode::components::multiple; use strict; use warnings; my %map_status_1000 = (0 => 'false', 1 => 'true'); my $mapping_acm1000 = { label => { oid => '.1.3.6.1.4.1.15416.37.8.2.1.2' }, active => { oid => '.1.3.6.1.4.1.15416.37.8.2.1.3', map => \%map_status_1000 }, }; my $mapping_acmi1000 = { label => { oid => '.1.3.6.1.4.1.15416.38.8.2.1.2' }, active => { oid => '.1.3.6.1.4.1.15416.38.8.2.1.3', map => \%map_status_1000 }, }; my $oid_multAlarmTableEntryAcm1000 = '.1.3.6.1.4.1.15416.37.8.2.1'; my $oid_multAlarmTableEntryAcmi1000 = '.1.3.6.1.4.1.15416.38.8.2.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_multAlarmTableEntryAcm1000 }, { oid => $oid_multAlarmTableEntryAcmi1000 }; } sub check_alarms { my ($self, %options) = @_; foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$options{entry}}})) { next if ($oid !~ /^$options{mapping}->{label}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $options{mapping}, results => $self->{results}->{$options{entry}}, instance => $instance); next if (centreon::plugins::misc::trim($result->{label}) eq ''); next if ($self->check_filter(section => 'multiple', instance => $instance)); $self->{components}->{multiple}->{total}++; $self->{output}->output_add(long_msg => sprintf("Multiple alarm '%s' status is '%s' [instance = %s]", centreon::plugins::misc::trim($result->{label}), $result->{active}, $instance)); my $exit = $self->get_severity(section => 'multiple', instance => $instance, value => $result->{active}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Multiple alarm '%s' status is '%s'", centreon::plugins::misc::trim($result->{label}), $result->{active})); } } } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking multiple alarms"); $self->{components}->{multiple} = {name => 'multiple alarms', total => 0, skip => 0}; return if ($self->check_filter(section => 'multiple')); check_alarms($self, entry => $oid_multAlarmTableEntryAcm1000, mapping => $mapping_acm1000); check_alarms($self, entry => $oid_multAlarmTableEntryAcmi1000, mapping => $mapping_acmi1000); } 1; centreon-plugins-20220113/hardware/devices/aeg/acm/snmp/mode/components/simple.pm000066400000000000000000000074331417000230700276730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::aeg::acm::snmp::mode::components::simple; use strict; use warnings; my %map_status_1000 = (0 => 'false', 1 => 'true'); my %map_status_1d = (0 => 'off', 1 => 'on'); my $mapping_acm1000 = { label => { oid => '.1.3.6.1.4.1.15416.37.8.1.1.2' }, active => { oid => '.1.3.6.1.4.1.15416.37.8.1.1.3', map => \%map_status_1000 }, }; my $mapping_acmi1000 = { label => { oid => '.1.3.6.1.4.1.15416.38.8.1.1.2' }, active => { oid => '.1.3.6.1.4.1.15416.38.8.1.1.3', map => \%map_status_1000 }, }; my $mapping_acm1d = { label => { oid => '.1.3.6.1.4.1.15416.29.8.1.4' }, active => { oid => '.1.3.6.1.4.1.15416.29.8.1.3', map => \%map_status_1d }, }; my $oid_simpleAlarmTableEntryAcm1000 = '.1.3.6.1.4.1.15416.37.8.1.1'; my $oid_simpleAlarmTableEntryAcmi1000 = '.1.3.6.1.4.1.15416.38.8.1.1'; my $oid_simpleAlarmTableEntryAcm1d = '.1.3.6.1.4.1.15416.29.8.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_simpleAlarmTableEntryAcm1000 }, { oid => $oid_simpleAlarmTableEntryAcmi1000 }, { oid => $oid_simpleAlarmTableEntryAcm1d }; } sub check_alarms { my ($self, %options) = @_; foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$options{entry}}})) { next if ($oid !~ /^$options{mapping}->{label}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $options{mapping}, results => $self->{results}->{$options{entry}}, instance => $instance); next if (centreon::plugins::misc::trim($result->{label}) eq ''); next if ($self->check_filter(section => 'simple', instance => $instance)); $self->{components}->{simple}->{total}++; $self->{output}->output_add(long_msg => sprintf("Simple alarm '%s' status is '%s' [instance = %s]", centreon::plugins::misc::trim($result->{label}), $result->{active}, $instance)); my $exit = $self->get_severity(section => 'simple', instance => $instance, value => $result->{active}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Simple alarm '%s' status is '%s'", centreon::plugins::misc::trim($result->{label}), $result->{active})); } } } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking simple alarms"); $self->{components}->{simple} = {name => 'simple alarms', total => 0, skip => 0}; return if ($self->check_filter(section => 'simple')); check_alarms($self, entry => $oid_simpleAlarmTableEntryAcm1000, mapping => $mapping_acm1000); check_alarms($self, entry => $oid_simpleAlarmTableEntryAcmi1000, mapping => $mapping_acmi1000); check_alarms($self, entry => $oid_simpleAlarmTableEntryAcm1d, mapping => $mapping_acm1d); } 1; centreon-plugins-20220113/hardware/devices/aeg/acm/snmp/mode/loadstatus.pm000066400000000000000000000127061417000230700263770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::aeg::acm::snmp::mode::loadstatus; 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, skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ { label => 'voltage', set => { key_values => [ { name => 'loadVoltage' } ], output_template => 'Voltage : %s V', perfdatas => [ { label => 'voltage', value => 'loadVoltage', template => '%s', unit => 'V' }, ], } }, { label => 'current', set => { key_values => [ { name => 'loadCurrent' } ], output_template => 'Current : %s A', perfdatas => [ { label => 'current', value => 'loadCurrent', template => '%s', min => 0, unit => 'A' }, ], } }, { label => 'power', set => { key_values => [ { name => 'loadPower' } ], output_template => 'Power : %s W', perfdatas => [ { label => 'power', value => 'loadPower', template => '%s', unit => 'w'}, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); } my $mapping_acm1000 = { loadVoltage => { oid => '.1.3.6.1.4.1.15416.37.3.1', divider => '100' }, loadCurrent => { oid => '.1.3.6.1.4.1.15416.37.3.2', divider => '100' }, loadPower => { oid => '.1.3.6.1.4.1.15416.37.3.3' }, }; my $mapping_acmi1000 = { loadVoltage => { oid => '.1.3.6.1.4.1.15416.38.3.1', divider => '100' }, loadCurrent => { oid => '.1.3.6.1.4.1.15416.38.3.2', divider => '100' }, loadPower => { oid => '.1.3.6.1.4.1.15416.38.3.3' }, }; my $mapping_acm1d = { loadVoltage => { oid => '.1.3.6.1.4.1.15416.29.4.1' }, loadCurrent => { oid => '.1.3.6.1.4.1.15416.29.4.2' }, }; my $oid_acm1000Load = '.1.3.6.1.4.1.15416.37.3'; my $oid_acmi1000Load = '.1.3.6.1.4.1.15416.38.3'; my $oid_acm1dLoad = '.1.3.6.1.4.1.15416.29.4'; sub manage_selection { my ($self, %options) = @_; $self->{global} = {}; $self->{results} = $options{snmp}->get_multiple_table(oids => [ { oid => $oid_acm1000Load }, { oid => $oid_acmi1000Load }, { oid => $oid_acm1dLoad }, ], nothing_quit => 1); my $result_acm1000 = $options{snmp}->map_instance(mapping => $mapping_acm1000, results => $self->{results}->{$oid_acm1000Load}, instance => '0'); my $result_acmi1000 = $options{snmp}->map_instance(mapping => $mapping_acmi1000, results => $self->{results}->{$oid_acmi1000Load}, instance => '0'); my $result_acm1d = $options{snmp}->map_instance(mapping => $mapping_acm1d, results => $self->{results}->{$oid_acm1dLoad}, instance => '0'); foreach my $name (keys %{$mapping_acm1000}) { if (defined($result_acm1000->{$name})) { $self->{global}->{$name} = $result_acm1000->{$name}; $self->{global}->{$name} = $result_acm1000->{$name} / $mapping_acm1000->{$name}->{divider} if defined($mapping_acm1000->{$name}->{divider}); } } foreach my $name (keys %{$mapping_acmi1000}) { if (defined($result_acmi1000->{$name})) { $self->{global}->{$name} = $result_acmi1000->{$name}; $self->{global}->{$name} = $result_acmi1000->{$name} / $mapping_acmi1000->{$name}->{divider} if defined($mapping_acmi1000->{$name}->{divider}); } } foreach my $name (keys %{$mapping_acm1d}) { $self->{global}->{$name} = $result_acm1d->{$name} unless (!defined($result_acm1d->{$name})); } } 1; __END__ =head1 MODE Check load plant statistics. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^current$' =item B<--warning-*> Threshold warning. Can be: 'voltage', 'current', 'power'. =item B<--critical-*> Threshold critical. Can be: 'voltage', 'current', 'power'. =back =cut centreon-plugins-20220113/hardware/devices/aeg/acm/snmp/mode/rectifierstatus.pm000066400000000000000000000164171417000230700274370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::aeg::acm::snmp::mode::rectifierstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("status is '%s'", $self->{result_values}->{status}); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_rectState'}; return 0; } sub prefix_rect_output { my ($self, %options) = @_; return "Rectifier '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'rect', type => 1, cb_prefix_output => 'prefix_rect_output', message_multiple => 'All rectifiers are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ { label => 'voltage', set => { key_values => [ { name => 'rectVoltage' } ], output_template => 'Voltage : %s V', perfdatas => [ { label => 'voltage', value => 'rectVoltage', template => '%s', unit => 'V' }, ], } }, { label => 'current', set => { key_values => [ { name => 'rectCurrent' } ], output_template => 'Current : %s A', perfdatas => [ { label => 'current', value => 'rectCurrent', template => '%s', min => 0, unit => 'A' }, ], } }, { label => 'faulty-count', set => { key_values => [ { name => 'nbrOfFaultyRect' } ], output_template => 'Faulty rectifiers : %s', perfdatas => [ { label => 'faulty_count', value => 'nbrOfFaultyRect', template => '%s', min => 0, unit => '' }, ], } }, ]; $self->{maps_counters}->{rect} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'rectState' }, { 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 => \&catalog_status_threshold, } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning-status:s" => { name => 'warning_status', default => '' }, "critical-status:s" => { name => 'critical_status', default => '%{status} !~ /ok|notInstalled/i' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } my %map_state = ( 1 => 'ok', 255 => 'notInstalled', ); my $mapping_acm1000 = { rectVoltage => { oid => '.1.3.6.1.4.1.15416.37.2.1', divider => '100' }, rectCurrent => { oid => '.1.3.6.1.4.1.15416.37.2.2', divider => '100' }, nbrOfFaultyRect => { oid => '.1.3.6.1.4.1.15416.37.2.4' }, }; my $mapping_acmi1000 = { rectVoltage => { oid => '.1.3.6.1.4.1.15416.38.2.1', divider => '100' }, rectCurrent => { oid => '.1.3.6.1.4.1.15416.38.2.2', divider => '100' }, nbrOfFaultyRect => { oid => '.1.3.6.1.4.1.15416.38.2.4' }, }; my $mapping_acm1d = { rectState => { oid => '.1.3.6.1.4.1.15416.29.3.1.2' }, }; my $oid_acm1000DcPlant = '.1.3.6.1.4.1.15416.37.2'; my $oid_acmi1000DcPlant = '.1.3.6.1.4.1.15416.38.2'; my $oid_acm1dRectEntry = '.1.3.6.1.4.1.15416.29.3.1'; sub manage_selection { my ($self, %options) = @_; $self->{global} = {}; $self->{rect} = {}; $self->{results} = $options{snmp}->get_multiple_table(oids => [ { oid => $oid_acm1000DcPlant }, { oid => $oid_acmi1000DcPlant }, { oid => $oid_acm1dRectEntry }, ], nothing_quit => 1); my $result_acm1000 = $options{snmp}->map_instance(mapping => $mapping_acm1000, results => $self->{results}->{$oid_acm1000DcPlant}, instance => '0'); my $result_acmi1000 = $options{snmp}->map_instance(mapping => $mapping_acmi1000, results => $self->{results}->{$oid_acmi1000DcPlant}, instance => '0'); foreach my $name (keys %{$mapping_acm1000}) { if (defined($result_acm1000->{$name})) { $self->{global}->{$name} = $result_acm1000->{$name}; $self->{global}->{$name} = $result_acm1000->{$name} / $mapping_acm1000->{$name}->{divider} if defined($mapping_acm1000->{$name}->{divider}); } } foreach my $name (keys %{$mapping_acmi1000}) { if (defined($result_acmi1000->{$name})) { $self->{global}->{$name} = $result_acmi1000->{$name}; $self->{global}->{$name} = $result_acmi1000->{$name} / $mapping_acmi1000->{$name}->{divider} if defined($mapping_acmi1000->{$name}->{divider}); } } foreach my $oid (keys %{$self->{results}->{$oid_acm1dRectEntry}}) { next if ($oid !~ /^$mapping_acm1d->{rectState}->{oid}\.(.*)$/); my $instance = $1; $self->{rect}->{$instance} = { rectState => $map_state{$self->{results}->{$oid_acm1dRectEntry}->{$mapping_acm1d->{rectState}->{oid} . '.' . $instance}}, display => $instance }; } } 1; __END__ =head1 MODE Check rectifiers status and statistics. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^status|current$' =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status} =item B<--critical-status> Set critical threshold for status (Default: '%{status} !~ /ok|notInstalled/i'). Can used special variables like: %{status} =item B<--warning-*> Threshold warning. Can be: 'voltage', 'current', 'faulty-count'. =item B<--critical-*> Threshold critical. Can be: 'voltage', 'current', 'faulty-count'. =back =cut centreon-plugins-20220113/hardware/devices/aeg/acm/snmp/plugin.pm000066400000000000000000000031501417000230700245570ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::aeg::acm::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}} = ( 'ac-status' => 'hardware::devices::aeg::acm::snmp::mode::acstatus', 'alarms-status' => 'hardware::devices::aeg::acm::snmp::mode::alarmsstatus', 'battery-status' => 'hardware::devices::aeg::acm::snmp::mode::batterystatus', 'load-status' => 'hardware::devices::aeg::acm::snmp::mode::loadstatus', 'rectifier-status' => 'hardware::devices::aeg::acm::snmp::mode::rectifierstatus', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check AEG ACM modules in SNMP. =cut centreon-plugins-20220113/hardware/devices/barco/000077500000000000000000000000001417000230700215415ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/barco/cs/000077500000000000000000000000001417000230700221465ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/barco/cs/restapi/000077500000000000000000000000001417000230700236155ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/barco/cs/restapi/custom/000077500000000000000000000000001417000230700251275ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/barco/cs/restapi/custom/api.pm000066400000000000000000000145621417000230700262460ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::barco::cs::restapi::custom::api; use strict; use warnings; use centreon::plugins::http; use JSON::XS; 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 => { 'api-username:s' => { name => 'api_username' }, 'api-password:s' => { name => 'api_password' }, 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'timeout:s' => { name => 'timeout' }, 'unknown-http-status:s' => { name => 'unknown_http_status' }, 'warning-http-status:s' => { name => 'warning_http_status' }, 'critical-http-status:s' => { name => 'critical_http_status' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 4001; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : ''; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : ''; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300'; $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } if ($self->{api_username} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-username option."); $self->{output}->option_exit(); } if ($self->{api_password} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-password option."); $self->{output}->option_exit(); } return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{credentials} = 1; $self->{option_results}->{basic} = 1; $self->{option_results}->{username} = $self->{api_username}; $self->{option_results}->{password} = $self->{api_password}; } sub settings { my ($self, %options) = @_; return if (defined($self->{settings_done})); $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->set_options(%{$self->{option_results}}); $self->{settings_done} = 1; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub request_api { my ($self, %options) = @_; $self->settings(); my $content = $self->{http}->request( url_path => $options{endpoint}, unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status}, cookies_file => '' # in memory ); if (!defined($content) || $content eq '') { $self->{output}->add_option_msg(short_msg => "API returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } return $decoded; } 1; __END__ =head1 NAME Barco ClickShare Rest API =head1 REST API OPTIONS Barco ClickShare Rest API =over 8 =item B<--hostname> Barco ClickShare hostname. =item B<--port> Port used (Default: 4001) =item B<--proto> Specify https if needed (Default: 'https') =item B<--api-username> API username. =item B<--api-password> API password. =item B<--timeout> Set timeout in seconds (Default: 10). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/hardware/devices/barco/cs/restapi/mode/000077500000000000000000000000001417000230700245415ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/barco/cs/restapi/mode/device.pm000066400000000000000000000224721417000230700263450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::barco::cs::restapi::mode::device; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_device_status_output { my ($self, %options) = @_; return sprintf('status: %s', $self->{result_values}->{status}); } sub custom_process_status_output { my ($self, %options) = @_; return sprintf('status is %s', $self->{result_values}->{status}); } sub custom_cpu_temp_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel}, unit => 'C', instances => 'cpu', value => $self->{result_values}->{cpu}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}) ); } sub custom_pcie_temp_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel}, unit => 'C', instances => 'pcie', value => $self->{result_values}->{pcie}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}) ); } sub custom_sio_temp_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel}, unit => 'C', instances => 'sio', value => $self->{result_values}->{sio}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}) ); } sub custom_cpu_fan_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => $self->{nlabel}, unit => 'rpm', instances => 'cpu', value => $self->{result_values}->{cpu}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}) ); } sub device_long_output { my ($self, %options) = @_; return 'checking device'; } sub prefix_temperature_output { my ($self, %options) = @_; return 'temperature '; } sub prefix_process_output { my ($self, %options) = @_; return "process '" . $options{instance_value}->{name} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'device', type => 3, cb_long_output => 'device_long_output', indent_long_output => ' ', group => [ { name => 'status', type => 0, display_short => 0, skipped_code => { -10 => 1 } }, { name => 'temperature', type => 0, cb_prefix_output => 'prefix_temperature_output', display_short => 0, skipped_code => { -10 => 1 } }, { name => 'fan', type => 0, display_short => 0, skipped_code => { -10 => 1 } }, { name => 'processes', type => 1, display_long => 1, display_short => 0, cb_prefix_output => 'prefix_process_output', skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{status} = [ { label => 'device-status', type => 2, warning_default => '%{status} =~ /warning/', critical_default => '%{status} =~ /error/', set => { key_values => [ { name => 'status' }, ], closure_custom_output => $self->can('custom_device_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{temperature} = [ { label => 'cpu-temperature', nlabel => 'hardware.temperature.celsius', set => { key_values => [ { name => 'cpu' } ], output_template => 'cpu %s C', closure_custom_perfdata => $self->can('custom_cpu_temp_perfdata') } }, { label => 'pcie-temperature', nlabel => 'hardware.temperature.celsius', set => { key_values => [ { name => 'pcie' } ], output_template => 'pcie %s C', closure_custom_perfdata => $self->can('custom_pcie_temp_perfdata') } }, { label => 'sio-temperature', nlabel => 'hardware.temperature.celsius', set => { key_values => [ { name => 'sio' } ], output_template => 'sio %s C', closure_custom_perfdata => $self->can('custom_sio_temp_perfdata') } } ]; $self->{maps_counters}->{fan} = [ { label => 'cpu-fanspeed', nlabel => 'hardware.fan.speed.rpm', set => { key_values => [ { name => 'cpu' } ], output_template => 'cpu fan speed %s rpm', closure_custom_perfdata => $self->can('custom_cpu_fan_perfdata') } } ]; $self->{maps_counters}->{processes} = [ { label => 'process-status', type => 2, set => { key_values => [ { name => 'name' }, { name => 'status' } ], closure_custom_output => $self->can('custom_process_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $map_status = { 0 => 'ok', 1 => 'warning', 2 => 'error' }; my $versions = $options{custom}->request_api(endpoint => '/SupportedVersions'); my $version = 'v1.0'; foreach (@{$versions->{data}->{value}}) { $version = 'v1.11' if ($_ eq 'v1.11'); } my $device_status = $options{custom}->request_api(endpoint => '/v1.0/DeviceInfo/Status'); my $sensors = $options{custom}->request_api(endpoint => '/' . $version . '/DeviceInfo/Sensors'); my $processes = $options{custom}->request_api(endpoint => '/v1.0/DeviceInfo/Processes/ProcessTable'); $self->{output}->output_add(short_msg => 'device is ok'); $self->{device} = { global => { status => { status => $map_status->{ $device_status->{data}->{value} } }, temperature => { cpu => (defined($sensors->{data}->{value}->{CpuTemperature}) && $sensors->{data}->{value}->{CpuTemperature} != 0) ? $sensors->{data}->{value}->{CpuTemperature} : undef, pcie => (defined($sensors->{data}->{value}->{PcieTemperature}) && $sensors->{data}->{value}->{PcieTemperature} != 0) ? $sensors->{data}->{value}->{PcieTemperature} : undef, sio => (defined($sensors->{data}->{value}->{SioTemperature}) && $sensors->{data}->{value}->{SioTemperature} != 0) ? $sensors->{data}->{value}->{SioTemperature} : undef }, fan => { cpu => (defined($sensors->{data}->{value}->{CpuFanSpeed}) && $sensors->{data}->{value}->{CpuFanSpeed} != 0) ? $sensors->{data}->{value}->{CpuFanSpeed} : undef }, processes => {} } }; foreach (values %{$processes->{data}->{value}}) { $self->{device}->{global}->{processes}->{ $_->{Name} } = { name => $_->{Name}, status => $_->{Status} =~ /true|1/i ? 'running' : 'notRunning' }; } } 1; __END__ =head1 MODE Check device. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='status' =item B<--warning-device-status> Set warning threshold (Default: '%{status} =~ /warning/'). Can used special variables like: %{status} =item B<--critical-device-status> Set critical threshold (Default: '%{status} =~ /error/'). Can used special variables like: %{status} =item B<--warning-process-status> Set warning threshold. Can used special variables like: %{name}, %{status} =item B<--critical-process-status> Set critical threshold. Can used special variables like: %{name}, %{status} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'cpu-temperature', 'pcie-temperature', 'sio-temperature', 'cpu-fanspeed'. =back =cut centreon-plugins-20220113/hardware/devices/barco/cs/restapi/plugin.pm000066400000000000000000000025171417000230700254560ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::barco::cs::restapi::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} = { 'device' => 'hardware::devices::barco::cs::restapi::mode::device' }; $self->{custom_modes}->{api} = 'hardware::devices::barco::cs::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Barco ClickShare using Rest API. =cut centreon-plugins-20220113/hardware/devices/camera/000077500000000000000000000000001417000230700217035ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/camera/hanwha/000077500000000000000000000000001417000230700231515ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/camera/hanwha/snmp/000077500000000000000000000000001417000230700241265ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/camera/hanwha/snmp/mode/000077500000000000000000000000001417000230700250525ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/camera/hanwha/snmp/mode/components/000077500000000000000000000000001417000230700272375ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/camera/hanwha/snmp/mode/components/sdcard.pm000066400000000000000000000042301417000230700310340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::camera::hanwha::snmp::mode::components::sdcard; use strict; use warnings; my $oid_nwCam = '.1.3.6.1.4.1.36849.1.2'; sub load {} sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking sdcard"); $self->{components}->{sdcard} = { name => 'sdcard', total => 0, skip => 0 }; return if ($self->check_filter(section => 'sdcard')); my $branch_sdcard_status = '4.3.0'; foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_nwCam}})) { next if ($oid !~ /^$oid_nwCam\.(\d+)\.$branch_sdcard_status$/); my $instance = '0'; my $sdcard_status = $self->{results}->{$oid_nwCam}->{$oid}; next if ($self->check_filter(section => 'sdcard', instance => $instance)); $self->{components}->{sdcard}->{total}++; $self->{output}->output_add(long_msg => sprintf("sdcard '%s' status is '%s' [instance = %s]", $instance, $sdcard_status, $instance)); my $exit = $self->get_severity(section => 'sdcard', instance => $instance, value => $sdcard_status); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("sdcard '%s' status is '%s'", $instance, $sdcard_status)); } } } 1; centreon-plugins-20220113/hardware/devices/camera/hanwha/snmp/mode/components/service.pm000066400000000000000000000062221417000230700312370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::camera::hanwha::snmp::mode::components::service; use strict; use warnings; my $services = { '3.1.1.1' => 'alarmInput1', '3.1.2.1' => 'alarmInput2', '3.1.3.1' => 'alarmInput3', '3.1.4.1' => 'alarmInput4', '3.2.1.1' => 'relayOutput1', '3.2.2.1' => 'relayOutput2', '3.2.3.1' => 'relayOutput3', '3.2.4.1' => 'relayOutput4', '3.3.1' => 'motionDetection', '3.4.1' => 'videoAnalytics', '3.5.1' => 'faceDetection', '3.6.1' => 'networkDisconnection', '3.7.1' => 'tampering', '3.8.1' => 'audioDetection', '3.10.1' => 'defocus', '3.11.1' => 'fogDetection', '3.12.1' => 'soundClassification', '3.13.1' => 'shockDetection', '3.14.1' => 'temperatureDetection', }; my $oid_nwCam = '.1.3.6.1.4.1.36849.1.2'; sub load {} sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking services"); $self->{components}->{service} = { name => 'services', total => 0, skip => 0 }; return if ($self->check_filter(section => 'service')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_nwCam}})) { next if ($oid !~ /^$oid_nwCam\.(\d+)\.(.*?)\.0$/); my ($product_id, $service) = ($1, $2); next if (!defined($services->{$service})); my $instance = $services->{$service}; my $service_status = $self->{results}->{$oid_nwCam}->{$oid}; my $service_date = defined($self->{results}->{$oid_nwCam}->{$oid_nwCam . '.' . $product_id . '.' . $service . '.1'}) ? $self->{results}->{$oid_nwCam}->{$oid_nwCam . '.' . $product_id . '.' . $service . '.1'} : '-'; next if ($self->check_filter(section => 'service', instance => $instance)); $self->{components}->{service}->{total}++; $self->{output}->output_add(long_msg => sprintf("service '%s' status is '%s' [instance = %s] [date = %s]", $instance, $service_status, $instance, $service_date)); my $exit = $self->get_severity(section => 'service', instance => $instance, value => $service_status); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("service '%s' status is '%s'", $instance, $service_status)); } } } 1; centreon-plugins-20220113/hardware/devices/camera/hanwha/snmp/mode/hardware.pm000066400000000000000000000047341417000230700272150ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::camera::hanwha::snmp::mode::hardware; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { service => [ ['low', 'OK'], ['high', 'CRITICAL'] ], sdcard => [ ['normal', 'OK'], ['fail', 'CRITICAL'] ] }; $self->{components_path} = 'hardware::devices::camera::hanwha::snmp::mode::components'; $self->{components_module} = ['service', 'sdcard']; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; my $oid_nwCam = '.1.3.6.1.4.1.36849.1.2'; $self->{results} = $self->{snmp}->get_multiple_table(oids => [ { oid => $oid_nwCam } ]); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1, no_performance => 1, no_absent => 1); bless $self, $class; $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: 'service', 'sdcard'. =item B<--filter> Exclude some parts (comma seperated list) Can also exclude specific instance: --filter=instance,relayOutput1 =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='service,relayOutpu1,OK,high' =back =cut centreon-plugins-20220113/hardware/devices/camera/hanwha/snmp/plugin.pm000066400000000000000000000023651417000230700257700ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::camera::hanwha::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}} = ( 'hardware' => 'hardware::devices::camera::hanwha::snmp::mode::hardware', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Hanwha camera in SNMP. =cut centreon-plugins-20220113/hardware/devices/camera/hikvision/000077500000000000000000000000001417000230700237065ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/camera/hikvision/snmp/000077500000000000000000000000001417000230700246635ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/camera/hikvision/snmp/mode/000077500000000000000000000000001417000230700256075ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/camera/hikvision/snmp/mode/cpu.pm000066400000000000000000000044661417000230700267460ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::camera::hikvision::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 => 0 } ]; $self->{maps_counters}->{cpu} = [ { label => 'usage', nlabel => 'cpu.utilization.percentage', set => { key_values => [ { name => 'used' } ], output_template => 'CPU Usage: %.2f %%', perfdatas => [ { value => 'used', template => '%.2f', min => 0, max => 100, unit => '%' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $oid_cpuPercent = '.1.3.6.1.4.1.39165.1.7.0'; my $snmp_result = $options{snmp}->get_leef( oids => [$oid_cpuPercent], nothing_quit => 1 ); if ($snmp_result->{$oid_cpuPercent} !~ /(\d+)/) { $self->{output}->add_option_msg(short_msg => 'cannot parse cpu usage: ' . $snmp_result->{$oid_cpuPercent}); $self->{output}->option_exit(); } my $prct_used = $1; $self->{cpu} = { used => $prct_used }; } 1; __END__ =head1 MODE Check cpu usage. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'usage' (%). =back =cut centreon-plugins-20220113/hardware/devices/camera/hikvision/snmp/mode/disk.pm000066400000000000000000000107211417000230700271000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::camera::hikvision::snmp::mode::disk; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; sub custom_disk_output { my ($self, %options) = @_; my $msg = sprintf("Disk Total: %s %s Used: %s %s (%.2f%%) Free: %s %s (%.2f%%)", $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}), $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}), $self->{result_values}->{prct_used}, $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}), $self->{result_values}->{prct_free} ); return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'disk', type => 0 } ]; $self->{maps_counters}->{disk} = [ { label => 'usage', nlabel => 'disk.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_disk_output'), perfdatas => [ { value => 'used', template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1 }, ], } }, { label => 'usage-free', display_ok => 0, nlabel => 'disk.free.bytes', set => { key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_disk_output'), perfdatas => [ { value => 'free', template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1 }, ], } }, { label => 'usage-prct', display_ok => 0, nlabel => 'disk.usage.percentage', set => { key_values => [ { name => 'prct_used' } ], output_template => 'Disk Used : %.2f %%', perfdatas => [ { value => 'prct_used', template => '%.2f', min => 0, max => 100, unit => '%' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $oid_diskSize = '.1.3.6.1.4.1.39165.1.8.0'; my $oid_diskPercent = '.1.3.6.1.4.1.39165.1.9.0'; my $snmp_result = $options{snmp}->get_leef( oids => [$oid_diskSize, $oid_diskPercent], nothing_quit => 1 ); if ($snmp_result->{$oid_diskSize} !~ /([0-9\.]+)\s+(\S+)/) { $self->{output}->add_option_msg(short_msg => 'cannot parse disk size: ' . $snmp_result->{$oid_diskSize}); $self->{output}->option_exit(); } my ($total, $unit) = ($1, $2); $total = centreon::plugins::misc::convert_bytes(value => $total, unit => $unit); if ($snmp_result->{$oid_diskPercent} !~ /([0-9\.]+)/) { $self->{output}->add_option_msg(short_msg => 'cannot parse disk used: ' . $snmp_result->{$oid_diskPercent}); $self->{output}->option_exit(); } my $prct_used = $1; $self->{disk} = { free => $total * (100 - $prct_used) / 100, used => $total * $prct_used / 100, prct_used => $prct_used, prct_free => 100 - $prct_used, total => $total, }; } 1; __END__ =head1 MODE Check disk usage. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'usage' (B), 'usage-free' (B), 'usage-prct' (%). =back =cut centreon-plugins-20220113/hardware/devices/camera/hikvision/snmp/mode/memory.pm000066400000000000000000000107241417000230700274610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::camera::hikvision::snmp::mode::memory; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; sub custom_mem_output { my ($self, %options) = @_; my $msg = sprintf("Memory Total: %s %s Used: %s %s (%.2f%%) Free: %s %s (%.2f%%)", $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}), $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}), $self->{result_values}->{prct_used}, $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}), $self->{result_values}->{prct_free} ); return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'memory', type => 0 } ]; $self->{maps_counters}->{memory} = [ { label => 'usage', nlabel => 'memory.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_mem_output'), perfdatas => [ { value => 'used', template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1 }, ], } }, { label => 'usage-free', display_ok => 0, nlabel => 'memory.free.bytes', set => { key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_mem_output'), perfdatas => [ { value => 'free', template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1 }, ], } }, { label => 'usage-prct', display_ok => 0, nlabel => 'memory.usage.percentage', set => { key_values => [ { name => 'prct_used' } ], output_template => 'Memory Used : %.2f %%', perfdatas => [ { value => 'prct_used', template => '%.2f', min => 0, max => 100, unit => '%' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $oid_memSize = '.1.3.6.1.4.1.39165.1.10.0'; my $oid_memUsed = '.1.3.6.1.4.1.39165.1.11.0'; my $snmp_result = $options{snmp}->get_leef( oids => [$oid_memSize, $oid_memUsed], nothing_quit => 1 ); if ($snmp_result->{$oid_memSize} !~ /([0-9\.]+)\s+(\S+)/) { $self->{output}->add_option_msg(short_msg => 'cannot parse memory size: ' . $snmp_result->{$oid_memSize}); $self->{output}->option_exit(); } my ($total, $unit) = ($1, $2); $total = centreon::plugins::misc::convert_bytes(value => $total, unit => $unit); if ($snmp_result->{$oid_memUsed} !~ /([0-9\.]+)/) { $self->{output}->add_option_msg(short_msg => 'cannot parse memory used: ' . $snmp_result->{$oid_memUsed}); $self->{output}->option_exit(); } my $prct_used = $1; $self->{memory} = { free => $total * (100 - $prct_used) / 100, used => $total * $prct_used / 100, prct_used => $prct_used, prct_free => 100 - $prct_used, total => $total, }; } 1; __END__ =head1 MODE Check memory usage. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'usage' (B), 'usage-free' (B), 'usage-prct' (%). =back =cut centreon-plugins-20220113/hardware/devices/camera/hikvision/snmp/mode/time.pm000066400000000000000000000055311417000230700271070ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::camera::hikvision::snmp::mode::time; use base qw(snmp_standard::mode::ntp); 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; } sub get_target_time { my ($self, %options) = @_; my $oid_sysTime = '.1.3.6.1.4.1.39165.1.19.0'; my $snmp_result = $options{snmp}->get_leef(oids => [ $oid_sysTime ], nothing_quit => 1); # format: "2019-11-18 20:13:17" if ($snmp_result->{$oid_sysTime} !~ /^(\d+)-(\d+)-(\d+)\s+(\d+):(\d+):(\d+)/) { $self->{output}->add_option_msg(short_msg => 'cannot parse date format: ' . $snmp_result->{$oid_sysTime}); $self->{output}->option_exit(); } my $remote_date = [$1, $2, $3, $4, $5, $6]; my $timezone = 'UTC'; if (defined($self->{option_results}->{timezone}) && $self->{option_results}->{timezone} ne '') { $timezone = $self->{option_results}->{timezone}; } my $tz = centreon::plugins::misc::set_timezone(name => $timezone); my $dt = DateTime->new( year => $remote_date->[0], month => $remote_date->[1], day => $remote_date->[2], hour => $remote_date->[3], minute => $remote_date->[4], second => $remote_date->[5], %$tz ); return ($dt->epoch, $remote_date, $timezone); } 1; __END__ =head1 MODE Check time offset of server with ntp server. Use local time if ntp-host option is not set. SNMP gives a date with second precision (no milliseconds). Time precision is not very accurate. Use threshold with (+-) 2 seconds offset (minimum). =over 8 =item B<--warning-offset> Time offset warning threshold (in seconds). =item B<--critical-offset> Time offset critical Threshold (in seconds). =item B<--ntp-hostname> Set the ntp hostname (if not set, localtime is used). =item B<--ntp-port> Set the ntp port (Default: 123). =item B<--timezone> Set the timezone of distant server. For Windows, you need to set it. Can use format: 'Europe/London' or '+0100'. =back =cut centreon-plugins-20220113/hardware/devices/camera/hikvision/snmp/plugin.pm000066400000000000000000000027411417000230700265230ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::camera::hikvision::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}} = ( 'cpu' => 'hardware::devices::camera::hikvision::snmp::mode::cpu', 'disk' => 'hardware::devices::camera::hikvision::snmp::mode::disk', 'memory' => 'hardware::devices::camera::hikvision::snmp::mode::memory', 'time' => 'hardware::devices::camera::hikvision::snmp::mode::time' ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Hikvision camera in SNMP. =cut centreon-plugins-20220113/hardware/devices/camera/mobotix/000077500000000000000000000000001417000230700233645ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/camera/mobotix/snmp/000077500000000000000000000000001417000230700243415ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/camera/mobotix/snmp/mode/000077500000000000000000000000001417000230700252655ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/camera/mobotix/snmp/mode/system.pm000066400000000000000000000126671417000230700271630ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::camera::mobotix::snmp::mode::system; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'system', type => 0, message_separator => ' - ', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{system} = [ { label => 'sdcard-usage', nlabel => 'system.sdcard.usage.percent', set => { key_values => [ { name => 'storageArchiveBufferFillLevel', no_value => -1 } ], output_template => 'sd card usage: %.2f %%', perfdatas => [ { value => 'storageArchiveBufferFillLevel', template => '%d', min => 0, max => 100, unit => '%' }, ], } }, { label => 'temperature-internal', nlabel => 'system.temperature.internal.celsius', set => { key_values => [ { name => 'statusTemperatureCameraC', no_value => -1000 } ], output_template => 'internal temperature: %s C', perfdatas => [ { value => 'statusTemperatureCameraC', template => '%s', unit => 'C' }, ], } }, { label => 'temperature-external', nlabel => 'system.temperature.external.celsius', set => { key_values => [ { name => 'statusTemperatureOutsideC', no_value => -1000 } ], output_template => 'external temperature: %s C', perfdatas => [ { value => 'statusTemperatureOutsideC', template => '%s', unit => 'C' }, ], } }, { label => 'temperature-gps', nlabel => 'system.temperature.gps.celsius', set => { key_values => [ { name => 'statusTemperatureGpsC', no_value => -1000 } ], output_template => 'gps temperature: %s C', perfdatas => [ { value => 'statusTemperatureGpsC', template => '%s', unit => 'C' }, ], } }, { label => 'illumination-right', nlabel => 'system.illumination.right.lux', set => { key_values => [ { name => 'statusSensorIlluminationR', no_value => -1000 } ], output_template => 'illumination right: %s lx', perfdatas => [ { value => 'statusSensorIlluminationR', template => '%s', unit => 'lx' }, ], } }, { label => 'illumination-left', nlabel => 'system.illumination.left.lux', set => { key_values => [ { name => 'statusSensorIlluminationL', no_value => -1000 } ], output_template => 'illumination left: %s lx', perfdatas => [ { value => 'statusSensorIlluminationL', template => '%s', unit => 'lx' }, ], } }, { label => 'video-framerate', nlabel => 'system.video.framerate.persecond', set => { key_values => [ { name => 'videoMainCurrentFrameRate', no_value => -1000 } ], output_template => 'video framerate: %s fps', perfdatas => [ { value => 'videoMainCurrentFrameRate', template => '%s', unit => 'fps' }, ], } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $mapping = { storageArchiveBufferFillLevel => { oid => '.1.3.6.1.4.1.21701.2.3.8' }, statusTemperatureCameraC => { oid => '.1.3.6.1.4.1.21701.2.7.2.1.1' }, statusTemperatureOutsideC => { oid => '.1.3.6.1.4.1.21701.2.7.2.2.1' }, statusTemperatureGpsC => { oid => '.1.3.6.1.4.1.21701.2.7.2.4.1' }, statusSensorIlluminationR => { oid => '.1.3.6.1.4.1.21701.2.7.3.1' }, statusSensorIlluminationL => { oid => '.1.3.6.1.4.1.21701.2.7.3.2' }, videoMainCurrentFrameRate => { oid => '.1.3.6.1.4.1.21701.2.7.5.1.2' } }; my $snmp_result = $options{snmp}->get_leef( oids => [ map($_->{oid} . '.0', values(%$mapping)) ], nothing_quit => 1 ); $self->{system} = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => '0'); } 1; __END__ =head1 MODE Check system. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'sdcard-usage', 'temperature-internal', 'temperature-external', 'temperature-gps', 'illumination-right', 'illumination-left', 'video-framerate'. =back =cut centreon-plugins-20220113/hardware/devices/camera/mobotix/snmp/plugin.pm000066400000000000000000000026001417000230700261730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::camera::mobotix::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}} = ( 'list-interfaces' => 'snmp_standard::mode::listinterfaces', 'interfaces' => 'snmp_standard::mode::interfaces', 'system' => 'hardware::devices::camera::mobotix::snmp::mode::system', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Mobotix camera in SNMP. =cut centreon-plugins-20220113/hardware/devices/cisco/000077500000000000000000000000001417000230700215535ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/cisco/ces/000077500000000000000000000000001417000230700223255ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/cisco/ces/restapi/000077500000000000000000000000001417000230700237745ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/cisco/ces/restapi/custom/000077500000000000000000000000001417000230700253065ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/cisco/ces/restapi/custom/api.pm000066400000000000000000000204141417000230700264160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::cisco::ces::restapi::custom::api; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::http; use centreon::plugins::statefile; use XML::LibXML::Simple; use Digest::MD5 qw(md5_hex); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port'}, 'proto:s' => { name => 'proto' }, 'api-username:s' => { name => 'api_username' }, 'api-password:s' => { name => 'api_password' }, 'timeout:s' => { name => 'timeout', default => 30 }, 'no-session' => { name => 'no_session' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); $self->{cache} = centreon::plugins::statefile->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 30; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : ''; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : ''; $self->{no_session} = (defined($self->{option_results}->{no_session})) ? 1 : 0; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } if ($self->{api_username} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-username option."); $self->{output}->option_exit(); } if ($self->{api_password} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-password option."); $self->{output}->option_exit(); } $self->{cache}->check_options(option_results => $self->{option_results}) if ($self->{no_session} == 0); return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; if ($self->{no_session} == 1) { $self->{option_results}->{credentials} = 1; $self->{option_results}->{basic} = 1; $self->{option_results}->{username} = $self->{api_username}; $self->{option_results}->{password} = $self->{api_password}; } } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Content-Type', value => 'text/xml'); $self->{http}->add_header(key => 'Accept', value => 'text/xml'); $self->{http}->set_options(%{$self->{option_results}}); } sub clean_session_cookie { my ($self, %options) = @_; my $datas = { last_timestamp => time() }; $options{statefile}->write(data => $datas); $self->{session_cookie} = undef; $self->{http}->add_header(key => 'Cookie', value => undef); } sub authenticate { my ($self, %options) = @_; my $has_cache_file = $options{statefile}->read(statefile => 'cces_api_' . md5_hex($self->{option_results}->{hostname}) . '_' . md5_hex($self->{option_results}->{api_username})); my $session_cookie = $options{statefile}->get(name => 'session_cookie'); if ($has_cache_file == 0 || !defined($session_cookie)) { my $content = $self->{http}->request( method => 'POST', url_path => '/xmlapi/session/begin', credentials => 1, basic => 1, username => $self->{api_username}, password => $self->{api_password}, warning_status => '', unknown_status => '', critical_status => '', curl_backend_options => { header => ['Content-Length: 0'] }, ); if ($self->{http}->get_code() < 200 || $self->{http}->get_code() >= 300) { $self->{output}->add_option_msg(short_msg => "Login error [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } ($session_cookie) = $self->{http}->get_header(name => 'Set-Cookie'); if (!defined($session_cookie)) { $self->{output}->add_option_msg(short_msg => "Error retrieving cookie"); $self->{output}->option_exit(); } my $datas = { last_timestamp => time(), session_cookie => $session_cookie }; $options{statefile}->write(data => $datas); } $self->{session_cookie} = $session_cookie; $self->{http}->add_header(key => 'Cookie', value => $self->{session_cookie}); } sub request_api { my ($self, %options) = @_; $self->settings(); if ($self->{no_session} == 0 && !defined($self->{session_cookie})) { $self->authenticate(statefile => $self->{cache}); } my $content = $self->{http}->request( %options, warning_status => '', unknown_status => '', critical_status => '' ); # Maybe there is an issue with the session_cookie. So we retry. if ($self->{no_session} == 0 && ($self->{http}->get_code() < 200 || $self->{http}->get_code() >= 300)) { $self->clean_session_cookie(statefile => $self->{cache}); $self->authenticate(statefile => $self->{cache}); $content = $self->{http}->request( %options, warning_status => '', unknown_status => '', critical_status => '' ); } if ($self->{http}->get_code() < 200 || $self->{http}->get_code() >= 300) { $self->{output}->add_option_msg(short_msg => 'api request error. use --debug.'); $self->{output}->option_exit(); } my $result; eval { $SIG{__WARN__} = sub {}; $result = XMLin($content, ForceArray => $options{ForceArray}, KeyAttr => []); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode xml response: $@"); $self->{output}->option_exit(); } return $result; } 1; __END__ =head1 NAME CCES Rest API =head1 REST API OPTIONS =over 8 =item B<--hostname> Set hostname. =item B<--port> Set port (Default: '443'). =item B<--proto> Specify https if needed (Default: 'https'). =item B<--api-username> Set username. =item B<--api-password> Set password. =item B<--timeout> Threshold for HTTP timeout (Default: '30'). =item B<--no-session> To be used for legacy version (before CE 8.0). =back =cut centreon-plugins-20220113/hardware/devices/cisco/ces/restapi/mode/000077500000000000000000000000001417000230700247205ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/cisco/ces/restapi/mode/callsrt.pm000066400000000000000000000222611417000230700267250ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::cisco::ces::restapi::mode::callsrt; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); sub custom_traffic_calc { my ($self, %options) = @_; if (!defined($options{delta_time})) { $self->{error_msg} = 'Buffer creation'; return -1; } my $total_bytes = 0; foreach (keys %{$options{new_datas}}) { if (/\Q$self->{instance}\E_.*_bytes/) { my $new_bytes = $options{new_datas}->{$_}; next if (!defined($options{old_datas}->{$_})); my $old_bytes = $options{old_datas}->{$_}; my $bytes = $new_bytes - $old_bytes; $bytes = $new_bytes if ($bytes < 0); $total_bytes += $bytes; } } $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{traffic_per_seconds} = ($total_bytes * 8) / $options{delta_time}; return 0; } sub custom_jitter_calc { my ($self, %options) = @_; my $max_jitter = 0; foreach (keys %{$options{new_datas}}) { if (/\Q$self->{instance}\E_.*_maxjitter/) { $max_jitter = $options{new_datas}->{$_} if ($options{new_datas}->{$_} > $max_jitter); } } $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{max_jitter} = $max_jitter; return 0; } sub custom_loss_calc { my ($self, %options) = @_; my ($total_loss, $total_pkts) = (0, 0); foreach (keys %{$options{new_datas}}) { if (/\Q$self->{instance}\E_.*_loss/) { my $new_loss = $options{new_datas}->{$_}; next if (!defined($options{old_datas}->{$_})); my $old_loss = $options{old_datas}->{$_}; my $loss = $new_loss - $old_loss; $loss = $new_loss if ($loss < 0); $total_loss += $loss; } elsif (/\Q$self->{instance}\E_.*_packets/) { my $new_pkts = $options{new_datas}->{$_}; next if (!defined($options{old_datas}->{$_})); my $old_pkts = $options{old_datas}->{$_}; my $pkts = $new_pkts - $old_pkts; $pkts = $new_pkts if ($pkts < 0); $total_pkts += $pkts; } } $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{packets_loss} = $total_loss; $self->{result_values}->{packets_loss_prct} = 0; $self->{result_values}->{packets} = $total_pkts; if ($total_pkts > 0) { $self->{result_values}->{packets_loss_prct} = ($total_loss * 100) / $total_pkts; } return 0; } sub custom_loss_output { my ($self, %options) = @_; return sprintf( "packets loss: %.2f%% (%s on %s)", $self->{result_values}->{packets_loss_prct}, $self->{result_values}->{packets_loss}, $self->{result_values}->{packets} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'channels', type => 1, cb_prefix_output => 'prefix_channels_output', message_multiple => 'All call channels are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{channels} = [ { label => 'channels-traffic', nlabel => 'call.channels.traffic.bytes', set => { key_values => [], manual_keys => 1, closure_custom_calc => $self->can('custom_traffic_calc'), output_template => 'traffic: %s %s/s', output_change_bytes => 1, output_use => 'traffic_per_seconds', threshold_use => 'traffic_per_seconds', perfdatas => [ { value => 'traffic_per_seconds', template => '%d', unit => 'B/s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'channels-maxjitter', nlabel => 'call.channels.maxjitter.milliseconds', set => { key_values => [], manual_keys => 1, closure_custom_calc => $self->can('custom_jitter_calc'), output_template => 'max jitter: %s ms', output_use => 'max_jitter', threshold_use => 'max_jitter', perfdatas => [ { value => 'max_jitter', template => '%d', unit => 'ms', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'channels-packetloss', nlabel => 'call.channels.packetloss.count', set => { key_values => [], manual_keys => 1, closure_custom_calc => $self->can('custom_loss_calc'), closure_custom_output => $self->can('custom_loss_output'), threshold_use => 'packets_loss', perfdatas => [ { value => 'packets_loss', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'channels-packetloss-prct', nlabel => 'call.channels.packetloss.percentage', display_ok => 0, set => { key_values => [], manual_keys => 1, closure_custom_calc => $self->can('custom_loss_calc'), closure_custom_output => $self->can('custom_loss_output'), threshold_use => 'packets_loss_prct', perfdatas => [ { value => 'packets_loss_prct', template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub prefix_channels_output { my ($self, %options) = @_; return "Channel '" . $options{instance_value}->{display} ."' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1, statefile => 1); bless $self, $class; $self->{version} = '1.0'; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = 'cces_' . $options{custom}->{hostname} . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); my $result = $options{custom}->request_api(url_path => '/status.xml', ForceArray => ['Call']); foreach (('data~incoming', 'video~incoming~main', 'video~outgoing~main', 'video~outgoing~presentation', 'video~incoming~presentation', 'audio~incoming~main', 'audio~outgoing~main')) { $self->{channels}->{$_} = { display => $_ }; } if (!defined($result->{version}) || $result->{version} !~ /^(?:CE|TC)(\d+\.\d+)/i) { $self->{output}->add_option_msg(short_msg => 'cannot find firmware version'); $self->{output}->option_exit(); } my ($version_major, $version_minor) = split(/\./, $1); if (($version_major < 8) || ($version_major == 8 && $version_minor < 3)) { $self->{output}->add_option_msg(short_msg => 'firmware version is too old (' . $version_major . '.' . $version_minor . ')'); $self->{output}->option_exit(); } return if (!defined($result->{MediaChannels}->{Call})); foreach my $call (@{$result->{MediaChannels}->{Call}}) { foreach (@{$call->{Channel}}) { my $instance = lc($_->{Type}) . '~' . lc($_->{Direction}); $instance .= '~' . lc($_->{Audio}->{ChannelRole}) if (defined($_->{Audio})); $instance .= '~' . lc($_->{Video}->{ChannelRole}) if (defined($_->{Video})); $self->{channels}->{$instance}->{$_->{item} . '_bytes'} = defined($_->{Netstat}->{Bytes}) ? $_->{Netstat}->{Bytes} : 0; $self->{channels}->{$instance}->{$_->{item} . '_maxjitter'} = $_->{Netstat}->{MaxJitter} if (defined($_->{Netstat}->{MaxJitter})); $self->{channels}->{$instance}->{$_->{item} . '_loss'} = defined($_->{Netstat}->{Loss}) ? $_->{Netstat}->{Loss} : 0; $self->{channels}->{$instance}->{$_->{item} . '_packets'} = defined($_->{Netstat}->{Packets}) ? $_->{Netstat}->{Packets} : 0; } } } 1; __END__ =head1 MODE Check call channels in real-time (since CE 8.3) =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'channels-traffic', 'channels-maxjitter' 'channels-packetloss', 'channels-packetloss-prct'. =back =cut centreon-plugins-20220113/hardware/devices/cisco/ces/restapi/mode/callssummary.pm000066400000000000000000000217551417000230700300040ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::cisco::ces::restapi::mode::callssummary; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::statefile; use Digest::MD5 qw(md5_hex); sub custom_loss_output { my ($self, %options) = @_; return sprintf( "packets loss: %.2f%% (%s on %s)", $self->{result_values}->{loss_prct}, $self->{result_values}->{loss}, $self->{result_values}->{pkts} ); } sub prefix_global_output { my ($self, %options) = @_; return $options{instance_value}->{label} . ' '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'global_roomanalytics', type => 0, skipped_code => { -10 => 1 } }, { name => 'global_video_incoming', cb_prefix_output => 'prefix_global_output', type => 0, skipped_code => { -10 => 1 } }, { name => 'global_video_outgoing', cb_prefix_output => 'prefix_global_output', type => 0, skipped_code => { -10 => 1 } }, { name => 'global_audio_incoming', cb_prefix_output => 'prefix_global_output', type => 0, skipped_code => { -10 => 1 } }, { name => 'global_audio_outgoing', cb_prefix_output => 'prefix_global_output', type => 0, skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'total-finished', nlabel => 'calls.total.finished.count', set => { key_values => [ { name => 'new_calls' } ], output_template => 'total calls finished: %d', perfdatas => [ { template => '%d', min => 0 } ] } } ]; $self->{maps_counters}->{'global_roomanalytics'} = [ { label => 'peoplecount', nlabel => 'calls.roomanalytics.people.count', set => { key_values => [ { name => 'peoplecount' } ], output_template => 'people count: %s', perfdatas => [ { template => '%d', min => 0 } ] } } ]; foreach my $type (('video', 'audio')) { foreach my $direction (('incoming', 'outgoing')) { $self->{maps_counters}->{'global_' . $type . '_' . $direction} = [ { label => 'packetloss', nlabel => 'calls.' . $type . '.' . $direction . '.packetloss.count', set => { key_values => [ { name => 'loss' }, { name => 'pkts' }, { name => 'loss_prct' } ], closure_custom_output => $self->can('custom_loss_output'), perfdatas => [ { template => '%d', min => 0 } ] } }, { label => 'packetloss-prct', nlabel => 'calls.' . $type . '.' . $direction . '.packetloss.percentage', display_ok => 0, set => { key_values => [ { name => 'loss_prct' }, { name => 'loss' }, { name => 'pkts' } ], closure_custom_output => $self->can('custom_loss_output'), perfdatas => [ { template => '%d', unit => '%', min => 0, max => 100 } ] } }, { label => 'maxjitter', nlabel => 'calls.' . $type . '.' . $direction . '.maxjitter.count', set => { key_values => [ { name => 'maxjitter' } ], output_template => 'max jitter: %s ms', perfdatas => [ { template => '%d', unit => 'ms', min => 0 } ] } } ]; } } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $self->{version} = '1.0'; $options{options}->add_options(arguments => { }); centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'Date::Parse', error_msg => "Cannot load module 'Date::Parse'." ); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{statefile_cache}->check_options(%options); } sub manage_selection { my ($self, %options) = @_; $self->{statefile_cache}->read( statefile => 'cces_' . $options{custom}->{hostname} . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) ); my $last_call_endtime = $self->{statefile_cache}->get(name => 'last_call_endtime'); $last_call_endtime = 0 if (!defined($last_call_endtime)); my $result = $options{custom}->request_api( method => 'POST', url_path => '/putxml', query_form_post => 'Full', ForceArray => ['Entry'] ); $self->{global} = { new_calls => 0 }; $self->{global_video_incoming} = { loss => 0, pkts => 0, loss_prct => 0, maxjitter => 0, label => 'video incoming' }; $self->{global_video_outgoing} = { loss => 0, pkts => 0, loss_prct => 0, maxjitter => 0, label => 'video outgoing' }; $self->{global_audio_incoming} = { loss => 0, pkts => 0, loss_prct => 0, maxjitter => 0, label => 'audio incoming' }; $self->{global_audio_outgoing} = { loss => 0, pkts => 0, loss_prct => 0, maxjitter => 0, label => 'audio outgoing' }; $self->{global_roomanalytics} = {}; return if (!defined($result->{CallHistoryGetResult}->{Entry})); my $save_last_time = 0; foreach (@{$result->{CallHistoryGetResult}->{Entry}}) { my $end_time_utc = ref($_->{EndTimeUTC}) eq 'HASH' ? $_->{EndTimeUTC}->{content} : $_->{EndTimeUTC}; my $end_time = Date::Parse::str2time($end_time_utc); if (!defined($end_time)) { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => "can't parse date '" . $end_time_utc . "'" ); next; } $save_last_time = $end_time if ($save_last_time < $end_time); next if ($end_time <= $last_call_endtime); $self->{global}->{new_calls}++; foreach my $type (('Video', 'Audio')) { foreach my $direction (('Incoming', 'Outgoing')) { my $max_jitter = ref($_->{$type}->{$direction}->{MaxJitter}) eq 'HASH' ? $_->{$type}->{$direction}->{MaxJitter}->{content} : $_->{$type}->{$direction}->{MaxJitter}; my $packet_loss = ref($_->{$type}->{$direction}->{PacketLoss}) eq 'HASH' ? $_->{$type}->{$direction}->{PacketLoss}->{content} : $_->{$type}->{$direction}->{PacketLoss}; $self->{'global_' . lc($type) . '_' . lc($direction)}->{maxjitter} = $max_jitter if ($self->{'global_' . lc($type) . '_' . lc($direction)}->{maxjitter} < $max_jitter); if ($packet_loss =~ /^(\d+)\/(\d+)/) { $self->{'global_' . lc($type) . '_' . lc($direction)}->{loss} += $1; $self->{'global_' . lc($type) . '_' . lc($direction)}->{pkts} += $2; } } } if (defined($_->{RoomAnalytics}->{PeopleCount})) { $self->{global_roomanalytics}->{peoplecount} = $_->{RoomAnalytics}->{PeopleCount}; if ($_->{RoomAnalytics}->{PeopleCount} =~ /^N\/A$/) { $self->{global_roomanalytics}->{peoplecount} = 0; } } } foreach my $type (('video', 'audio')) { foreach my $direction (('incoming', 'outgoing')) { $self->{'global_' . $type . '_' . $direction}->{loss_prct} = $self->{'global_' . $type . '_' . $direction}->{loss} * 100 / $self->{'global_' . $type . '_' . $direction}->{pkts} if ($self->{'global_' . $type . '_' . $direction}->{pkts} > 0); } } $self->{statefile_cache}->write(data => { last_call_endtime => $save_last_time }); } 1; __END__ =head1 MODE Check call history (since TC 6.3) =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'total-finished', 'packetloss' 'packetloss-prct', 'maxjitter'. =back =cut centreon-plugins-20220113/hardware/devices/cisco/ces/restapi/mode/certificates.pm000066400000000000000000000074461417000230700277360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::cisco::ces::restapi::mode::certificates; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; sub custom_validity_output { my ($self, %options) = @_; return sprintf( 'expires in %s', $self->{result_values}->{generation_time} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'certificates', type => 1, cb_prefix_output => 'prefix_certificate_output', message_multiple => 'All certificates are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{certificates} = [ { label => 'certificate-expire', nlabel => 'system.certificate.expire.seconds', set => { key_values => [ { name => 'validity_time' }, { name => 'generation_time' } ], closure_custom_output => $self->can('custom_validity_output'), perfdatas => [ { template => '%d', min => 0, unit => 's' } ] } } ]; } sub prefix_certificate_output { my ($self, %options) = @_; return "Certificate '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $self->{version} = '1.0'; $options{options}->add_options(arguments => { }); centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'Date::Parse', error_msg => "Cannot load module 'Date::Parse'." ); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->request_api( method => 'POST', url_path => '/putxml', query_form_post => '', ForceArray => ['Details'] ); $self->{certificates} = {}; if (defined($result->{ServicesShowResult}->{Details})) { foreach (@{$result->{ServicesShowResult}->{Details}}) { my $end_date = Date::Parse::str2time($_->{notAfter}); if (!defined($end_date)) { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => "can't parse date '" . $_->{notAfter} . "'" ); next; } $self->{certificates}->{$_->{item}} = { display => $_->{SubjectName}, validity_time => $end_date - time(), generation_time => centreon::plugins::misc::change_seconds(value => $end_date - time()) }; } } if (scalar(keys %{$self->{certificates}}) <= 0) { $self->{output}->add_option_msg(short_msg => 'No certificate found.'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check certificates validity (since CE 9.2) =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'certificate-expire'. =back =cut centreon-plugins-20220113/hardware/devices/cisco/ces/restapi/mode/components.pm000066400000000000000000000114271417000230700274500ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::cisco::ces::restapi::mode::components; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^(?:aiclatency|aocdelay)$'; $self->{cb_hook2} = 'execute_custom'; $self->{thresholds} = { connection_status => [ ['NotConnected', 'OK'], ['Connected', 'OK'], ['Unknown', 'UNKNOWN'] ], connected => [ ['True', 'OK'], ['False', 'WARNING'], ['Unknown', 'UNKNOWN'] ], temperature => [ ['n/a', 'OK'], ['Normal', 'OK'], ['.*', 'CRITICAL'] ], software_status => [ ['None', 'OK'], ['InProgress', 'OK'], ['InstallationFailed', 'CRITICAL'], ['Failed', 'CRITICAL'], ['Succeeded', 'OK'] ], software_urgency => [ ['n/a', 'OK'], ['Low', 'OK'], ['Medium', 'OK'], ['Critical', 'CRITICAL'] ], signal_state => [ ['OK', 'OK'], ['Unsupported', 'WARNING'], ['Unknown', 'UNKNOWN'] ], format_status => [ ['Ok', 'OK'], ['OutOfRange', 'WARNING'], ['NotFound', 'OK'], ['Error', 'CRITICAL'], ['Interlaced', 'OK'], ['Unknown', 'UNKNOWN'] ], webex => [ ['Disabled', 'OK'], ['Stopped', 'OK'], ['Error', 'CRITICAL'], ['Registered', 'OK'], ['Registering', 'OK'] ], st_status => [ ['Inactive', 'WARNING'], ['Active', 'OK'] ], st_availability => [ ['Unavailable', 'WARNING'], ['Available', 'OK'], ['Off', 'OK'] ] }; $self->{components_exec_load} = 0; $self->{components_path} = 'hardware::devices::cisco::ces::restapi::mode::components'; $self->{components_module} = [ 'ad', 'aic', 'aoc', 'camera', 'st', 'software', 'temperature', 'vic', 'vis', 'voc', 'webex' ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_absent => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub execute_custom { my ($self, %options) = @_; $self->{results} = $options{custom}->request_api( url_path => '/status.xml', ForceArray => ['Microphone', 'HDMI', 'Line', 'InternalSpeaker', 'Camera', 'Connector', 'Source'] ); my $system_version = 'unknown'; $system_version = $self->{results}->{version} if (defined($self->{results}->{version})); $self->{output}->output_add(long_msg => 'firmware version: ' . $system_version); } 1; =head1 MODE Check components. =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'ad' (audio device), 'aic' (audio input connectors), 'aoc' (audio output connectors), 'camera', 'st' (speakerTrack), 'software', 'temperature', 'vic' (video input connectors), 'vis' (video input source), 'voc', (video output connectors), 'webex'. =item B<--filter> Exclude some parts (comma seperated list) Can also exclude specific instance: --filter='aic,Microphone.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='ad.status,CRITICAL,NotConnected' =item B<--warning> Set warning threshold for 'temperature', 'fan', 'psu' (syntax: type,regexp,threshold) Example: --warning='aiclatency,.*,20' =item B<--critical> Set critical threshold for 'temperature', 'fan', 'psu' (syntax: type,regexp,threshold) Example: --critical='aiclatency,.*,50' =back =cut centreon-plugins-20220113/hardware/devices/cisco/ces/restapi/mode/components/000077500000000000000000000000001417000230700271055ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/cisco/ces/restapi/mode/components/ad.pm000066400000000000000000000044351417000230700300350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::cisco::ces::restapi::mode::components::ad; use strict; use warnings; sub check_ad { my ($self, %options) = @_; return if (!defined($options{entry})); my $instance = $options{instance}; next if ($self->check_filter(section => 'ad', instance => $instance)); $self->{components}->{ad}->{total}++; $self->{output}->output_add( long_msg => sprintf( "audio device '%s' connection status is '%s' [instance: %s]", $instance, $options{entry}->{ConnectionStatus}, $instance ) ); my $exit = $self->get_severity(label => 'connection_status', section => 'ad.status', value => $options{entry}->{ConnectionStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("audio device '%s' connection status is '%s'", $instance, $options{entry}->{ConnectionStatus}) ); } } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => 'checking audio devices'); $self->{components}->{ad} = { name => 'audio devices', total => 0, skip => 0 }; return if ($self->check_filter(section => 'ad')); # since CE 9.8 check_ad( $self, entry => $self->{results}->{Audio}->{Devices}->{HandsetUSB}, instance => 'handsetUSB' ); # since CE 9.8 check_ad( $self, entry => $self->{results}->{Audio}->{Devices}->{HeadsetUSB}, instance => 'headsetUSB' ); } 1; centreon-plugins-20220113/hardware/devices/cisco/ces/restapi/mode/components/aic.pm000066400000000000000000000100311417000230700301720ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::cisco::ces::restapi::mode::components::aic; use strict; use warnings; # # # 0 # # # 0 # # sub check_aic { my ($self, %options) = @_; foreach (@{$options{entry}->{ $options{element} }}) { my $instance = $options{element} . ':' . $_->{item}; my $ec_reference_delay = ref($_->{EcReferenceDelay}) eq 'HASH' ? $_->{EcReferenceDelay}->{content} : $_->{EcReferenceDelay}; next if (!defined($_->{ConnectionStatus}) && !defined($ec_reference_delay)); next if ($self->check_filter(section => 'aic', instance => $instance)); $self->{components}->{aic}->{total}++; $self->{output}->output_add( long_msg => sprintf( "audio input connector '%s' connection status is '%s' [instance: %s, latency: %s ms]", $instance, defined($_->{ConnectionStatus}) ? $_->{ConnectionStatus} : 'n/a', $instance, defined($ec_reference_delay) ? $ec_reference_delay : '-' ) ); if (defined($_->{ConnectionStatus})) { my $exit = $self->get_severity(label => 'connection_status', section => 'aic.status', value => $_->{ConnectionStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("audio input connector '%s' connection status is '%s'", $instance, $_->{ConnectionStatus}) ); } } if (defined($ec_reference_delay)) { my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'aiclatency', instance => $instance, value => $ec_reference_delay); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "audio input connector '%s' latency is %s ms", $instance, $ec_reference_delay ) ); } $self->{output}->perfdata_add( unit => 'ms', nlabel => 'component.audio.input.connector.latency.milliseconds', instances => [$options{element}, $_->{item}], value => $ec_reference_delay, warning => $warn, critical => $crit ); } } } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => 'checking audio input connectors'); $self->{components}->{aic} = { name => 'audio input connectors', total => 0, skip => 0 }; return if ($self->check_filter(section => 'aic')); check_aic( $self, entry => $self->{results}->{Audio}->{Input}->{Connectors}, element => 'Microphone', instance => 'item' ); check_aic( $self, entry => $self->{results}->{Audio}->{Input}->{Connectors}, element => 'HDMI', instance => 'item' ); } 1; centreon-plugins-20220113/hardware/devices/cisco/ces/restapi/mode/components/aoc.pm000066400000000000000000000075341417000230700302160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::cisco::ces::restapi::mode::components::aoc; use strict; use warnings; sub check_aoc { my ($self, %options) = @_; foreach (@{$options{entry}->{ $options{element} }}) { my $instance = $options{element} . ':' . $_->{item}; next if (!defined($_->{ConnectionStatus}) && !defined($_->{DelayMs})); next if ($self->check_filter(section => 'aoc', instance => $instance)); $self->{components}->{aoc}->{total}++; $self->{output}->output_add( long_msg => sprintf( "audio output connector '%s' connection status is '%s' [instance: %s, delay: %s ms]", $instance, defined($_->{ConnectionStatus}) ? $_->{ConnectionStatus} : 'n/a', $instance, defined($_->{DelayMs}) ? $_->{DelayMs} : '-' ) ); if (defined($_->{ConnectionStatus})) { my $exit = $self->get_severity(label => 'connection_status', section => 'aoc.status', value => $_->{ConnectionStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("audio output connector '%s' connection status is '%s'", $instance, $_->{ConnectionStatus}) ); } } if (defined($_->{DelayMs})) { my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'aocdelay', instance => $instance, value => $_->{DelayMs}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "audio output connector '%s' delay is %s ms", $instance, $_->{EcReferenceDelay} ) ); } $self->{output}->perfdata_add( unit => 'ms', nlabel => 'component.audio.output.connector.delay.milliseconds', instances => [$options{element}, $_->{item}], value => $_->{DelayMs}, warning => $warn, critical => $crit, ); } } } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => 'checking audio output connectors'); $self->{components}->{aoc} = { name => 'audio output connectors', total => 0, skip => 0 }; return if ($self->check_filter(section => 'aoc')); # since CE 9.4 check_aoc( $self, entry => $self->{results}->{Audio}->{Output}->{Connectors}, element => 'HDMI', instance => 'item' ); # since CE 9.4 check_aoc( $self, entry => $self->{results}->{Audio}->{Output}->{Connectors}, element => 'InternalSpeaker', instance => 'item' ); # since CE 8.1 check_aoc( $self, entry => $self->{results}->{Audio}->{Output}->{Connectors}, element => 'Line', instance => 'item' ); } 1; centreon-plugins-20220113/hardware/devices/cisco/ces/restapi/mode/components/camera.pm000066400000000000000000000045451417000230700307030ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::cisco::ces::restapi::mode::components::camera; use strict; use warnings; # # # ptzf # # True # ... # # sub check { my ($self) = @_; $self->{output}->output_add(long_msg => 'checking cameras'); $self->{components}->{camera} = { name => 'cameras', total => 0, skip => 0 }; return if ($self->check_filter(section => 'camera')); my $cameras = defined($self->{results}->{Cameras}->{Camera}) ? $self->{results}->{Cameras}->{Camera} : $self->{results}->{Camera}; return if (!$cameras); foreach (@$cameras) { my $instance = $_->{item}; next if ($self->check_filter(section => 'camera', instance => $instance)); $self->{components}->{camera}->{total}++; my $connected = ref($_->{Connected}) eq 'HASH' ? $_->{Connected}->{content} : $_->{Connected}; $self->{output}->output_add( long_msg => sprintf( "camera '%s' connection status is '%s' [instance: %s]", $instance, $connected, $instance ) ); my $exit = $self->get_severity(label => 'connected', section => 'camera.status', value => $connected); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("camera '%s' connection status is '%s'", $instance, $connected) ); } } } 1; centreon-plugins-20220113/hardware/devices/cisco/ces/restapi/mode/components/software.pm000066400000000000000000000055111417000230700312770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::cisco::ces::restapi::mode::components::software; use strict; use warnings; sub check { my ($self) = @_; $self->{output}->output_add(long_msg => 'checking software'); $self->{components}->{software} = { name => 'software', total => 0, skip => 0 } ; return if ($self->check_filter(section => 'software')); return if (!defined($self->{results}->{Provisioning}->{Software}->{UpgradeStatus})); my $instance = 'upgrade'; return if ($self->check_filter(section => 'software', instance => $instance)); $self->{components}->{software}->{total}++; my $status = ref($self->{results}->{Provisioning}->{Software}->{UpgradeStatus}->{Status}) eq 'HASH' ? $self->{results}->{Provisioning}->{Software}->{UpgradeStatus}->{Status}->{content} : $self->{results}->{Provisioning}->{Software}->{UpgradeStatus}->{Status}; my $urgency = ref($self->{results}->{Provisioning}->{Software}->{UpgradeStatus}->{Urgency}) eq 'HASH' ? $self->{results}->{Provisioning}->{Software}->{UpgradeStatus}->{Urgency}->{content} : $self->{results}->{Provisioning}->{Software}->{UpgradeStatus}->{Urgency}; $urgency = 'n/a' if (!defined($urgency)); $self->{output}->output_add( long_msg => sprintf( "software '%s' status is '%s' [instance: %s, urgency: %s]", $instance, $status, $instance, $urgency ) ); my $exit = $self->get_severity(section => 'software_status', value => $status); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("software '%s' status is '%s'", $instance, $status) ); } $exit = $self->get_severity(section => 'software_urgency', value => $urgency); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("software '%s' urgency is '%s'", $instance, $urgency) ); } } 1; centreon-plugins-20220113/hardware/devices/cisco/ces/restapi/mode/components/st.pm000066400000000000000000000047751417000230700301060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::cisco::ces::restapi::mode::components::st; use strict; use warnings; sub check { my ($self) = @_; $self->{output}->output_add(long_msg => 'checking speaker track'); $self->{components}->{st} = { name => 'speaker track', total => 0, skip => 0 } ; return if ($self->check_filter(section => 'st')); return if (!defined($self->{results}->{Cameras}->{SpeakerTrack})); my $instance = 1; return if ($self->check_filter(section => 'st', instance => $instance)); $self->{components}->{st}->{total}++; $self->{output}->output_add( long_msg => sprintf( "speaker track '%s' status is '%s' [instance: %s, availability: %s]", $instance, $self->{results}->{Cameras}->{SpeakerTrack}->{Status}, $instance, $self->{results}->{Cameras}->{SpeakerTrack}->{Availability} ) ); my $exit = $self->get_severity(section => 'st_status', value => $self->{results}->{Cameras}->{SpeakerTrack}->{Status}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("speaker track '%s' status is '%s'", $instance, $self->{results}->{Cameras}->{SpeakerTrack}->{Status}) ); } $exit = $self->get_severity(section => 'st_availability', value => $self->{results}->{Cameras}->{SpeakerTrack}->{Availability}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("speaker track '%s' availability is '%s'", $instance, $self->{results}->{Cameras}->{SpeakerTrack}->{Availability}) ); } } 1; centreon-plugins-20220113/hardware/devices/cisco/ces/restapi/mode/components/temperature.pm000066400000000000000000000057551417000230700320140ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::cisco::ces::restapi::mode::components::temperature; use strict; use warnings; sub check { my ($self) = @_; $self->{output}->output_add(long_msg => 'checking temperature'); $self->{components}->{temperature} = { name => 'temperature', total => 0, skip => 0 } ; return if ($self->check_filter(section => 'temperature')); my $temp_status = $self->{results}->{SystemUnit}->{Hardware}->{Monitoring}->{Temperature}->{Status}; $temp_status = 'n/a' if (!defined($temp_status)); my $temp_value = ref($self->{results}->{SystemUnit}->{Hardware}->{Temperature}) eq 'HASH' ? $self->{results}->{SystemUnit}->{Hardware}->{Temperature}->{content} : undef; return if (!defined($temp_status) && !defined($temp_value)); my $instance = 1; return if ($self->check_filter(section => 'temperature', instance => $instance)); $self->{components}->{temperature}->{total}++; $self->{output}->output_add( long_msg => sprintf( "temperature '%s' status is '%s' [instance: %s, value: %s]", $instance, $temp_status, $instance, defined($temp_value) ? $temp_value : '-' ) ); my $exit = $self->get_severity(section => 'temperature', value => $temp_status); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("temperature '%s' status is '%s'", $instance, $temp_status) ); } return if (!defined($temp_value)); my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $instance, value => $temp_value); if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "temperature '%s' is %s C", $instance, $temp_value ) ); } $self->{output}->perfdata_add( unit => 'C', nlabel => 'component.hardware.temperature.celsius', instances => 'system', value => $temp_value, warning => $warn, critical => $crit ); } 1; centreon-plugins-20220113/hardware/devices/cisco/ces/restapi/mode/components/vic.pm000066400000000000000000000051211417000230700302230ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::cisco::ces::restapi::mode::components::vic; use strict; use warnings; sub check { my ($self) = @_; $self->{output}->output_add(long_msg => 'checking video input connectors'); $self->{components}->{vic} = { name => 'video input connectors', total => 0, skip => 0 }; return if ($self->check_filter(section => 'vic')); return if (!defined($self->{results}->{Video}->{Input}->{Connector})); foreach (@{$self->{results}->{Video}->{Input}->{Connector}}) { my $instance = $_->{Type} . ':' . $_->{item}; next if ($self->check_filter(section => 'vic', instance => $instance)); $self->{components}->{vic}->{total}++; $self->{output}->output_add( long_msg => sprintf( "video input connector '%s' connection status is '%s' [instance: %s, signal state: %s]", $instance, $_->{Connected}, $instance, $_->{SignalState} ) ); my $exit = $self->get_severity(label => 'connected', section => 'vic.status', value => $_->{Connected}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("video input connector '%s' connection status is '%s'", $instance, $_->{Connected}) ); } $exit = $self->get_severity(label => 'signal_state', section => 'vic.signal_state', value => $_->{SignalState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("video input connector '%s' signal state is '%s'", $instance, $_->{SignalState}) ); } } } 1; centreon-plugins-20220113/hardware/devices/cisco/ces/restapi/mode/components/vis.pm000066400000000000000000000044001417000230700302420ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::cisco::ces::restapi::mode::components::vis; use strict; use warnings; sub check { my ($self) = @_; $self->{output}->output_add(long_msg => 'checking video input sources'); $self->{components}->{vis} = { name => 'video input sources', total => 0, skip => 0 }; return if ($self->check_filter(section => 'vis')); return if (!defined($self->{results}->{Video}->{Input}->{Source})); foreach (@{$self->{results}->{Video}->{Input}->{Source}}) { my $instance = $_->{item}; next if ($self->check_filter(section => 'vis', instance => $instance)); $self->{components}->{vis}->{total}++; my $format_status = defined($_->{Resolution}->{FormatStatus}) && ref($_->{Resolution}->{FormatStatus}) eq 'HASH' ? $_->{Resolution}->{FormatStatus}->{content} : $_->{FormatStatus}; $self->{output}->output_add( long_msg => sprintf( "video input source '%s' format status is '%s' [instance: %s]", $instance, $format_status, $instance ) ); my $exit = $self->get_severity(section => 'format_status', value => $format_status); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("video input source '%s' format status is '%s'", $instance, $format_status) ); } } } 1; centreon-plugins-20220113/hardware/devices/cisco/ces/restapi/mode/components/voc.pm000066400000000000000000000041621417000230700302350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::cisco::ces::restapi::mode::components::voc; use strict; use warnings; sub check { my ($self) = @_; $self->{output}->output_add(long_msg => 'checking video output connectors'); $self->{components}->{voc} = { name => 'video output connectors', total => 0, skip => 0 }; return if ($self->check_filter(section => 'voc')); return if (!defined($self->{results}->{Video}->{Output}->{Connector})); foreach (@{$self->{results}->{Video}->{Output}->{Connector}}) { my $instance = $_->{Type} . ':' . $_->{item}; next if ($self->check_filter(section => 'voc', instance => $instance)); $self->{components}->{vic}->{total}++; $self->{output}->output_add( long_msg => sprintf( "video output connector '%s' connection status is '%s' [instance: %s]", $instance, $_->{Connected}, $instance ) ); my $exit = $self->get_severity(label => 'connected', section => 'voc.status', value => $_->{Connected}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("video output connector '%s' connection status is '%s'", $instance, $_->{Connected}) ); } } } 1; centreon-plugins-20220113/hardware/devices/cisco/ces/restapi/mode/components/webex.pm000066400000000000000000000035771417000230700305710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::cisco::ces::restapi::mode::components::webex; use strict; use warnings; sub check { my ($self) = @_; $self->{output}->output_add(long_msg => 'checking webex'); $self->{components}->{webex} = { name => 'webex', total => 0, skip => 0 } ; return if ($self->check_filter(section => 'webex')); return if (!defined($self->{results}->{Webex})); my $instance = 1; return if ($self->check_filter(section => 'webex', instance => $instance)); $self->{components}->{webex}->{total}++; $self->{output}->output_add( long_msg => sprintf( "webex '%s' status is '%s' [instance: %s]", $instance, $self->{results}->{Webex}->{Status}, $instance ) ); my $exit = $self->get_severity(section => 'webex', value => $self->{results}->{Webex}->{Status}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("webex '%s' status is '%s'", $instance, $self->{results}->{Webex}->{Status}) ); } } 1; centreon-plugins-20220113/hardware/devices/cisco/ces/restapi/mode/diagnostics.pm000066400000000000000000000121531417000230700275670ustar00rootroot00000000000000# # Copyright 2018 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::devices::cisco::ces::restapi::mode::diagnostics; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use POSIX; use centreon::plugins::misc; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; return sprintf( 'alarm [level: %s] [type: %s] [description: %s]', $self->{result_values}->{level}, $self->{result_values}->{type}, $self->{result_values}->{description} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'alarms', type => 2, message_multiple => '0 problem(s) detected', display_counter_problem => { label => 'alerts', min => 0 }, group => [ { name => 'alarm', skipped_code => { -11 => 1 } } ] } ]; $self->{maps_counters}->{alarm} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'description' }, { name => 'level' }, { name => 'type' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-msg:s' => { name => 'filter_msg' }, 'legacy-tc' => { name => 'legacy_tc' }, 'warning-status:s' => { name => 'warning_status', default => '%{level} =~ /warning|minor/i' }, 'critical-status:s' => { name => 'critical_status', default => '%{level} =~ /critical|major/i' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } # # # # System is in standby mode. # Skipped # # SelectedVideoInputSourceConnected # # # sub manage_selection { my ($self, %options) = @_; my $post = 'Alerts'; my $label = 'DiagnosticsRunResult'; if (defined($self->{option_results}->{legacy_tc})) { $post = 'Alerts'; $label = 'DiagnosticsResult'; } my $result = $options{custom}->request_api( method => 'POST', url_path => '/putxml', query_form_post => $post, ForceArray => ['Message'] ); $self->{alarms}->{global} = { alarm => {} }; foreach (@{$result->{$label}->{Message}}) { my $description = ref($_->{Description}) eq 'HASH' ? $_->{Description}->{content} : $_->{Description}; my $level = ref($_->{Level}) eq 'HASH' ? $_->{Level}->{content} : $_->{Level}; my $type = ref($_->{Type}) eq 'HASH' ? $_->{Type}->{content} : $_->{Type}; if (defined($self->{option_results}->{filter_msg}) && $self->{option_results}->{filter_msg} ne '' && $description !~ /$self->{option_results}->{filter_msg}/) { $self->{output}->output_add(long_msg => "skipping '" . $description . "': no matching filter.", debug => 1); next; } $self->{alarms}->{global}->{alarm}->{ $_->{item} } = { description => $description, level => $level, type => $type }; } } 1; __END__ =head1 MODE Check diagnostic messages. Since TC 6.0: SystemUnit Diagnostics Run (use --legacy-tc option) Since CE 8.0: Diagnostics Run =over 8 =item B<--filter-msg> Filter by message (can be a regexp). =item B<--legacy-tc> Use old legacy command. =item B<--warning-status> Set warning threshold for status (Default: '%{level} =~ /warning|minor/i') Can used special variables like: %{description}, %{level}, %{type} =item B<--critical-status> Set critical threshold for status (Default: '%{level} =~ /critical|major/i'). Can used special variables like: %{description}, %{level}, %{type} =back =cut centreon-plugins-20220113/hardware/devices/cisco/ces/restapi/mode/peripherals.pm000066400000000000000000000070071417000230700276000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::cisco::ces::restapi::mode::peripherals; 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 } ]; $self->{maps_counters}->{global} = [ { label => 'peripherals-connected', nlabel => 'system.peripherals.connected.count', set => { key_values => [ { name => 'connected' } ], output_template => 'peripherals connected: %d', perfdatas => [ { template => '%d', min => 0 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $self->{version} = '1.0'; $options{options}->add_options(arguments => { 'filter-since:s' => { name => 'filter_since', default => 86400 } }); centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'Date::Parse', error_msg => "Cannot load module 'Date::Parse'." ); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->request_api( method => 'POST', url_path => '/putxml', query_form_post => '', ForceArray => ['Device'] ); $self->{global} = { connected => 0 }; return if (!defined($result->{PeripheralsListResult}->{Device})); foreach (@{$result->{PeripheralsListResult}->{Device}}) { if (defined($self->{option_results}->{filter_since}) && $self->{option_results}->{filter_since} =~ /\d+/) { my $last_seen = Date::Parse::str2time($_->{LastSeen}); if (!defined($last_seen)) { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => "can't parse date '" . $_->{LastSeen} . "'" ); next; } next if ($last_seen < time() - $self->{option_results}->{filter_since}); } $self->{output}->output_add( long_msg => sprintf( 'peripheral [name: %s] [Last Seen: %s] [NetworkAddress: %s] [SerialNumber: %s]', $_->{Name}, $_->{LastSeen}, $_->{NetworkAddress}, $_->{SerialNumber} ) ); $self->{global}->{connected}++; } } 1; __END__ =head1 MODE Check peripherals device connected (since TC 7.2). =over 8 =item B<--filter-since> Filter by since X seconds (Default: 86400). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'peripherals-connected'. =back =cut centreon-plugins-20220113/hardware/devices/cisco/ces/restapi/mode/sessions.pm000066400000000000000000000051141417000230700271250ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::cisco::ces::restapi::mode::sessions; 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 } ]; $self->{maps_counters}->{global} = [ { label => 'sessions-current', nlabel => 'system.sessions.current.count', set => { key_values => [ { name => 'sessions' } ], output_template => 'total current sessions: %d', perfdatas => [ { template => '%d', min => 0 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $self->{version} = '1.0'; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->request_api( method => 'POST', url_path => '/putxml', query_form_post => '', ForceArray => ['Session'] ); $self->{global} = { sessions => 0 }; return if (!defined($result->{SessionListResult}->{Session})); foreach (@{$result->{SessionListResult}->{Session}}) { $self->{output}->output_add( long_msg => sprintf( 'session [username: %s] [origin: %s] [address: %s]', $_->{UserName}, $_->{Origin}, $_->{RemoteAddress} ) ); $self->{global}->{sessions}++; } } 1; __END__ =head1 MODE Check sessions (since CE 8.2) =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'sessions-current'. =back =cut centreon-plugins-20220113/hardware/devices/cisco/ces/restapi/plugin.pm000066400000000000000000000036231417000230700256340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::cisco::ces::restapi::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} = '1.0'; $self->{modes} = { 'components' => 'hardware::devices::cisco::ces::restapi::mode::components', 'calls-summary' => 'hardware::devices::cisco::ces::restapi::mode::callssummary', 'calls-rt' => 'hardware::devices::cisco::ces::restapi::mode::callsrt', 'certificates' => 'hardware::devices::cisco::ces::restapi::mode::certificates', 'diagnostics' => 'hardware::devices::cisco::ces::restapi::mode::diagnostics', 'peripherals' => 'hardware::devices::cisco::ces::restapi::mode::peripherals', 'sessions' => 'hardware::devices::cisco::ces::restapi::mode::sessions' }; $self->{custom_modes}->{api} = 'hardware::devices::cisco::ces::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Cisco Collaboration Endpoint Software through HTTP/REST API. =over 8 =back =cut centreon-plugins-20220113/hardware/devices/cisco/cts/000077500000000000000000000000001417000230700223445ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/cisco/cts/snmp/000077500000000000000000000000001417000230700233215ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/cisco/cts/snmp/mode/000077500000000000000000000000001417000230700242455ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/cisco/cts/snmp/mode/calls.pm000066400000000000000000000357051417000230700257130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::cisco::cts::snmp::mode::calls; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); sub custom_traffic_calc { my ($self, %options) = @_; if (!defined($options{delta_time})) { $self->{error_msg} = 'Buffer creation'; return -1; } my $total_bytes = 0; foreach (keys %{$options{new_datas}}) { if (/\Q$self->{instance}\E_.*_bytes/) { my $new_bytes = $options{new_datas}->{$_}; next if (!defined($options{old_datas}->{$_})); my $old_bytes = $options{old_datas}->{$_}; my $bytes = $new_bytes - $old_bytes; $bytes = $new_bytes if ($bytes < 0); $total_bytes += $bytes; } } $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{traffic_per_seconds} = ($total_bytes * 8) / $options{delta_time}; return 0; } sub custom_jitter_calc { my ($self, %options) = @_; my $max_jitter = 0; foreach (keys %{$options{new_datas}}) { if (/\Q$self->{instance}\E_.*_maxjitter/) { $max_jitter = $options{new_datas}->{$_} if ($options{new_datas}->{$_} > $max_jitter); } } $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{max_jitter} = $max_jitter; return 0; } sub custom_loss_calc { my ($self, %options) = @_; my ($total_loss, $total_pkts) = (0, 0); foreach (keys %{$options{new_datas}}) { if (/\Q$self->{instance}\E_.*_loss_$options{extra_options}->{label_ref}/) { my $new_loss = $options{new_datas}->{$_}; next if (!defined($options{old_datas}->{$_})); my $old_loss = $options{old_datas}->{$_}; my $loss = $new_loss - $old_loss; $loss = $new_loss if ($loss < 0); $total_loss += $loss; } elsif (/\Q$self->{instance}\E_.*_packets_$options{extra_options}->{label_ref}/) { my $new_pkts = $options{new_datas}->{$_}; next if (!defined($options{old_datas}->{$_})); my $old_pkts = $options{old_datas}->{$_}; my $pkts = $new_pkts - $old_pkts; $pkts = $new_pkts if ($pkts < 0); $total_pkts += $pkts; } } $self->{result_values}->{label} = $options{extra_options}->{label_ref}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{packets_loss} = $total_loss; $self->{result_values}->{packets_loss_prct} = 0; $self->{result_values}->{packets} = $total_pkts; if ($total_pkts > 0) { $self->{result_values}->{packets_loss_prct} = ($total_loss * 100) / $total_pkts; } return 0; } sub custom_loss_output { my ($self, %options) = @_; return sprintf( "packets %s loss: %.2f%% (%s on %s)", $self->{result_values}->{label}, $self->{result_values}->{packets_loss_prct}, $self->{result_values}->{packets_loss}, $self->{result_values}->{packets} ); } sub prefix_global_output { my ($self, %options) = @_; return 'Calls '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }, { name => 'streams_active', type => 1, cb_prefix_output => 'prefix_stream_active_output', message_multiple => 'All active call streams are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'dummy', threshold => 0, display_ok => 0, set => { key_values => [ { name => 'calls_instance_finished' } ], output_template => 'none', perfdatas => [] } }, { label => 'active', nlabel => 'calls.active.count', set => { key_values => [ { name => 'active' } ], output_template => 'active: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'total', nlabel => 'calls.total.count', display_ok => 0, set => { key_values => [ { name => 'total' } ], output_template => 'total: %s', perfdatas => [ { template => '%s', min => 0 } ] } } ]; my @map = ( ['total-unknown', 'unknown: %s', 'unknown'], ['total-other', 'other: %s', 'other'], ['total-internal-error', 'internal error: %s', 'internal.error'], ['total-local-disconnected', 'local disconnected: %s', 'local.disconnected'], ['total-remote-disconnected', 'remote disconnected: %s', 'remote.disconnected'], ['total-network-congestion', 'network congestion: %s', 'network.congestion'], ['total-media-negotiation-failure', 'media negotiation failure: %s', 'media.negotiation.failure'], ['total-security-config-mismatched', 'security config mismatched: %s', 'security.config.mismatched'], ['total-incompatible-remote-endpoint', 'incompatible remote endpoint: %s', 'incompatible.remote.endpoint'], ['total-service-unavailable', 'service unaivalable: %s', 'service.unavailable'], ['total-remote-terminated-error', 'remote terminated with error: %s', 'remote.terminated.error'] ); foreach (@map) { push @{$self->{maps_counters}->{global}}, { label => $_->[0], nlabel => 'calls.total.' . $_->[2] . '.count', display_ok => 0, set => { key_values => [ { name => $_->[2] } ], output_template => $_->[1], perfdatas => [ { template => '%s', min => 0 } ] } }; } $self->{maps_counters}->{streams_active} = [ { label => 'streams-active-maxjitter', nlabel => 'calls.streams.active.maxjitter.milliseconds', set => { key_values => [], manual_keys => 1, closure_custom_calc => $self->can('custom_jitter_calc'), output_template => 'max jitter: %s ms', output_use => 'max_jitter', threshold_use => 'max_jitter', perfdatas => [ { value => 'max_jitter', template => '%d', unit => 'ms', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } } ]; foreach (('in', 'out')) { push @{$self->{maps_counters}->{streams_active}}, { label => 'streams-active-traffic-' . $_, nlabel => 'calls.streams.active.traffic.' . $_ . '.bytes', set => { key_values => [], manual_keys => 1, closure_custom_calc => $self->can('custom_traffic_calc'), closure_custom_calc_extra_options => { label_ref => $_ }, output_template => 'traffic ' . $_ . ': %s %s/s', output_change_bytes => 1, output_use => 'traffic_per_seconds', threshold_use => 'traffic_per_seconds', perfdatas => [ { value => 'traffic_per_seconds', template => '%d', unit => 'B/s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'streams-active-packetloss-' . $_, nlabel => 'calls.streams.active.packetloss.' . $_ . '.count', set => { key_values => [], manual_keys => 1, closure_custom_calc => $self->can('custom_loss_calc'), closure_custom_calc_extra_options => { label_ref => $_ }, closure_custom_output => $self->can('custom_loss_output'), threshold_use => 'packets_loss', perfdatas => [ { value => 'packets_loss', template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'streams-active-packetloss-' . $_ . '-prct', nlabel => 'calls.streams.active.packetloss.' . $_ . '.percentage', display_ok => 0, set => { key_values => [], manual_keys => 1, closure_custom_calc => $self->can('custom_loss_calc'), closure_custom_calc_extra_options => { label_ref => $_ }, closure_custom_output => $self->can('custom_loss_output'), threshold_use => 'packets_loss_prct', perfdatas => [ { value => 'packets_loss_prct', template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1, instance_use => 'display' } ] } }; } } sub prefix_stream_active_output { my ($self, %options) = @_; return "Stream '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1, statefile => 1); bless $self, $class; $self->{version} = '1.0'; $options{options}->add_options(arguments => { }); return $self; } my $map_term_reason = { 1 => 'unknown', 2 => 'other', 3 => 'internal.error', 4 => 'local.disconnected', 5 => 'remote.disconnected', 6 => 'network.congestion', 7 => 'media.negotiation.failure', 8 => 'security.config.mismatched', 9 => 'incompatible.remote.endpoint', 10 => 'service.unavailable', 11 => 'remote.terminated.error', 12 => 'incall' }; my $map_stream_type = { 1 => 'video', 2 => 'audio', 3 => 'content' }; my $oid_ctpcCallTermReason = '.1.3.6.1.4.1.9.9.644.1.4.8.1.17'; my $mapping = { traffic_out => { oid => '.1.3.6.1.4.1.9.9.644.1.4.10.1.3' }, # ctpcTxTotalBytes packets_out => { oid => '.1.3.6.1.4.1.9.9.644.1.4.10.1.4' }, # ctpcTxTotalPackets packets_lost_out => { oid => '.1.3.6.1.4.1.9.9.644.1.4.10.1.5' }, # ctpcTxLostPackets traffic_in => { oid => '.1.3.6.1.4.1.9.9.644.1.4.10.1.11' }, # ctpcRxTotalBytes packets_in => { oid => '.1.3.6.1.4.1.9.9.644.1.4.10.1.12' }, # ctpcRxTotalPackets packets_lost_in => { oid => '.1.3.6.1.4.1.9.9.644.1.4.10.1.13' }, # ctpcRxLostPackets maxjitter => { oid => '.1.3.6.1.4.1.9.9.644.1.4.10.1.25' }, # ctpcMaxCallJitter }; sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = 'cisco_cts_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); my $calls_instance_finished = $self->read_statefile_key(key => 'global_calls_instance_finished'); $calls_instance_finished = {} if (!defined($calls_instance_finished)); my $calls_instance_finished_new = {}; my $active_calls = {}; $self->{global} = { active => 0, total => 0 }; foreach (values %$map_term_reason) { $self->{global}->{$_} = 0; } my $snmp_result = $options{snmp}->get_table( oid => $oid_ctpcCallTermReason ); foreach (keys %$snmp_result) { /^$oid_ctpcCallTermReason\.(\d+)/; my $instance = $1; if ($map_term_reason->{ $snmp_result->{$_} } eq 'incall') { $active_calls->{$instance} = 1; $self->{global}->{active}++; } else { $calls_instance_finished_new->{$instance} = 1; next if (defined($calls_instance_finished->{$instance})); $self->{global}->{total}++; $self->{global}->{ $map_term_reason->{ $snmp_result->{$_} } }++; } } $snmp_result = $options{snmp}->get_multiple_table( oids => [ map({ oid => $_->{oid} }, values(%$mapping)) ], return_type => 1 ); $self->{streams_active} = {}; foreach (('audio', 'video', 'content')) { $self->{streams_active}->{$_} = { display => $_ }; } foreach my $oid (keys %$snmp_result) { next if ($oid !~ /^$mapping->{traffic_out}->{oid}\.(\d+)\.(\d+)\.(\d+)/); my ($index, $type, $source) = ($1, $2, $3); my $instance = $index . '.' . $type . '.' . $source; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); my $stream_type = $map_stream_type->{$type}; if (defined($active_calls->{$index})) { $self->{streams_active}->{$stream_type}->{$instance . '_traffic_in'} = defined($result->{traffic_in}) ? $result->{traffic_in} : 0; $self->{streams_active}->{$stream_type}->{$instance . '_traffic_out'} = defined($result->{traffic_out}) ? $result->{traffic_out} : 0; $self->{streams_active}->{$stream_type}->{$instance . '_loss_in'} = defined($result->{packets_lost_in}) ? $result->{packets_lost_in} : 0; $self->{streams_active}->{$stream_type}->{$instance . '_packets_in'} = defined($result->{packets_in}) ? $result->{packets_in} : 0; $self->{streams_active}->{$stream_type}->{$instance . '_loss_out'} = defined($result->{packets_lost_out}) ? $result->{packets_lost_out} : 0; $self->{streams_active}->{$stream_type}->{$instance . '_packets_out'} = defined($result->{packets_out}) ? $result->{packets_out} : 0; $self->{streams_active}->{$stream_type}->{$instance . '_maxjitter'} = defined($result->{maxjitter}) ? $result->{maxjitter} : 0; } } $self->{global}->{calls_instance_finished} = $calls_instance_finished_new; } 1; __END__ =head1 MODE Check call stream (real-time and history) =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'active', 'total', 'total-unknown', 'total-other', 'total-internal-error', 'total-local-disconnected', 'total-remote-disconnected', 'total-network-congestion', 'total-media-negotiation-failure', 'total-security-config-mismatched', 'total-incompatible-remote-endpoint', 'total-service-unavailable', 'total-remote-terminated-error', 'streams-active-maxjitter', 'streams-active-traffic-in', 'streams-active-packetloss-in', 'streams-active-packetloss-in-prct', 'streams-active-traffic-out', 'streams-active-packetloss-out', 'streams-active-packetloss-out-prct'. =back =cut centreon-plugins-20220113/hardware/devices/cisco/cts/snmp/mode/peripherals.pm000066400000000000000000000114771417000230700271330ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::cisco::cts::snmp::mode::peripherals; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf( 'status: %s', $self->{result_values}->{status} ); } sub prefix_peripheral_output { my ($self, %options) = @_; return "Peripheral '" . $options{instance_value}->{description} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'peripherals', type => 1, cb_prefix_output => 'prefix_peripheral_output', message_multiple => 'All peripherals are ok' } ]; $self->{maps_counters}->{peripherals} = [ { label => 'status', type => 2, critical_default => '%{status} !~ /noError/i', set => { key_values => [ { name => 'status' }, { name => 'description' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{global} = [ { label => 'total', nlabel => 'peripherals.total.count', set => { key_values => [ { name => 'total' } ], output_template => 'Total peripherals: %s', perfdatas => [ { template => '%s', min => 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-description:s' => { name => 'filter_description' } }); return $self; } my $mapping_status = { 0 => 'noError', 1 => 'other', 2 => 'cableError', 3 => 'powerError', 4 => 'mgmtSysConfigError', 5 => 'systemError', 6 => 'deviceError', 7 => 'linkError', 8 => 'commError', 9 => 'detectionDisabled' }; my $mapping = { description => { oid => '.1.3.6.1.4.1.9.9.643.1.2.1.1.2' }, # ctpPeripheralDescription status => { oid => '.1.3.6.1.4.1.9.9.643.1.2.1.1.3', map => $mapping_status } # ctpPeripheralStatus }; my $oid_ctpPeripheralStatusEntry = '.1.3.6.1.4.1.9.9.643.1.2.1.1'; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_table( oid => $oid_ctpPeripheralStatusEntry, start => $mapping->{description}->{oid}, end => $mapping->{status}->{oid}, nothing_quit => 1 ); $self->{peripherals} = {}; foreach my $oid (keys %$snmp_result) { next if ($oid !~ /^$mapping->{status}->{oid}\.(.*)/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); if (defined($self->{option_results}->{filter_description}) && $self->{option_results}->{filter_description} ne '' && $result->{description} !~ /$self->{option_results}->{filter_description}/) { $self->{output}->output_add(long_msg => "skipping phone '" . $instance . "': no matching filter.", debug => 1); next; } $self->{peripherals}->{$instance} = $result; } $self->{global} = { total => scalar(keys %{$self->{peripherals}}) }; } 1; __END__ =head1 MODE Check peripherals. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='status' =item B<--filter-description> Filter peripheral by description (can be a regexp). =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{status}, %{description} =item B<--critical-status> Set critical threshold for status (Default: '%{status} !~ /^registered/'). Can used special variables like: %{status}, %{description} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'total'. =back =cut centreon-plugins-20220113/hardware/devices/cisco/cts/snmp/plugin.pm000066400000000000000000000025151417000230700251600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::cisco::cts::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} = { 'calls' => 'hardware::devices::cisco::cts::snmp::mode::calls', 'peripherals' => 'hardware::devices::cisco::cts::snmp::mode::peripherals' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Cisco Telepresence System (CTS) in SNMP. =cut centreon-plugins-20220113/hardware/devices/eltek/000077500000000000000000000000001417000230700215575ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/eltek/enexus/000077500000000000000000000000001417000230700230665ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/eltek/enexus/snmp/000077500000000000000000000000001417000230700240435ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/eltek/enexus/snmp/mode/000077500000000000000000000000001417000230700247675ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/eltek/enexus/snmp/mode/alarms.pm000066400000000000000000000127431417000230700266130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::eltek::enexus::snmp::mode::alarms; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); use centreon::plugins::misc; sub custom_status_output { my ($self, %options) = @_; return sprintf('status: %s', $self->{result_values}->{status} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'alarm', type => 1, cb_prefix_output => 'prefix_alarm_output', message_multiple => 'All alarms are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'alarms-active', nlabel => 'alarms.active.count', display_ok => 0, set => { key_values => [ { name => 'active' }, { name => 'total' } ], output_template => 'current active alarms: %d', perfdatas => [ { value => 'active', template => '%d', min => 0, max => 'total' } ] } } ]; $self->{maps_counters}->{alarm} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'name' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } } ]; } sub prefix_alarm_output { my ($self, %options) = @_; return "Alarm '" . $options{instance_value}->{name} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'unknown-status:s' => { name => 'unknown_status', default => '' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{status} eq "alarm"' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['unknown_status', 'warning_status', 'critical_status']); } my $map_status = { 0 => 'normal', 1 => 'alarm' }; my $mapping = { alarmGroupStatus => { oid => '.1.3.6.1.4.1.12148.10.14.1.1.2', map => $map_status }, alarmGroupDescription => { oid => '.1.3.6.1.4.1.12148.10.14.1.1.3' } }; sub manage_selection { my ($self, %options) = @_; my $oid_alarmGroupEntry = '.1.3.6.1.4.1.12148.10.14.1.1'; my $snmp_result = $options{snmp}->get_table( oid => $oid_alarmGroupEntry, start => $mapping->{alarmGroupStatus}->{oid}, nothing_quit => 1 ); $self->{global} = { total => 0, active => 0 }; $self->{alarm} = {}; foreach my $oid (keys %$snmp_result) { next if ($oid !~ /^$mapping->{alarmGroupStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); $result->{alarmGroupDescription} = centreon::plugins::misc::trim($result->{alarmGroupDescription}); $result->{alarmGroupDescription} = $instance if ($result->{alarmGroupDescription} eq ''); if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $result->{alarmGroupDescription} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping alarm '" . $result->{alarmGroupDescription} . "'.", debug => 1); next; } $self->{alarm}->{$instance} = { name => $result->{alarmGroupDescription}, status => $result->{alarmGroupStatus} }; $self->{global}->{total}++; $self->{global}->{active}++ if ($result->{alarmGroupStatus} eq 'alarm'); } } 1; __END__ =head1 MODE Check alarms. =over 8 =item B<--filter-name> Filter name (can be a regexp). =item B<--unknown-status> Set unknown threshold for status (Default: ''). Can used special variables like: %{state}, %{status}, %{lastOpError}, %{display} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{name}, %{status} =item B<--critical-status> Set critical threshold for status (Default: '%{status} eq "alarm"). Can used special variables like: %{name}, %{status} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'alarms-active'. =back =cut centreon-plugins-20220113/hardware/devices/eltek/enexus/snmp/mode/battery.pm000066400000000000000000000324641417000230700270100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::eltek::enexus::snmp::mode::battery; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); use centreon::plugins::misc; sub custom_status_output { my ($self, %options) = @_; return sprintf('status: %s', $self->{result_values}->{status} ); } sub custom_temperature_output { my ($self, %options) = @_; return sprintf('temperature: %s %s', $self->{result_values}->{temperature}, $self->{result_values}->{temperature_unit} ); } sub custom_temperature_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => 'battery.temperature.' . ($self->{result_values}->{temperature_unit} eq 'C' ? 'celsius' : 'fahrenheit'), unit => $self->{result_values}->{temperature_unit}, value => $self->{result_values}->{temperature}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}), ); } sub custom_charge_remaining_output { my ($self, %options) = @_; return sprintf('remaining capacity: %s %s', $self->{result_values}->{charge_remaining}, $self->{result_values}->{charge_remaining_unit} ); } sub custom_charge_remaining_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => 'battery.charge.remaining.' . ($self->{result_values}->{charge_remaining_unit} eq '%' ? 'percentage' : 'amperehour'), unit => $self->{result_values}->{charge_remaining_unit}, value => $self->{result_values}->{charge_remaining}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}), min => 0, max => $self->{result_values}->{charge_remaining_unit} eq '%' ? 100 : undef ); } sub custom_charge_time_output { my ($self, %options) = @_; return sprintf( 'remaining time: %s', centreon::plugins::misc::change_seconds(value => $self->{result_values}->{charge_remaining_time}) ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'battery', type => 0, cb_prefix_output => 'prefix_battery_output', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{battery} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } }, { label => 'temperature', display_ok => 0, set => { key_values => [ { name => 'temperature' }, { name => 'temperature_unit' } ], closure_custom_output => $self->can('custom_temperature_output'), closure_custom_perfdata => $self->can('custom_temperature_perfdata') } }, { label => 'charge-remaining', set => { key_values => [ { name => 'charge_remaining' }, { name => 'charge_remaining_unit' } ], closure_custom_output => $self->can('custom_charge_remaining_output'), closure_custom_perfdata => $self->can('custom_charge_remaining_perfdata') } }, { label => 'charge-remaining-time', nlabel => 'battery.charge.remaining.time.seconds', set => { key_values => [ { name => 'charge_remaining_time' } ], closure_custom_output => $self->can('custom_charge_time_output'), perfdatas => [ { value => 'charge_remaining_time', template => '%s', min => 0, unit => 's' }, ], } }, { label => 'voltage', nlabel => 'battery.voltage.volt', display_ok => 0, set => { key_values => [ { name => 'voltage' } ], output_template => 'voltage: %.2f V', perfdatas => [ { value => 'voltage', template => '%.2f', unit => 'V' } ] } }, { label => 'current', nlabel => 'battery.current.ampere', display_ok => 0, set => { key_values => [ { name => 'current' } ], output_template => 'current: %.2f A', perfdatas => [ { value => 'current', template => '%.2f', min => 0, unit => 'A' } ] } } ]; } sub prefix_battery_output { my ($self, %options) = @_; return 'Battery '; } 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 => { 'unknown-status:s' => { name => 'unknown_status', default => '' }, 'warning-status:s' => { name => 'warning_status', default => '%{status} =~ /minor|warning/i' }, 'critical-status:s' => { name => 'critical_status', default => '%{status} =~ /error|major|critical/i' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => [ 'warning_status', 'critical_status', 'unknown_status', ]); } my $map_status = { 0 => 'error', 1 => 'normal', 2 => 'minorAlarm', 3 => 'majorAlarm', 4 => 'disabled', 5 => 'disconnected', 6 => 'notPresent', 7 => 'minorAndMajor', 8 => 'majorLow', 9 => 'minorLow', 10 => 'majorHigh', 11 => 'minorHigh', 12 => 'event', 13 => 'valueVolt', 14 => 'valueAmp', 15 => 'valueTemp', 16 => 'valueUnit', 17 => 'valuePerCent', 18 => 'critical', 19 => 'warning' }; my $map_decimal_setting = { 0 => 'ampere', 1 => 'deciAmpere' }; my $map_temp_setting = { 0 => 'celsius', 1 => 'fahrenheit' }; my $map_capacity = { 0 => 'ah', 1 => 'percent' }; my $mapping = { powerSystemCurrentDecimalSetting => { oid => '.1.3.6.1.4.1.12148.10.2.15', map => $map_decimal_setting }, powerSystemTemperatureScale => { oid => '.1.3.6.1.4.1.12148.10.2.16', map => $map_temp_setting }, powerSystemCapacityScale => { oid => '.1.3.6.1.4.1.12148.10.2.17', map => $map_capacity }, batteryStatus => { oid => '.1.3.6.1.4.1.12148.10.10.1', map => $map_status }, batteryVoltageValue => { oid => '.1.3.6.1.4.1.12148.10.10.5.5' }, batteryVoltageMajorHighLevel => { oid => '.1.3.6.1.4.1.12148.10.10.5.6' }, batteryVoltageMinorHighLevel => { oid => '.1.3.6.1.4.1.12148.10.10.5.7' }, # 0.01 for vdc batteryVoltageMinorLowLevel => { oid => '.1.3.6.1.4.1.12148.10.10.5.8' }, batteryVoltageMajorLowLevel => { oid => '.1.3.6.1.4.1.12148.10.10.5.9' }, batteryCurrentsValue => { oid => '.1.3.6.1.4.1.12148.10.10.6.5' }, # A or dA batteryCurrentsMajorHighLevel => { oid => '.1.3.6.1.4.1.12148.10.10.6.6' }, batteryCurrentsMinorHighLevel => { oid => '.1.3.6.1.4.1.12148.10.10.6.7' }, batteryCurrentsMinorLowLevel => { oid => '.1.3.6.1.4.1.12148.10.10.6.8' }, batteryCurrentsMajorLowLevel => { oid => '.1.3.6.1.4.1.12148.10.10.6.9' }, batteryTemperaturesValue => { oid => '.1.3.6.1.4.1.12148.10.10.7.5' }, # C or F batteryTemperaturesMajorHighLevel => { oid => '.1.3.6.1.4.1.12148.10.10.7.6' }, batteryTemperaturesMinorHighLevel => { oid => '.1.3.6.1.4.1.12148.10.10.7.7' }, batteryTemperaturesMinorLowLevel => { oid => '.1.3.6.1.4.1.12148.10.10.7.8' }, batteryTemperaturesMajorLowLevel => { oid => '.1.3.6.1.4.1.12148.10.10.7.9' }, batteryRemainingCapacityValue => { oid => '.1.3.6.1.4.1.12148.10.10.9.5' }, # ah or % batteryRemainingCapacityMinorLowLevel => { oid => '.1.3.6.1.4.1.12148.10.10.9.6' }, batteryRemainingCapacityMajorLowLevel => { oid => '.1.3.6.1.4.1.12148.10.10.9.7' }, loadCurrentValue => { oid => '.1.3.6.1.4.1.12148.10.9.2.5' }, # A or dA }; sub threshold_eltek_configured { my ($self, %options) = @_; if ((!defined($self->{option_results}->{'critical-' . $options{label}}) || $self->{option_results}->{'critical-' . $options{label}} eq '') && (!defined($self->{option_results}->{'warning-' . $options{label}}) || $self->{option_results}->{'warning-' . $options{label}} eq '')) { my ($crit, $warn) = ('', ''); $crit = $options{low_crit} . ':' if (defined($options{low_crit}) && $options{low_crit} ne ''); $crit .= $options{high_crit} if (defined($options{high_crit}) && $options{high_crit} ne ''); $warn = $options{low_warn} . ':' if (defined($options{low_warn}) && $options{low_warn} ne ''); $warn .= $options{high_warn} if (defined($options{high_warn}) && $options{high_warn} ne ''); $self->{perfdata}->threshold_validate(label => 'critical-' . $options{label}, value => $crit); $self->{perfdata}->threshold_validate(label => 'warning-' . $options{label}, value => $warn); } } sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_leef( oids => [ map($_->{oid} . '.0', values(%$mapping)) ], nothing_quit => 1 ); my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => '0'); my $scale_current = 1; $scale_current = 0.1 if ($result->{powerSystemCurrentDecimalSetting} eq 'deciAmpere'); $self->{battery} = { status => $result->{batteryStatus}, temperature => $result->{batteryTemperaturesValue}, temperature_unit => $result->{powerSystemTemperatureScale} eq 'celsius' ? 'C' : 'F', voltage => $result->{batteryVoltageValue} * 0.01, current => $result->{batteryCurrentsValue} * $scale_current, charge_remaining => $result->{batteryRemainingCapacityValue}, charge_remaining_unit => $result->{powerSystemCapacityScale} }; # we can calculate the time remaining if unit is ah (amperehour) and current battery is discharging (negative value) my $current; if ($result->{batteryCurrentsValue} < 0) { $current = $result->{batteryCurrentsValue} * -1 } elsif ($result->{loadCurrentValue} > 0) { $current = $result->{loadCurrentValue}; } if ($result->{powerSystemCapacityScale} eq 'ah' && defined($current)) { $self->{battery}->{charge_remaining_time} = int(($result->{batteryRemainingCapacityValue} * 3600) / ($current * $scale_current)); } $self->threshold_eltek_configured( label => 'temperature', high_crit => $result->{batteryTemperaturesMajorHighLevel}, low_crit => $result->{batteryTemperaturesMajorLowLevel}, high_warn => $result->{batteryTemperaturesMinorHighLevel}, low_warn => $result->{batteryTemperaturesMinorLowLevel} ); $self->threshold_eltek_configured( label => 'battery-voltage-volt', high_crit => $result->{batteryVoltageMajorHighLevel} * 0.01, low_crit => $result->{batteryVoltageMajorLowLevel} * 0.01, high_warn => $result->{batteryVoltageMinorHighLevel} * 0.01, low_warn => $result->{batteryVoltageMinorLowLevel} * 0.01 ); $self->threshold_eltek_configured( label => 'battery-current-ampere', high_crit => $result->{batteryCurrentsMajorHighLevel} * $scale_current, low_crit => $result->{batteryCurrentsMajorLowLevel} * $scale_current, high_warn => $result->{batteryCurrentsMinorHighLevel} * $scale_current, low_warn => $result->{batteryCurrentsMinorLowLevel} * $scale_current ); $self->threshold_eltek_configured( label => 'charge-remaining', low_crit => $result->{batteryRemainingCapacityMajorLowLevel}, low_warn => $result->{batteryRemainingCapacityMinorLowLevel} ); } 1; __END__ =head1 MODE Check battery. =over 8 =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{status} =item B<--warning-status> Set warning threshold for status (Default: '%{status} =~ /minor|warning/i'). Can used special variables like: %{status} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /error|major|critical/i'). Can used special variables like: %{status} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'temperature', 'voltage', 'current', 'charge-remaining', 'charge-remaining-time'. =back =cut centreon-plugins-20220113/hardware/devices/eltek/enexus/snmp/mode/load.pm000066400000000000000000000174561417000230700262610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::eltek::enexus::snmp::mode::load; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); sub custom_status_output { my ($self, %options) = @_; return sprintf( 'status: %s', $self->{result_values}->{status} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'load', type => 0, cb_prefix_output => 'prefix_load_output', skipped_code => { -10 => 1 } }, { name => 'phase', type => 1, cb_prefix_output => 'prefix_phase_output', message_multiple => 'All phases are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{load} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } }, { label => 'current', nlabel => 'load.current.ampere', set => { key_values => [ { name => 'current' } ], output_template => 'current: %s A', perfdatas => [ { value => 'current', template => '%s', unit => 'A', min => 0 } ] } }, { label => 'power', nlabel => 'load.power.watt', display_ok => 0, set => { key_values => [ { name => 'power' } ], output_template => 'power: %s W', perfdatas => [ { value => 'power', template => '%s', unit => 'W', min => 0 } ] } } ]; $self->{maps_counters}->{phase} = [ { label => 'voltage', nlabel => 'phase.voltage.volt', set => { key_values => [ { name => 'voltage' } ], output_template => 'voltage: %.2f V', perfdatas => [ { value => 'voltage', template => '%.2f', unit => 'V', label_extra_instance => 1 } ] } } ]; } sub prefix_load_output { my ($self, %options) = @_; return 'Load '; } sub prefix_phase_output { my ($self, %options) = @_; return "Phase '" . $options{instance_value}->{display} . "' "; } 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 => { 'unknown-status:s' => { name => 'unknown_status', default => '' }, 'warning-status:s' => { name => 'warning_status', default => '%{status} =~ /minor|warning/i' }, 'critical-status:s' => { name => 'critical_status', default => '%{status} =~ /error|major|critical/i' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => [ 'warning_status', 'critical_status', 'unknown_status', ]); } my $map_status = { 0 => 'error', 1 => 'normal', 2 => 'minorAlarm', 3 => 'majorAlarm', 4 => 'disabled', 5 => 'disconnected', 6 => 'notPresent', 7 => 'minorAndMajor', 8 => 'majorLow', 9 => 'minorLow', 10 => 'majorHigh', 11 => 'minorHigh', 12 => 'event', 13 => 'valueVolt', 14 => 'valueAmp', 15 => 'valueTemp', 16 => 'valueUnit', 17 => 'valuePerCent', 18 => 'critical', 19 => 'warning' }; my $map_decimal_setting = { 0 => 'ampere', 1 => 'deciAmpere' }; my $mapping = { powerSystemCurrentDecimalSetting => { oid => '.1.3.6.1.4.1.12148.10.2.15', map => $map_decimal_setting }, loadStatus => { oid => '.1.3.6.1.4.1.12148.10.9.1', map => $map_status }, loadCurrentValue => { oid => '.1.3.6.1.4.1.12148.10.9.2.5' }, # A or dA loadCurrentMajorHighLevel => { oid => '.1.3.6.1.4.1.12148.10.9.2.6' }, loadCurrentMinorHighLevel => { oid => '.1.3.6.1.4.1.12148.10.9.2.7' }, loadEnergyLogAccumulated => { oid => '.1.3.6.1.4.1.12148.10.9.8.1' }, # Watt batteryVoltageValue => { oid => '.1.3.6.1.4.1.12148.10.10.5.5' } # not sure we should use that value }; sub threshold_eltek_configured { my ($self, %options) = @_; if ((!defined($self->{option_results}->{'critical-' . $options{label}}) || $self->{option_results}->{'critical-' . $options{label}} eq '') && (!defined($self->{option_results}->{'warning-' . $options{label}}) || $self->{option_results}->{'warning-' . $options{label}} eq '')) { my ($crit, $warn) = ('', ''); $crit = $options{low_crit} . ':' if (defined($options{low_crit}) && $options{low_crit} ne ''); $crit .= $options{high_crit} if (defined($options{high_crit}) && $options{high_crit} ne ''); $warn = $options{low_warn} . ':' if (defined($options{low_warn}) && $options{low_warn} ne ''); $warn .= $options{high_warn} if (defined($options{high_warn}) && $options{high_warn} ne ''); $self->{perfdata}->threshold_validate(label => 'critical-' . $options{label}, value => $crit); $self->{perfdata}->threshold_validate(label => 'warning-' . $options{label}, value => $warn); } } sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_leef( oids => [ map($_->{oid} . '.0', values(%$mapping)) ], nothing_quit => 1 ); my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => '0'); my $scale_current = 1; $scale_current = 0.1 if ($result->{powerSystemCurrentDecimalSetting} eq 'deciAmpere'); $self->{load} = { status => $result->{loadStatus}, power => $result->{loadCurrentValue} * $scale_current * ($result->{batteryVoltageValue} * 0.01), current => $result->{loadCurrentValue} * $scale_current }; $self->threshold_eltek_configured( label => 'load-current-ampere', high_crit => $result->{loadCurrentMajorHighLevel} * $scale_current, high_warn => $result->{loadCurrentMinorHighLevel} * $scale_current ); my $oid_loadVoltageValue = '.1.3.6.1.4.1.12148.10.9.9.1.6'; $snmp_result = $options{snmp}->get_table(oid => $oid_loadVoltageValue); $self->{phase} = {}; foreach (keys %$snmp_result) { /\.(\d+)$/; $self->{phase}->{$1} = { display => $1, voltage => $snmp_result->{$_} * 0.01 }; } } 1; __END__ =head1 MODE Check load. =over 8 =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{status} =item B<--warning-status> Set warning threshold for status (Default: '%{status} =~ /minor|warning/i'). Can used special variables like: %{status} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /error|major|critical/i'). Can used special variables like: %{status} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'current', 'power'. =back =cut centreon-plugins-20220113/hardware/devices/eltek/enexus/snmp/mode/outputs.pm000066400000000000000000000154011417000230700270510ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::eltek::enexus::snmp::mode::outputs; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); use centreon::plugins::misc; sub custom_status_output { my ($self, %options) = @_; return sprintf('status: %s', $self->{result_values}->{status} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'cuo', type => 1, cb_prefix_output => 'prefix_cuo_output', message_multiple => 'All outputs for control units are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'outputs-disconnected', nlabel => 'outputs.disconnected.count', display_ok => 0, set => { key_values => [ { name => 'disconnected' }, { name => 'total_contactors' } ], output_template => 'current disconnected outputs: %d', perfdatas => [ { value => 'disconnected', template => '%d', min => 0, max => 'total_contactors' } ] } }, { label => 'outputs-notenergized', nlabel => 'outputs.notenergized.count', display_ok => 0, set => { key_values => [ { name => 'notenergized' }, { name => 'total_relay' } ], output_template => 'current not energized outputs: %d', perfdatas => [ { value => 'notenergized', template => '%d', min => 0, max => 'total_relay' } ] } } ]; $self->{maps_counters}->{cuo} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'name' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } } ]; } sub prefix_cuo_output { my ($self, %options) = @_; return "Control unit output '" . $options{instance_value}->{name} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'unknown-status:s' => { name => 'unknown_status', default => '' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{status} =~ /notenergized|disconnected/i' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => [ 'warning_status', 'critical_status', 'unknown_status', ]); } my $map_status = { 0 => 'notenergized', 1 => 'energized', 2 => 'disconnected', 3 => 'connected' }; my $mapping = { outputControlUnitOutputStatus => { oid => '.1.3.6.1.4.1.12148.10.12.2.1.2', map => $map_status }, outputControlUnitOutputDescription => { oid => '.1.3.6.1.4.1.12148.10.12.2.1.3' } }; sub manage_selection { my ($self, %options) = @_; my $oid_outputControlUnitOutputEntry = '.1.3.6.1.4.1.12148.10.12.2.1'; my $snmp_result = $options{snmp}->get_table( oid => $oid_outputControlUnitOutputEntry, start => $mapping->{outputControlUnitOutputStatus}->{oid}, nothing_quit => 1 ); $self->{global} = { total_relay => 0, total_contactors => 0, energized => 0, notenergized => 0, connected => 0, disconnected => 0 }; $self->{cuo} = {}; my $duplicated = {}; foreach my $oid (keys %$snmp_result) { next if ($oid !~ /^$mapping->{outputControlUnitOutputStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); my $name = centreon::plugins::misc::trim($result->{outputControlUnitOutputDescription}); $name = $instance if ($name eq ''); $name = $instance if (defined($duplicated->{$name})); 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 control unit output '" . $name . "'.", debug => 1); next; } if (defined($self->{cuo}->{$name})) { $duplicated->{$name} = 1; my $instance2 = $self->{cuo}->{$name}->{instance}; $self->{cuo}->{$instance2} = $self->{cuo}->{$name}; $self->{cuo}->{$instance2}->{name} = $instance2; delete $self->{cuo}->{$name}; $name = $instance; } $self->{cuo}->{$name} = { instance => $instance, name => $name, status => $result->{outputControlUnitOutputStatus} }; $self->{global}->{total_relay}++ if ($result->{outputControlUnitOutputStatus} =~ /energized/); $self->{global}->{total_contactors}++ if ($result->{outputControlUnitOutputStatus} =~ /connected/); $self->{global}->{$result->{outputControlUnitOutputStatus}}++; } } 1; __END__ =head1 MODE Check outputs for control units. =over 8 =item B<--filter-name> Filter name (can be a regexp). =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{status}, %{name} =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{status}, %{name} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /notenergized|disconnected/i'). Can used special variables like: %{status}, %{name} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'outputs-disconnected', 'outputs-notenergized'. =back =cut centreon-plugins-20220113/hardware/devices/eltek/enexus/snmp/plugin.pm000066400000000000000000000030151417000230700256760ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::eltek::enexus::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}} = ( 'alarms' => 'hardware::devices::eltek::enexus::snmp::mode::alarms', 'battery' => 'hardware::devices::eltek::enexus::snmp::mode::battery', 'load' => 'hardware::devices::eltek::enexus::snmp::mode::load', 'outputs' => 'hardware::devices::eltek::enexus::snmp::mode::outputs' ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Eltek eNexus in SNMP (SmartPack2 V2.x, SmartPack S V2.x and Compack V2.x). =cut centreon-plugins-20220113/hardware/devices/gorgy/000077500000000000000000000000001417000230700216025ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/gorgy/ntpserver/000077500000000000000000000000001417000230700236325ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/gorgy/ntpserver/snmp/000077500000000000000000000000001417000230700246075ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/gorgy/ntpserver/snmp/mode/000077500000000000000000000000001417000230700255335ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/gorgy/ntpserver/snmp/mode/globalstatus.pm000066400000000000000000000160701417000230700306010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::gorgy::ntpserver::snmp::mode::globalstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_sync_status_output { my ($self, %options) = @_; my $msg = 'Current synchronization status : ' . $self->{result_values}->{sync_status}; return $msg; } sub custom_timebase_status_output { my ($self, %options) = @_; my $msg = 'Internal time base status : ' . $self->{result_values}->{timebase_status}; return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{$options{extra_options}->{label_ref}} = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{label_ref}}; $self->{result_values}->{label} = $options{extra_options}->{label_ref}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, message_separator => ' - ' } ]; $self->{maps_counters}->{global} = [ { label => 'sync-status', threshold => 0, set => { key_values => [ { name => 'sync_status' } ], closure_custom_calc => $self->can('custom_status_calc'), closure_custom_calc_extra_options => { label_ref => 'sync_status' }, closure_custom_output => $self->can('custom_sync_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold, } }, { label => 'timebase-status', threshold => 0, set => { key_values => [ { name => 'timebase_status' } ], closure_custom_calc => $self->can('custom_status_calc'), closure_custom_calc_extra_options => { label_ref => 'timebase_status' }, closure_custom_output => $self->can('custom_timebase_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold, } }, { label => 'ntp-requests', set => { key_values => [ { name => 'ntp_requests', diff => 1 } ], output_template => 'Number of ntp requests : %s', perfdatas => [ { label => 'ntp_requests', value => 'ntp_requests', template => '%s', min => 0 }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'warning-sync-status:s' => { name => 'warning_sync_status', default => '%{sync_status} =~ /Running with autonomy|Free running/i' }, 'critical-sync-status:s' => { name => 'critical_sync_status', default => '%{sync_status} =~ /Server locked|Never synchronized|Server not synchronized/i' }, 'warning-timebase-status:s' => { name => 'warning_timebase_status', default => '%{timebase_status} =~ /^(?!(XO|XO OK|TCXO Precision < 2usec|OCXO Precision < 1usec)$)/i' }, 'critical-timebase-status:s' => { name => 'critical_timebase_status', default => '%{timebase_status} =~ /^XO$/i' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_sync_status', 'critical_sync_status', 'warning_timebase_status', 'critical_timebase_status']); } # timeBaseState values: # XO Warming up... # XO OK # TCXO # TCXO Precision > 25usec # 2usec < TCXO Precision < 25usec # TCXO Precision < 2usec # OCXO Warming up... # OCXO Precision > 20usec # 1usec < OCXO Precision < 20usec # OCXO Precision < 1usec # XO # currentSyncState values: # Server locked # Free running # Never synchronized # Server synchronized # Running with autonomy # Server not synchronized # Computing synchronization my $mapping = { currentSyncState => { oid => '.1.3.6.1.4.1.8955.1.8.1.10' }, timeBaseState => { oid => '.1.3.6.1.4.1.8955.1.8.1.12' }, powerDownFlags => { oid => '.1.3.6.1.4.1.8955.1.8.1.20' }, ntpRequestsNumber => { oid => '.1.3.6.1.4.1.8955.1.8.2.3' }, }; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_leef( oids => [ $mapping->{currentSyncState}->{oid} . '.0', $mapping->{timeBaseState}->{oid} . '.0', $mapping->{ntpRequestsNumber}->{oid} . '.0' ], nothing_quit => 1 ); my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => '0'); $self->{global} = { sync_status => $result->{currentSyncState}, timebase_status => $result->{timeBaseState}, ntp_requests => $result->{ntpRequestsNumber} }; $self->{cache_name} = "gorgy_ntpserver_" . $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')); } 1; __END__ =head1 MODE Check ntp server status. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^sync-status$' =item B<--warning-sync-status> Set warning threshold for status (Default: '%{sync_status} =~ /Running with autonomy|Free running/i'). Can used special variables like: %{sync_status} =item B<--critical-sync-status> Set critical threshold for status (Default: '%{sync_status} =~ /Server locked|Never synchronized|Server not synchronized/i'). Can used special variables like: %{sync_status} =item B<--warning-timebase-status> Set warning threshold for status (Default: '%{timebase_status} =~ /^(?!(XO|XO OK|TCXO Precision < 2usec|OCXO Precision < 1usec)$)/i'). Can used special variables like: %{timebase_status} =item B<--critical-timebase-status> Set critical threshold for status (Default: '%{timebase_status} =~ /^XO$/i'). Can used special variables like: %{timebase_status} =item B<--warning-*> Threshold warning. Can be: 'ntp-requests'. =item B<--critical-*> Threshold critical. Can be: 'ntp-requests'. =back =cut centreon-plugins-20220113/hardware/devices/gorgy/ntpserver/snmp/plugin.pm000066400000000000000000000026161417000230700264500ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::gorgy::ntpserver::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}} = ( 'global-status' => 'hardware::devices::gorgy::ntpserver::snmp::mode::globalstatus', 'interfaces' => 'snmp_standard::mode::interfaces', 'list-interfaces' => 'snmp_standard::mode::listinterfaces', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Gorgy ntp servers in SNMP. =cut centreon-plugins-20220113/hardware/devices/hikvision/000077500000000000000000000000001417000230700224565ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/hikvision/nvr/000077500000000000000000000000001417000230700232635ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/hikvision/nvr/isapi/000077500000000000000000000000001417000230700243705ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/hikvision/nvr/isapi/custom/000077500000000000000000000000001417000230700257025ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/hikvision/nvr/isapi/custom/api.pm000066400000000000000000000145121417000230700270140ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::hikvision::nvr::isapi::custom::api; use strict; use warnings; use centreon::plugins::http; use XML::LibXML::Simple; 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 => { 'api-username:s' => { name => 'api_username' }, 'api-password:s' => { name => 'api_password' }, 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'timeout:s' => { name => 'timeout' }, 'unknown-http-status:s' => { name => 'unknown_http_status' }, 'warning-http-status:s' => { name => 'warning_http_status' }, 'critical-http-status:s' => { name => 'critical_http_status' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'ISAPI OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 50; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : ''; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : ''; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300'; $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } if ($self->{api_username} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-username option."); $self->{output}->option_exit(); } if ($self->{api_password} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-password option."); $self->{output}->option_exit(); } return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{credentials} = 1; $self->{option_results}->{digest} = 1; $self->{option_results}->{username} = $self->{api_username}; $self->{option_results}->{password} = $self->{api_password}; } sub settings { my ($self, %options) = @_; return if (defined($self->{settings_done})); $self->build_options_for_httplib(); $self->{http}->set_options(%{$self->{option_results}}); $self->{settings_done} = 1; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub get_port { my ($self, %options) = @_; return $self->{port}; } sub request_api { my ($self, %options) = @_; $self->settings(); my $content = $self->{http}->request( url_path => $options{endpoint}, unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status} ); if (!defined($content) || $content eq '') { $self->{output}->add_option_msg(short_msg => "API returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $xml_result; eval { $SIG{__WARN__} = sub {}; $xml_result = XMLin($content, ForceArray => $options{force_array}, KeyAttr => []); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode xml response: $@"); $self->{output}->option_exit(); } return $xml_result; } 1; __END__ =head1 NAME Hikvision ISAPI =head1 ISAPI OPTIONS Hikvision ISAPI =over 8 =item B<--hostname> Set hostname. =item B<--port> Port used (Default: 443) =item B<--proto> Specify https if needed (Default: 'https') =item B<--api-username> API username. =item B<--api-password> API password. =item B<--timeout> Set timeout in seconds (Default: 50). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/hardware/devices/hikvision/nvr/isapi/mode/000077500000000000000000000000001417000230700253145ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/hikvision/nvr/isapi/mode/cpu.pm000066400000000000000000000043301417000230700264410ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and alarm 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::devices::hikvision::nvr::isapi::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, skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'cpu-utilization', nlabel => 'cpu.utilization.percentage', set => { key_values => [ { name => 'cpu_util' } ], output_template => 'Cpu utilization: %.2f%%', perfdatas => [ { template => '%s', min => 0, max => 100, unit => '%' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->request_api(endpoint => '/ISAPI/System/status'); if (!defined($result->{CPUList}->{CPU}->{cpuUtilization})) { $self->{output}->add_option_msg(short_msg => "Cannot find cpu informations"); $self->{output}->option_exit(); } $self->{global} = { cpu_util => $result->{CPUList}->{CPU}->{cpuUtilization} }; }; 1; __END__ =head1 MODE Check cpu. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'cpu-utilization' (%). =back centreon-plugins-20220113/hardware/devices/hikvision/nvr/isapi/mode/device.pm000066400000000000000000000036631417000230700271210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and alarm 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::devices::hikvision::nvr::isapi::mode::device; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub run { my ($self, %options) = @_; my $result = $options{custom}->request_api(endpoint => '/ISAPI/System/deviceInfo'); my $model = defined($result->{model}) ? $result->{model} : 'unknown'; my $serial = defined($result->{serialNumber}) ? $result->{serialNumber} : 'unknown'; my $firmware = defined($result->{firmwareVersion}) ? $result->{firmwareVersion} : 'unknown'; $self->{output}->output_add( short_msg => sprintf( 'Model: %s, Serial: %s, Firmware: %s', $model, $serial, $firmware ) );; $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); }; 1; __END__ =head1 MODE Display device information. =over 8 =back centreon-plugins-20220113/hardware/devices/hikvision/nvr/isapi/mode/disks.pm000066400000000000000000000171351417000230700267760ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::hikvision::nvr::isapi::mode::disks; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_space_usage_output { my ($self, %options) = @_; my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); return sprintf( 'space usage total: %s used: %s (%.2f%%) free: %s (%.2f%%)', $total_size_value . " " . $total_size_unit, $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}, $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free} ); } sub disk_long_output { my ($self, %options) = @_; return sprintf( "checking disk '%s'", $options{instance} ); } sub prefix_disk_output { my ($self, %options) = @_; return sprintf( "disk '%s' ", $options{instance} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'disks', type => 3, cb_prefix_output => 'prefix_disk_output', cb_long_output => 'disk_long_output', indent_long_output => ' ', message_multiple => 'All disks are ok', group => [ { name => 'status', type => 0, skipped_code => { -10 => 1 } }, { name => 'space', type => 0, skipped_code => { -10 => 1 } }, { name => 'temperature', type => 0, skipped_code => { -10 => 1 } } ] } ]; # status: ok,unformatted,error,idle,mismatch,offline,smartFailed,reparing,formating,notexist,unRecordHostFormatted $self->{maps_counters}->{status} = [ { label => 'status', type => 2, warning_default => '%{status} =~ /reparing/i', critical_default => '%{status} =~ /error|smartFailed/i', set => { key_values => [ { name => 'status' }, { name => 'name' } ], output_template => 'status: %s', closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; $self->{maps_counters}->{space} = [ { label => 'space-usage', nlabel => 'disk.space.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_space_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1, label_extra_instance => 1 } ] } }, { label => 'space-usage-free', nlabel => 'disk.space.free.bytes', display_ok => 0, set => { key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_space_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1, label_extra_instance => 1 } ] } }, { label => 'space-usage-prct', nlabel => 'disk.space.usage.percentage', display_ok => 0, set => { key_values => [ { name => 'prct_used' }, { name => 'used' }, { name => 'free' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_space_usage_output'), perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{temperature} = [ { label => 'temperature', nlabel => 'disk.temperature.celsius', set => { key_values => [ { name => 'value' } ], output_template => 'temperature: %s C', perfdatas => [ { template => '%s', unit => 'C', label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->request_api(endpoint => '/ISAPI/ContentMgmt/Storage/hdd', force_array => ['hdd']); if (!defined($result->{hdd})) { $self->{output}->add_option_msg(short_msg => "Cannot find disk informations"); $self->{output}->option_exit(); } $self->{disks} = {}; foreach my $hdd (@{$result->{hdd}}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $hdd->{hddName} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping disk '" . $hdd->{hddName} . "'.", debug => 1); next; } $hdd->{capacity} *= 1024 * 1024; $hdd->{freeSpace} *= 1024 * 1024; $self->{disks}->{ $hdd->{hddName} } = { status => { name => $hdd->{hddName}, status => $hdd->{status} }, space => { total => $hdd->{capacity}, used => $hdd->{capacity} - $hdd->{freeSpace}, free => $hdd->{freeSpace}, prct_used => 100 - ($hdd->{freeSpace} * 100 / $hdd->{capacity}), prct_free => ($hdd->{freeSpace} * 100 / $hdd->{capacity}) } }; my $smart = $options{custom}->request_api(endpoint => '/ISAPI/ContentMgmt/Storage/hdd/' . $hdd->{id} . '/SMARTTest/status'); $self->{disks}->{ $hdd->{hddName} }->{temperature} = { value => $smart->{temprature} }; } } 1; __END__ =head1 MODE Check disks. =over 8 =item B<--filter-name> Filter disks by name (can be a regexp). =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{status}, %{name} =item B<--warning-status> Set warning threshold for status (Default: '%{status} =~ /reparing/i'). Can used special variables like: %{status}, %{name} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /error|smartFailed/i'). Can used special variables like: %{status}, %{name} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'space-usage', 'space-usage-free', 'space-usage-prct', 'temperature'. =back =cut centreon-plugins-20220113/hardware/devices/hikvision/nvr/isapi/mode/memory.pm000066400000000000000000000110031417000230700271550ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::hikvision::nvr::isapi::mode::memory; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_memory_usage_output { my ($self, %options) = @_; my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); return sprintf( "memory usage total: %s used: %s (%.2f%%) free: %s (%.2f%%)", $total_size_value . " " . $total_size_unit, $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}, $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'memory-usage', nlabel => 'memory.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_memory_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1 } ] } }, { label => 'memory-usage-free', display_ok => 0, nlabel => 'memory.free.bytes', set => { key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_memory_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1 } ] } }, { label => 'memory-usage-prct', display_ok => 0, nlabel => 'memory.usage.percentage', set => { key_values => [ { name => 'prct_used' }, { name => 'free' }, { name => 'used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_memory_usage_output'), perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->request_api(endpoint => '/ISAPI/System/status'); if (!defined($result->{MemoryList}->{Memory}->{memoryUsage})) { $self->{output}->add_option_msg(short_msg => "Cannot find memory informations"); $self->{output}->option_exit(); } my ($mem_used, $mem_free); $mem_used = $1 * 1024 * 1024 if ($result->{MemoryList}->{Memory}->{memoryUsage} =~ /([0-9\.]+)/m); $mem_free = $1 * 1024 * 1024 if ($result->{MemoryList}->{Memory}->{memoryAvailable} =~ /([0-9\.]+)/m); $self->{global} = { used => $mem_used, free => $mem_free, total => $mem_used + $mem_free }; $self->{global}->{prct_used} = $mem_used * 100 / $self->{global}->{total}; $self->{global}->{prct_free} = 100 - $self->{global}->{prct_used}; } 1; __END__ =head1 MODE Check memory. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'memory-usage-prct', 'memory-usage', 'memory-usage-free', =back =cut centreon-plugins-20220113/hardware/devices/hikvision/nvr/isapi/mode/protocols.pm000066400000000000000000000070151417000230700277010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::hikvision::nvr::isapi::mode::protocols; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub prefix_protocol_output { my ($self, %options) = @_; return sprintf( "protocol '%s' ", $options{instance} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'protocols', type => 1, cb_prefix_output => 'prefix_protocol_output', message_multiple => 'All protocols are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{protocols} = [ { label => 'status', type => 2, set => { key_values => [ { name => 'enabled' }, { name => 'name' } ], output_template => 'enabled: %s', closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->request_api(endpoint => '/ISAPI/Security/adminAccesses/capabilities', force_array => ['AdminAccessProtocol']); if (!defined($result->{AdminAccessProtocol})) { $self->{output}->add_option_msg(short_msg => "Cannot find protocol informations"); $self->{output}->option_exit(); } $self->{protocols} = {}; foreach (@{$result->{AdminAccessProtocol}}) { if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $_->{protocol}->{content} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping protocol '" . $_->{protocol}->{content} . "'.", debug => 1); next; } $self->{protocols}->{ $_->{protocol}->{content} } = { name => $_->{protocol}->{content}, enabled => $_->{enabled}->{content} }; } } 1; __END__ =head1 MODE Check protocols. =over 8 =item B<--filter-name> Filter protocols by name (can be a regexp). =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{enabled}, %{name} =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{enabled}, %{name} =item B<--critical-status> Set critical threshold for status. Can used special variables like: %{enabled}, %{name} =back =cut centreon-plugins-20220113/hardware/devices/hikvision/nvr/isapi/mode/time.pm000066400000000000000000000113201417000230700266050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::hikvision::nvr::isapi::mode::time; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use DateTime; sub custom_usage_output { my ($self, %options) = @_; return sprintf( 'Time offset %d second(s): %s', $self->{result_values}->{offset}, $self->{result_values}->{date} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'offset', type => 0 } ]; $self->{maps_counters}->{offset} = [ { label => 'offset', nlabel => 'time.offset.seconds', set => { key_values => [ { name => 'offset' }, { name => 'date' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%d', unit => 's' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'ntp-hostname:s' => { name => 'ntp_hostname' }, 'ntp-port:s' => { name => 'ntp_port', default => 123 }, 'timezone:s' => { name => 'timezone' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (defined($self->{option_results}->{ntp_hostname})) { centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'Net::NTP', error_msg => "Cannot load module 'Net::NTP'." ); } } sub get_target_time { my ($self, %options) = @_; my $result = $options{custom}->request_api(endpoint => '/ISAPI/System/time/capabilities'); if (!defined($result->{localTime})) { $self->{output}->add_option_msg(short_msg => "Cannot find time informations"); $self->{output}->option_exit(); } if ($result->{localTime} !~ /^(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)(.*)$/) { $self->{output}->add_option_msg(short_msg => "unsupported date format"); $self->{output}->option_exit(); } my $tz = $7; if (defined($self->{option_results}->{timezone}) && $self->{option_results}->{timezone} ne '') { $tz = centreon::plugins::misc::set_timezone(name => $self->{option_results}->{timezone}); } my $dt = DateTime->new( year => $1, month => $2, day => $3, hour => $4, minute => $5, second => $6, time_zone => $7 ); return ($dt->epoch(), $result->{localTime}); } sub manage_selection { my ($self, %options) = @_; my ($distant_time, $remote_date) = $self->get_target_time(%options); my $ref_time; if (defined($self->{option_results}->{ntp_hostname}) && $self->{option_results}->{ntp_hostname} ne '') { my %ntp; eval { %ntp = Net::NTP::get_ntp_response($self->{option_results}->{ntp_hostname}, $self->{option_results}->{ntp_port}); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Couldn't connect to ntp server: " . $@); $self->{output}->option_exit(); } $ref_time = $ntp{'Transmit Timestamp'}; } else { $ref_time = time(); } my $offset = $distant_time - $ref_time; $self->{offset} = { offset => sprintf('%d', $offset), date => $remote_date }; } 1; __END__ =head1 MODE Check time offset of server with ntp server. Use local time if ntp-host option is not set. =over 8 =item B<--warning-offset> Time offset warning threshold (in seconds). =item B<--critical-offset> Time offset critical Threshold (in seconds). =item B<--ntp-hostname> Set the ntp hostname (if not set, localtime is used). =item B<--ntp-port> Set the ntp port (Default: 123). =item B<--timezone> Override the timezone of distant equipment. Can use format: 'Europe/London' or '+0100'. =back =cut centreon-plugins-20220113/hardware/devices/hikvision/nvr/isapi/mode/uptime.pm000066400000000000000000000102501417000230700271530ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::hikvision::nvr::isapi::mode::uptime; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use POSIX; use centreon::plugins::misc; my $unitdiv = { s => 1, w => 604800, d => 86400, h => 3600, m => 60 }; my $unitdiv_long = { s => 'seconds', w => 'weeks', d => 'days', h => 'hours', m => 'minutes' }; sub custom_uptime_output { my ($self, %options) = @_; return sprintf( 'System uptime is: %s', centreon::plugins::misc::change_seconds(value => $self->{result_values}->{uptime}, start => 'd') ); } sub custom_uptime_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => 'system.uptime.' . $unitdiv_long->{ $self->{instance_mode}->{option_results}->{unit} }, value => floor($self->{result_values}->{uptime} / $unitdiv->{ $self->{instance_mode}->{option_results}->{unit} }), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}), min => 0 ); } sub custom_uptime_threshold { my ($self, %options) = @_; return $self->{perfdata}->threshold_check( value => floor($self->{result_values}->{uptime} / $unitdiv->{ $self->{instance_mode}->{option_results}->{unit} }), threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel}, exit_litteral => 'warning' }, { label => 'unknown-'. $self->{thlabel}, exit_litteral => 'unknown' } ] ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 } ]; $self->{maps_counters}->{global} = [ { label => 'uptime', set => { key_values => [ { name => 'uptime' } ], closure_custom_output => $self->can('custom_uptime_output'), closure_custom_perfdata => $self->can('custom_uptime_perfdata'), closure_custom_threshold_check => $self->can('custom_uptime_threshold') } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'unit:s' => { name => 'unit', default => 's' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if ($self->{option_results}->{unit} eq '' || !defined($unitdiv->{$self->{option_results}->{unit}})) { $self->{option_results}->{unit} = 's'; } } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->request_api(endpoint => '/ISAPI/System/status'); if (!defined($result->{deviceUpTime})) { $self->{output}->add_option_msg(short_msg => "Cannot find uptime information"); $self->{output}->option_exit(); } $self->{global} = { uptime => $result->{deviceUpTime} }; } 1; __END__ =head1 MODE Check system uptime. =over 8 =item B<--warning-uptime> Threshold warning. =item B<--critical-uptime> Threshold critical. =item B<--unit> Select the unit for performance data and thresholds. May be 's' for seconds, 'm' for minutes, 'h' for hours, 'd' for days, 'w' for weeks. Default is seconds =back =cut centreon-plugins-20220113/hardware/devices/hikvision/nvr/isapi/plugin.pm000066400000000000000000000035201417000230700262240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::hikvision::nvr::isapi::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->{modes} = { 'cpu' => 'hardware::devices::hikvision::nvr::isapi::mode::cpu', 'device' => 'hardware::devices::hikvision::nvr::isapi::mode::device', 'disks' => 'hardware::devices::hikvision::nvr::isapi::mode::disks', 'memory' => 'hardware::devices::hikvision::nvr::isapi::mode::memory', 'protocols' => 'hardware::devices::hikvision::nvr::isapi::mode::protocols', 'time' => 'hardware::devices::hikvision::nvr::isapi::mode::time', 'uptime' => 'hardware::devices::hikvision::nvr::isapi::mode::uptime' }; $self->{custom_modes}->{isapi} = 'hardware::devices::hikvision::nvr::isapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Hikvision Network Video Recorder (NVR) using ISAPI (Intelligent Security API). =cut centreon-plugins-20220113/hardware/devices/hikvision/nvr/snmp/000077500000000000000000000000001417000230700242405ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/hikvision/nvr/snmp/mode/000077500000000000000000000000001417000230700251645ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/hikvision/nvr/snmp/mode/disks.pm000066400000000000000000000206241417000230700266430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::hikvision::nvr::snmp::mode::disks; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf( 'status: %s', $self->{result_values}->{status} ); } sub custom_space_usage_output { my ($self, %options) = @_; my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total_space}); my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used_space}); my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free_space}); return sprintf( 'space usage total: %s used: %s (%.2f%%) free: %s (%.2f%%)', $total_size_value . " " . $total_size_unit, $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used_space}, $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free_space} ); } sub prefix_disk_output { my ($self, %options) = @_; return "Disk '" . $options{instance}. "' "; } sub prefix_global_output { my ($self, %options) = @_; return 'Disks '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', cb_prefix_output => 'prefix_global_output', type => 0, skipped_code => { -10 => 1 } }, { name => 'disks', type => 1, cb_prefix_output => 'prefix_disk_output', message_multiple => 'All disks are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'disks-total', nlabel => 'disks.total.count', set => { key_values => [ { name => 'total' } ], output_template => 'total: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'disks-errors', nlabel => 'disks.errors.count', set => { key_values => [ { name => 'errors' }, { name => 'total' } ], output_template => 'errors: %s', perfdatas => [ { template => '%s', min => 0, max => 'total' } ] } } ]; $self->{maps_counters}->{disks} = [ { label => 'status', type => 2, warning_default => '%{status} =~ /reparing|formatting/i', critical_default => '%{status} =~ /abnormal|smartfailed/i', set => { key_values => [ { name => 'status' }, { name => 'name' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'space-usage', nlabel => 'disk.space.usage.bytes', set => { key_values => [ { name => 'used_space' }, { name => 'free_space' }, { name => 'prct_used_space' }, { name => 'prct_free_space' }, { name => 'total_space' } ], closure_custom_output => $self->can('custom_space_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total_space', unit => 'B', cast_int => 1, label_extra_instance => 1 } ] } }, { label => 'space-usage-free', nlabel => 'disk.space.free.bytes', display_ok => 0, set => { key_values => [ { name => 'free_space' }, { name => 'used_space' }, { name => 'prct_used_space' }, { name => 'prct_free_space' }, { name => 'total_space' } ], closure_custom_output => $self->can('custom_space_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total_space', unit => 'B', cast_int => 1, label_extra_instance => 1 } ] } }, { label => 'space-usage-prct', nlabel => 'disk.space.usage.percentage', display_ok => 0, set => { key_values => [ { name => 'prct_used_space' }, { name => 'used_space' }, { name => 'free_space' }, { name => 'prct_free_space' }, { name => 'total_space' } ], closure_custom_output => $self->can('custom_space_usage_output'), perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $map_status = { 0 => 'normal', 1 => 'unformatted', 2 => 'abnormal', 3 => 'smartfailed', 4 => 'mismatch', 5 => 'idle', 6 => 'notOnline', 10 => 'reparing', 11 => 'formatting' }; my $mapping = { name => { oid => '.1.3.6.1.4.1.50001.1.241.1.2' }, # hikDiskVolume status => { oid => '.1.3.6.1.4.1.50001.1.241.1.3', map => $map_status }, # hikDiskStatus free => { oid => '.1.3.6.1.4.1.50001.1.241.1.4' }, # hikDiskFreeSpace total => { oid => '.1.3.6.1.4.1.50001.1.241.1.5' } # hikDiskCapability }; my $oid_diskEntry = '.1.3.6.1.4.1.50001.1.241.1'; my $snmp_result = $options{snmp}->get_table(oid => $oid_diskEntry, nothing_quit => 1); $self->{global} = { total => 0, errors => 0 }; $self->{disks} = {}; foreach my $oid (keys %$snmp_result) { next if ($oid !~ /^$mapping->{status}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); my $name = defined($result->{name}) && $result->{name} ne '' ? $result->{name} : $instance; 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 disk '" . $name . "': no matching filter.", debug => 1); next; } $result->{total} *= 1024 * 1024; $result->{free} *= 1024 * 1024; $self->{disks}->{$name} = { name => $name, status => $result->{status}, free_space => $result->{free}, total_space => $result->{total}, used_space => $result->{total} - $result->{free}, prct_used_space => ($result->{total} - $result->{free}) * 100 / $result->{total}, prct_free_space => $result->{free} * 100 / $result->{total}, }; if ($result->{status} =~ /abnormal|smartfailed/) { $self->{global}->{errors}++; } $self->{global}->{total}++; } } 1; __END__ =head1 MODE Check disks. =over 8 =item B<--filter-name> Filter disks by name (can be a regexp). =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{status}, %{name} =item B<--warning--status> Set warning threshold for status (Default: '%{status} =~ /reparing|formatting/i'). Can used special variables like: %{status}, %{name} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /abnormal|smartfailed/i'). Can used special variables like: %{status}, %{name} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'space-usage', 'space-usage-free', 'space-usage-prct', 'disks-total', 'disks-errors'. =back =cut centreon-plugins-20220113/hardware/devices/hikvision/nvr/snmp/mode/memory.pm000066400000000000000000000100171417000230700270310ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::hikvision::nvr::snmp::mode::memory; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_usage_output { my ($self, %options) = @_; return sprintf( 'Memory total: %s %s used: %s %s (%.2f%%) free: %s %s (%.2f%%)', $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}), $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}), $self->{result_values}->{prct_used}, $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}), $self->{result_values}->{prct_free} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'ram', type => 0, skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{ram} = [ { label => 'usage', nlabel => 'memory.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1 } ] } }, { label => 'usage-free', display_ok => 0, nlabel => 'memory.free.bytes', set => { key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1 } ] } }, { label => 'usage-prct', display_ok => 0, nlabel => 'memory.usage.percentage', set => { key_values => [ { name => 'prct_used' }, { name => 'used' }, { name => 'free' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_usage_output'), perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; return $self; } sub manage_selection { my ($self, %options) = @_; my $oid_total = '.1.3.6.1.4.1.50001.1.220.0'; # hikMemoryCapability my $oid_prct_used = '.1.3.6.1.4.1.50001.1.221.0'; # hikMemoryUsage my $snmp_result = $options{snmp}->get_leef( oids => [ $oid_total, $oid_prct_used ], nothing_quit => 1 ); $snmp_result->{$oid_total} *= 1024 * 1024; $self->{ram} = { total => $snmp_result->{$oid_total}, used => $snmp_result->{$oid_total} * $snmp_result->{$oid_prct_used} / 100, free => $snmp_result->{$oid_total} * (100 - $snmp_result->{$oid_prct_used}) / 100, prct_used => $snmp_result->{$oid_prct_used}, prct_free => 100 - $snmp_result->{$oid_prct_used} }; } 1; __END__ =head1 MODE Check memory. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'usage' (B), 'usage-free' (B), 'usage-prct' (%). =back =cut centreon-plugins-20220113/hardware/devices/hikvision/nvr/snmp/mode/uptime.pm000066400000000000000000000035371417000230700270350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::hikvision::nvr::snmp::mode::uptime; use base qw(snmp_standard::mode::uptime); 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 system uptime. =over 8 =item B<--warning-uptime> Threshold warning. =item B<--critical-uptime> Threshold critical. =item B<--add-sysdesc> Display system description. =item B<--force-oid> Can choose your oid (numeric format only). =item B<--check-overload> Uptime counter limit is 4294967296 and overflow. With that option, we manage the counter going back. But there is a few chance we can miss a reboot. =item B<--reboot-window> To be used with check-overload option. Time in milliseconds (Default: 5000) You increase the chance of not missing a reboot if you decrease that value. =item B<--unit> Select the unit for performance data and thresholds. May be 's' for seconds, 'm' for minutes, 'h' for hours, 'd' for days, 'w' for weeks. Default is seconds =back centreon-plugins-20220113/hardware/devices/hikvision/nvr/snmp/plugin.pm000066400000000000000000000026001417000230700260720ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::hikvision::nvr::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} = { 'disks' => 'hardware::devices::hikvision::nvr::snmp::mode::disks', 'memory' => 'hardware::devices::hikvision::nvr::snmp::mode::memory', 'uptime' => 'hardware::devices::hikvision::nvr::snmp::mode::uptime' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Hikvision Network Video Recorder (NVR) in SNMP. =cut centreon-plugins-20220113/hardware/devices/hms/000077500000000000000000000000001417000230700212425ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/hms/ewon/000077500000000000000000000000001417000230700222125ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/hms/ewon/snmp/000077500000000000000000000000001417000230700231675ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/hms/ewon/snmp/mode/000077500000000000000000000000001417000230700241135ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/hms/ewon/snmp/mode/listtags.pm000066400000000000000000000071661417000230700263150ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::hms::ewon::snmp::mode::listtags; use base qw(centreon::plugins::mode); use strict; use warnings; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-tag-name:s' => { name => 'filter_tag_name' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } my $mapping = { name => { oid => '.1.3.6.1.4.1.8284.2.1.3.1.11.1.3' }, # tagCfgName value => { oid => '.1.3.6.1.4.1.8284.2.1.3.1.11.1.4' } # tagValue }; my $oid_tagEntry = '.1.3.6.1.4.1.8284.2.1.3.1.11.1'; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_table( oid => $oid_tagEntry, start => $mapping->{name}->{oid}, end => $mapping->{value}->{oid}, nothing_quit => 1 ); my $results = {}; foreach my $oid (keys %$snmp_result) { next if ($oid !~ /^$mapping->{name}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); if (defined($self->{option_results}->{filter_tag_name}) && $self->{option_results}->{filter_tag_name} ne '' && $result->{name} !~ /$self->{option_results}->{filter_tag_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{name} . "': no matching filter.", debug => 1); next; } $result->{name} = $self->{output}->decode($result->{name}); $results->{$instance} = $result; } return $results; } sub run { my ($self, %options) = @_; my $results = $self->manage_selection(%options); foreach my $index (sort keys %$results) { $self->{output}->output_add( long_msg => sprintf( '[name: %s][index: %s][value: %s]', $results->{$index}->{name}, $index, $results->{$index}->{value} ) ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List tags:' ); $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 => ['index', 'name', 'value']); } sub disco_show { my ($self, %options) = @_; my $results = $self->manage_selection(%options); foreach my $index (sort keys %$results) { $self->{output}->add_disco_entry( index => $index, %{$results->{$index}} ); } } 1; __END__ =head1 MODE List tags. =over 8 =item B<--filter-tag-name> Filter tags by name (can be a regexp). =back =cut centreon-plugins-20220113/hardware/devices/hms/ewon/snmp/mode/tags.pm000066400000000000000000000253331417000230700254150ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::hms::ewon::snmp::mode::tags; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::statefile; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return 'status: ' . $self->{result_values}->{status}; } sub custom_value_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( nlabel => 'tag.value.count', instances => $self->{result_values}->{name}, value => $self->{result_values}->{value}, warning => defined($self->{instance_mode}->{warning_instance}) ? $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{instance_mode}->{warning_instance}) : undef, critical => defined($self->{instance_mode}->{critical_instance}) ? $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{instance_mode}->{critical_instance}) : undef ); } sub custom_value_threshold { my ($self, %options) = @_; $self->{instance_mode}->{warning_instance} = undef; $self->{instance_mode}->{critical_instance} = undef; my $thresholds = []; foreach my $th (('critical', 'warning')) { my $i = 0; foreach (@{$self->{instance_mode}->{'tag_threshold_' . $th}}) { if ($self->{result_values}->{name} =~ /$_/ || $self->{result_values}->{index} =~ /$_/) { $self->{instance_mode}->{$th . '_instance'} = $i; push @$thresholds, { label => $th . '-' . $i, exit_litteral => $th }; last; } $i++; } } return 'ok' if (scalar(@$thresholds) <= 0); return $self->{perfdata}->threshold_check( value => $self->{result_values}->{value}, threshold => $thresholds ); } sub custom_value_output { my ($self, %options) = @_; my $output = 'value: %s'; foreach (@{$self->{instance_mode}->{tag_output_values}}) { if ($self->{result_values}->{name} =~ /$_->{match}/ || $self->{result_values}->{index} =~ /$_->{match}/) { $output = $_->{output}; last; } } return sprintf( $output, $self->{result_values}->{value} ); } sub prefix_tag_output { my ($self, %options) = @_; return "Tag '" . $options{instance_value}->{name} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'tags', type => 1, cb_prefix_output => 'prefix_tag_output', message_multiple => 'All tags are ok' } ]; $self->{maps_counters}->{tags} = [ { label => 'status', type => 2, critical_default => '%{status} =~ /alarm/', set => { key_values => [ { name => 'status' }, { name => 'name' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'value', threshold => 0, set => { key_values => [ { name => 'value' }, { name => 'index' }, { name => 'name' } ], closure_custom_output => $self->can('custom_value_output'), closure_custom_perfdata => $self->can('custom_value_perfdata'), closure_custom_threshold_check => $self->can('custom_value_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 => { 'filter-tag-index:s' => { name => 'filter_tag_index' }, 'filter-tag-name:s' => { name => 'filter_tag_name' }, 'cache-expires-in:s' => { name => 'cache_expires_in' }, 'tag-output-value:s@' => { name => 'tag_output_value' }, 'tag-threshold-warning:s@' => { name => 'tag_threshold_warning' }, 'tag-threshold-critical:s@' => { name => 'tag_threshold_critical' } }); $self->{cache} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{option_results}->{cache_expires_in} = (defined($self->{option_results}->{cache_expires_in})) && $self->{option_results}->{cache_expires_in} =~ /(\d+)/ ? $1 : 7200; $self->{cache}->check_options(option_results => $self->{option_results}); $self->{tag_output_values} = []; if (defined($self->{option_results}->{tag_output_value})) { foreach (@{$self->{option_results}->{tag_output_value}}) { my @fields = split /,/; my ($tag_output, $tag_match) = ($fields[0], '.*'); if (defined($fields[1]) && $fields[1] ne '') { $tag_output = $fields[1]; $tag_match = $fields[0]; } next if (!defined($tag_output) || $tag_output eq ''); push @{$self->{tag_output_values}}, { match => $tag_match, output => $tag_output}; } } foreach (('warning', 'critical')) { my $i = 0; $self->{'tag_threshold_' . $_} = []; next if (!defined($self->{option_results}->{'tag_threshold_' . $_})); foreach my $option (@{$self->{option_results}->{'tag_threshold_' . $_}}) { my @fields = split(/,/, $option); my ($tag_threshold, $tag_match) = ($fields[0], '.*'); if (defined($fields[1]) && $fields[1] ne '') { $tag_threshold = $fields[1]; $tag_match = $fields[0]; } next if (!defined($tag_threshold) || $tag_threshold eq ''); if (($self->{perfdata}->threshold_validate(label => $_ . '-' . $i, value => $tag_threshold)) == 0) { $self->{output}->add_option_msg(short_msg => "Wrong threshold '" . $tag_threshold . "'."); $self->{output}->option_exit(); } push @{$self->{'tag_threshold_' . $_}}, $tag_match; $i++; } } } sub get_tags { my ($self, %options) = @_; my $has_cache_file = $self->{cache}->read(statefile => 'hms_ewon_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . $self->{mode}); my $updated = $self->{cache}->get(name => 'updated'); my $tags = $self->{cache}->get(name => 'tags'); if ($has_cache_file == 0 || !defined($updated) || (time() > ($updated + $self->{option_results}->{cache_expires_in}))) { my $snmp_result = $options{snmp}->get_table( oid => '.1.3.6.1.4.1.8284.2.1.3.1.11.1.3', # tagCfgName nothing_quit => 1 ); foreach (keys %$snmp_result) { /\.(\d+)$/; $tags->{$1} = $snmp_result->{$_}; } $self->{cache}->write(data => { tags => $tags, updated => time() }); } return $tags; } my $map_status = { 0 => 'none', 1 => 'pretrig', 2 => 'alarm', 3 => 'ack', 4 => 'rtn' }; my $mapping = { value => { oid => '.1.3.6.1.4.1.8284.2.1.3.1.11.1.4' }, # tagValue status => { oid => '.1.3.6.1.4.1.8284.2.1.3.1.11.1.9', map => $map_status } # tagAlStatus }; sub manage_selection { my ($self, %options) = @_; my $tags = $self->get_tags(snmp => $options{snmp}); $self->{tags} = {}; foreach (keys %$tags) { $tags->{$_} = $self->{output}->decode($tags->{$_}); if (defined($self->{option_results}->{filter_tag_index}) && $self->{option_results}->{filter_tag_index} ne '' && $_ !~ /$self->{option_results}->{filter_tag_index}/) { $self->{output}->output_add(long_msg => "skipping '" . $tags->{$_} . "': no matching 'org' filter.", debug => 1); next; } if (defined($self->{option_results}->{filter_tag_name}) && $self->{option_results}->{filter_tag_name} ne '' && $tags->{$_} !~ /$self->{option_results}->{filter_tag_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $tags->{$_} . "': no matching 'org' filter.", debug => 1); next; } $self->{tags}->{$_} = { name => $tags->{$_}, index => $_ }; } if (scalar(keys %{$self->{tags}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No tags found."); $self->{output}->option_exit(); } $options{snmp}->load( oids => [ map($_->{oid}, values(%$mapping)) ], instances => [keys %{$self->{tags}}], instance_regexp => '^(.*)$' ); my $snmp_result = $options{snmp}->get_leef(nothing_quit => 1); foreach (keys %{$self->{tags}}) { my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $_); $self->{tags}->{$_}->{value} = $result->{value}; $self->{tags}->{$_}->{status} = $result->{status}; } } 1; __END__ =head1 MODE Check ewon tags. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='status' =item B<--filter-tag-index> Filter tags by index (can be a regexp). =item B<--filter-tag-name> Filter tags by name (can be a regexp). =item B<--cache-expires-in> Cache expires each X secondes (Default: 7200) =item B<--tag-output-value> Change tag output (syntax: [regexp,]output) (Default: 'value: %s'). E.g: --tag-output-value='tagNameMatch,remaining: %s%%' =item B<--tag-threshold-warning> B<--tag-threshold-critical> Set tag value threshold (syntax: [regexp,]threshold). E.g: --tag-threshold-warning='tagNameMatch,50' --tag-threshold-critical='tagNameMatch,80' =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{status}, %{name} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /alarm/'). Can used special variables like: %{status}, %{name} =item B<--warning-*> B<--critical-*> Threshold warning. Can be: 'usage' (B), 'usage-free' (B), 'usage-prct' (%). =back =cut centreon-plugins-20220113/hardware/devices/hms/ewon/snmp/plugin.pm000066400000000000000000000024561417000230700250320ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::hms::ewon::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}} = ( 'list-tags' => 'hardware::devices::hms::ewon::snmp::mode::listtags', 'tags' => 'hardware::devices::hms::ewon::snmp::mode::tags' ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check HMS Ewon in SNMP. =cut centreon-plugins-20220113/hardware/devices/masterclock/000077500000000000000000000000001417000230700227625ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/masterclock/ntp100gps/000077500000000000000000000000001417000230700245165ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/masterclock/ntp100gps/snmp/000077500000000000000000000000001417000230700254735ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/masterclock/ntp100gps/snmp/mode/000077500000000000000000000000001417000230700264175ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/masterclock/ntp100gps/snmp/mode/gpsstatus.pm000066400000000000000000000103711417000230700310140ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::masterclock::ntp100gps::snmp::mode::gpsstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("GPS receiver health : '%s', Satellites seen : '%s', Latitude : '%s', Longitude : '%s'", $self->{result_values}->{health}, $self->{result_values}->{satellites}, $self->{result_values}->{latitude}, $self->{result_values}->{longitude}); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{health} = $options{new_datas}->{$self->{instance} . '_health'}; $self->{result_values}->{satellites} = $options{new_datas}->{$self->{instance} . '_satellites'}; $self->{result_values}->{latitude} = $options{new_datas}->{$self->{instance} . '_latitude'}; $self->{result_values}->{longitude} = $options{new_datas}->{$self->{instance} . '_longitude'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, ]; $self->{maps_counters}->{global} = [ { label => 'status', set => { key_values => [ { name => 'health' }, { name => 'satellites' }, { name => 'latitude' }, { name => 'longitude' } ], 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 => \&catalog_status_threshold, } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning-status:s" => { name => 'warning_status', default => '%{satellites} =~ /No satellites in view/' }, "critical-status:s" => { name => 'critical_status', default => '' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; my $oid_gps_health = ".1.3.6.1.4.1.45561.1.1.1.26.0"; my $oid_gps_latitude = ".1.3.6.1.4.1.45561.1.1.1.27.0"; my $oid_gps_longitude = ".1.3.6.1.4.1.45561.1.1.1.28.0"; my $oid_gps_satellites = ".1.3.6.1.4.1.45561.1.1.1.29.0"; my $snmp_result = $options{snmp}->get_leef(oids => [ $oid_gps_health, $oid_gps_latitude, $oid_gps_longitude, $oid_gps_satellites ]); $self->{global} = { health => $snmp_result->{$oid_gps_health}, latitude => $snmp_result->{$oid_gps_latitude}, longitude => $snmp_result->{$oid_gps_longitude}, satellites => $snmp_result->{$oid_gps_satellites}, }; } 1; __END__ =head1 MODE Check GPS status =over 8 =item B<--warning-status> Set warning threshold for status (Default: '%{satellites} =~ /No satellites in view/') Can used special variables like: %{health}, %{satellites}, %{latitude}, %{longitude} =item B<--critical-status> Set critical threshold for status (Default: '') Can used special variables like: %{health}, %{satellites}, %{latitude}, %{longitude} =back =cut centreon-plugins-20220113/hardware/devices/masterclock/ntp100gps/snmp/mode/ntpperformance.pm000066400000000000000000000116701417000230700320050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::masterclock::ntp100gps::snmp::mode::ntpperformance; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("Leap : '%s'", $self->{result_values}->{leap}); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{leap} = $options{new_datas}->{$self->{instance} . '_leap'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, ]; $self->{maps_counters}->{global} = [ { label => 'status', set => { key_values => [ { name => 'leap' } ], 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 => \&catalog_status_threshold, } }, { label => 'stratum-level', set => { key_values => [ { name => 'stratum_level' } ], output_template => 'Stratum level : %d', perfdatas => [ { label => 'stratum_level', value => 'stratum_level', template => '%d', min => 0, max => 16 }, ], } }, { label => 'precision', set => { key_values => [ { name => 'precision' } ], output_template => 'Precision : %s seconds', perfdatas => [ { label => 'precision', value => 'precision', template => '%s', min => 0, unit => "seconds" }, ], } }, { label => 'poll-interval', set => { key_values => [ { name => 'poll_interval' } ], output_template => 'Poll interval : %d seconds', perfdatas => [ { label => 'poll_interval', value => 'poll_interval', template => '%d', min => 0, unit => "seconds" }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning-status:s" => { name => 'warning_status', default => '%{health} !~ /No leap second today/' }, "critical-status:s" => { name => 'critical_status', default => '' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub manage_selection { my ($self, %options) = @_; my $oid_ntp_leap_id = ".1.3.6.1.4.1.45561.1.1.1.4.0"; my $oid_ntp_stratum_level = ".1.3.6.1.4.1.45561.1.1.1.5.0"; my $oid_ntp_precision = ".1.3.6.1.4.1.45561.1.1.1.6.0"; my $oid_ntp_poll_interval = ".1.3.6.1.4.1.45561.1.1.1.11.0"; my $snmp_result = $options{snmp}->get_leef(oids => [ $oid_ntp_leap_id, $oid_ntp_stratum_level, $oid_ntp_precision, $oid_ntp_poll_interval ]); $self->{global} = { leap => $snmp_result->{$oid_ntp_leap_id}, stratum_level => $snmp_result->{$oid_ntp_stratum_level}, precision => (2 ** $snmp_result->{$oid_ntp_precision}), poll_interval => $snmp_result->{$oid_ntp_poll_interval}, }; } 1; __END__ =head1 MODE Check NTP performances =over 8 =item B<--warning-status> Set warning threshold for status (Default: '%{health} !~ /No leap second today/') Can used special variables like: %{leap} =item B<--critical-status> Set critical threshold for status (Default: '') Can used special variables like: %{health} =item B<--warning-*> Threshold warning. Can be : 'stratum-level', 'precision', 'poll-interval' =item B<--critical-*> Threshold critical. Can be : 'stratum-level', 'precision', 'poll-interval' =back =cut centreon-plugins-20220113/hardware/devices/masterclock/ntp100gps/snmp/plugin.pm000066400000000000000000000027121417000230700273310ustar00rootroot00000000000000# # Copyright 2015 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::devices::masterclock::ntp100gps::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}} = ( 'gps-status' => 'hardware::devices::masterclock::ntp100gps::snmp::mode::gpsstatus', 'ntp-performance' => 'hardware::devices::masterclock::ntp100gps::snmp::mode::ntpperformance', 'uptime' => 'snmp_standard::mode::uptime', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Masterclock NTP100-GPS NTP servers through SNMP =cut centreon-plugins-20220113/hardware/devices/nvidia/000077500000000000000000000000001417000230700217255ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/nvidia/gpu/000077500000000000000000000000001417000230700225205ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/nvidia/gpu/smi/000077500000000000000000000000001417000230700233105ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/nvidia/gpu/smi/mode/000077500000000000000000000000001417000230700242345ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/nvidia/gpu/smi/mode/stats.pm000066400000000000000000000344011417000230700257320ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::nvidia::gpu::smi::mode::stats; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use XML::LibXML::Simple; sub custom_memory_usage_output { my ($self, %options) = @_; my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); return sprintf( "memory usage total: %s used: %s (%.2f%%) free: %s (%.2f%%)", $total_size_value . " " . $total_size_unit, $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}, $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free} ); } sub device_long_output { my ($self, %options) = @_; return "checking device gpu '" . $options{instance} . "'"; } sub prefix_device_output { my ($self, %options) = @_; return "Device gpu '" . $options{instance} . "' "; } sub prefix_util_output { my ($self, %options) = @_; return 'utilization '; } sub prefix_fb_output { my ($self, %options) = @_; return 'frame buffer '; } sub prefix_bar1_output { my ($self, %options) = @_; return 'bar1 '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'devices', type => 3, cb_prefix_output => 'prefix_device_output', cb_long_output => 'device_long_output', indent_long_output => ' ', message_multiple => 'All devices are ok', group => [ { name => 'util', cb_prefix_output => 'prefix_util_output', type => 0, skipped_code => { -10 => 1 } }, { name => 'fb', type => 0, cb_prefix_output => 'prefix_fb_output', skipped_code => { -10 => 1 } }, { name => 'bar1', type => 0, cb_prefix_output => 'prefix_bar1_output', skipped_code => { -10 => 1 } }, { name => 'fan', type => 0, skipped_code => { -10 => 1 } }, { name => 'temp', type => 0, skipped_code => { -10 => 1 } }, { name => 'power', type => 0, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'devices-gpu-total', nlabel => 'devices.gpu.total.count', display_ok => 0, set => { key_values => [ { name => 'devices'} ], output_template => 'total gpu devices: %s', perfdatas => [ { template => '%s', min => 0 }, ] } } ]; $self->{maps_counters}->{util} = [ { label => 'gpu-utilization', nlabel => 'device.gpu.utilization.percentage', set => { key_values => [ { name => 'gpu_util' } ], output_template => 'gpu: %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 } ] } }, { label => 'gpu-memory-utilization', nlabel => 'device.gpu.memory.utilization.percentage', set => { key_values => [ { name => 'mem_util' } ], output_template => 'memory: %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 } ] } }, { label => 'gpu-encoder-utilization', nlabel => 'device.gpu.encoder.utilization.percentage', set => { key_values => [ { name => 'encoder_util' } ], output_template => 'encoder: %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 } ] } }, { label => 'gpu-decoder-utilization', nlabel => 'device.gpu.decoder.utilization.percentage', set => { key_values => [ { name => 'decoder_util' } ], output_template => 'decoder: %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{fb} = [ { label => 'fb-memory-usage', nlabel => 'device.gpu.frame_buffer.memory.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_memory_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1, label_extra_instance => 1 } ] } }, { label => 'fb-memory-usage-free', display_ok => 0, nlabel => 'device.gpu.frame_buffer.memory.free.bytes', set => { key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_memory_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1, label_extra_instance => 1 } ] } }, { label => 'fb-memory-usage-prct', display_ok => 0, nlabel => 'device.gpu.frame_buffer.memory.usage.percentage', set => { key_values => [ { name => 'prct_used' }, { name => 'free' }, { name => 'used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_memory_usage_output'), perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{bar1} = [ { label => 'bar1-memory-usage', nlabel => 'device.gpu.bar1.memory.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_memory_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1, label_extra_instance => 1 } ] } }, { label => 'bar1-memory-usage-free', display_ok => 0, nlabel => 'device.gpu.bar1.memory.free.bytes', set => { key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_memory_usage_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1, label_extra_instance => 1 } ] } }, { label => 'bar1-memory-usage-prct', display_ok => 0, nlabel => 'device.gpu.bar1.memory.usage.percentage', set => { key_values => [ { name => 'prct_used' }, { name => 'free' }, { name => 'used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_memory_usage_output'), perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{fan} = [ { label => 'fan-speed', nlabel => 'device.gpu.fan.speed.percentage', set => { key_values => [ { name => 'speed' } ], output_template => 'fan speed: %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{temp} = [ { label => 'temperature', nlabel => 'device.gpu.temperature.celsius', set => { key_values => [ { name => 'current' } ], output_template => 'gpu temperature: %s C', perfdatas => [ { template => '%s', unit => 'C', label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{power} = [ { label => 'power', nlabel => 'device.gpu.power.consumption.watt', set => { key_values => [ { name => 'current' } ], output_template => 'power consumption: %s W', perfdatas => [ { template => '%s', min => 0, unit => 'W', label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } sub get_bytes { my ($self, %options) = @_; return undef if ($options{value} !~ /(\d+)\s*([a-zA-Z]+)/); my ($value, $unit) = ($1, $2); if ($unit =~ /KiB*/i) { $value = $value * 1024; } elsif ($unit =~ /MiB*/i) { $value = $value * 1024 * 1024; } elsif ($unit =~ /GiB*/i) { $value = $value * 1024 * 1024 * 1024; } elsif ($unit =~ /TiB*/i) { $value = $value * 1024 * 1024 * 1024 * 1024; } return $value; } sub manage_selection { my ($self, %options) = @_; my ($stdout) = $options{custom}->execute_command( command => 'nvidia-smi', command_options => '-q -x' ); my $decoded; eval { $SIG{__WARN__} = sub {}; $decoded = XMLin($stdout, KeyAttr => [], ForceArray => ['gpu']); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode xml response: $@"); $self->{output}->option_exit(); } $self->{global} = { devices => 0 }; $self->{devices} = {}; foreach my $entry (@{$decoded->{gpu}}) { my $name = $entry->{product_name} . ':' . $entry->{id}; 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 device '" . $name . "'.", debug => 1); next; } $self->{devices}->{$name} = { util => {} }; if (defined($entry->{utilization}->{gpu_util}) && $entry->{utilization}->{gpu_util} =~ /([0-9\.]+)\s*%/) { $self->{devices}->{$name}->{util}->{gpu_util} = $1; } if (defined($entry->{utilization}->{memory_util}) && $entry->{utilization}->{memory_util} =~ /([0-9\.]+)\s*%/) { $self->{devices}->{$name}->{util}->{mem_util} = $1; } if (defined($entry->{utilization}->{encoder_util}) && $entry->{utilization}->{encoder_util} =~ /([0-9\.]+)\s*%/) { $self->{devices}->{$name}->{util}->{encoder_util} = $1; } if (defined($entry->{utilization}->{decoder_util}) && $entry->{utilization}->{decoder_util} =~ /([0-9\.]+)\s*%/) { $self->{devices}->{$name}->{util}->{decoder_util} = $1; } if (defined($entry->{fb_memory_usage})) { my $total = $self->get_bytes(value => $entry->{fb_memory_usage}->{total}); my $used = $self->get_bytes(value => $entry->{fb_memory_usage}->{used}); my $free = $self->get_bytes(value => $entry->{fb_memory_usage}->{free}); $self->{devices}->{$name}->{fb} = { total => $total, used => $used, free => $free, prct_used => $used * 100 / $total, prct_free => 100 - ($used * 100 / $total) }; } if (defined($entry->{bar1_memory_usage})) { my $total = $self->get_bytes(value => $entry->{bar1_memory_usage}->{total}); my $used = $self->get_bytes(value => $entry->{bar1_memory_usage}->{used}); my $free = $self->get_bytes(value => $entry->{bar1_memory_usage}->{free}); $self->{devices}->{$name}->{bar1} = { total => $total, used => $used, free => $free, prct_used => $used * 100 / $total, prct_free => 100 - ($used * 100 / $total) }; } if (defined($entry->{fan_speed}) && $entry->{fan_speed} =~ /([0-9\.]+)\s*%/) { $self->{devices}->{$name}->{fan} = { speed => $1 }; } if (defined($entry->{temperature}) && $entry->{temperature}->{gpu_temp} =~ /([0-9\.]+)\s*C/) { $self->{devices}->{$name}->{temp} = { current => $1 }; } if (defined($entry->{power_readings}) && $entry->{power_readings}->{power_draw} =~ /([0-9\.]+)\s*W/) { $self->{devices}->{$name}->{power} = { current => $1 }; } $self->{global}->{devices}++; } } 1; __END__ =head1 MODE Check GPU statistics. Command used: nvidia-smi -q -x =over 8 =item B<--filter-name> Filter gpu devices by name (can be a regexp). =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'devices-gpu-total', 'bar1-memory-usage', 'bar1-memory-usage-free', 'bar1-memory-usage-prct', 'fb-memory-usage', 'fb-memory-usage-free', 'fb-memory-usage-prct', 'gpu-utilization', 'gpu-memory-utilization', 'gpu-encoder-utilization', 'gpu-decoder-utilization', 'temperature', 'fan-speed', 'power'. =back =cut centreon-plugins-20220113/hardware/devices/nvidia/gpu/smi/plugin.pm000066400000000000000000000025361417000230700251520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::nvidia::gpu::smi::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} = { 'stats' => 'hardware::devices::nvidia::gpu::smi::mode::stats' }; $self->{custom_modes}->{cli} = 'centreon::plugins::script_custom::cli'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check NVIDIA GPU devices using system management interface program (smi). =cut centreon-plugins-20220113/hardware/devices/pexip/000077500000000000000000000000001417000230700216005ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/pexip/infinity/000077500000000000000000000000001417000230700234315ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/pexip/infinity/managementapi/000077500000000000000000000000001417000230700262375ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/pexip/infinity/managementapi/custom/000077500000000000000000000000001417000230700275515ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/pexip/infinity/managementapi/custom/api.pm000066400000000000000000000160351417000230700306650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::pexip::infinity::managementapi::custom::api; use strict; use warnings; use centreon::plugins::http; use JSON::XS; 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 => { 'api-username:s' => { name => 'api_username' }, 'api-password:s' => { name => 'api_password' }, 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port' }, 'proto:s' => { name => 'proto' }, 'timeout:s' => { name => 'timeout' }, 'unknown-http-status:s' => { name => 'unknown_http_status' }, 'warning-http-status:s' => { name => 'warning_http_status' }, 'critical-http-status:s' => { name => 'critical_http_status' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : ''; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : ''; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300'; $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } if ($self->{api_username} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-username option."); $self->{output}->option_exit(); } if ($self->{api_password} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-password option."); $self->{output}->option_exit(); } return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{credentials} = 1; $self->{option_results}->{basic} = 1; $self->{option_results}->{username} = $self->{api_username}; $self->{option_results}->{password} = $self->{api_password}; } sub settings { my ($self, %options) = @_; return if (defined($self->{settings_done})); $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->add_header(key => 'Content-Type', value => 'application/json'); $self->{http}->set_options(%{$self->{option_results}}); $self->{settings_done} = 1; } sub get_hostname { my ($self, %options) = @_; return $self->{hostname}; } sub get_port { my ($self, %options) = @_; return $self->{port}; } sub request_api { my ($self, %options) = @_; $self->settings(); my $results = []; my ($limit, $offset) = (1000, 0); my $get_param = defined($options{get_param}) ? $options{get_param} : []; while (1) { my $content = $self->{http}->request( url_path => $options{endpoint}, get_param => ['limit=' . $limit, 'offset=' . $offset, @$get_param], unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status} ); if (!defined($content) || $content eq '') { $self->{output}->add_option_msg(short_msg => "API returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@ || !defined($decoded->{objects})) { $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } push @$results, @{$decoded->{objects}}; if (($limit + $offset) > $decoded->{meta}->{total_count}) { last; } $offset += $limit; } return $results; } 1; __END__ =head1 NAME Pexip Infinity management API =head1 REST API OPTIONS Pexip Infinity management API =over 8 =item B<--hostname> Pexip manager hostname. =item B<--port> Port used (Default: 443) =item B<--proto> Specify https if needed (Default: 'https') =item B<--api-username> API username. =item B<--api-password> API password. =item B<--timeout> Set timeout in seconds (Default: 10). =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/hardware/devices/pexip/infinity/managementapi/mode/000077500000000000000000000000001417000230700271635ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/pexip/infinity/managementapi/mode/alarms.pm000066400000000000000000000124661417000230700310110ustar00rootroot00000000000000# # Copyright 2018 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::devices::pexip::infinity::managementapi::mode::alarms; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::statefile; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf( 'alarm [level: %s] [name: %s] [details: %s] %s', $self->{result_values}->{level}, $self->{result_values}->{name}, $self->{result_values}->{details}, centreon::plugins::misc::change_seconds(value => $self->{result_values}->{opened}) ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'alarms', type => 2, message_multiple => '0 problem(s) detected', display_counter_problem => { nlabel => 'alerts.problems.current.count', min => 0 }, group => [ { name => 'alarm', skipped_code => { -11 => 1 } } ] } ]; $self->{maps_counters}->{alarm} = [ { label => 'status', type => 2, warning_default => '%{level} =~ /warning|minor/i', critical_default => '%{level} =~ /critical|major|error/i', set => { key_values => [ { name => 'name' }, { name => 'level' }, { name => 'details' }, { name => 'opened' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'memory' => { name => 'memory' } }); centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'Date::Parse', error_msg => "Cannot load module 'Date::Parse'." ); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->check_options(%options); } } sub manage_selection { my ($self, %options) = @_; $self->{alarms}->{global} = { alarm => {} }; my $results = $options{custom}->request_api(endpoint => '/api/admin/status/v1/alarm/'); my $last_time; if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->read(statefile => 'cache_pexip_' . $options{custom}->get_hostname() . '_' . $options{custom}->get_port(). '_' . $self->{mode}); $last_time = $self->{statefile_cache}->get(name => 'last_time'); } my ($i, $current_time) = (1, time()); foreach my $alarm (@$results) { my $create_time = Date::Parse::str2time($alarm->{time_raised}, 'UTC'); if (!defined($create_time)) { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => "Can't Parse date '" . $alarm->{time_raised} . "'" ); next; } next if (defined($self->{option_results}->{memory}) && defined($last_time) && $last_time > $create_time); if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $alarm->{name} !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $alarm->{name} . "': no matching filter.", debug => 1); next; } my $diff_time = $current_time - $create_time; $self->{alarms}->{global}->{alarm}->{$i} = { %$alarm, opened => $diff_time }; $i++; } if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->write(data => { last_time => $current_time }); } } 1; __END__ =head1 MODE Check alarms. =over 8 =item B<--filter-name> Filter by alert name (can be a regexp). =item B<--warning-status> Set warning threshold for status (Default: '%{level} =~ /warning|minor/i') Can used special variables like: %{level}, %{details}, %{name} =item B<--critical-status> Set critical threshold for status (Default: '%{level} =~ /critical|major|error/i'). Can used special variables like: %{level}, %{details}, %{name} =item B<--memory> Only check new alarms. =back =cut centreon-plugins-20220113/hardware/devices/pexip/infinity/managementapi/mode/conferences.pm000066400000000000000000000155441417000230700320240ustar00rootroot00000000000000# # Copyright 2018 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::devices::pexip::infinity::managementapi::mode::conferences; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::statefile; use POSIX; use Time::HiRes; use Digest::MD5 qw(md5_hex); sub prefix_quality_output { my ($self, %options) = @_; return 'Participants call quality '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'conferences', type => 0, skipped_code => { -10 => 1 } }, { name => 'participants_quality', type => 0, cb_prefix_output => 'prefix_quality_output', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{conferences} = [ { label => 'conferences-total', nlabel => 'conferences.total.count', set => { key_values => [ { name => 'total_conferences' } ], output_template => 'conferences total: %d', perfdatas => [ { template => '%d', min => 0 } ] } }, { label => 'participants-total', nlabel => 'participants.total.count', set => { key_values => [ { name => 'total_participants' } ], output_template => 'participants total: %d', perfdatas => [ { template => '%d', min => 0 } ] } }, ]; $self->{maps_counters}->{participants_quality} = []; foreach (('good', 'ok', 'bad', 'terrible', 'unknown')) { push @{$self->{maps_counters}->{participants_quality}}, { label => 'participants-callquality-' . $_, nlabel => 'participants.callquality.' . $_ . '.count', set => { key_values => [ { name => $_ }, { name => 'total' } ], output_template => $_ . ': %s', perfdatas => [ { template => '%d', min => 0, max => 'total' } ] } }; } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $self->{version} = '1.0'; $options{options}->add_options(arguments => { }); centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'Date::Parse', error_msg => "Cannot load module 'Date::Parse'." ); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{statefile_cache}->check_options(%options); } sub manage_selection { my ($self, %options) = @_; $self->{statefile_cache}->read( statefile => 'cache_pexip_' . $options{custom}->{hostname} . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) ); my $last_conference_endtime = $self->{statefile_cache}->get(name => 'last_conference_endtime'); if (!defined($last_conference_endtime)) { $last_conference_endtime = Time::HiRes::time(); } my $date_end = POSIX::strftime('%Y-%m-%dT%H:%M:%S', gmtime($last_conference_endtime)); $date_end .= sprintf('.%06d', ($last_conference_endtime - int($last_conference_endtime)) * 1000000); my $conferences = $options{custom}->request_api( endpoint => '/api/admin/history/v1/conference/', get_param => ['end_time__gt=' . $date_end] ); $self->{conferences} = { total_participants => 0, total_conferences => 0 }; $self->{participants_quality} = { total => 0, unknown => 0, ok => 0, good => 0, bad => 0, terrible => 0 }; my $conference_ids = {}; my ($conf_min_starttime, $conf_max_endtime) = (0, 0); foreach (@$conferences) { $self->{conferences}->{total_conferences}++; $conference_ids->{ $_->{id} } = 1; my $tmp_time = Date::Parse::str2time($_->{start_time}); if (!defined($tmp_time)) { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => "can't parse date '" . $_->{start_time} . "'" ); next; } $conf_min_starttime = $tmp_time if ($conf_min_starttime == 0 || $conf_min_starttime > $tmp_time); $tmp_time = Date::Parse::str2time($_->{end_time}); if (!defined($tmp_time)) { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => "can't parse date '" . $_->{end_time} . "'" ); next; } $conf_max_endtime = $tmp_time if ($conf_max_endtime < $tmp_time); } $self->{statefile_cache}->write(data => { last_conference_endtime => $last_conference_endtime }); return if ($conf_min_starttime == 0); my $date_end2 = POSIX::strftime('%Y-%m-%dT%H:%M:%S', gmtime($conf_max_endtime + 1)); $date_end2 .= sprintf('.%06d', ($conf_max_endtime - int($conf_max_endtime)) * 1000000); my $date_start2 = POSIX::strftime('%Y-%m-%dT%H:%M:%S', gmtime($conf_min_starttime - 1)); $date_start2 .= sprintf('.%06d', ($conf_min_starttime - int($conf_min_starttime)) * 1000000); my $participants = $options{custom}->request_api( endpoint => '/api/admin/history/v1/participant/', get_param => ['start_time__gte=' . $date_start2, 'end_time__lte=' . $date_end2] ); foreach (@$participants) { next if ($_->{conference} !~ /conference\/(.*?)\/$/ && !defined($conference_ids->{ $1 })); $self->{conferences}->{total_participants}++; $self->{participants_quality}->{total}++; my ($num, $label) = split(/_/, $_->{call_quality}); if (defined($self->{participants_quality}->{ lc($label) })) { $self->{participants_quality}->{ lc($label) }++; } } } 1; __END__ =head1 MODE Check conferences and participants. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'conferences-total', 'participants-total', 'participants-callquality-good', 'participants-callquality-ok', 'participants-callquality-bad', 'participants-callquality-terrible', 'participants-callquality-unknown'. =back =cut centreon-plugins-20220113/hardware/devices/pexip/infinity/managementapi/mode/licenses.pm000066400000000000000000000152171417000230700313340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::pexip::infinity::managementapi::mode::licenses; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_license_output { my ($self, %options) = @_; return sprintf( 'total: %s used: %s (%.2f%%) free: %s (%.2f%%)', $self->{result_values}->{total}, $self->{result_values}->{used}, $self->{result_values}->{prct_used}, $self->{result_values}->{free}, $self->{result_values}->{prct_free} ); } sub licenses_long_output { my ($self, %options) = @_; return 'checking licenses'; } sub prefix_audio_output { my ($self, %options) = @_; return 'audio '; } sub prefix_port_output { my ($self, %options) = @_; return 'port '; } sub prefix_vmr_output { my ($self, %options) = @_; return 'vmr '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'licenses', type => 3, cb_long_output => 'licenses_long_output', indent_long_output => ' ', group => [ { name => 'audio', type => 0, display_short => 0, cb_prefix_output => 'prefix_audio_output', skipped_code => { -10 => 1 } }, { name => 'port', type => 0, display_short => 0, cb_prefix_output => 'prefix_port_output', skipped_code => { -10 => 1 } }, { name => 'vmr', type => 0, display_short => 0, cb_prefix_output => 'prefix_vmr_output', skipped_code => { -10 => 1 } } ] } ]; foreach (('audio', 'port', 'vmr')) { $self->{maps_counters}->{$_} = [ { label => 'license-' . $_ . '-usage', nlabel => 'license.' . $_ . '.usage.count', set => { key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_license_output'), perfdatas => [ { template => '%d', min => 0, max => 'total' } ] } }, { label => 'license-'. $_ . '-free', display_ok => 0, nlabel => 'license.' . $_ . '.free.count', set => { key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_license_output'), perfdatas => [ { template => '%d', min => 0, max => 'total' } ] } }, { label => 'license-' . $_ . '-usage-prct', display_ok => 0, nlabel => 'license.' . $_ . '.usage.percentage', set => { key_values => [ { name => 'prct_used' }, { name => 'used' }, { name => 'free' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_license_output'), perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%' } ] } } ]; } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $licenses = $options{custom}->request_api( endpoint => '/api/admin/status/v1/licensing/' ); $self->{output}->output_add(short_msg => 'Licenses are ok'); $self->{licenses} = { global => { audio => {}, port => {}, vmr => {} } }; if ($licenses->[0]->{audio_total} > 0) { $self->{licenses}->{global}->{audio}->{used} = $licenses->[0]->{audio_count}; $self->{licenses}->{global}->{audio}->{total} = $licenses->[0]->{audio_total}; $self->{licenses}->{global}->{audio}->{free} = $licenses->[0]->{audio_total} - $licenses->[0]->{audio_count}; $self->{licenses}->{global}->{audio}->{prct_used} = $self->{licenses}->{global}->{audio}->{used} * 100 / $self->{licenses}->{global}->{audio}->{total}; $self->{licenses}->{global}->{audio}->{prct_free} = 100 - $self->{licenses}->{global}->{audio}->{prct_used}; } if ($licenses->[0]->{port_total} > 0) { $self->{licenses}->{global}->{port}->{used} = $licenses->[0]->{port_count}; $self->{licenses}->{global}->{port}->{total} = $licenses->[0]->{port_total}; $self->{licenses}->{global}->{port}->{free} = $licenses->[0]->{port_total} - $licenses->[0]->{port_count}; $self->{licenses}->{global}->{port}->{prct_used} = $self->{licenses}->{global}->{port}->{used} * 100 / $self->{licenses}->{global}->{port}->{total}; $self->{licenses}->{global}->{port}->{prct_free} = 100 - $self->{licenses}->{global}->{port}->{prct_used}; } if ($licenses->[0]->{vmr_total} > 0) { $self->{licenses}->{global}->{vmr}->{used} = $licenses->[0]->{vmr_count}; $self->{licenses}->{global}->{vmr}->{total} = $licenses->[0]->{vmr_total}; $self->{licenses}->{global}->{vmr}->{free} = $licenses->[0]->{vmr_total} - $licenses->[0]->{vmr_count}; $self->{licenses}->{global}->{vmr}->{prct_used} = $self->{licenses}->{global}->{vmr}->{used} * 100 / $self->{licenses}->{global}->{vmr}->{total}; $self->{licenses}->{global}->{vmr}->{prct_free} = 100 - $self->{licenses}->{global}->{vmr}->{prct_used}; } } 1; __END__ =head1 MODE Check licenses. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='audio' =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'license-port-usage', 'license-port-free', 'license-port-usage-prct', 'license-vmr-usage', 'license-vmr-free', 'license-vmr-usage-prct', 'license-audio-usage', 'license-audio-free', 'license-audio-usage-prct'. =back =cut centreon-plugins-20220113/hardware/devices/pexip/infinity/managementapi/plugin.pm000066400000000000000000000032611417000230700300750ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::pexip::infinity::managementapi::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} = { 'alarms' => 'hardware::devices::pexip::infinity::managementapi::mode::alarms', 'conferences' => 'hardware::devices::pexip::infinity::managementapi::mode::conferences', 'licenses' => 'hardware::devices::pexip::infinity::managementapi::mode::licenses' }; $self->{custom_modes}->{api} = 'hardware::devices::pexip::infinity::managementapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Pexip Infinity using management API. If you use http curl backend (try: --curl-opt="CURLOPT_SSL_VERIFYPEER => 0" --curl-opt="CURLOPT_SSL_VERIFYHOST => 0") =cut centreon-plugins-20220113/hardware/devices/polycom/000077500000000000000000000000001417000230700221355ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/polycom/dma/000077500000000000000000000000001417000230700226765ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/polycom/dma/snmp/000077500000000000000000000000001417000230700236535ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/polycom/dma/snmp/mode/000077500000000000000000000000001417000230700245775ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/polycom/dma/snmp/mode/alerts.pm000066400000000000000000000162741417000230700264410ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::polycom::dma::snmp::mode::alerts; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::statefile; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; return sprintf( "alarm [code: %s] [severity: %s] [description: %s] %s", $self->{result_values}->{code}, $self->{result_values}->{severity}, $self->{result_values}->{description}, $self->{result_values}->{timestamp} ); } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{code} = $options{new_datas}->{$self->{instance} . '_alActAlertCode'}; $self->{result_values}->{severity} = $options{new_datas}->{$self->{instance} . '_alActAlertSeverity'}; $self->{result_values}->{description} = $options{new_datas}->{$self->{instance} . '_alActAlertDescription'}; $self->{result_values}->{timestamp} = $options{new_datas}->{$self->{instance} . '_alActAlertTimestamp'}; $self->{result_values}->{since} = $options{new_datas}->{$self->{instance} . '_since'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'alerts', type => 2, message_multiple => 'No problem detected', display_counter_problem => { label => 'dma.alerts.total.count', min => 0 }, group => [ { name => 'alert', skipped_code => { -11 => 1 } } ] } ]; $self->{maps_counters}->{alert} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'alActAlertCode' }, { name => 'alActAlertSeverity' }, { name => 'since' }, { name => 'alActAlertDescription' }, { name => 'alActAlertTimestamp' } ], 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 => \&catalog_status_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 => { 'filter-msg:s' => { name => 'filter_msg' }, 'warning-status:s' => { name => 'warning_status', default => '%{severity} =~ /warn/i' }, 'critical-status:s' => { name => 'critical_status', default => '%{severity} =~ /severe/i' }, 'memory' => { name => 'memory' } }); centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'Date::Parse', error_msg => "Cannot load module 'Date::Parse'." ); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->check_options(%options); } } my %map_severity = (0 => 'warn', 1 => 'severe', 2 => 'critical'); my $mapping = { alActAlertTimestamp => { oid => '.1.3.6.1.4.1.13885.13.2.4.1.2.1.3' }, alActAlertCode => { oid => '.1.3.6.1.4.1.23916.3.1.4.1.4' }, alActAlertSeverity => { oid => '.1.3.6.1.4.1.23916.3.1.4.1.6' }, alActAlertDescription => { oid => '.1.3.6.1.4.1.23916.3.1.4.1.13', map => \%map_severity } }; my $oid_alActiveAlertsEntry = '.1.3.6.1.4.1.13885.13.2.4.1.2.1'; sub manage_selection { my ($self, %options) = @_; $self->{alerts}->{global} = { alarm => {} }; my $alert_result = $options{snmp}->get_table( oid => $oid_alActiveAlertsEntry, nothing_quit => 0 ); my $last_time; if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->read(statefile => 'cache_polycom_dma_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port(). '_' . $self->{mode}); $last_time = $self->{statefile_cache}->get(name => 'last_time'); } my ($i, $current_time) = (1, time()); foreach my $oid (keys %{$alert_result}) { next if ($oid !~ /^$mapping->{alActAlertSeverity}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $alert_result, instance => $instance); my $create_time = Date::Parse::str2time($result->{msgGenerationTime}); if (!defined($create_time)) { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => "Can't Parse date '" . $result->{msgGenerationTime} . "'" ); next; } next if (defined($self->{option_results}->{memory}) && defined($last_time) && $last_time > $create_time); if (defined($self->{option_results}->{filter_msg}) && $self->{option_results}->{filter_msg} ne '' && $result->{filter_severity} !~ /$self->{option_results}->{filter_msg}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{filter_severity} . "': no matching filter.", debug => 1); next; } if (defined($self->{option_results}->{filter_severity}) && $self->{option_results}->{filter_severity} ne '' && $result->{alActAlertSeverity} !~ /$self->{option_results}->{filter_severity}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{alActAlertSeverity} . "': no matching filter.", debug => 1); next; } my $diff_time = $current_time - $create_time; $self->{alerts}->{global}->{alert}->{$i} = { %$result, since => $diff_time }; $i++; } if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->write(data => { last_time => $current_time }); } } 1; __END__ =head1 MODE Check alerts. =over 8 =item B<--filter-msg> Filter by message (can be a regexp). =item B<--warning-status> Set warning threshold for status (Default: '%{severity} =~ /warn/i') Can use special variables like: %{severity}, %{text}, %{code}, %{since} =item B<--critical-status> Set critical threshold for status (Default: '%{severity} =~ /severe/i'). Can use special variables like: %{severity}, %{text}, %{source}, %{since} =item B<--memory> Only check new alarms. =back =cut centreon-plugins-20220113/hardware/devices/polycom/dma/snmp/mode/clusters.pm000066400000000000000000000216271417000230700270110ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::polycom::dma::snmp::mode::clusters; use base qw(centreon::plugins::templates::counter); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'cluster', type => 1, cb_prefix_output => 'prefix_cluster_output', message_multiple => 'All clusters are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'dma-total-clusters', nlabel => 'dma.clusters.total.count', set => { key_values => [ { name => 'clusters_count' } ], output_template => 'Total clusters : %s', perfdatas => [ { template => '%d', min => 0 } ] } }, ]; $self->{maps_counters}->{cluster} = [ { label => 'cluster-status', type => 2, critical_default => '%{cluster_status} =~ /outOfService/i', display_ok => 0, set => { key_values => [ { name => 'cluster_status' }, { name => 'display' } ], closure_custom_output => $self->can('custom_cluster_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'license-status', type => 2, critical_default => '%{license_status} =~ /invalid/i', display_ok => 0, set => { key_values => [ { name => 'license_status' }, { name => 'display' } ], closure_custom_output => $self->can('custom_license_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } }, { label => 'cluster-active-calls', nlabel => 'dma.cluster.activecalls.count', set => { key_values => [ { name => 'active_calls' }, { name => 'licenses_total' }, { name => 'display' } ], output_template => 'Active calls : %s', perfdatas => [ { template => '%s', max => 'licenses_total', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'cluster-license-usage-free', nlabel => 'dma.cluster.licenses.free.count', set => { key_values => [ { name => 'licenses_free' }, { name => 'display' } ], output_template => 'Free licenses : %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'cluster-license-usage-prct', nlabel => 'dma.cluster.licenses.usage.percentage', set => { key_values => [ { name => 'licenses_used_prct' }, { name => 'display' } ], output_template => 'Licenses percentage usage : %.2f%%', perfdatas => [ { template => '%.2f', min => 0, unit => '%', label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub prefix_cluster_output { my ($self, %options) = @_; return "Cluster '" . $options{instance_value}->{display} . "' "; } sub custom_cluster_status_output { my ($self, %options) = @_; return sprintf('Cluster status: %s', $self->{result_values}->{cluster_status}); } sub custom_license_status_output { my ($self, %options) = @_; return sprintf('License status: %s', $self->{result_values}->{license_status}); } 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-cluster:s' => { name => 'filter_cluster' } }); return $self; } my %map_cluster_status = (1 => 'inService', 2 => 'busyOut', 3 => 'outOfService'); my %map_licensing_status = (1 => 'valid', 2 => 'invalid', 3 => 'notInstalled'); my $mapping_status = { stClClusterName => { oid => '.1.3.6.1.4.1.13885.13.2.2.3.2.1.2' }, stClClusterStatus => { oid => '.1.3.6.1.4.1.13885.13.2.2.3.2.1.3', map => \%map_cluster_status } }; my $mapping_licenses = { stLicClusterName => { oid => '.1.3.6.1.4.1.13885.13.2.2.3.3.1.2' }, stLicLicenseStatus => { oid => '.1.3.6.1.4.1.13885.13.2.2.3.3.1.3', map => \%map_licensing_status}, stLicLicensedCalls => { oid => '.1.3.6.1.4.1.13885.13.2.2.3.3.1.4' }, stLicCallserverActiveCalls => { oid => '.1.3.6.1.4.1.13885.13.2.2.3.3.1.5' } }; my $oid_stClustersEntry = '.1.3.6.1.4.1.13885.13.2.2.3.2.1'; my $oid_stLicensesEntry = '.1.3.6.1.4.1.13885.13.2.2.3.3.1'; my $oid_stClustersCount = '.1.3.6.1.4.1.13885.13.2.2.3.1.0'; #global sub manage_selection { my ($self, %options) = @_; my $global_result = $options{snmp}->get_leef( oids => [ $oid_stClustersCount ], nothing_quit => 1 ); $self->{global} = { clusters_count => $global_result->{$oid_stClustersCount} }; $self->{clusters_result} = {}; $self->{clusters_result} = $options{snmp}->get_multiple_table( oids => [ { oid => $oid_stClustersEntry }, { oid => $oid_stLicensesEntry } ], nothing_quit => 1 ); foreach my $oid (keys %{$self->{clusters_result}->{$oid_stClustersEntry}}) { next if ($oid !~ /^$mapping_status->{stClClusterName}->{oid}\.(.*)$/); my $instance = $1; my $result_status = $options{snmp}->map_instance(mapping => $mapping_status, results => $self->{clusters_result}->{$oid_stClustersEntry}, instance => $instance); my $result_licenses = $options{snmp}->map_instance(mapping => $mapping_licenses, results => $self->{clusters_result}->{$oid_stLicensesEntry}, instance => $instance); if (defined($self->{option_results}->{filter_cluster}) && $self->{option_results}->{filter_cluster} ne '' && $result_status->{stClClusterName} !~ /$self->{option_results}->{filter_cluster}/) { $self->{output}->output_add(long_msg => "skipping '" . $result_status->{stClClusterName} . "': no matching filter.", debug => 1); next; } my ($licenses_used, $licenses_total) = ($result_licenses->{stLicCallserverActiveCalls}, $result_licenses->{stLicLicensedCalls}); my $licenses_free = $licenses_total - $licenses_used; $self->{cluster}->{$instance} = { display => $result_status->{stClClusterName}, cluster_status => $result_status->{stClClusterStatus}, active_calls => $result_licenses->{stLicCallserverActiveCalls}, license_status => $result_licenses->{stLicLicenseStatus}, licenses_total => $licenses_total, licenses_free => $licenses_free, licenses_used_prct => ( $licenses_used * 100 ) / $licenses_total }; } } 1; __END__ =head1 MODE Check information about clusters in the Polycom DMA supercluster. =over 8 =item B<--filter-cluster> Filter on one or several cluster (POSIX regexp) =item B<--warning-cluster-status> Custom Warning threshold of the cluster state (Default: none) Syntax: --warning-cluster-status='%{cluster_status} =~ /busyOut/i' =item B<--critical-cluster-status> Custom Critical threshold of the cluster state (Default: '%{cluster_status} =~ /outOfService/i' ) Syntax: --critical-cluster-status='%{cluster_status} =~ /busyOut/i' =item B<--warning-license-status> Custom Warning threshold of the cluster license state (Default: none) Syntax: --warning-license-status='%{license_status} =~ /notinstalled/i' =item B<--critical-license-status> Custom Critical threshold of the cluster license state (Default: '%{license_status} =~ /invalid/i') Syntax: --critical-license-status='%{license_status} =~ /notinstalled/i' =item B<--warning-* --critical-*> Warning & Critical Thresholds for the collected metrics. Possible values: [PER-CLUSTER] cluster-active-calls cluster-license-usage-free cluster-license-usage-prct [GLOBAL] dma-total-clusters =back =cut centreon-plugins-20220113/hardware/devices/polycom/dma/snmp/mode/conferencemanager.pm000066400000000000000000000273131417000230700306050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::polycom::dma::snmp::mode::conferencemanager; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_video_port_output { my ($self, %options) = @_; return sprintf( 'video ports [total: %s used: %s (%.2f%%) free: %s (%.2f%%)]', $self->{result_values}->{vp_total}, $self->{result_values}->{vp_used}, $self->{result_values}->{vp_prct_used}, $self->{result_values}->{vp_free}, $self->{result_values}->{vp_prct_free} ); } sub custom_voice_port_output { my ($self, %options) = @_; return sprintf( 'voice ports [total: %s used: %s (%.2f%%) free: %s (%.2f%%)]', $self->{result_values}->{vop_total}, $self->{result_values}->{vop_used}, $self->{result_values}->{vop_prct_used}, $self->{result_values}->{vop_free}, $self->{result_values}->{vop_prct_free} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'cluster', type => 1, cb_prefix_output => 'prefix_cluster_output', message_multiple => 'All clusters are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'dma-total-conferences', nlabel => 'dma.conferences.active.count', set => { key_values => [ { name => 'useConfMgrUsageCount' } ], output_template => 'Total conferences : %s', perfdatas => [ { template => '%d', min => 0, instance_use => 'display', template => '%d', min => 0 } ] } } ]; $self->{maps_counters}->{cluster} = [ { label => 'cluster-conferences', nlabel => 'dma.cluster.conferences.active.count', set => { key_values => [ { name => 'useCMUsageActiveConfs' }, { name => 'display' } ], output_template => 'current conferences : %s', perfdatas => [ { template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'cluster-participants', nlabel => 'dma.cluster.participants.active.count', set => { key_values => [ { name => 'useCMUsageActiveParts' }, { name => 'display' } ], output_template => 'current participants : %s', perfdatas => [ { template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'cluster-local-users', nlabel => 'dma.cluster.local.database.users.count', set => { key_values => [ { name => 'useCMUsageLocalUsers' }, { name => 'display' } ], output_template => 'local users : %s', perfdatas => [ { template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'cluster-custom-rooms', nlabel => 'dma.cluster.custom.conference.rooms.count', set => { key_values => [ { name => 'useCMUsageCustomConfRooms' }, { name => 'display' } ], output_template => 'custom conference rooms : %s', perfdatas => [ { template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'cluster-video-ports-usage', nlabel => 'dma.cluster.video.port.usage.count', set => { key_values => [ { name => 'vp_used' }, { name => 'vp_free' }, { name => 'vp_prct_used' }, { name => 'vp_prct_free' }, { name => 'vp_total' }, { name => 'display' } ], closure_custom_output => $self->can('custom_video_port_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', cast_int => 1, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'cluster-video-ports-free', display_ok => 0, nlabel => 'dma.cluster.video.port.free.count', set => { key_values => [ { name => 'vp_free' }, { name => 'vp_used' }, { name => 'vp_prct_used' }, { name => 'vp_prct_free' }, { name => 'vp_total' }, { name => 'display' } ], closure_custom_output => $self->can('custom_video_port_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', cast_int => 1, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'cluster-video-ports-prct', display_ok => 0, nlabel => 'dma.cluster.video.port.percentage', set => { key_values => [ { name => 'vp_prct_used' }, { name => 'display' } ], output_template => 'video ports used: %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'cluster-voice-ports-usage', nlabel => 'dma.cluster.voice.port.usage.count', set => { key_values => [ { name => 'vop_used' }, { name => 'vop_free' }, { name => 'vop_prct_used' }, { name => 'vop_prct_free' }, { name => 'vop_total' }, { name => 'display' } ], closure_custom_output => $self->can('custom_voice_port_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', cast_int => 1, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'cluster-voice-ports-free', display_ok => 0, nlabel => 'dma.cluster.voice.port.free.count', set => { key_values => [ { name => 'vop_free' }, { name => 'vop_used' }, { name => 'vop_prct_used' }, { name => 'vop_prct_free' }, { name => 'vop_total' }, { name => 'display' } ], closure_custom_output => $self->can('custom_voice_port_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', cast_int => 1, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'cluster-voice-ports-prct', display_ok => 0, nlabel => 'dma.cluster.voice.port.percentage', set => { key_values => [ { name => 'vop_prct_used' }, { name => 'display' } ], output_template => 'voice ports used: %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' } ] } } ]; } 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-cluster:s' => { name => 'filter_cluster' } }); return $self; } sub prefix_cluster_output { my ($self, %options) = @_; return "Cluster '" . $options{instance_value}->{display} . "' "; } my $mapping = { useCMUsageClusterName => { oid => '.1.3.6.1.4.1.13885.13.2.3.2.1.2.1.2' }, useCMUsageActiveConfs => { oid => '.1.3.6.1.4.1.13885.13.2.3.2.1.2.1.3' }, useCMUsageActiveParts => { oid => '.1.3.6.1.4.1.13885.13.2.3.2.1.2.1.4' }, useCMUsageTotalVideoPorts => { oid => '.1.3.6.1.4.1.13885.13.2.3.2.1.2.1.5' }, useCMUsageUsedVideoPorts => { oid => '.1.3.6.1.4.1.13885.13.2.3.2.1.2.1.6' }, useCMUsageTotalVoicePorts => { oid => '.1.3.6.1.4.1.13885.13.2.3.2.1.2.1.7' }, useCMUsageUsedVoicePorts => { oid => '.1.3.6.1.4.1.13885.13.2.3.2.1.2.1.8' }, useCMUsageLocalUsers => { oid => '.1.3.6.1.4.1.13885.13.2.3.2.1.2.1.9' }, useCMUsageCustomConfRooms => { oid => '.1.3.6.1.4.1.13885.13.2.3.2.1.2.1.10' }, }; my $oid_useConfMgrUsageEntry = '.1.3.6.1.4.1.13885.13.2.3.2.1.2.1'; sub manage_selection { my ($self, %options) = @_; my $oid_useConfMgrUsageCount = '.1.3.6.1.4.1.13885.13.2.3.2.1.1.0'; my $global_result = $options{snmp}->get_leef(oids => [$oid_useConfMgrUsageCount], nothing_quit => 1); $self->{global} = { useConfMgrUsageCount => $global_result->{$oid_useConfMgrUsageCount} }; $self->{cluster} = {}; my $cluster_result = $options{snmp}->get_table( oid => $oid_useConfMgrUsageEntry, nothing_quit => 1 ); foreach my $oid (keys %{$cluster_result}) { next if ($oid !~ /^$mapping->{useCMUsageClusterName}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $cluster_result, instance => $instance); $result->{useCMUsageClusterName} = centreon::plugins::misc::trim($result->{useCMUsageClusterName}); if (defined($self->{option_results}->{filter_cluster}) && $self->{option_results}->{filter_cluster} ne '' && $result->{useCMUsageClusterName} !~ /$self->{option_results}->{filter_cluster}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{useCMUsageClusterName} . "': no matching filter.", debug => 1); next; } my ($video_port_used, $video_port_total) = ($result->{useCMUsageUsedVideoPorts},$result->{useCMUsageTotalVideoPorts}); my ($voice_port_used, $voice_port_total) = ($result->{useCMUsageUsedVoicePorts},$result->{useCMUsageTotalVoicePorts}); $self->{cluster}->{$instance} = { display => $result->{useCMUsageClusterName}, vp_free => $video_port_total - $video_port_used, vp_prct_free => ($video_port_total != 0) ? 100 - ($video_port_used * 100 / $video_port_total) : '0', vp_prct_used => ($video_port_total != 0) ? $video_port_used * 100 / $video_port_total : '0', vp_total => $video_port_total, vp_used => $video_port_used, vop_free => $voice_port_total - $voice_port_used, vop_prct_free => ($voice_port_total != 0) ? 100 - ($voice_port_used * 100 / $voice_port_total) : '0', vop_prct_used => ($voice_port_total != 0) ? $voice_port_used * 100 / $voice_port_total : '0', vop_total => $voice_port_total, vop_used => $voice_port_used, %$result, }; } } 1; __END__ =head1 MODE Check conferences metrics. =over 8 =item B<--filter-cluster> Filter on one or several cluster (POSIX regexp) =item B<--warning-* --critical-*> TWarning & Critical Thresholds. Possible values: [PER-CLUSTER] cluster-conferences, cluster-participants, cluster-local-users, cluster-custom-rooms, cluster-video-ports-usage, cluster-video-ports-free, cluster-video-ports-prct, cluster-voice-ports-usage, cluster-voice-ports-free, cluster-voice-ports-prct [GLOBAL] dma-total-conferences =back =cut centreon-plugins-20220113/hardware/devices/polycom/dma/snmp/mode/deviceregistrations.pm000066400000000000000000000121711417000230700312140ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::polycom::dma::snmp::mode::deviceregistrations; 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 }, { name => 'cluster', type => 1, cb_prefix_output => 'prefix_cluster_output', message_multiple => 'All clusters are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'dma-total-registrations', nlabel => 'dma.registrations.count', set => { key_values => [ { name => 'useDevRegistrationsCount' } ], output_template => 'Total registrations : %s', perfdatas => [ { template => '%d', min => 0 } ] } } ]; $self->{maps_counters}->{cluster} = [ { label => 'cluster-endpoint-active-registration', nlabel => 'dma.cluster.endpoint.registrations.active.count', set => { key_values => [ { name => 'useDevRegActiveEndpointReg' }, { name => 'display'} ], output_template => 'endpoint active registrations: %s', perfdatas => [ { template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'cluster-endpoint-inactive-registration', nlabel => 'dma.cluster.endpoint.registrations.inactive.count', set => { key_values => [ { name => 'useDevRegInactiveEndpointReg' }, { name => 'display'} ], output_template => 'endpoint inactive registrations: %s', perfdatas => [ { template => '%d', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } } ]; } 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-cluster:s' => { name => 'filter_cluster' }, }); return $self; } sub prefix_cluster_output { my ($self, %options) = @_; return "Cluster '" . $options{instance_value}->{display} . "' "; } my $mapping = { useDevRegClusterName => { oid => '.1.3.6.1.4.1.13885.13.2.3.3.1.2.1.2' }, useDevRegActiveEndpointReg => { oid => '.1.3.6.1.4.1.13885.13.2.3.3.1.2.1.3' }, useDevRegInactiveEndpointReg => { oid => '.1.3.6.1.4.1.13885.13.2.3.3.1.2.1.4' }, }; my $oid_useDevRegistrationsEntry = '.1.3.6.1.4.1.13885.13.2.3.3.1.2.1'; sub manage_selection { my ($self, %options) = @_; my $oid_useDevRegistrationsCount = '.1.3.6.1.4.1.13885.13.2.3.3.1.1.0'; my $global_result = $options{snmp}->get_leef( oids => [$oid_useDevRegistrationsCount], nothing_quit => 1 ); $self->{global} = { useDevRegistrationsCount => $global_result->{$oid_useDevRegistrationsCount} }; $self->{cluster} = {}; my $cluster_result = $options{snmp}->get_table( oid => $oid_useDevRegistrationsEntry, nothing_quit => 1 ); foreach my $oid (keys %{$cluster_result}) { next if ($oid !~ /^$mapping->{useDevRegClusterName}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $cluster_result, instance => $instance); $result->{useDevRegClusterName} = centreon::plugins::misc::trim($result->{useDevRegClusterName}); if (defined($self->{option_results}->{filter_cluster}) && $self->{option_results}->{filter_cluster} ne '' && $result->{useDevRegClusterName} !~ /$self->{option_results}->{filter_cluster}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{useDevRegClusterName} . "': no matching filter.", debug => 1); next; } $self->{cluster}->{$instance} = { display => $result->{useDevRegClusterName}, %$result }; } } 1; __END__ =head1 MODE Check global and per-cluster devices registrations metrics. =over 8 =item B<--filter-cluster> Filter on one or several cluster (POSIX regexp) =item B<--warning-* --critical-*> Warning & Critical Thresholds. Possible values: [PER-CLUSTER] cluster-endpoint-active-registration cluster-endpoint-inactive-registration [GLOBAL] dma-total-registrations =back =cut centreon-plugins-20220113/hardware/devices/polycom/dma/snmp/mode/serversusage.pm000066400000000000000000000422141417000230700276560ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::polycom::dma::snmp::mode::serversusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_memory_output { my ($self, %options) = @_; return sprintf( 'Memory Total: %s %s, Used: %s %s (%.2f%%), Free: %s %s (%.2f%%)', $self->{perfdata}->change_bytes(value => $self->{result_values}->{memory_total}), $self->{perfdata}->change_bytes(value => $self->{result_values}->{memory_used}), $self->{result_values}->{memory_prct_used}, $self->{perfdata}->change_bytes(value => $self->{result_values}->{memory_free}), $self->{result_values}->{memory_prct_free} ); } sub custom_swap_output { my ($self, %options) = @_; return sprintf( 'Swap Total: %s %s, Used: %s %s (%.2f%%), Free: %s %s (%.2f%%)', $self->{perfdata}->change_bytes(value => $self->{result_values}->{swap_total}), $self->{perfdata}->change_bytes(value => $self->{result_values}->{swap_used}), $self->{result_values}->{swap_prct_used}, $self->{perfdata}->change_bytes(value => $self->{result_values}->{swap_free}), $self->{result_values}->{swap_prct_free} ); } sub custom_disk_output { my ($self, %options) = @_; return sprintf( 'Disk Total: %s %s, Used: %s %s (%.2f%%), Free: %s %s (%.2f%%)', $self->{perfdata}->change_bytes(value => $self->{result_values}->{disk_total}), $self->{perfdata}->change_bytes(value => $self->{result_values}->{disk_used}), $self->{result_values}->{disk_prct_used}, $self->{perfdata}->change_bytes(value => $self->{result_values}->{disk_free}), $self->{result_values}->{disk_prct_free} ); } sub custom_logs_output { my ($self, %options) = @_; return sprintf( 'Logs Total: %s %s, Used: %s %s (%.2f%%), Free: %s %s (%.2f%%)', $self->{perfdata}->change_bytes(value => $self->{result_values}->{logs_total}), $self->{perfdata}->change_bytes(value => $self->{result_values}->{logs_used}), $self->{result_values}->{logs_prct_used}, $self->{perfdata}->change_bytes(value => $self->{result_values}->{logs_free}), $self->{result_values}->{logs_prct_free} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'server', type => 1, cb_prefix_output => 'prefix_server_output', message_multiple => 'All servers are ok' } ]; $self->{maps_counters}->{server} = [ { label => 'server-cpu-usage', nlabel => 'dma.server.cpu.utilization.percentage', set => { key_values => [ { name => 'stRsrcCPUUsageCPUUtilizationPct' }, { name => 'display'} ], output_template => 'CPU Utilization: %.2f %%', perfdatas => [ { template => '%d', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' } ] } }, # Memory counters { label => 'server-memory-usage', nlabel => 'dma.server.memory.usage.bytes', set => { key_values => [ { name => 'memory_used' }, { name => 'memory_free' }, { name => 'memory_prct_used' }, { name => 'memory_prct_free' }, { name => 'memory_total' }, { name => 'display' } ], closure_custom_output => $self->can('custom_memory_output'), perfdatas => [ { template => '%d', cast_int => 1, min => 0, max => 'memory_total', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'server-memory-free', display_ok => 0, nlabel => 'dma.server.memory.free.bytes', set => { key_values => [ { name => 'memory_free' }, { name => 'memory_used' }, { name => 'memory_prct_used' }, { name => 'memory_prct_free' }, { name => 'memory_total' }, { name => 'display' } ], closure_custom_output => $self->can('custom_memory_output'), perfdatas => [ { template => '%d', cast_int => 1, min => 0, max => 'memory_total', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'server-memory-prct', display_ok => 0, nlabel => 'dma.server.memory.usage.percentage', set => { key_values => [ { name => 'memory_prct_used' }, { name => 'display' } ], output_template => 'RAM used: %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' } ] } }, # Swap counters { label => 'server-swap-usage', nlabel => 'dma.server.swap.usage.percentage', set => { key_values => [ { name => 'swap_used' }, { name => 'swap_free' }, { name => 'swap_prct_used' }, { name => 'swap_prct_free' }, { name => 'swap_total' }, { name => 'display' } ], closure_custom_output => $self->can('custom_swap_output'), perfdatas => [ { template => '%d', cast_int => 1, min => 0, max => 'swap_total', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'server-swap-free', display_ok => 0, nlabel => 'dma.server.swap.free.bytes', set => { key_values => [ { name => 'swap_free' }, { name => 'swap_used' }, { name => 'swap_prct_used' }, { name => 'swap_prct_free' }, { name => 'swap_total' }, { name => 'display' } ], closure_custom_output => $self->can('custom_swap_output'), perfdatas => [ { template => '%d', cast_int => 1, min => 0, max => 'swap_total', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'server-swap-prct', display_ok => 0, nlabel => 'dma.server.swap.usage.percentage', set => { key_values => [ { name => 'swap_prct_used' }, { name => 'display' } ], output_template => 'swap used: %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' } ] } }, # Disk counters { label => 'server-disk-usage', nlabel => 'dma.server.disk.usage.bytes', set => { key_values => [ { name => 'disk_used' }, { name => 'disk_free' }, { name => 'disk_prct_used' }, { name => 'disk_prct_free' }, { name => 'disk_total' }, { name => 'display' } ], closure_custom_output => $self->can('custom_disk_output'), perfdatas => [ { template => '%d', min => 0, max => 'disk_total', cast_int => 1, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'server-disk-free', display_ok => 0, nlabel => 'dma.server.disk.free.bytes', set => { key_values => [ { name => 'disk_free' }, { name => 'disk_used' }, { name => 'disk_prct_used' }, { name => 'disk_prct_free' }, { name => 'disk_total' }, { name => 'display' } ], closure_custom_output => $self->can('custom_disk_output'), perfdatas => [ { template => '%d', cast_int => 1, min => 0, max => 'disk_total', label_extra_instance => 1, instance_use => 'display', } ] } }, { label => 'server-disk-prct', display_ok => 0, nlabel => 'dma.server.disk.usage.percentage', set => { key_values => [ { name => 'disk_prct_used' }, { name => 'display' } ], output_template => 'disk used: %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' } ] } }, # Log counters { label => 'server-logs-usage', nlabel => 'dma.server.logs.usage.bytes', set => { key_values => [ { name => 'logs_used' }, { name => 'logs_free' }, { name => 'logs_prct_used' }, { name => 'logs_prct_free' }, { name => 'logs_total' }, { name => 'display' } ], closure_custom_output => $self->can('custom_logs_output'), perfdatas => [ { template => '%d', cast_int => 1, min => 0, max => 'logs_total', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'server-logs-free', display_ok => 0, nlabel => 'dma.server.logs.free.bytes', set => { key_values => [ { name => 'logs_free' }, { name => 'logs_used' }, { name => 'logs_prct_used' }, { name => 'logs_prct_free' }, { name => 'logs_total' }, { name => 'display' } ], closure_custom_output => $self->can('custom_logs_output'), perfdatas => [ { template => '%d', cast_int => 1, min => 0, max => 'logs_total', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'server-logs-prct', display_ok => 0, nlabel => 'dma.server.logs.usage.percentage', set => { key_values => [ { name => 'logs_prct_used' }, { name => 'display' } ], output_template => 'logs used: %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' } ] } } ]; } 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-server:s' => { name => 'filter_server' } }); return $self; } sub prefix_server_output { my ($self, %options) = @_; return "Server '" . $options{instance_value}->{display} . "' "; } my $mapping_cpu = { stRsrcCPUUsageHostName => { oid => '.1.3.6.1.4.1.13885.13.2.2.1.4.1.1.2' }, stRsrcCPUUsageCPUUtilizationPct => { oid => '.1.3.6.1.4.1.13885.13.2.2.1.4.1.1.3' } }; my $mapping_memory = { stRsrcMemUsageHostName => { oid => '.1.3.6.1.4.1.13885.13.2.2.1.4.2.1.2' }, stRsrcMemUsageTotalMemory => { oid => '.1.3.6.1.4.1.13885.13.2.2.1.4.2.1.3' }, stRsrcMemUsageBuffersAndCache => { oid => '.1.3.6.1.4.1.13885.13.2.2.1.4.2.1.4' }, stRsrcMemUsageUsed => { oid => '.1.3.6.1.4.1.13885.13.2.2.1.4.2.1.5' }, stRsrcMemUsageFree => { oid => '.1.3.6.1.4.1.13885.13.2.2.1.4.2.1.6' } }; my $mapping_swap = { stRsrcSwapHostName => { oid => '.1.3.6.1.4.1.13885.13.2.2.1.4.3.1.2' }, stRsrcSwapTotal => { oid => '.1.3.6.1.4.1.13885.13.2.2.1.4.3.1.3' }, stRsrcSwapUsed => { oid => '.1.3.6.1.4.1.13885.13.2.2.1.4.3.1.4' } }; my $mapping_disk = { stRsrcDiskHostName => { oid => '.1.3.6.1.4.1.13885.13.2.2.1.4.4.1.2' }, stRsrcDiskTotal => { oid => '.1.3.6.1.4.1.13885.13.2.2.1.4.4.1.3' }, stRsrcDiskUsed => { oid => '.1.3.6.1.4.1.13885.13.2.2.1.4.4.1.4' } }; my $mapping_logs = { stRsrcLogHostName => { oid => '.1.3.6.1.4.1.13885.13.2.2.1.4.5.1.2'}, stRsrcLogTotal => { oid => '.1.3.6.1.4.1.13885.13.2.2.1.4.5.1.3'}, stRsrcLogUsed => { oid => '.1.3.6.1.4.1.13885.13.2.2.1.4.5.1.4'} }; my $oid_stRsrcCPUUsageEntry = '.1.3.6.1.4.1.13885.13.2.2.1.4.1.1'; my $oid_stRsrcMemoryUsageEntry = '.1.3.6.1.4.1.13885.13.2.2.1.4.2.1'; my $oid_stRsrcSwapUsageEntry = '.1.3.6.1.4.1.13885.13.2.2.1.4.3.1'; my $oid_stRsrcDiskSpaceEntry = '.1.3.6.1.4.1.13885.13.2.2.1.4.4.1'; my $oid_stRsrcLogSpaceEntry = '.1.3.6.1.4.1.13885.13.2.2.1.4.5.1'; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_multiple_table( oids => [ { oid => $oid_stRsrcCPUUsageEntry }, { oid => $oid_stRsrcMemoryUsageEntry }, { oid => $oid_stRsrcSwapUsageEntry }, { oid => $oid_stRsrcDiskSpaceEntry }, { oid => $oid_stRsrcLogSpaceEntry } ], nothing_quit => 1 ); $self->{server} = {}; foreach my $oid (keys %{$snmp_result->{$oid_stRsrcCPUUsageEntry}}) { next if ($oid !~ /^$mapping_cpu->{stRsrcCPUUsageHostName}->{oid}\.(.*)$/); my $instance = $1; my $result_cpu = $options{snmp}->map_instance(mapping => $mapping_cpu, results => $snmp_result->{$oid_stRsrcCPUUsageEntry}, instance => $instance); my $result_memory = $options{snmp}->map_instance(mapping => $mapping_memory, results => $snmp_result->{$oid_stRsrcMemoryUsageEntry}, instance => $instance); my $result_swap = $options{snmp}->map_instance(mapping => $mapping_swap, results => $snmp_result->{$oid_stRsrcSwapUsageEntry}, instance => $instance); my $result_disk = $options{snmp}->map_instance(mapping => $mapping_disk, results => $snmp_result->{$oid_stRsrcDiskSpaceEntry}, instance => $instance); my $result_logs = $options{snmp}->map_instance(mapping => $mapping_logs, results => $snmp_result->{$oid_stRsrcLogSpaceEntry}, instance => $instance); $result_cpu->{stRsrcCPUUsageHostName} = centreon::plugins::misc::trim($result_cpu->{stRsrcCPUUsageHostName}); if (defined($self->{option_results}->{filter_server}) && $self->{option_results}->{filter_server} ne '' && $result_cpu->{stRsrcCPUUsageHostName} !~ /$self->{option_results}->{filter_server}/) { $self->{output}->output_add(long_msg => "skipping '" . $result_cpu->{stRsrcCPUUsageHostName} . "': no matching filter.", debug => 1); next; } my ($memory_used, $memory_total) = (($result_memory->{stRsrcMemUsageUsed} + $result_memory->{stRsrcMemUsageBuffersAndCache} * 1024 * 1024), $result_memory->{stRsrcMemUsageTotalMemory} * 1024 * 1024); my ($swap_used, $swap_total) = (($result_swap->{stRsrcSwapUsed} * 1024 * 1024), ($result_swap->{stRsrcSwapTotal} * 1024 * 1024)); my ($disk_used, $disk_total) = (($result_disk->{stRsrcDiskUsed} * 1024 * 1024), ($result_disk->{stRsrcDiskTotal} * 1024 * 1024)); my ($logs_used, $logs_total) = (($result_logs->{stRsrcLogUsed} * 1024 * 1024, $result_logs->{stRsrcLogTotal} * 1024 * 1024)); $self->{server}->{$instance} = { display => $result_cpu->{stRsrcCPUUsageHostName}, stRsrcCPUUsageCPUUtilizationPct => $result_cpu->{stRsrcCPUUsageCPUUtilizationPct}, memory_free => $memory_total - $memory_used, memory_prct_free => 100 - ($memory_used * 100 / $memory_total), memory_prct_used => ($memory_total != 0) ? $memory_used * 100 / $memory_total : '0', memory_total => $memory_total, memory_used => $memory_used, swap_free => $swap_total - $swap_used, swap_prct_free => 100 - ($swap_used * 100 / $swap_total), swap_prct_used => ($swap_total != 0) ? $swap_used * 100 / $swap_total : '0', swap_total => $swap_total, swap_used => $swap_used, disk_free => $disk_total - $disk_used, disk_prct_free => 100 - ($disk_used * 100 / $disk_total), disk_prct_used => ($disk_total != 0) ? $disk_used * 100 / $disk_total : '0', disk_total => $disk_total, disk_used => $disk_used, logs_free => $logs_total - $logs_used, logs_prct_free => 100 - ($logs_used * 100 / $logs_total), logs_prct_used => ($logs_total != 0) ? $logs_used * 100 / $logs_total : '0', logs_total => $logs_total, logs_used => $logs_used }; } } 1; __END__ =head1 MODE Check managed servers system usage metrics =over 8 =item B<--filter-server> Filter on one or several server (POSIX regexp) =item B<--warning-* --critical-*> Warning & Critical Thresholds. Possible values: [CPU] server-cpu-usage [RAM] server-memory-usage server-memory-free server-memory-prct [SWAP] server-swap-usage server-swap-free server-swap-prct [DISK] server-disk-usage server-disk-free server-disk-prct [LOGS] server-logs-usage server-logs-free server-logs-prct =back =cut centreon-plugins-20220113/hardware/devices/polycom/dma/snmp/plugin.pm000066400000000000000000000042471417000230700255160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::polycom::dma::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} = { 'alerts' => 'hardware::devices::polycom::dma::snmp::mode::alerts', 'clusters' => 'hardware::devices::polycom::dma::snmp::mode::clusters', 'cpu' => 'snmp_standard::mode::cpu', 'cpu-detailed' => 'snmp_standard::mode::cpudetailed', 'conference-manager' => 'hardware::devices::polycom::dma::snmp::mode::conferencemanager', 'device-registrations' => 'hardware::devices::polycom::dma::snmp::mode::deviceregistrations', 'interfaces' => 'snmp_standard::mode::interfaces', 'load' => 'snmp_standard::mode::loadaverage', 'memory' => 'snmp_standard::mode::memory', 'servers-usage' => 'hardware::devices::polycom::dma::snmp::mode::serversusage', 'storage' => 'snmp_standard::mode::storage', 'swap' => 'snmp_standard::mode::swap', 'uptime' => 'snmp_standard::mode::uptime' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Polycom DMA Cluster Manager in SNMP. =cut centreon-plugins-20220113/hardware/devices/polycom/groupseries/000077500000000000000000000000001417000230700245045ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/polycom/groupseries/snmp/000077500000000000000000000000001417000230700254615ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/polycom/groupseries/snmp/plugin.pm000066400000000000000000000025721417000230700273230ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::polycom::groupseries::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}} = ( 'hardware' => 'centreon::common::polycom::endpoint::snmp::mode::hardware', 'videoconferencing' => 'centreon::common::polycom::endpoint::snmp::mode::videoconferencing' ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Polycom GroupSeries equipments in SNMP. =cut centreon-plugins-20220113/hardware/devices/polycom/hdx/000077500000000000000000000000001417000230700227205ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/polycom/hdx/snmp/000077500000000000000000000000001417000230700236755ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/polycom/hdx/snmp/mode/000077500000000000000000000000001417000230700246215ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/polycom/hdx/snmp/mode/viewstationstats.pm000066400000000000000000000074161417000230700306220ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::polycom::hdx::snmp::mode::viewstationstats; 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, cb_prefix_output => 'prefix_global_output' } ]; $self->{maps_counters}->{global} = [ { label => 'h323-packet-loss', nlabel => 'viewstation.h323.packet.loss.percentage', set => { key_values => [ { name => 'polycomVSPercentPacketLoss' } ], output_template => 'H323 Packet Loss %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%' } ] } }, { label => 'h323-jitter', nlabel => 'viewstation.h323.jitter.milliseconds', set => { key_values => [ { name => 'polycomVSJitter' } ], output_template => 'H323 (audio/video) Jitter %.2f ms', perfdatas => [ { template => '%.2f', min => 0, unit => 'ms' } ] } }, { label => 'h323-latency', nlabel => 'viewstation.h323.latency.count', set => { key_values => [ { name => 'polycomVSLatency' }], output_template => 'H323 (audio/video) Latency %.2f', perfdatas => [ { template => '%.2f', min => 0 } ] } } ]; } sub prefix_global_output { my ($self, %options) = @_; return "View Station Phone Number: '" . $options{instance_value}->{display} . "' Stats: "; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); return $self; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(); return $self; } sub manage_selection { my ($self, %options) = @_; my $oid_polycomVSPhoneNumber = '.1.3.6.1.4.1.2684.1.1.2.0'; my $oid_polycomVSPercentPacketLoss = '.1.3.6.1.4.1.2684.1.1.21.0'; my $oid_polycomVSJitter = '.1.3.6.1.4.1.2684.1.1.22.0'; my $oid_polycomVSLatency = '.1.3.6.1.4.1.2684.1.1.23.0'; my $result = $options{snmp}->get_leef( oids => [ $oid_polycomVSPhoneNumber, $oid_polycomVSPercentPacketLoss, $oid_polycomVSJitter, $oid_polycomVSLatency ], nothing_quit => 1 ); $self->{global} = { display => $result->{$oid_polycomVSPhoneNumber}, polycomVSPercentPacketLoss => $result->{$oid_polycomVSPercentPacketLoss}, polycomVSJitter => $result->{$oid_polycomVSJitter}, polycomVSLatency => $result->{$oid_polycomVSLatency} }; } 1; __END__ =head1 MODE Check HDX ViewStation statistics during H323 communications =over 8 =item B<--warning-* --critical-*> Warning and Critical thresholds. Possible values are: h323-packet-loss, h323-jitter, h323-latency =back =cut centreon-plugins-20220113/hardware/devices/polycom/hdx/snmp/plugin.pm000066400000000000000000000031251417000230700255320ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::polycom::hdx::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} = { 'cpu-detailed' => 'snmp_standard::mode::cpudetailed', 'interfaces' => 'snmp_standard::mode::interfaces', 'load' => 'snmp_standard::mode::loadaverage', 'memory' => 'snmp_standard::mode::memory', 'uptime' => 'snmp_standard::mode::uptime', 'viewstation-stats' => 'hardware::devices::polycom::hdx::snmp::mode::viewstationstats' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Polycom HDX View Stations Devices in SNMP. =cut centreon-plugins-20220113/hardware/devices/polycom/rprm/000077500000000000000000000000001417000230700231155ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/polycom/rprm/snmp/000077500000000000000000000000001417000230700240725ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/polycom/rprm/snmp/mode/000077500000000000000000000000001417000230700250165ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/polycom/rprm/snmp/mode/clusterstatus.pm000066400000000000000000000074371417000230700303140ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::polycom::rprm::snmp::mode::clusterstatus; use base qw(centreon::plugins::templates::counter); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' } ]; $self->{maps_counters}->{global} = [ { label => 'cluster-status', type => 2, critical_default => '%{cluster_status} =~ /outOfService/i', set => { key_values => [ { name => 'cluster_status' } ], output_template => 'Current status %s', closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'cluster-change-cause', type => 2, set => { key_values => [ { name => 'cluster_change_cause' } ], output_template => 'Last change cause: %s', closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub prefix_global_output { my ($self, %options) = @_; return 'RPRM HA Super Cluster: '; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $oid_serviceHASuperClstrStatus = '.1.3.6.1.4.1.13885.102.1.2.16.1.0'; my $oid_serviceHAStatusChgReason = '.1.3.6.1.4.1.13885.102.1.2.16.2.0'; my %cluster_status = ( 1 => 'inService', 2 => 'busyOut', 3 => 'outOfService' ); my $result = $options{snmp}->get_leef( oids => [ $oid_serviceHASuperClstrStatus, $oid_serviceHAStatusChgReason ], nothing_quit => 1 ); $self->{global} = { cluster_status => $cluster_status{$result->{$oid_serviceHASuperClstrStatus}}, cluster_change_cause => $result->{$oid_serviceHAStatusChgReason} }; } 1; __END__ =head1 MODE Check Polycom HA SuperCluster status =over 8 =item B<--warning-cluster-status> Custom Warning threshold of the cluster state (Default: none) Syntax: --warning-cluster-status='%{cluster_status} =~ /busyOut/i' =item B<--critical-cluster-status> Custom Critical threshold of the cluster state (Default: '%{cluster_status} =~ /outOfService/i' ) Syntax: --critical-cluster-status='%{cluster_status} =~ /failed/i' =item B<--warning-cluster-change-cause> Custom Warning threshold of the cluster state change cause (Default: none) Syntax: --warning-cluster-change-cause='%{cluster_change_cause} =~ /manualFailover/i' =item B<--critical-cluster-change-cause> Custom Critical threshold of the cluster state change cause (Default: none) Syntax: --critical-cluster-change-cause='%{cluster_change_cause} =~ /manualFailover/i' =back =cut centreon-plugins-20220113/hardware/devices/polycom/rprm/snmp/mode/license.pm000066400000000000000000000133231417000230700270000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::polycom::rprm::snmp::mode::license; 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 } ]; $self->{maps_counters}->{global} = [ { label => 'total-license-usage', nlabel => 'rprm.license.total.usage.count', set => { key_values => [ { name => 'total_license_usage' }, { name => 'total_license_capability' }, { name => 'total_license_usage_prct' }, { name => 'license_mode' } ], closure_custom_output => $self->can('custom_license_output'), perfdatas => [ { template => '%d', max => 'total_license_capability' } ] } }, { label => 'audio-license-usage', nlabel => 'rprm.license.audio.usage.count', set => { key_values => [ { name => 'audio_license_usage' }, { name => 'audio_license_capability' }, { name => 'audio_license_usage_prct' } ], output_template => 'Audio licenses used: %s', perfdatas => [ { template => '%d', max => 'audio_license_capability' } ] } }, { label => 'video-license-usage', nlabel => 'rprm.license.video.usage.count', set => { key_values => [ { name => 'video_license_usage' }, { name => 'video_license_capability' }, { name => 'video_license_usage_prct' } ], output_template => 'Video licenses used: %s', perfdatas => [ { template => '%d', max => 'video_license_capability' } ] } } ]; } sub custom_license_output { my ($self, %options) = @_; return sprintf( 'Current license usage (mode: "%s"): Total %s of %s (%.2f%%)', $self->{result_values}->{license_mode}, $self->{result_values}->{total_license_usage}, $self->{result_values}->{total_license_capability}, $self->{result_values}->{total_license_usage_prct} ); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(); return $self; } sub manage_selection { my ($self, %options) = @_; my %license_mode = (0 => 'user', 1 => 'device'); my $oid_serviceLicenseCapability = '.1.3.6.1.4.1.13885.102.1.2.20.1.0'; my $oid_serviceLicenseUsage = '.1.3.6.1.4.1.13885.102.1.2.20.2.0'; my $oid_serviceLicenseMode = '.1.3.6.1.4.1.13885.102.1.2.20.3.0'; my $oid_serviceAudioEPLicenseCapability = '.1.3.6.1.4.1.13885.102.1.2.23.1.0'; my $oid_serviceAudioEPLicenseUsage = '.1.3.6.1.4.1.13885.102.1.2.23.2.0'; my $oid_serviceVideoEPLicenseCapability = '.1.3.6.1.4.1.13885.102.1.2.24.1.0'; my $oid_serviceVideoEPLicenseUsage = '.1.3.6.1.4.1.13885.102.1.2.24.2.0'; my $result = $options{snmp}->get_leef( oids => [ $oid_serviceLicenseCapability, $oid_serviceLicenseUsage, $oid_serviceLicenseMode, $oid_serviceAudioEPLicenseCapability, $oid_serviceAudioEPLicenseUsage, $oid_serviceVideoEPLicenseCapability, $oid_serviceVideoEPLicenseUsage ], nothing_quit => 1 ); my $total_license_usage_prct = defined($result->{$oid_serviceLicenseCapability}) && $result->{$oid_serviceLicenseCapability} != '0' ? ($result->{$oid_serviceLicenseUsage} * 100 / $result->{$oid_serviceLicenseCapability}) : 0; my $audio_license_usage_prct = defined($result->{$oid_serviceAudioEPLicenseCapability}) && $result->{$oid_serviceAudioEPLicenseCapability} != '0' ? ($result->{$oid_serviceAudioEPLicenseUsage} * 100 / $result->{$oid_serviceAudioEPLicenseCapability}) : 0; my $video_license_usage_prct = defined($result->{$oid_serviceVideoEPLicenseCapability}) && $result->{$oid_serviceVideoEPLicenseCapability} != '0' ? ($result->{$oid_serviceVideoEPLicenseUsage} * 100 / $result->{$oid_serviceVideoEPLicenseCapability}) : 0; $self->{global} = { total_license_usage => $result->{$oid_serviceLicenseUsage}, total_license_capability => $result->{$oid_serviceLicenseCapability}, total_license_usage_prct => $total_license_usage_prct, license_mode => $license_mode{$result->{$oid_serviceLicenseMode}}, audio_license_usage => $result->{$oid_serviceAudioEPLicenseUsage}, audio_license_capability => $result->{$oid_serviceAudioEPLicenseCapability}, audio_license_usage_prct => $audio_license_usage_prct, video_license_usage => $result->{$oid_serviceVideoEPLicenseUsage}, video_license_capability => $result->{$oid_serviceVideoEPLicenseCapability}, video_license_usage_prct => $video_license_usage_prct }; } 1; __END__ =head1 MODE Check licenses statistics of Polycom RPRM devices. =over 8 =item B<--warning-* --critical-*> Warning & Critical Thresholds for the collected metrics. Possible values: total-license-usage, audio-license-usage, video-license-usage. =back =cut centreon-plugins-20220113/hardware/devices/polycom/rprm/snmp/mode/provisioning.pm000066400000000000000000000106231417000230700301040ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::polycom::rprm::snmp::mode::provisioning; use base qw(centreon::plugins::templates::counter); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' } ]; $self->{maps_counters}->{global} = [ { label => 'provisioning-status', type => 2, critical_default => '%{provisioning_status} =~ /failed/i', set => { key_values => [ { name => 'provisioning_status' } ], closure_custom_output => $self->can('custom_provisioning_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'provisioning-failed', nlabel => 'rprm.provisioning.failed.count', set => { key_values => [ { name => 'provisioning_failed' } ], output_template => 'Failed last 60m: %s', perfdatas => [ { template => '%s', min => 0, unit => '' } ] } }, { label => 'provisioning-success', nlabel => 'rprm.provisioning.success.count', set => { key_values => [ { name => 'provisioning_success' } ], output_template => 'Successed last 60m: %s', perfdatas => [ { template => '%s', min => 0, unit => '' } ] } } ]; } sub custom_provisioning_status_output { my ($self, %options) = @_; return sprintf('Current status: "%s"', $self->{result_values}->{provisioning_status}); } sub prefix_global_output { my ($self, %options) = @_; return 'RPRM Provisioning jobs stats: '; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $oid_serviceProvisioningStatus = '.1.3.6.1.4.1.13885.102.1.2.2.1.0'; my $oid_serviceProvisioningFailuresLast60Mins = '.1.3.6.1.4.1.13885.102.1.2.2.2.0'; my $oid_serviceProvisioningSuccessLast60Mins = '.1.3.6.1.4.1.13885.102.1.2.2.3.0'; my %provisioning_status = ( 0 => 'clear', 2 => 'in-progress', 3 => 'success', 4 => 'failed' ); my $result = $options{snmp}->get_leef( oids => [ $oid_serviceProvisioningStatus, $oid_serviceProvisioningFailuresLast60Mins, $oid_serviceProvisioningSuccessLast60Mins ], nothing_quit => 1 ); $self->{global} = { provisioning_status => $provisioning_status{$result->{$oid_serviceProvisioningStatus}}, provisioning_failed => $result->{$oid_serviceProvisioningFailuresLast60Mins}, provisioning_success => $result->{$oid_serviceProvisioningSuccessLast60Mins} }; } 1; __END__ =head1 MODE Check Polycom RPRM provisioning jobs =over 8 =item B<--warning-provisioning-status> Custom Warning threshold of the provisioning state (Default: none) Syntax: --warning-provisioning-status='%{provisioning_status} =~ /clear/i' =item B<--critical-provisioning-status> Custom Critical threshold of the provisioning state (Default: '%{provisioning_status} =~ /failed/i' ) Syntax: --critical-provisioning-status='%{provisioning_status} =~ /failed/i' =item B<--warning-* --critical-*> Warning and Critical thresholds. Possible values are: provisioning-failed, provisioning-success =back =cut centreon-plugins-20220113/hardware/devices/polycom/rprm/snmp/mode/sitelinks.pm000066400000000000000000000243521417000230700273670ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::polycom::rprm::snmp::mode::sitelinks; use base qw(centreon::plugins::templates::counter); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'sitelink', type => 1, cb_prefix_output => 'prefix_sitelink_output', message_multiple => 'All SiteLinks are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'rprm-total-sitelinks', nlabel => 'rprm.sitelinks.total.count', set => { key_values => [ { name => 'sitelinks_count' } ], output_template => 'Total sitelinks : %s', perfdatas => [ { template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{sitelink} = [ { label => 'sitelink-status', type => 2, critical_default => '%{sitelink_status} =~ /failed/i', set => { key_values => [ { name => 'sitelink_status' }, { name => 'display' } ], closure_custom_output => $self->can('custom_sitelink_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'sitelink-active-calls', nlabel => 'rprm.sitelink.calls.active.count', set => { key_values => [ { name => 'sitelink_active_calls' }, { name => 'display' } ], output_template => 'current active calls: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'sitelink-bandwidth-used-prct', nlabel => 'rprm.sitelink.bandwidth.used.percentage', set => { key_values => [ { name => 'sitelink_bandwidth_used_prct' }, { name => 'display' } ], output_template => 'current bandwidth usage: %.2f %%', perfdatas => [ { unit => '%', template => '%.2f', min => 0, max => 100, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'sitelink-bandwidth-total', nlabel => 'rprm.sitelink.bandwidth.total.bytespersecond', set => { key_values => [ { name => 'sitelink_bandwidth_total' }, { name => 'display' } ], closure_custom_output => $self->can('custom_bandwidth_total_output'), perfdatas => [ { template => '%.2f', min => 0, unit => 'B/s', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'sitelink-callbitrate', nlabel => 'rprm.sitelink.callbitrate.average.ratio', set => { key_values => [ { name => 'sitelink_callbitrate' }, { name => 'display' } ], output_template => 'Average call bit rate: %.2f', perfdatas => [ { template => '%.2f', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'sitelink-packetloss-prct', nlabel => 'rprm.sitelink.packetloss.average.percentage', set => { key_values => [ { name => 'sitelink_packetloss_prct' }, { name => 'display' } ], output_template => 'Average packetloss: %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'sitelink-jitter', nlabel => 'rprm.sitelink.jitter.average.milliseconds', set => { key_values => [ { name => 'sitelink_jitter' }, { name => 'display' } ], output_template => 'Average jitter time: %.2f ms', perfdatas => [ { template => '%.2f', min => 0, unit => 'ms', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'sitelink-delay', nlabel => 'rprm.sitelink.delay.average.milliseconds', set => { key_values => [ { name => 'sitelink_delay' }, { name => 'display'} ], output_template => 'Average delay time: %.2f ms', perfdatas => [ { template => '%.2f', min => 0, unit => 'ms', label_extra_instance => 1, instance_use => 'display' } ] } } ]; } 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-sitelink:s' => { name => 'filter_sitelink' } }); return $self; } sub custom_sitelink_status_output { my ($self, %options) = @_; return sprintf('Current status: "%s"', $self->{result_values}->{sitelink_status}); } sub prefix_sitelink_output { my ($self, %options) = @_; return "SiteLink '" . $options{instance_value}->{display} . "' "; } sub custom_bandwidth_total_output { my ($self, %options) = @_; my ($bandwidth, $unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{sitelink_bandwidth_total}, network => 1); return sprintf("Total allowed bandwidth: %.2f %s/s", $bandwidth, $unit); } sub manage_selection { my ($self, %options) = @_; my $mapping = { serviceTopologySiteLinkName => { oid => '.1.3.6.1.4.1.13885.102.1.2.14.6.1.3' }, serviceTopologySiteLinkStatus => { oid => '.1.3.6.1.4.1.13885.102.1.2.14.6.1.4' }, serviceTopologySiteLinkCallCount => { oid => '.1.3.6.1.4.1.13885.102.1.2.14.6.1.7' }, serviceTopologySiteLinkBandwidthUsed => { oid => '.1.3.6.1.4.1.13885.102.1.2.14.6.1.8' }, serviceTopologySiteLinkBandwidthTotal => { oid => '.1.3.6.1.4.1.13885.102.1.2.14.6.1.9' }, serviceTopologySiteLinkAverageCallBitRate => { oid => '.1.3.6.1.4.1.13885.102.1.2.14.6.1.10' }, serviceTopologySiteLinkPacketLoss => { oid => '.1.3.6.1.4.1.13885.102.1.2.14.6.1.11' }, serviceTopologySiteLinkAverageJitter => { oid => '.1.3.6.1.4.1.13885.102.1.2.14.6.1.12' }, serviceTopologySiteLinkAverageDelay => { oid => '.1.3.6.1.4.1.13885.102.1.2.14.6.1.13' }, }; my %sitelink_status = ( 1 => 'disabled', 2 => 'ok', 3 => 'failed' ); my $oid_serviceTopologySiteLinkEntry = '.1.3.6.1.4.1.13885.102.1.2.14.6.1'; my $oid_serviceTopologySiteLinkCount = '.1.3.6.1.4.1.13885.102.1.2.14.5.0'; my $global_result = $options{snmp}->get_leef(oids => [$oid_serviceTopologySiteLinkCount], nothing_quit => 1); $self->{global} = { sitelinks_count => $global_result->{$oid_serviceTopologySiteLinkCount} }; my $sitelink_result = $options{snmp}->get_table( oid => $oid_serviceTopologySiteLinkEntry, nothing_quit => 1 ); foreach my $oid (keys %{$sitelink_result}) { next if ($oid !~ /^$mapping->{serviceTopologySiteLinkName}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $sitelink_result, instance => $instance); $result->{serviceTopologySiteLinkName} = centreon::plugins::misc::trim($result->{serviceTopologySiteLinkName}); if (defined($self->{option_results}->{filter_sitelink}) && $self->{option_results}->{filter_sitelink} ne '' && $result->{serviceTopologySiteLinkName} !~ /$self->{option_results}->{filter_sitelink}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{serviceTopologySiteLinkName} . "': no matching filter.", debug => 1); next; } my $sitelink_bandwidth_total = $result->{serviceTopologySiteLinkBandwidthTotal} * 1000000 ; #Mbps $result->{serviceTopologySiteLinkName} =~ s/\ /\_/g; #instance perfdata compat $self->{sitelink}->{$instance} = { display => $result->{serviceTopologySiteLinkName}, sitelink_status => $sitelink_status{$result->{serviceTopologySiteLinkStatus}}, sitelink_active_calls => $result->{serviceTopologySiteLinkCallCount}, sitelink_bandwidth_used_prct => $result->{serviceTopologySiteLinkBandwidthUsed}, sitelink_bandwidth_total => $sitelink_bandwidth_total, sitelink_callbitrate => $result->{serviceTopologySiteLinkAverageCallBitRate}, sitelink_packetloss_prct => $result->{serviceTopologySiteLinkPacketLoss}, sitelink_jitter => $result->{serviceTopologySiteLinkAverageJitter}, sitelink_delay => $result->{serviceTopologySiteLinkAverageDelay} }; } } 1; __END__ =head1 MODE Check Polycom RPRM SiteLinks. =over 8 =item B<--filter-sitelink> Filter on one or several SiteLinks (POSIX regexp) =item B<--warning-sitelink-status> Custom Warning threshold of the SiteLink state (Default: none) Syntax: --warning-sitelink-status='%{sitelink_status} =~ /disabled/i' =item B<--critical-sitelink-status> Custom Critical threshold of the SiteLink state (Default: '%{sitelink_status} =~ /failed/i' ) Syntax: --critical-sitelink-status='%{sitelink_status} =~ /failed/i' =item B<--warning-* --critical-*> Warning & Critical Thresholds. Possible values: [GLOBAL] rprm-total-sitelinks [SITE] sitelink-active-calls, sitelink-bandwidth-used-prct, sitelink-bandwidth-total, sitelink-callbitrate, sitelink-packetloss-prct, sitelink-jitter, sitelink-delay =back =cut centreon-plugins-20220113/hardware/devices/polycom/rprm/snmp/mode/sites.pm000066400000000000000000000212461417000230700265100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::polycom::rprm::snmp::mode::sites; 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 }, { name => 'site', type => 1, cb_prefix_output => 'prefix_site_output', message_multiple => 'All sites are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'rprm-total-sites', nlabel => 'rprm.sites.total.count', set => { key_values => [ { name => 'sites_count' } ], output_template => 'Total sites: %s', perfdatas => [ { template => '%d', min => 0 } ] } } ]; $self->{maps_counters}->{site} = [ { label => 'site-active-calls', nlabel => 'rprm.site.calls.active.count', set => { key_values => [ { name => 'site_active_calls' }, { name => 'display' } ], output_template => 'current active calls: %s', perfdatas => [ { template => '%s', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'site-bandwidth-used-prct', nlabel => 'rprm.site.bandwidth.used.percentage', set => { key_values => [ { name => 'site_bandwidth_used_prct' }, { name => 'display' } ], output_template => 'current bandwidth usage: %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'site-bandwidth-total', nlabel => 'rprm.site.bandwidth.total.bytespersecond', set => { key_values => [ { name => 'site_bandwidth_total' }, { name => 'display' } ], closure_custom_output => $self->can('custom_bandwidth_total_output'), perfdatas => [ { template => '%.2f', min => 0, unit => 'B/s', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'site-callbitrate', nlabel => 'rprm.site.callbitrate.average.ratio', set => { key_values => [ { name => 'site_callbitrate' }, { name => 'display' } ], output_template => 'Average call bit rate: %.2f', perfdatas => [ { template => '%.2f', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'site-packetloss-prct', nlabel => 'rprm.site.packetloss.average.percentage', set => { key_values => [ { name => 'site_packetloss_prct' }, { name => 'display' } ], output_template => 'Average packetloss: %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'site-jitter', nlabel => 'rprm.site.jitter.average.milliseconds', set => { key_values => [ { name => 'site_jitter' }, { name => 'display' } ], output_template => 'Average jitter time: %.2f ms', perfdatas => [ { template => '%.2f', min => 0, unit => 'ms', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'site-delay', nlabel => 'rprm.site.delay.average.milliseconds', set => { key_values => [ { name => 'site_delay' }, { name => 'display' } ], output_template => 'Average delay time: %.2f ms', perfdatas => [ { template => '%.2f', min => 0, unit => 'ms', label_extra_instance => 1, instance_use => 'display' } ] } } ]; } 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-site:s' => { name => 'filter_site' } }); return $self; } sub prefix_site_output { my ($self, %options) = @_; return "Site '" . $options{instance_value}->{display} . "' "; } sub custom_bandwidth_total_output { my ($self, %options) = @_; my ($bandwidth, $unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{site_bandwidth_total}, network => 1); return sprintf("Total allowed bandwidth: %.2f %s/s", $bandwidth, $unit); } sub manage_selection { my ($self, %options) = @_; my $mapping = { serviceTopologySiteName => { oid => '.1.3.6.1.4.1.13885.102.1.2.14.4.1.2' }, serviceTopologySiteTerritoryId => { oid => '.1.3.6.1.4.1.13885.102.1.2.14.4.1.3' }, serviceTopologySiteCallCount => { oid => '.1.3.6.1.4.1.13885.102.1.2.14.4.1.4' }, serviceTopologySiteBandwidthUsed => { oid => '.1.3.6.1.4.1.13885.102.1.2.14.4.1.5' }, serviceTopologySiteBandwidthTotal => { oid => '.1.3.6.1.4.1.13885.102.1.2.14.4.1.6' }, serviceTopologySiteAverageCallBitRate => { oid => '.1.3.6.1.4.1.13885.102.1.2.14.4.1.7' }, serviceTopologySitePacketLoss => { oid => '.1.3.6.1.4.1.13885.102.1.2.14.4.1.8' }, serviceTopologySiteAverageJitter => { oid => '.1.3.6.1.4.1.13885.102.1.2.14.4.1.9' }, serviceTopologySiteAverageDelay => { oid => '.1.3.6.1.4.1.13885.102.1.2.14.4.1.10' } }; my $oid_serviceTopologySiteEntry = '.1.3.6.1.4.1.13885.102.1.2.14.4.1'; my $oid_serviceTopologySiteCount = '.1.3.6.1.4.1.13885.102.1.2.14.3.0'; my $global_result = $options{snmp}->get_leef(oids => [$oid_serviceTopologySiteCount], nothing_quit => 1); $self->{global} = { sites_count => $global_result->{$oid_serviceTopologySiteCount} }; my $site_result = $options{snmp}->get_table( oid => $oid_serviceTopologySiteEntry, nothing_quit => 1 ); foreach my $oid (keys %{$site_result}) { next if ($oid !~ /^$mapping->{serviceTopologySiteName}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $site_result, instance => $instance); $result->{serviceTopologySiteName} = centreon::plugins::misc::trim($result->{serviceTopologySiteName}); if (defined($self->{option_results}->{filter_site}) && $self->{option_results}->{filter_site} ne '' && $result->{serviceTopologySiteName} !~ /$self->{option_results}->{filter_site}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{serviceTopologySiteName} . "': no matching filter.", debug => 1); next; } my $site_bandwidth_total = $result->{serviceTopologySiteBandwidthTotal} * 1000000 ; #Mbps $result->{serviceTopologySiteName} =~ s/\ /\_/g; #instance perfdata compat $self->{site}->{$instance} = { display => $result->{serviceTopologySiteName}, site_active_calls => $result->{serviceTopologySiteCallCount}, site_bandwidth_used_prct => $result->{serviceTopologySiteBandwidthUsed}, site_bandwidth_total => $site_bandwidth_total, site_callbitrate => $result->{serviceTopologySiteAverageCallBitRate}, site_packetloss_prct => $result->{serviceTopologySitePacketLoss}, site_jitter => $result->{serviceTopologySiteAverageJitter}, site_delay => $result->{serviceTopologySiteAverageDelay} }; } } 1; __END__ =head1 MODE Check Polycom RPRM sites. =over 8 =item B<--filter-site> Filter on one or several site (POSIX regexp) =item B<--warning-* --critical-*> Warning & Critical Thresholds. Possible values: [GLOBAL] rprm-total-sites [SITE] site-active-calls, site-bandwidth-used-prct, site-bandwidth-total, site-callbitrate, site-packetloss-prct, site-jitter, site-delay =back =cut centreon-plugins-20220113/hardware/devices/polycom/rprm/snmp/mode/updates.pm000066400000000000000000000103411417000230700270200ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::polycom::rprm::snmp::mode::updates; use base qw(centreon::plugins::templates::counter); use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' } ]; $self->{maps_counters}->{global} = [ { label => 'updates-status', type => 2, critical_default => '%{updates_status} =~ /failed/i',set => { key_values => [ { name => 'updates_status' } ], closure_custom_output => $self->can('custom_updates_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'updates-failed', nlabel => 'rprm.updates.failed.count', set => { key_values => [ { name => 'updates_failed' } ], output_template => 'Failed last 60m: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'updates-successed', nlabel => 'rprm.updates.successed.count', set => { key_values => [ { name => 'updates_success' } ], output_template => 'Successed last 60m: %s', perfdatas => [ { template => '%s', min => 0 } ] } } ]; } sub custom_updates_status_output { my ($self, %options) = @_; return sprintf('Current status: "%s"', $self->{result_values}->{updates_status}); } sub prefix_global_output { my ($self, %options) = @_; return 'RPRM Updates jobs stats: '; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $oid_serviceSoftwareUpdateStatus = '.1.3.6.1.4.1.13885.102.1.2.3.1.0'; my $oid_serviceSoftwareUpdateFailuresLast60Mins = '.1.3.6.1.4.1.13885.102.1.2.3.2.0'; my $oid_serviceSoftwareUpdateSuccessLast60Mins = '.1.3.6.1.4.1.13885.102.1.2.3.3.0'; my %updates_status = ( 1 => 'disabled', 2 => 'ok', 3 => 'failed' ); my $result = $options{snmp}->get_leef( oids => [ $oid_serviceSoftwareUpdateStatus, $oid_serviceSoftwareUpdateFailuresLast60Mins, $oid_serviceSoftwareUpdateSuccessLast60Mins ], nothing_quit => 1 ); $self->{global} = { updates_status => $updates_status{$result->{$oid_serviceSoftwareUpdateStatus}}, updates_failed => $result->{$oid_serviceSoftwareUpdateFailuresLast60Mins}, updates_success => $result->{$oid_serviceSoftwareUpdateSuccessLast60Mins} }; } 1; __END__ =head1 MODE Check Polycom RPRM updates jobs =over 8 =item B<--warning-updates-status> Custom Warning threshold of the updates state (Default: none) Syntax: --warning-updates-status='%{updates_status} =~ /clear/i' =item B<--critical-updates-status> Custom Critical threshold of the updates state (Default: '%{updates_status} =~ /failed/i' ) Syntax: --critical-updates-status='%{updates_status} =~ /failed/i' =item B<--warning-* --critical-*> Warning and Critical thresholds. Possible values are: updates-failed, updates-successed =back =cut centreon-plugins-20220113/hardware/devices/polycom/rprm/snmp/plugin.pm000066400000000000000000000033161417000230700257310ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::polycom::rprm::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-status' => 'hardware::devices::polycom::rprm::snmp::mode::clusterstatus', 'license' => 'hardware::devices::polycom::rprm::snmp::mode::license', 'provisioning' => 'hardware::devices::polycom::rprm::snmp::mode::provisioning', 'sitelinks' => 'hardware::devices::polycom::rprm::snmp::mode::sitelinks', 'sites' => 'hardware::devices::polycom::rprm::snmp::mode::sites', 'updates' => 'hardware::devices::polycom::rprm::snmp::mode::updates' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Polycom RealPresence Resource Manager (RPRM) Devices in SNMP. =cut centreon-plugins-20220113/hardware/devices/polycom/trio/000077500000000000000000000000001417000230700231125ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/polycom/trio/restapi/000077500000000000000000000000001417000230700245615ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/polycom/trio/restapi/custom/000077500000000000000000000000001417000230700260735ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/polycom/trio/restapi/custom/api.pm000066400000000000000000000204661417000230700272120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::polycom::trio::restapi::custom::api; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::http; use JSON::XS; use Digest::MD5 qw(md5_hex); use Fcntl qw(:flock); use POSIX; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port'}, 'proto:s' => { name => 'proto' }, 'api-username:s' => { name => 'api_username', default => 'Polycom' }, 'api-password:s' => { name => 'api_password' }, 'timeout:s' => { name => 'timeout', default => 50 }, 'lockfile-dir:s' => { name => 'lockfile_dir', default => '/var/lib/centreon/centplugins' }, 'unknown-http-status:s' => { name => 'unknown_http_status' }, 'warning-http-status:s' => { name => 'warning_http_status' }, 'critical-http-status:s' => { name => 'critical_http_status' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : undef; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{timeout} = (defined($self->{option_results}->{timeout}) && $self->{option_results}->{timeout} =~ /(\d+)/) ? $1 : 50; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : 'Polycom'; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : undef; $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300'; $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; $self->{lockfile_dir} = (defined($self->{option_results}->{lockfile_dir})) ? $self->{option_results}->{lockfile_dir} : '/var/lib/centreon/centplugins'; if (!defined($self->{hostname}) || $self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } if (!defined($self->{api_username}) || $self->{api_username} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-username option."); $self->{output}->option_exit(); } if (!defined($self->{api_password}) || $self->{api_password} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-password option."); $self->{output}->option_exit(); } return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; $self->{option_results}->{credentials} = 1; $self->{option_results}->{basic} = 1; $self->{option_results}->{username} = $self->{api_username}; $self->{option_results}->{password} = $self->{api_password}; } sub settings { my ($self, %options) = @_; return if (defined($self->{settings_done})); $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->add_header(key => 'Content-Type', value => 'application/json'); $self->{http}->set_options(%{$self->{option_results}}); $self->{settings_done} = 1; } sub request_api { my ($self, %options) = @_; $self->settings(); my ($fh, $content); my $lockfile = $self->{lockfile_dir} . '/polycom_trio_' . md5_hex($self->{hostname}) . '.lock'; if (!sysopen($fh, $lockfile, O_WRONLY | O_CREAT)) { $self->{output}->add_option_msg(short_msg => "cannot open/create lock file '" . $lockfile . "': $!"); $self->{output}->option_exit(); } my $locked = 0; eval { local $SIG{ALRM} = sub { die 'timeout' }; alarm($self->{timeout} + 5); flock($fh, LOCK_EX); $locked = 1; my $count = 0; while (1) { $content = $self->{http}->request( method => 'GET', url_path => $options{url_path}, unknown_status => $self->{unknown_http_status}, warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status}, ); last if ($self->{http}->get_code() != 403); if ($count == 5) { $self->{output}->add_option_msg(short_msg => 'cannot get data from polycom trio - tried 5 times'); $self->{output}->option_exit(); } sleep(10); $count++; } alarm(0); flock($fh, LOCK_UN); $locked = 0; }; if ($@) { flock($fh, LOCK_UN) if ($locked == 1); $self->{output}->add_option_msg(short_msg => 'plugin timeout: ' . $@); $self->{output}->option_exit(); } if (!defined($content) || $content eq '') { $self->{output}->add_option_msg(short_msg => "API returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($content); }; if ($@ || !defined($decoded->{Status})) { $self->{output}->add_option_msg(short_msg => "cannot decode response (add --debug option to display returned content)"); $self->{output}->option_exit(); } if ($decoded->{Status} != 2000) { $self->{output}->add_option_msg(short_msg => 'api error code ' . $decoded->{Status}); $self->{output}->option_exit(); } return $decoded; } 1; __END__ =head1 NAME Polycom Trio Rest API =head1 REST API OPTIONS =over 8 =item B<--hostname> Set hostname. =item B<--port> Set port (Default: '443'). =item B<--proto> Specify https if needed (Default: 'https'). =item B<--api-username> Set username. =item B<--api-password> Set password. =item B<--lockfile-dir> Specify the lock file directory (Default: '/var/lib/centreon/centplugins'). =item B<--timeout> Threshold for HTTP timeout (Default: '30'). =back =cut centreon-plugins-20220113/hardware/devices/polycom/trio/restapi/mode/000077500000000000000000000000001417000230700255055ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/polycom/trio/restapi/mode/callsrt.pm000066400000000000000000000150261417000230700275130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::polycom::trio::restapi::mode::callsrt; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use Digest::MD5 qw(md5_hex); sub custom_loss_calc { my ($self, %options) = @_; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; my $diff_pkts = ($options{new_datas}->{$self->{instance} . '_packets'} - $options{old_datas}->{$self->{instance} . '_packets'}); my $diff_loss = ($options{new_datas}->{$self->{instance} . '_loss'} - $options{old_datas}->{$self->{instance} . '_loss'}); $self->{result_values}->{packets_loss} = $diff_loss; $self->{result_values}->{packets_loss_prct} = 0; $self->{result_values}->{packets} = $diff_pkts; if ($diff_pkts > 0) { $self->{result_values}->{packets_loss_prct} = ($diff_loss * 100) / $diff_pkts; } return 0; } sub custom_loss_output { my ($self, %options) = @_; return sprintf( "packets loss: %.2f%% (%s on %s)", $self->{result_values}->{packets_loss_prct}, $self->{result_values}->{packets_loss}, $self->{result_values}->{packets} ); } sub prefix_channels_output { my ($self, %options) = @_; return "Channel '" . $options{instance_value}->{display} ."' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'channels', type => 1, cb_prefix_output => 'prefix_channels_output', message_multiple => 'All call channels are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{channels} = [ { label => 'channel-traffic-in', nlabel => 'call.channel.traffic.in.bytes', set => { key_values => [ { name => 'traffic_in', per_second => 1 }, { name => 'display' } ], output_change_bytes => 1, output_template => 'traffic in: %s %s/s', perfdatas => [ { template => '%d', unit => 'B/s', min => 0, label_extra_instance => 1 } ] } }, { label => 'channel-traffic-out', nlabel => 'call.channel.traffic.out.bytes', set => { key_values => [ { name => 'traffic_out', per_second => 1 }, { name => 'display' } ], output_change_bytes => 1, output_template => 'traffic out: %s %s/s', perfdatas => [ { template => '%d', unit => 'B/s', min => 0, label_extra_instance => 1 } ] } }, { label => 'channel-maxjitter', nlabel => 'call.channel.maxjitter.milliseconds', set => { key_values => [ { name => 'max_jitter' }, { name => 'display' } ], output_template => 'max jitter: %s ms', perfdatas => [ { template => '%d', unit => 'ms', min => 0, label_extra_instance => 1 } ] } }, { label => 'channel-packetloss', nlabel => 'call.channel.packetloss.count', set => { key_values => [ { name => 'loss', diff => 1 }, { name => 'packets', diff => 1 }, { name => 'display' } ], closure_custom_calc => $self->can('custom_loss_calc'), closure_custom_output => $self->can('custom_loss_output'), threshold_use => 'packets_loss', perfdatas => [ { value => 'packets_loss', template => '%d', min => 0, label_extra_instance => 1 } ] } }, { label => 'channel-packetloss-prct', nlabel => 'call.channel.packetloss.percentage', display_ok => 0, set => { key_values => [ { name => 'loss', diff => 1 }, { name => 'packets', diff => 1 }, { name => 'display' } ], closure_custom_calc => $self->can('custom_loss_calc'), closure_custom_output => $self->can('custom_loss_output'), threshold_use => 'packets_loss_prct', perfdatas => [ { value => 'packets_loss_prct', template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = 'polycom_trio_' . $options{custom}->{hostname} . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); my $result = $options{custom}->request_api(url_path => '/api/v1/mgmt/media/sessionStats'); $self->{channels} = {}; if (!defined($result->{data}) || ref($result->{data}) ne 'ARRAY') { $self->{output}->add_option_msg(short_msg => "cannot find session information."); $self->{output}->option_exit(); } if (!defined($result->{data}->[0]->{Streams})) { $self->{output}->output_add( severity => 'OK', short_msg => ' no audio/video call running' ); return ; } foreach (@{$result->{data}->[0]->{Streams}}) { $self->{channels}->{lc($_->{Category})} = { display => lc($_->{Category}), traffic_in => $_->{OctetsReceived}, traffic_out => $_->{OctetsSent}, max_jitter => $_->{MaxJitter}, loss => $_->{PacketsLost}, packets => $_->{PacketsReceived} }; } } 1; __END__ =head1 MODE Check call audio/video channels in real-time. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'channel-traffic-in', 'channel-traffic-out', 'channel-maxjitter' 'channel-packetloss', 'channel-packetloss-prct'. =back =cut centreon-plugins-20220113/hardware/devices/polycom/trio/restapi/mode/callssummary.pm000066400000000000000000000116761417000230700305720ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::polycom::trio::restapi::mode::callssummary; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::statefile; use Digest::MD5 qw(md5_hex); sub prefix_global_output { my ($self, %options) = @_; return 'total calls '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'total', nlabel => 'calls.total.count', display_ok => 0, set => { key_values => [ { name => 'total' } ], output_template => 'total: d', perfdatas => [ { template => '%d', min => 0 } ] } }, { label => 'placed', nlabel => 'calls.placed.count', set => { key_values => [ { name => 'placed' } ], output_template => 'placed: %d', perfdatas => [ { template => '%d', min => 0 } ] } }, { label => 'missed', nlabel => 'calls.missed.count', set => { key_values => [ { name => 'missed' } ], output_template => 'missed: %d', perfdatas => [ { template => '%d', min => 0 } ] } }, { label => 'received', nlabel => 'calls.received.count', set => { key_values => [ { name => 'received' } ], output_template => 'received: %d', perfdatas => [ { template => '%d', min => 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 => { }); centreon::plugins::misc::mymodule_load( output => $self->{output}, module => 'Date::Parse', error_msg => "Cannot load module 'Date::Parse'." ); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->{statefile_cache}->check_options(%options); } sub manage_selection { my ($self, %options) = @_; $self->{statefile_cache}->read( statefile => 'polycom_trio_' . $options{custom}->{hostname} . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) ); my $last_times = $self->{statefile_cache}->get(name => 'last_times'); $last_times = { placed => 0, missed => 0, received => 0 } if (!defined($last_times)); my $result = $options{custom}->request_api(url_path => '/api/v1/mgmt/callLogs'); if (!defined($result->{data}->{Placed})) { $self->{output}->add_option_msg(short_msg => "cannot find callLogs information."); $self->{output}->option_exit(); } $self->{global} = { total => 0, placed => 0, missed => 0, received => 0 }; my $new_last_times = { placed => 0, missed => 0, received => 0 }; foreach (('placed', 'missed', 'received')) { foreach my $entry (@{$result->{data}->{ucfirst($_)}}) { my $start_time = Date::Parse::str2time($entry->{StartTime}); if (!defined($start_time)) { $self->{output}->output_add( severity => 'UNKNOWN', short_msg => "can't parse date '" . $entry->{StartTime} . "'" ); next; } $new_last_times->{$_} = $start_time if ($new_last_times->{$_} < $start_time); next if ($start_time <= $last_times->{$_}); $self->{global}->{total}++; $self->{global}->{$_}++; } } $self->{statefile_cache}->write(data => { last_times => $new_last_times }); } 1; __END__ =head1 MODE Check call history. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'total', 'placed', 'missed', 'received'. =back =cut centreon-plugins-20220113/hardware/devices/polycom/trio/restapi/mode/device.pm000066400000000000000000000132451417000230700273070ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::polycom::trio::restapi::mode::device; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return "status is '" . $self->{result_values}->{status} . "'"; } sub custom_memory_output { my ($self, %options) = @_; return sprintf( "memory total: %s %s used: %s %s (%.2f%%) free: %s %s (%.2f%%)", $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}), $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}), $self->{result_values}->{prct_used}, $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}), $self->{result_values}->{prct_free} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ { label => 'status', type => 2, critical_default => '%{status} =~ /error/i', set => { key_values => [ { name => 'status' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'cpu-utilization-average', nlabel => 'device.cpu.utilization.average.percentage', set => { key_values => [ { name => 'cpu_average' } ], output_template => 'cpu average: %.2f%%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%' } ] } }, { label => 'memory-usage', nlabel => 'device.memory.usage.bytes', set => { key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_memory_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1 } ] } }, { label => 'memory-usage-free', display_ok => 0, nlabel => 'device.memory.free.bytes', set => { key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ], closure_custom_output => $self->can('custom_memory_output'), perfdatas => [ { template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1 } ] } }, { label => 'memory-usage-prct', display_ok => 0, nlabel => 'device.memory.usage.percentage', set => { key_values => [ { name => 'prct_used' } ], output_template => 'Memory Used: %.2f %%', perfdatas => [ { template => '%.2f', min => 0, max => 100, unit => '%' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->request_api(url_path => '/api/v1/mgmt/device/stats'); if (!defined($result->{data}->{CPU})) { $self->{output}->add_option_msg(short_msg => "cannot find device information."); $self->{output}->option_exit(); } my $used = $result->{data}->{Memory}->{Used} - $result->{data}->{Memory}->{SReclaim}; $self->{global} = { cpu_average => $result->{data}->{CPU}->{Average}, total => $result->{data}->{Memory}->{Total}, free => $result->{data}->{Memory}->{Total} - $used, used => $used, prct_free => ($result->{data}->{Memory}->{Total} - $used) * 100 / $result->{data}->{Memory}->{Total}, prct_used => $used * 100 / $result->{data}->{Memory}->{Total} }; $result = $options{custom}->request_api(url_path => '/api/v1/mgmt/pollForStatus'); return if (!defined($result->{data}->{State})); $self->{global}->{status} = $result->{data}->{State}; } 1; __END__ =head1 MODE Check device cpu, memory and state. =over 8 =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /error/i'). Can used special variables like: %{status} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'cpu-utilization-average', 'memory-usage', 'memory-usage-free', 'memory-usage-prct'. =back =cut centreon-plugins-20220113/hardware/devices/polycom/trio/restapi/mode/network.pm000066400000000000000000000056021417000230700275370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::polycom::trio::restapi::mode::network; 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 => 'global', type => 0 }, ]; $self->{maps_counters}->{global} = [ { label => 'packets-in', nlabel => 'network.packets.in.persecond', set => { key_values => [ { name => 'packets_in', per_second => 1 } ], output_template => 'packets in: %.2f/s', perfdatas => [ { template => '%.2f', min => 0, unit => '/s' } ], } }, { label => 'packets-out', nlabel => 'network.packets.out.persecond', set => { key_values => [ { name => 'packets_out', per_second => 1 } ], output_template => 'packets out: %.2f/s', perfdatas => [ { template => '%.2f', min => 0, unit => '/s' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1, statefile => 1); $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->request_api(url_path => '/api/v1/mgmt/network/stats'); if (!defined($result->{data}->{TxPackets})) { $self->{output}->add_option_msg(short_msg => "cannot find network information."); $self->{output}->option_exit(); } $self->{global} = { packets_in => $result->{data}->{RxPackets}, packets_out => $result->{data}->{TxPackets} }; $self->{cache_name} = 'polycom_trio_' . $options{custom}->{hostname} . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; __END__ =head1 MODE Check network traffic. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'packets-in', 'packets-out'. =back =cut centreon-plugins-20220113/hardware/devices/polycom/trio/restapi/mode/paired.pm000066400000000000000000000111621417000230700273100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::polycom::trio::restapi::mode::paired; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub prefix_global_output { my ($self, %options) = @_; return 'Devices paired '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'camera-paired', nlabel => 'devices.camera.paired.count', set => { key_values => [ { name => 'cameraSrc' } ], output_template => 'camera: %d', perfdatas => [ { template => '%d', min => 0 } ] } }, { label => 'audio-paired', nlabel => 'devices.audio.paired.count', set => { key_values => [ { name => 'audioSrcSink' } ], output_template => 'audio: %d', perfdatas => [ { template => '%d', min => 0 } ] } }, { label => 'displayui-paired', nlabel => 'devices.display_ui.paired.count', set => { key_values => [ { name => 'displayUI' } ], output_template => 'display ui: %d', perfdatas => [ { template => '%d', min => 0 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); $options{options}->add_options(arguments => { 'filter-device-name:s' => { name => 'filter_device_name' }, 'filter-device-type:s' => { name => 'filter_device_type' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->request_api(url_path => '/api/v1/mgmt/mrpair/info'); $self->{global} = { cameraSrc => 0, displayUI => 0, audioSrcSink => 0 }; foreach my $ConnectedDeviceList (@{$result->{data}->{ConnectedDeviceList}}) { foreach my $component (@{$ConnectedDeviceList->{ComponentList}}) { next if ($component->{componentType} !~ /^(?:cameraSrc|audioSrcSink|displayUI)$/); if (defined($self->{option_results}->{filter_device_name}) && $self->{option_results}->{filter_device_name} ne '' && $component->{componentName} !~ /$self->{option_results}->{filter_device_name}/) { $self->{output}->output_add(long_msg => "skipping device '" . $component->{componentName} . "': no matching filter.", debug => 1); next; } if (defined($self->{option_results}->{filter_device_type}) && $self->{option_results}->{filter_device_type} ne '' && $component->{componentType} !~ /$self->{option_results}->{filter_device_type}/) { $self->{output}->output_add(long_msg => "skipping device '" . $component->{componentName} . "': no matching filter.", debug => 1); next; } $self->{global}->{ $component->{componentType} }++; $self->{output}->output_add( long_msg => sprintf( 'componentType: %s [name: %s] [details: %s] [SerialNumer: %s] [componentUri: %s]', $component->{componentType}, $component->{componentName}, $component->{componentDetail}, $component->{componentSerialNumber}, $component->{componentUri} ) ); } } } 1; __END__ =head1 MODE Check paired devices. =over 8 =item B<--filter-device-name> Filter devices by name. =item B<--filter-device-type> Filter devices by type. =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'camera-paired', 'audio-paired', 'displayui-paired'. =back =cut centreon-plugins-20220113/hardware/devices/polycom/trio/restapi/mode/registration.pm000066400000000000000000000055101417000230700305560ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::polycom::trio::restapi::mode::registration; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return "SIP status is '" . $self->{result_values}->{status} . "'"; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'status', type => 2, critical_default => '%{status} !~ /registered/i', set => { key_values => [ { name => 'status' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $result = $options{custom}->request_api(url_path => '/api/v1/webCallControl/sipStatus'); $self->{global} = {}; foreach my $user (@{$result->{data}->{User}}) { foreach my $events (@{$user->{Events}}) { next if ($events->{Type} !~ /register/i); $self->{global}->{status} = $events->{RegistrationState}; } } if (!defined($self->{global}->{status})) { $self->{output}->add_option_msg(short_msg => 'Cannot find registration event'); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check SIP registration. =over 8 =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{status} =item B<--critical-status> Set critical threshold for status (Default: '%{status} !~ /registred/i'). Can used special variables like: %{status} =back =cut centreon-plugins-20220113/hardware/devices/polycom/trio/restapi/plugin.pm000066400000000000000000000035021417000230700264150ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::polycom::trio::restapi::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} = '1.0'; $self->{modes} = { 'calls-summary' => 'hardware::devices::polycom::trio::restapi::mode::callssummary', 'calls-rt' => 'hardware::devices::polycom::trio::restapi::mode::callsrt', 'device' => 'hardware::devices::polycom::trio::restapi::mode::device', 'network' => 'hardware::devices::polycom::trio::restapi::mode::network', 'paired' => 'hardware::devices::polycom::trio::restapi::mode::paired', 'registration' => 'hardware::devices::polycom::trio::restapi::mode::registration' }; $self->{custom_modes}->{api} = 'hardware::devices::polycom::trio::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Polycom Trio (8300, 8500, 8800) through HTTP/REST API. =over 8 =back =cut centreon-plugins-20220113/hardware/devices/safenet/000077500000000000000000000000001417000230700221005ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/safenet/hsm/000077500000000000000000000000001417000230700226675ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/safenet/hsm/protecttoolkit/000077500000000000000000000000001417000230700257555ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/safenet/hsm/protecttoolkit/mode/000077500000000000000000000000001417000230700267015ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/safenet/hsm/protecttoolkit/mode/components/000077500000000000000000000000001417000230700310665ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/safenet/hsm/protecttoolkit/mode/components/hwstatus.pm000066400000000000000000000032211417000230700333040ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::safenet::hsm::protecttoolkit::mode::components::hwstatus; use strict; use warnings; sub load { } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking hardware status"); return if ($self->check_filter(section => 'hwstatus')); return if ($self->{stdout} !~ /^Hardware Status\s+:\s+(.*?)\n/msi); my $status = $1; $self->{output}->output_add(long_msg => sprintf("hardware status is '%s'", $status)); my $exit = $self->get_severity(section => 'hwstatus', value => $status); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Hardware status is '%s'", $status)); } } 1;centreon-plugins-20220113/hardware/devices/safenet/hsm/protecttoolkit/mode/components/memory.pm000066400000000000000000000047011417000230700327360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::safenet::hsm::protecttoolkit::mode::components::memory; use strict; use warnings; sub load { } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking memory"); return if ($self->check_filter(section => 'memory')); return if ($self->{stdout} !~ /^SM Size Free\/Total\s*:\s+(\d+)\/(\d+)/msi); my ($free, $total) = ($1, $2); my $used = $total - $free; my $prct_used = $used * 100 / $total; my $prct_free = 100 - $prct_used; my ($free_value, $free_unit) = $self->{perfdata}->change_bytes(value => $free); my ($used_value, $used_unit) = $self->{perfdata}->change_bytes(value => $used); my ($total_value, $total_unit) = $self->{perfdata}->change_bytes(value => $total); my $message = sprintf("Memory Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", $total_value . " " . $total_unit, $used_value . " " . $used_unit, $prct_used, $free_value . " " . $free_unit, $prct_free); $self->{output}->output_add(long_msg => $message); my ($exit, $warn, $crit) = $self->get_severity_numeric(section => 'memory', instance => '0', value => $prct_used); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => $message); } $self->{output}->perfdata_add( label => "used_memory", unit => 'B', nlabel => 'hardware.memory.usage.bytes', value => $used, warning => $warn, critical => $crit, min => 0, total => $total ); } 1; centreon-plugins-20220113/hardware/devices/safenet/hsm/protecttoolkit/mode/components/temperature.pm000066400000000000000000000035431417000230700337660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::safenet::hsm::protecttoolkit::mode::components::temperature; use strict; use warnings; sub load { } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking temperature"); return if ($self->check_filter(section => 'temperature')); return if ($self->{stdout} !~ /^Temperature\s+:\s+(\d+)/msi); my $temperature = $1; $self->{output}->output_add(long_msg => sprintf("temperature is %d C", $temperature)); my ($exit, $warn, $crit) = $self->get_severity_numeric(section => 'temperature', instance => '0', value => $temperature); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Temperature is %s C", $temperature)); } $self->{output}->perfdata_add( label => "temp", unit => 'C', nlabel => 'hardware.temperature.celsius', value => $temperature, warning => $warn, critical => $crit ); } 1; centreon-plugins-20220113/hardware/devices/safenet/hsm/protecttoolkit/mode/hardware.pm000066400000000000000000000123271417000230700310410ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::safenet::hsm::protecttoolkit::mode::hardware; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; use centreon::plugins::misc; sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^(temperature|memory)$'; $self->{cb_hook2} = 'cmd_execute'; $self->{thresholds} = { hwstatus => [ ['BATTERY OK', 'OK'], ['.*', 'CRITICAL'] ] }; $self->{components_path} = 'hardware::devices::safenet::hsm::protecttoolkit::mode::components'; $self->{components_module} = ['hwstatus', 'temperature', 'memory']; } sub cmd_execute { my ($self, %options) = @_; ($self->{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->{stdout} =~ s/\r//msg; my ($model, $firmware, $fm_status, $transport_mode, $security_mode) = ('unknown', 'unknown', 'unknown', 'unknown', 'unknown'); $model = $1 if ($self->{stdout} =~ /^Model\s+:\s+(.*?)\s*\n/msi); $firmware = $1 if ($self->{stdout} =~ /^Firmware Version\s+:\s+(.*?)\s*\n/msi); $fm_status = $1 if ($self->{stdout} =~ /^FM Status\s+:\s+(.*?)\s*\n/msi); $transport_mode = $1 if ($self->{stdout} =~ /^Transport Mode\s+:\s+(.*?)\s*\n/msi); $security_mode = $1 if ($self->{stdout} =~ /^Security Mode\s+:\s+(.*?)\s*\n/msi); $self->{output}->output_add(long_msg => sprintf("model: %s, firmware version: %s", $model, $firmware)); $self->{output}->output_add(long_msg => sprintf("fm status: '%s', transport mode: '%s', security mode: '%s'", $fm_status, $transport_mode, $security_mode)); } sub display { my ($self, %options) = @_; $self->{output}->output_add( severity => 'OK', short_msg => sprintf("Hardware status is OK") ); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_absent => 1); bless $self, $class; $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 => 'ctconf' }, 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '-v' } }); return $self; } 1; __END__ =head1 MODE Check HSM hardware status. =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'hwstatus', 'temperature', 'memory'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=temperature) =item B<--threshold-overload> Set to overload default threshold values (syntax: section,status,regexp) It used before default thresholds (order stays). Example: --threshold-overload='hwstats,CRITICAL,^(?!(OK)$)' =item B<--warning> Set warning threshold for 'temperature', 'memory' (syntax: type,regexp,threshold) Example: --warning='temperature,.*,50' =item B<--critical> Set critical threshold for 'temperature', 'memory' (syntax: type,regexp,threshold) Example: --critical='temperature,.*,60' =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: 'ctconf'). Can be changed if you have output in a file. =item B<--command-path> Command path (Default: ''). =item B<--command-options> Command options (Default: '-v'). =back =cut centreon-plugins-20220113/hardware/devices/safenet/hsm/protecttoolkit/plugin.pm000066400000000000000000000024201417000230700276070ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::safenet::hsm::protecttoolkit::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} = '0.1'; %{$self->{modes}} = ( 'hardware' => 'hardware::devices::safenet::hsm::protecttoolkit::mode::hardware', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Safenet HSM with ProtectToolkit. =cut centreon-plugins-20220113/hardware/devices/safenet/keysecure/000077500000000000000000000000001417000230700240775ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/safenet/keysecure/snmp/000077500000000000000000000000001417000230700250545ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/safenet/keysecure/snmp/plugin.pm000066400000000000000000000033111417000230700267060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::safenet::keysecure::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}} = ( 'connections' => 'centreon::common::ingrian::snmp::mode::connections', 'cpu' => 'centreon::common::ingrian::snmp::mode::cpu', 'disk' => 'centreon::common::ingrian::snmp::mode::disk', 'interfaces' => 'snmp_standard::mode::interfaces', 'list-interfaces' => 'snmp_standard::mode::listinterfaces', 'memory' => 'centreon::common::ingrian::snmp::mode::memory', 'request-stats' => 'centreon::common::ingrian::snmp::mode::requeststats', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Safenet Keysecure in SNMP. =cut centreon-plugins-20220113/hardware/devices/timelinkmicro/000077500000000000000000000000001417000230700233215ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/timelinkmicro/tms6001/000077500000000000000000000000001417000230700244335ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/timelinkmicro/tms6001/snmp/000077500000000000000000000000001417000230700254105ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/timelinkmicro/tms6001/snmp/mode/000077500000000000000000000000001417000230700263345ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/timelinkmicro/tms6001/snmp/mode/alarms.pm000066400000000000000000000042071417000230700301540ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Authors : Thomas Gourdin thomas.gourdin@gmail.com package hardware::devices::timelinkmicro::tms6001::snmp::mode::alarms; 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 } ]; $self->{maps_counters}->{global} = [ { label => 'total', nlabel => 'alarms.total.count', set => { key_values => [ { name => 'alarms_count' } ], output_template => 'current number of alarms: %s', perfdatas => [ { value => 'alarms_count', template => '%s', min => 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 => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $oid_infoAlarmsCount = '.1.3.6.1.4.1.22641.100.3.3.0'; my $snmp_result = $options{snmp}->get_leef(oids => [ $oid_infoAlarmsCount ], nothing_quit => 1); $self->{global} = { alarms_count => $snmp_result->{$oid_infoAlarmsCount} }; } 1; __END__ =head1 MODE Check alarms. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'total'. =back =cut centreon-plugins-20220113/hardware/devices/timelinkmicro/tms6001/snmp/mode/antenna.pm000066400000000000000000000065011417000230700303200ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Authors : Thomas Gourdin thomas.gourdin@gmail.com package hardware::devices::timelinkmicro::tms6001::snmp::mode::antenna; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); sub custom_status_output { my ($self, %options) = @_; return 'antenna status: ' . $self->{result_values}->{status}; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 } ]; $self->{maps_counters}->{global} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_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 => { 'unknown-status:s' => { name => 'unknown_status', default => '' }, 'warning-status:s' => { name => 'warning_status', default => '%{status} =~ /shorted/i' }, 'critical-status:s' => { name => 'critical_status', default => '%{status} =~ /notConnected/i' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status', 'unknown_status']); } my $mapping_status = { C => 'connected', S => 'shorted/poweroff', N => 'notConnected' }; sub manage_selection { my ($self, %options) = @_; my $oid_tsGNSSAntenna = '.1.3.6.1.4.1.22641.100.4.1.4.0'; my $snmp_result = $options{snmp}->get_leef(oids => [ $oid_tsGNSSAntenna ], nothing_quit => 1); $self->{global} = { status => $mapping_status->{ $snmp_result->{$oid_tsGNSSAntenna} } }; } 1; __END__ =head1 MODE Check antenna. =over 8 =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{status} =item B<--warning-status> Set warning threshold for status (Default: '%{status} =~ /shorted/i'). Can used special variables like: %{status} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /notConnected/i'). Can used special variables like: %{status} =back =cut centreon-plugins-20220113/hardware/devices/timelinkmicro/tms6001/snmp/mode/frequency.pm000066400000000000000000000043051417000230700306750ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Authors : Thomas Gourdin thomas.gourdin@gmail.com package hardware::devices::timelinkmicro::tms6001::snmp::mode::frequency; 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 } ]; $self->{maps_counters}->{global} = [ { label => 'frequency-quality', nlabel => 'generation.frequency.quality.count', set => { key_values => [ { name => 'qual_frequency' } ], output_template => 'quality of frequency generation: %s', perfdatas => [ { value => 'qual_frequency', template => '%s' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $oid_infoQualFreq = '.1.3.6.1.4.1.22641.100.3.6.0'; my $snmp_result = $options{snmp}->get_leef(oids => [ $oid_infoQualFreq ], nothing_quit => 1); $self->{global} = { qual_frequency => $snmp_result->{$oid_infoQualFreq} }; } 1; __END__ =head1 MODE Check quality of frequency generation =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'frequency-quality'. =back =cut centreon-plugins-20220113/hardware/devices/timelinkmicro/tms6001/snmp/mode/gnss.pm000066400000000000000000000061701417000230700276500ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Authors : Thomas Gourdin thomas.gourdin@gmail.com package hardware::devices::timelinkmicro::tms6001::snmp::mode::gnss; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); sub custom_status_output { my ($self, %options) = @_; return 'GNSS status: ' . $self->{result_values}->{status}; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 } ]; $self->{maps_counters}->{global} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_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 => { 'unknown-status:s' => { name => 'unknown_status', default => '' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{status} !~ /nominal/i' } }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status', 'unknown_status']); } sub manage_selection { my ($self, %options) = @_; my $oid_tsGNSSStatus = '.1.3.6.1.4.1.22641.100.4.1.2.0'; my $snmp_result = $options{snmp}->get_leef(oids => [ $oid_tsGNSSStatus ], nothing_quit => 1); $self->{global} = { status => lc($snmp_result->{$oid_tsGNSSStatus}) }; } 1; __END__ =head1 MODE Check GNSS. =over 8 =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{status} =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{status} =item B<--critical-status> Set critical threshold for status (Default: '%{status} !~ /nominal/i'). Can used special variables like: %{status} =back =cut centreon-plugins-20220113/hardware/devices/timelinkmicro/tms6001/snmp/mode/satellites.pm000066400000000000000000000042171417000230700310470ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Authors : Thomas Gourdin thomas.gourdin@gmail.com package hardware::devices::timelinkmicro::tms6001::snmp::mode::satellites; 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 } ]; $self->{maps_counters}->{global} = [ { label => 'seen', nlabel => 'satellites.seen.count', set => { key_values => [ { name => 'sat_count' } ], output_template => 'current number of satellites seen: %s', perfdatas => [ { value => 'sat_count', template => '%s', min => 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 => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $oid_tsGNSSSatCount = '.1.3.6.1.4.1.22641.100.4.1.8.0'; my $snmp_result = $options{snmp}->get_leef(oids => [ $oid_tsGNSSSatCount ], nothing_quit => 1); $self->{global} = { sat_count => $snmp_result->{$oid_tsGNSSSatCount} }; } 1; __END__ =head1 MODE Check satellites. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'seen'. =back =cut centreon-plugins-20220113/hardware/devices/timelinkmicro/tms6001/snmp/mode/time.pm000066400000000000000000000042301417000230700276270ustar00rootroot00000000000000# # Copyright 2019 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Authors : Thomas Gourdin thomas.gourdin@gmail.com package hardware::devices::timelinkmicro::tms6001::snmp::mode::time; 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 } ]; $self->{maps_counters}->{global} = [ { label => 'time-quality', nlabel => 'generation.time.quality.count', set => { key_values => [ { name => 'qual_time' } ], output_template => 'quality of time generation: %s', perfdatas => [ { value => 'qual_time', template => '%s' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $oid_infoQualTime = '.1.3.6.1.4.1.22641.100.3.5.0'; my $snmp_result = $options{snmp}->get_leef(oids => [ $oid_infoQualTime ], nothing_quit => 1); $self->{global} = { qual_time => $snmp_result->{$oid_infoQualTime} }; } 1; __END__ =head1 MODE Check quality of time generation. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'time-quality'. =back =cut centreon-plugins-20220113/hardware/devices/timelinkmicro/tms6001/snmp/plugin.pm000066400000000000000000000034151417000230700272470ustar00rootroot00000000000000# # Copyright 2015 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. # # Authors : Thomas Gourdin thomas.gourdin@gmail.com package hardware::devices::timelinkmicro::tms6001::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} = { 'alarms' => 'hardware::devices::timelinkmicro::tms6001::snmp::mode::alarms', 'antenna' => 'hardware::devices::timelinkmicro::tms6001::snmp::mode::antenna', 'frequency' => 'hardware::devices::timelinkmicro::tms6001::snmp::mode::frequency', 'gnss' => 'hardware::devices::timelinkmicro::tms6001::snmp::mode::gnss', 'satellites' => 'hardware::devices::timelinkmicro::tms6001::snmp::mode::satellites', 'time' => 'hardware::devices::timelinkmicro::tms6001::snmp::mode::time' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check timelinkmicro TMS6001 NTP servers through SNMP =cut centreon-plugins-20220113/hardware/devices/video/000077500000000000000000000000001417000230700215615ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/video/appeartv/000077500000000000000000000000001417000230700234035ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/video/appeartv/snmp/000077500000000000000000000000001417000230700243605ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/video/appeartv/snmp/mode/000077500000000000000000000000001417000230700253045ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/video/appeartv/snmp/mode/alarms.pm000066400000000000000000000162711417000230700271300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::video::appeartv::snmp::mode::alarms; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::statefile; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("alarm [severity: %s] [source: %s] [text: %s] %s", $self->{result_values}->{severity}, $self->{result_values}->{source}, $self->{result_values}->{text}, $self->{result_values}->{generation_time}); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{source} = $options{new_datas}->{$self->{instance} . '_msgSourceName'}; $self->{result_values}->{text} = $options{new_datas}->{$self->{instance} . '_msgText'}; $self->{result_values}->{severity} = $options{new_datas}->{$self->{instance} . '_msgSeverity'}; $self->{result_values}->{since} = $options{new_datas}->{$self->{instance} . '_since'}; $self->{result_values}->{generation_time} = $options{new_datas}->{$self->{instance} . '_msgGenerationTime'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'alarms', type => 2, message_multiple => '0 problem(s) detected', display_counter_problem => { label => 'alerts', min => 0 }, group => [ { name => 'alarm', skipped_code => { -11 => 1 } } ] } ]; $self->{maps_counters}->{alarm} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'msgSourceName' }, { name => 'msgText' }, { name => 'since' }, { name => 'msgSeverity' }, { name => 'msgGenerationTime' } ], 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 => \&catalog_status_threshold, } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-msg:s" => { name => 'filter_msg' }, "warning-status:s" => { name => 'warning_status', default => '%{severity} =~ /minor|warning/i' }, "critical-status:s" => { name => 'critical_status', default => '%{severity} =~ /critical|major/i' }, "memory" => { name => 'memory' }, }); centreon::plugins::misc::mymodule_load(output => $self->{output}, module => 'Date::Parse', error_msg => "Cannot load module 'Date::Parse'."); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->check_options(%options); } } my %map_severity = (0 => 'indeterminate', 1 => 'critical', 2 => 'major', 3 => 'minor', 4 => 'warning', 5 => 'cleared', 6 => 'notify'); my $mapping = { msgSourceName => { oid => '.1.3.6.1.4.1.23916.3.1.4.1.3' }, msgText => { oid => '.1.3.6.1.4.1.23916.3.1.4.1.4' }, msgGenerationTime => { oid => '.1.3.6.1.4.1.23916.3.1.4.1.6' }, # 2016-12-16 14:49:18 msgSeverity => { oid => '.1.3.6.1.4.1.23916.3.1.4.1.13', map => \%map_severity }, }; sub manage_selection { my ($self, %options) = @_; $self->{alarms}->{global} = { alarm => {} }; my $snmp_result = $options{snmp}->get_multiple_table(oids => [ { oid => $mapping->{msgSourceName}->{oid} }, { oid => $mapping->{msgText}->{oid} }, { oid => $mapping->{msgGenerationTime}->{oid} }, { oid => $mapping->{msgSeverity}->{oid} }, ], return_type => 1); my $last_time; if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->read(statefile => "cache_appeartv_" . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port(). '_' . $self->{mode}); $last_time = $self->{statefile_cache}->get(name => 'last_time'); } my ($i, $current_time) = (1, time()); foreach my $oid (keys %{$snmp_result}) { next if ($oid !~ /^$mapping->{msgSeverity}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); my $create_time = Date::Parse::str2time($result->{msgGenerationTime}); if (!defined($create_time)) { $self->{output}->output_add(severity => 'UNKNOWN', short_msg => "Can't Parse date '" . $result->{msgGenerationTime} . "'"); next; } next if (defined($self->{option_results}->{memory}) && defined($last_time) && $last_time > $create_time); if (defined($self->{option_results}->{filter_msg}) && $self->{option_results}->{filter_msg} ne '' && $result->{msgText} !~ /$self->{option_results}->{filter_msg}/) { $self->{output}->output_add(long_msg => "skipping '" . $result->{msgText} . "': no matching filter.", debug => 1); next; } my $diff_time = $current_time - $create_time; $self->{alarms}->{global}->{alarm}->{$i} = { %$result, since => $diff_time }; $i++; } if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->write(data => { last_time => $current_time }); } } 1; __END__ =head1 MODE Check alarms. =over 8 =item B<--filter-msg> Filter by message (can be a regexp). =item B<--warning-status> Set warning threshold for status (Default: '%{severity} =~ /minor|warning/i') Can used special variables like: %{severity}, %{text}, %{source}, %{since} =item B<--critical-status> Set critical threshold for status (Default: '%{severity} =~ /critical|major/i'). Can used special variables like: %{severity}, %{text}, %{source}, %{since} =item B<--memory> Only check new alarms. =back =cut centreon-plugins-20220113/hardware/devices/video/appeartv/snmp/plugin.pm000066400000000000000000000023641417000230700262210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::video::appeartv::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}} = ( 'alarms' => 'hardware::devices::video::appeartv::snmp::mode::alarms', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check AppeartTV in SNMP. =cut centreon-plugins-20220113/hardware/devices/video/axis/000077500000000000000000000000001417000230700225255ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/video/axis/snmp/000077500000000000000000000000001417000230700235025ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/video/axis/snmp/mode/000077500000000000000000000000001417000230700244265ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/video/axis/snmp/mode/components/000077500000000000000000000000001417000230700266135ustar00rootroot00000000000000centreon-plugins-20220113/hardware/devices/video/axis/snmp/mode/components/audio.pm000066400000000000000000000050401417000230700302510ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::video::axis::snmp::mode::components::audio; use strict; use warnings; my %map_audio_status = ( 1 => 'signalOk', 2 => 'noSignal', ); my $mapping = { axisAudioState => { oid => '.1.3.6.1.4.1.368.4.1.5.1.2', map => \%map_audio_status }, }; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping->{axisAudioState}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking audio Signal"); $self->{components}->{audio} = {name => 'audio', total => 0, skip => 0}; return if ($self->check_filter(section => 'audio')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$mapping->{axisAudioState}->{oid}}})) { next if ($oid !~ /^$mapping->{axisAudioState}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$mapping->{axisAudioState}->{oid}}, instance => $instance); next if ($self->check_filter(section => 'audio', instance => $instance)); $self->{components}->{audio}->{total}++; $self->{output}->output_add(long_msg => sprintf("audio '%s' state is %s [instance: %s].", $instance, $result->{axisAudioState}, $instance )); my $exit = $self->get_severity(section => 'audio', value => $result->{axisAudioState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("audio '%s' state is %s", $instance, $result->{axisAudioState})); } } } 1;centreon-plugins-20220113/hardware/devices/video/axis/snmp/mode/components/casing.pm000066400000000000000000000053661417000230700304270ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::video::axis::snmp::mode::components::casing; use strict; use warnings; my %map_casing_status = ( 1 => 'closed', 2 => 'open', ); my $mapping = { axiscasingState => { oid => '.1.3.6.1.4.1.368.4.1.6.1.3', map => \%map_casing_status }, axiscasingName => { oid => '.1.3.6.1.4.1.368.4.1.6.1.2' }, }; my $oid_axiscasingEntry = '.1.3.6.1.4.1.368.4.1.6.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_axiscasingEntry, start => $mapping->{axiscasingState}->{oid}, end => $mapping->{axiscasingName}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking casings"); $self->{components}->{casing} = {name => 'casings', total => 0, skip => 0}; return if ($self->check_filter(section => 'casing')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_axiscasingEntry}})) { next if ($oid !~ /^$mapping->{axiscasingState}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_axiscasingEntry}, instance => $instance); next if ($self->check_filter(section => 'casing', instance => $instance)); $self->{components}->{casing}->{total}++; $self->{output}->output_add(long_msg => sprintf("casing '%s' status is %s [casing: %s]", $instance, $result->{axiscasingState}, $result->{axiscasingName}, )); my $exit = $self->get_severity(section => 'casing', value => $result->{axiscasingState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("casing state is %s [casing: %s]", $result->{axiscasingState}, $result->{axiscasingName})); } } } 1; centreon-plugins-20220113/hardware/devices/video/axis/snmp/mode/components/fan.pm000066400000000000000000000047541417000230700277270ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::video::axis::snmp::mode::components::fan; use strict; use warnings; my %map_fan_status = ( 0 => 'ok', 1 => 'failed', ); my $mapping = { axisFanState => { oid => '.1.3.6.1.4.1.368.4.1.2.1.3', map => \%map_fan_status }, }; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping->{axisFanState}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking fans"); $self->{components}->{fan} = {name => 'fans', total => 0, skip => 0}; return if ($self->check_filter(section => 'fan')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$mapping->{axisFanState}->{oid}}})) { next if ($oid !~ /^$mapping->{axisFanState}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$mapping->{axisFanState}->{oid}}, instance => $instance); next if ($self->check_filter(section => 'fan', instance => $instance)); $self->{components}->{fan}->{total}++; $self->{output}->output_add(long_msg => sprintf("fan '%s' state is %s [instance: %s].", $instance, $result->{axisFanState}, $instance )); my $exit = $self->get_severity(section => 'fan', value => $result->{axisFanState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("fan '%s' state is %s", $instance, $result->{axisFanState})); } } } 1; centreon-plugins-20220113/hardware/devices/video/axis/snmp/mode/components/psu.pm000066400000000000000000000047731417000230700277730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::video::axis::snmp::mode::components::psu; use strict; use warnings; my %map_psu_status = ( 1 => 'ok', 2 => 'failure', ); my $mapping = { axisPsState => { oid => '.1.3.6.1.4.1.368.4.1.2.1.3', map => \%map_psu_status }, }; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping->{axisPsState}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking power supply"); $self->{components}->{psu} = {name => 'psu', total => 0, skip => 0}; return if ($self->check_filter(section => 'psu')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$mapping->{axisPsState}->{oid}}})) { next if ($oid !~ /^$mapping->{axisPsState}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$mapping->{axisPsState}->{oid}}, 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' state is %s [instance: %s].", $instance, $result->{axisPsState}, $instance )); my $exit = $self->get_severity(section => 'psu', value => $result->{axisPsState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("power supply '%s' state is %s", $instance, $result->{axisPsState})); } } } 1; centreon-plugins-20220113/hardware/devices/video/axis/snmp/mode/components/storage.pm000066400000000000000000000050671417000230700306250ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::video::axis::snmp::mode::components::storage; use strict; use warnings; my %map_storage_status = ( 1 => 'no', 2 => 'yes', ); my $mapping = { axisStorageState => { oid => '.1.3.6.1.4.1.368.4.1.8.1.3', map => \%map_storage_status }, }; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping->{axisStorageState}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking Storage"); $self->{components}->{storage} = {name => 'storage', total => 0, skip => 0}; return if ($self->check_filter(section => 'storage')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$mapping->{axisStorageState}->{oid}}})) { next if ($oid !~ /^$mapping->{axisStorageState}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$mapping->{axisStorageState}->{oid}}, instance => $instance); next if ($self->check_filter(section => 'storage', instance => $instance)); $self->{components}->{storage}->{total}++; $self->{output}->output_add(long_msg => sprintf("storage '%s' state is %s [instance: %s].", $instance, $result->{axisStorageState}, $instance )); my $exit = $self->get_severity(section => 'storage', value => $result->{axisStorageState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("storage '%s' state is %s", $instance, $result->{axisStorageState})); } } } 1; centreon-plugins-20220113/hardware/devices/video/axis/snmp/mode/components/temperature.pm000066400000000000000000000075471417000230700315230ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::video::axis::snmp::mode::components::temperature; use strict; use warnings; my %map_temperature_status = ( 1 => 'ok', 2 => 'failed', 3 => 'outOfBoundary', ); my $mapping = { axisTemperatureState => { oid => '.1.3.6.1.4.1.368.4.1.3.1.3', map => \%map_temperature_status }, axisTemperatureCelsius => { oid => '.1.3.6.1.4.1.368.4.1.3.1.4' }, }; my $oid_axisTemperatureEntry = '.1.3.6.1.4.1.368.4.1.3.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_axisTemperatureEntry, start => $mapping->{axisTemperatureState}->{oid}, end => $mapping->{axisTemperatureCelsius}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking temperatures"); $self->{components}->{temperature} = {name => 'temperatures', total => 0, skip => 0}; return if ($self->check_filter(section => 'temperature')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_axisTemperatureEntry}})) { next if ($oid !~ /^$mapping->{axisTemperatureState}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_axisTemperatureEntry}, instance => $instance); next if ($self->check_filter(section => 'temperature', instance => $instance)); $self->{components}->{temperature}->{total}++; $self->{output}->output_add(long_msg => sprintf("Temperature '%s' status is %s [temperature: %s C]", $instance, $result->{axisTemperatureState}, $result->{axisTemperatureCelsius}, )); my $exit = $self->get_severity(section => 'temperature', value => $result->{axisTemperatureState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Temperature state is %s [temperature: %s C]", $result->{axisTemperatureState}, $result->{axisTemperaturecelsius})); } if (defined($result->{axisTemperatureCelsius}) && $result->{axisTemperatureCelsius} != -1) { my ($exit, $warn, $crit) = $self->get_severity_numeric(section => 'temperature', instance => $instance, value => $result->{axisTemperatureCelsius}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Temperature '%s' is %s degree centigrade", $instance, $result->{axisTemperatureCelsius})); } $self->{output}->perfdata_add( label => "temperature", unit => 'C', nlabel => 'hardware.temperature.celsius', instances => $instance, value => $result->{axisTemperatureCelsius}, warning => $warn, critical => $crit ); } } } 1; centreon-plugins-20220113/hardware/devices/video/axis/snmp/mode/components/video.pm000066400000000000000000000050411417000230700302570ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::video::axis::snmp::mode::components::video; use strict; use warnings; my %map_video_status = ( 1 => 'signalOk', 2 => 'noSignal', ); my $mapping = { axisVideoState => { oid => '.1.3.6.1.4.1.368.4.1.4.1.2', map => \%map_video_status }, }; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping->{axisVideoState}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking Video Signal"); $self->{components}->{video} = {name => 'video', total => 0, skip => 0}; return if ($self->check_filter(section => 'video')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$mapping->{axisVideoState}->{oid}}})) { next if ($oid !~ /^$mapping->{axisVideoState}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$mapping->{axisVideoState}->{oid}}, instance => $instance); next if ($self->check_filter(section => 'video', instance => $instance)); $self->{components}->{video}->{total}++; $self->{output}->output_add(long_msg => sprintf("video '%s' state is %s [instance: %s].", $instance, $result->{axisVideoState}, $instance )); my $exit = $self->get_severity(section => 'video', value => $result->{axisVideoState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("video '%s' state is %s", $instance, $result->{axisVideoState})); } } } 1;centreon-plugins-20220113/hardware/devices/video/axis/snmp/mode/environment.pm000066400000000000000000000063541417000230700273400ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::video::axis::snmp::mode::environment; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^(temperature)$'; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { video => [ ['signalOk', 'OK'], ['noSignal', 'CRITICAL'] ], psu => [ ['failure', 'CRITICAL'], ['ok', 'OK'] ], fan => [ ['failed', 'CRITICAL'], ['ok', 'OK'] ], temperature => [ ['failed', 'CRITICAL'], ['outOfBoundary', 'CRITICAL'], ['ok', 'OK'] ], audio => [ ['signalOk', 'OK'], ['noSignal', 'CRITICAL'] ], storage => [ ['yes', 'OK'], ['no', 'CRITICAL'] ], casing => [ ['open', 'OK'], ['closed', 'WARNING'] ] }; $self->{components_path} = 'hardware::devices::video::axis::snmp::mode::components'; $self->{components_module} = ['video', 'psu', 'fan', 'temperature', 'audio', 'storage', 'casing']; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } 1; __END__ =head1 MODE Check videos (AXIS-VIDEO-MIB). =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'video', 'psu', 'fan', 'temperature', 'audio', 'storage', 'casing'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=video) Can also exclude specific instance: --filter=video,fan.1 =item B<--absent-problem> Return an error if an entity is not 'present' (default is skipping) (comma seperated list) Can be specific or global: --absent-problem=video,temperature.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='video,CRITICAL,^(?!(good)$)' =back =cut centreon-plugins-20220113/hardware/devices/video/axis/snmp/plugin.pm000066400000000000000000000024721417000230700253430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::devices::video::axis::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}} = ( 'environment' => 'hardware::devices::video::axis::snmp::mode::environment', 'uptime' => 'snmp_standard::mode::uptime', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Video Camera Axis in SNMP. =cut centreon-plugins-20220113/hardware/kvm/000077500000000000000000000000001417000230700176265ustar00rootroot00000000000000centreon-plugins-20220113/hardware/kvm/adder/000077500000000000000000000000001417000230700207055ustar00rootroot00000000000000centreon-plugins-20220113/hardware/kvm/adder/aim/000077500000000000000000000000001417000230700214535ustar00rootroot00000000000000centreon-plugins-20220113/hardware/kvm/adder/aim/snmp/000077500000000000000000000000001417000230700224305ustar00rootroot00000000000000centreon-plugins-20220113/hardware/kvm/adder/aim/snmp/mode/000077500000000000000000000000001417000230700233545ustar00rootroot00000000000000centreon-plugins-20220113/hardware/kvm/adder/aim/snmp/mode/deviceusage.pm000066400000000000000000000144251417000230700262040ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::kvm::adder::aim::snmp::mode::deviceusage; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); 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} . '_device_status'}; $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, message_separator => ' - ' }, { name => 'device', type => 1, cb_prefix_output => 'prefix_device_output', message_multiple => 'All devices are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'total', set => { key_values => [ { name => 'total' } ], output_template => 'Total devices : %s', perfdatas => [ { label => 'devices_total', value => 'total', template => '%s', min => 0 }, ], } }, { label => 'online', set => { key_values => [ { name => 'online' }, { name => 'total' } ], output_template => 'Online devices : %s', perfdatas => [ { label => 'devices_online', value => 'online', template => '%s', min => 0, max => 'total' }, ], } }, ]; $self->{maps_counters}->{device} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'device_status' }, { 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 => \&catalog_status_threshold, } }, ]; } sub prefix_device_output { my ($self, %options) = @_; return "Device '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "filter-name:s" => { name => 'filter_name' }, "warning-status:s" => { name => 'warning_status', default => '' }, "critical-status:s" => { name => 'critical_status', default => 'not %{status} =~ /online|rebooting|upgrading/i' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } my %map_status = ( 1 => 'offline', 2 => 'online', 3 => 'rebooting', 4 => 'resetting', 5 => 'upgrading', 6 => 'unconfigured', 7 => 'backup', 8 => 'unknown', ); my $oid_deviceName = '.1.3.6.1.4.1.25119.1.1.1.4'; my $mapping = { deviceStatus => { oid => '.1.3.6.1.4.1.25119.1.1.1.20', map => \%map_status }, }; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_table(oid => $oid_deviceName, nothing_quit => 1); $self->{device} = {}; $self->{global} = { total => 0, online => 0 }; foreach my $oid (keys %{$snmp_result}) { $oid =~ /^$oid_deviceName\.(.*)$/; 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 device '" . $snmp_result->{$oid} . "'.", debug => 1); next; } $self->{device}->{$instance} = { display => $snmp_result->{$oid} }; } $options{snmp}->load(oids => [$mapping->{deviceStatus}->{oid}], instances => [keys %{$self->{device}}], instance_regexp => '^(.*)$'); $snmp_result = $options{snmp}->get_leef(nothing_quit => 1); foreach (keys %{$self->{device}}) { my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $_); $self->{device}->{$_}->{device_status} = $result->{deviceStatus}; $self->{global}->{$result->{deviceStatus}}++ if (defined($self->{global}->{$result->{deviceStatus}})); $self->{global}->{total}++; } if (scalar(keys %{$self->{device}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No device found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check device usage. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^total$' =item B<--filter-name> Filter by device name (can be a regexp). =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 (Default: 'not %{status} =~ /online|rebooting|upgrading/i'). Can used special variables like: %{status}, %{display} =item B<--warning-*> Threshold warning. Can be: 'total', 'online'. =item B<--critical-*> Threshold critical. Can be: 'total', 'online'. =back =cut centreon-plugins-20220113/hardware/kvm/adder/aim/snmp/mode/serverusage.pm000066400000000000000000000116521417000230700262520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::kvm::adder::aim::snmp::mode::serverusage; 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 => ' - ', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ { label => 'cpu-load', set => { key_values => [ { name => 'cpu_load' } ], output_template => 'CPU Load : %s', perfdatas => [ { label => 'cpu_load', value => 'cpu_load', template => '%s', min => 0 }, ], } }, { label => 'memory', set => { key_values => [ { name => 'memory_used' } ], output_template => 'Memory Used : %s %%', perfdatas => [ { label => 'memory_used', value => 'memory_used', template => '%s', unit => '%', min => 0, max => 100 }, ], } }, { label => 'disk', set => { key_values => [ { name => 'disk_used' } ], output_template => 'Disk Used : %s %%', perfdatas => [ { label => 'disk_used', value => 'disk_used', template => '%s', unit => '%', min => 0, max => 100 }, ], } }, { label => 'num-active-con', set => { key_values => [ { name => 'num_active_con' } ], output_template => 'Current Connected Rx : %s', perfdatas => [ { label => 'num_active_con', value => 'num_active_con', template => '%s', min => 0}, ], } }, { label => 'num-rx', set => { key_values => [ { name => 'num_rx' } ], output_template => 'Number Rx : %s', perfdatas => [ { label => 'num_rx', value => 'num_rx', template => '%s', min => 0 }, ], } }, { label => 'num-tx', set => { key_values => [ { name => 'num_tx' } ], output_template => 'Numbre Tx : %s', perfdatas => [ { label => 'num_tx', value => 'num_tx', template => '%s', min => 0 }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub manage_selection { my ($self, %options) = @_; my $oid_numRx = '.1.3.6.1.4.1.25119.1.2.1.0'; my $oid_numTx = '.1.3.6.1.4.1.25119.1.2.2.0'; my $oid_numActiveConnexions = '.1.3.6.1.4.1.25119.1.2.3.0'; my $oid_serverCPULoad = '.1.3.6.1.4.1.25119.1.3.1.0'; my $oid_serverMemoryUsage = '.1.3.6.1.4.1.25119.1.3.2.0'; my $oid_serverDiskSpace = '.1.3.6.1.4.1.25119.1.3.4.0'; my $result = $options{snmp}->get_leef(oids => [ $oid_numRx, $oid_numTx, $oid_numActiveConnexions, $oid_serverCPULoad, $oid_serverMemoryUsage, $oid_serverDiskSpace ], nothing_quit => 1); $result->{$oid_serverMemoryUsage} =~ s/%//g; $result->{$oid_serverDiskSpace} =~ s/%//g; $self->{global} = { num_rx => $result->{$oid_numRx}, num_tx => $result->{$oid_numTx}, num_active_con => $result->{$oid_numActiveConnexions}, cpu_load => $result->{$oid_serverCPULoad}, memory_used => $result->{$oid_serverMemoryUsage}, disk_used => $result->{$oid_serverDiskSpace}, }; } 1; __END__ =head1 MODE Check server usage. =over 8 =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^cpu-load$' =item B<--warning-*> Threshold warning. Can be: 'cpu-load', 'memory', 'disk', 'num-rx', 'num-tx', 'num-active-con'. =item B<--critical-*> Threshold critical. Can be: 'cpu-load', 'memory', 'disk', 'num-rx', 'num-tx', 'num-active-con'. =back =cut centreon-plugins-20220113/hardware/kvm/adder/aim/snmp/plugin.pm000066400000000000000000000025101417000230700242620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::kvm::adder::aim::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}} = ( 'device-usage' => 'hardware::kvm::adder::aim::snmp::mode::deviceusage', 'server-usage' => 'hardware::kvm::adder::aim::snmp::mode::serverusage', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check ADDERLink Infinity Manager in SNMP. =cut centreon-plugins-20220113/hardware/kvm/avocent/000077500000000000000000000000001417000230700212655ustar00rootroot00000000000000centreon-plugins-20220113/hardware/kvm/avocent/acs/000077500000000000000000000000001417000230700220335ustar00rootroot00000000000000centreon-plugins-20220113/hardware/kvm/avocent/acs/6000/000077500000000000000000000000001417000230700224205ustar00rootroot00000000000000centreon-plugins-20220113/hardware/kvm/avocent/acs/6000/snmp/000077500000000000000000000000001417000230700233755ustar00rootroot00000000000000centreon-plugins-20220113/hardware/kvm/avocent/acs/6000/snmp/mode/000077500000000000000000000000001417000230700243215ustar00rootroot00000000000000centreon-plugins-20220113/hardware/kvm/avocent/acs/6000/snmp/mode/components/000077500000000000000000000000001417000230700265065ustar00rootroot00000000000000centreon-plugins-20220113/hardware/kvm/avocent/acs/6000/snmp/mode/components/psu.pm000066400000000000000000000053371417000230700276630ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::kvm::avocent::acs::6000::snmp::mode::components::psu; use strict; use warnings; my %map_states = (1 => 'statePowerOn', 2 => 'statePowerOff', 9999 => 'powerNotInstalled'); my $mapping = { acsPowerSupplyStatePw1 => { oid => '.1.3.6.1.4.1.10418.16.2.1.8.2', map => \%map_states }, acsPowerSupplyStatePw2 => { oid => '.1.3.6.1.4.1.10418.16.2.1.8.3', map => \%map_states }, }; my $oid_acsPowerSupply = '.1.3.6.1.4.1.10418.16.2.1.8'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_acsPowerSupply }; } sub check_psu { my ($self, %options) = @_; return if ($self->check_filter(section => 'psu', instance => $options{instance})); return if ($options{state} eq 'powerNotInstalled' && $self->absent_problem(section => 'psu', instance => $options{instance})); $self->{components}->{psu}->{total}++; $self->{output}->output_add( long_msg => sprintf( "power supply '%s' status is %s.", $options{instance}, $options{state} ) ); my $exit = $self->get_severity(section => 'psu', value => $options{state}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Power supply '%s' status is %s", $options{instance}, $options{state} ) ); } } 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 $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_acsPowerSupply}, instance => '0'); check_psu($self, state => $result->{acsPowerSupplyStatePw1}, instance => '1'); check_psu($self, state => $result->{acsPowerSupplyStatePw2}, instance => '2'); } 1; centreon-plugins-20220113/hardware/kvm/avocent/acs/6000/snmp/mode/hardware.pm000066400000000000000000000047471417000230700264700ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::kvm::avocent::acs::6000::snmp::mode::hardware; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { psu => [ ['statePowerOn', 'OK'], ['statePowerOff', 'CRITICAL'], ['powerNotInstalled', 'OK'] ] }; $self->{components_path} = 'hardware::kvm::avocent::acs::6000::snmp::mode::components'; $self->{components_module} = ['psu']; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_performance => 1); bless $self, $class; $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: 'psu'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=psu) Can also exclude specific instance: --filter=psu,1 =item B<--absent-problem> Return an error if an entity is not 'present' (default is skipping) (comma seperated list) Can be specific or global: --absent-problem=psu =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,^(?!(statePowerOn)$)' =back =cut centreon-plugins-20220113/hardware/kvm/avocent/acs/6000/snmp/plugin.pm000066400000000000000000000026731417000230700252410ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::kvm::avocent::acs::6000::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}} = ( 'cpu-detailed' => 'snmp_standard::mode::cpudetailed', 'hardware' => 'hardware::kvm::avocent::acs::6000::snmp::mode::hardware', 'load' => 'snmp_standard::mode::loadaverage', 'memory' => 'snmp_standard::mode::memory', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Avocent ACS 6000 series in SNMP. =cut centreon-plugins-20220113/hardware/kvm/avocent/acs/8000/000077500000000000000000000000001417000230700224225ustar00rootroot00000000000000centreon-plugins-20220113/hardware/kvm/avocent/acs/8000/snmp/000077500000000000000000000000001417000230700233775ustar00rootroot00000000000000centreon-plugins-20220113/hardware/kvm/avocent/acs/8000/snmp/mode/000077500000000000000000000000001417000230700243235ustar00rootroot00000000000000centreon-plugins-20220113/hardware/kvm/avocent/acs/8000/snmp/mode/components/000077500000000000000000000000001417000230700265105ustar00rootroot00000000000000centreon-plugins-20220113/hardware/kvm/avocent/acs/8000/snmp/mode/components/psu.pm000066400000000000000000000053521417000230700276620ustar00rootroot00000000000000# # Copyright 2019 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::kvm::avocent::acs::8000::snmp::mode::components::psu; use strict; use warnings; my %map_states = (1 => 'statePowerOn', 2 => 'statePowerOff', 9999 => 'powerNotInstalled'); my $mapping = { acsPowerSupplyStatePw1 => { oid => '.1.3.6.1.4.1.10418.26.2.1.8.2', map => \%map_states }, acsPowerSupplyStatePw2 => { oid => '.1.3.6.1.4.1.10418.26.2.1.8.3', map => \%map_states } }; my $oid_acsPowerSupply = '.1.3.6.1.4.1.10418.26.2.1.8'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_acsPowerSupply }; } sub check_psu { my ($self, %options) = @_; return if ($self->check_filter(section => 'psu', instance => $options{instance})); return if ($options{state} eq 'powerNotInstalled' && $self->absent_problem(section => 'psu', instance => $options{instance})); $self->{components}->{psu}->{total}++; $self->{output}->output_add( long_msg => sprintf( "power supply '%s' status is %s.", $options{instance}, $options{state} ) ); my $exit = $self->get_severity(section => 'psu', value => $options{state}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Power supply '%s' status is %s", $options{instance}, $options{state} ) ); } } 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 $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_acsPowerSupply}, instance => '0'); check_psu($self, state => $result->{acsPowerSupplyStatePw1}, instance => '1'); check_psu($self, state => $result->{acsPowerSupplyStatePw2}, instance => '2'); } 1; centreon-plugins-20220113/hardware/kvm/avocent/acs/8000/snmp/mode/hardware.pm000066400000000000000000000050041417000230700264550ustar00rootroot00000000000000# # Copyright 2019 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::kvm::avocent::acs::8000::snmp::mode::hardware; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { psu => [ ['statePowerOn', 'OK'], ['statePowerOff', 'CRITICAL'], ['powerNotInstalled', 'OK'] ] }; $self->{components_path} = 'hardware::kvm::avocent::acs::8000::snmp::mode::components'; $self->{components_module} = ['psu']; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_performance => 1, force_new_perfdata => 1); bless $self, $class; $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: 'psu'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=psu) Can also exclude specific instance: --filter=psu,1 =item B<--absent-problem> Return an error if an entity is not 'present' (default is skipping) (comma seperated list) Can be specific or global: --absent-problem=psu =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,^(?!(statePowerOn)$)' =back =cut centreon-plugins-20220113/hardware/kvm/avocent/acs/8000/snmp/mode/serialports.pm000066400000000000000000000145031417000230700272330ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::kvm::avocent::acs::8000::snmp::mode::serialports; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); use Digest::MD5 qw(md5_hex); sub custom_status_output { my ($self, %options) = @_; return sprintf( 'status: %s', $self->{result_values}->{status} ); } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'serials', type => 1, cb_prefix_output => 'prefix_serial_output', message_multiple => 'All serial ports are ok' } ]; $self->{maps_counters}->{serials} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'display' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold } }, { label => 'traffic-in', nlabel => 'serialport.traffic.in.bitspersecond', set => { key_values => [ { name => 'traffic_in', per_second => 1 }, { name => 'display' } ], output_template => 'traffic in: %s%s/s', output_change_bytes => 2, perfdatas => [ { template => '%s', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'traffic-out', nlabel => 'serialport.traffic.out.bitspersecond', set => { key_values => [ { name => 'traffic_out', per_second => 1 }, { name => 'display' } ], output_template => 'traffic out: %s%s/s', output_change_bytes => 2, perfdatas => [ { template => '%s', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub prefix_serial_output { my ($self, %options) = @_; return "Serial port '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'unknown-status:s' => { name => 'unknown_status', default => '' }, '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); $self->change_macros( macros => [ 'unknown_status', 'warning_status', 'critical_status' ] ); } my $map_status = { 1 => 'disabled', 2 => 'idle', 3 => 'inUse' }; my $mapping = { status => { oid => '.1.3.6.1.4.1.10418.26.2.3.2.1.3', map => $map_status }, # acsSerialPortTableStatus traffic_out => { oid => '.1.3.6.1.4.1.10418.26.2.3.2.1.16' }, # acsSerialPortTableTxBytes traffic_in => { oid => '.1.3.6.1.4.1.10418.26.2.3.2.1.17' } # acsSerialPortTableRxBytes }; sub manage_selection { my ($self, %options) = @_; my $oid_acsSerialPortTableDeviceName = '.1.3.6.1.4.1.10418.26.2.3.2.1.2'; my $snmp_result = $options{snmp}->get_table( oid => $oid_acsSerialPortTableDeviceName, nothing_quit => 1 ); $self->{serials} = {}; foreach (keys %$snmp_result) { /\.(\d+)$/; my $instance = $1; my $name = $snmp_result->{$_}; 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 port '" . $name . "'.", debug => 1); next; } $self->{serials}->{$instance} = { display => $name }; } return if (scalar(keys %{$self->{serials}}) <= 0); $options{snmp}->load( oids => [ map($_->{oid}, values(%$mapping)) ], instances => [ keys %{$self->{serials}} ], instance_regexp => '^(.*)$' ); $snmp_result = $options{snmp}->get_leef(); foreach (keys %{$self->{serials}}) { my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $_); $self->{serials}->{$_} = { %{$self->{serials}->{$_}}, %$result }; } $self->{cache_name} = 'avocent_acs_8000_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')); } 1; __END__ =head1 MODE Check serial ports. =over 8 =item B<--filter-name> Filter by serial device name (can be a regexp). =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %{status}, %{display} =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-*> B<--critical-*> Thresholds. Can be: 'traffic-in', 'traffic-out'. =back =cut centreon-plugins-20220113/hardware/kvm/avocent/acs/8000/snmp/plugin.pm000066400000000000000000000030231417000230700252310ustar00rootroot00000000000000# # Copyright 2019 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::kvm::avocent::acs::8000::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}} = ( 'cpu-detailed' => 'snmp_standard::mode::cpudetailed', 'hardware' => 'hardware::kvm::avocent::acs::8000::snmp::mode::hardware', 'load' => 'snmp_standard::mode::loadaverage', 'memory' => 'snmp_standard::mode::memory', 'serial-ports' => 'hardware::kvm::avocent::acs::8000::snmp::mode::serialports' ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Avocent ACS 8000 series in SNMP. =cut centreon-plugins-20220113/hardware/pdu/000077500000000000000000000000001417000230700176215ustar00rootroot00000000000000centreon-plugins-20220113/hardware/pdu/apc/000077500000000000000000000000001417000230700203645ustar00rootroot00000000000000centreon-plugins-20220113/hardware/pdu/apc/snmp/000077500000000000000000000000001417000230700213415ustar00rootroot00000000000000centreon-plugins-20220113/hardware/pdu/apc/snmp/mode/000077500000000000000000000000001417000230700222655ustar00rootroot00000000000000centreon-plugins-20220113/hardware/pdu/apc/snmp/mode/components/000077500000000000000000000000001417000230700244525ustar00rootroot00000000000000centreon-plugins-20220113/hardware/pdu/apc/snmp/mode/components/humidity.pm000066400000000000000000000123051417000230700266450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::apc::snmp::mode::components::humidity; use strict; use warnings; my %map_status = ( 1 => 'notPresent', 2 => 'belowMin', 3 => 'belowLow', 4 => 'normal', 5 => 'aboveHigh', 6 => 'aboveMax', ); my %map_type = ( 1 => 'temperatureOnly', 2 => 'temperatureHumidity', 3 => 'commsLost', 4 => 'notInstalled', ); # In MIB 'PowerNet-MIB' my $mapping = { rPDU2SensorTempHumidityStatusName => { oid => '.1.3.6.1.4.1.318.1.1.26.10.2.2.1.3' }, rPDU2SensorTempHumidityStatusNumber => { oid => '.1.3.6.1.4.1.318.1.1.26.10.2.2.1.4' }, rPDU2SensorTempHumidityStatusType => { oid => '.1.3.6.1.4.1.318.1.1.26.10.2.2.1.5', map => \%map_type }, rPDU2SensorTempHumidityStatusRelativeHumidity => { oid => '.1.3.6.1.4.1.318.1.1.26.10.2.2.1.10' }, rPDU2SensorTempHumidityStatusHumidityStatus => { oid => '.1.3.6.1.4.1.318.1.1.26.10.2.2.1.11', map => \%map_status }, }; my $oid_rPDU2SensorTempHumidityStatusEntry = '.1.3.6.1.4.1.318.1.1.26.10.2.2.1'; sub load { my ($self) = @_; foreach (@{$self->{request}}) { return if ($_->{oid} eq $oid_rPDU2SensorTempHumidityStatusEntry); } push @{$self->{request}}, { oid => $oid_rPDU2SensorTempHumidityStatusEntry }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking humidities"); $self->{components}->{humidity} = {name => 'humidities', total => 0, skip => 0}; return if ($self->check_filter(section => 'humidity')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_rPDU2SensorTempHumidityStatusEntry}})) { next if ($oid !~ /^$mapping->{rPDU2SensorTempHumidityStatusHumidityStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_rPDU2SensorTempHumidityStatusEntry}, instance => $instance); next if ($result->{rPDU2SensorTempHumidityStatusType} !~ /temperatureHumidity/i); next if ($self->check_filter(section => 'humidity', instance => $result->{rPDU2SensorTempHumidityStatusNumber})); next if ($result->{rPDU2SensorTempHumidityStatusHumidityStatus} !~ /notPresent/i && $self->absent_problem(section => 'humidity', instance => $result->{rPDU2SensorTempHumidityStatusNumber})); $self->{components}->{humidity}->{total}++; $self->{output}->output_add(long_msg => sprintf("Humidity '%s' status is '%s' [instance: %s, value: %s]", $result->{rPDU2SensorTempHumidityStatusName}, $result->{rPDU2SensorTempHumidityStatusHumidityStatus}, $result->{rPDU2SensorTempHumidityStatusNumber}, $result->{rPDU2SensorTempHumidityStatusRelativeHumidity})); my $exit = $self->get_severity(section => 'humidity', instance => $result->{rPDU2SensorTempHumidityStatusName}, value => $result->{rPDU2SensorTempHumidityStatusHumidityStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Humidity '%s' status is %s", $result->{rPDU2SensorTempHumidityStatusName}, $result->{rPDU2SensorTempHumidityStatusHumidityStatus})); } if (defined($result->{rPDU2SensorTempHumidityStatusRelativeHumidity}) && $result->{rPDU2SensorTempHumidityStatusRelativeHumidity} =~ /[0-9]/) { my $value = $result->{rPDU2SensorTempHumidityStatusRelativeHumidity}; my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'humidity', instance => $result->{rPDU2SensorTempHumidityStatusNumber}, value => $value); if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit2, short_msg => sprintf("Humidity '%s' value is %s %%", $result->{rPDU2SensorTempHumidityStatusName}, $value)); } $self->{output}->perfdata_add( label => 'hum', unit => '%', nlabel => 'hardware.sensor.humidity.percentage', instances => $result->{rPDU2SensorTempHumidityStatusName}, value => $value, warning => $warn, critical => $crit, min => 0, max => 100 ); } } } 1; centreon-plugins-20220113/hardware/pdu/apc/snmp/mode/components/psu.pm000066400000000000000000000055631417000230700256300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::apc::snmp::mode::components::psu; use strict; use warnings; my %map_status = ( 1 => 'ok', 2 => 'failed', 3 => 'notPresent', ); # In MIB 'PowerNet-MIB' my $mapping = { rPDUPowerSupply1Status => { oid => '.1.3.6.1.4.1.318.1.1.12.4.1.1', map => \%map_status }, rPDUPowerSupply2Status => { oid => '.1.3.6.1.4.1.318.1.1.12.4.1.2', map => \%map_status }, }; my $oid_rPDUPowerSupplyDevice = '.1.3.6.1.4.1.318.1.1.12.4.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_rPDUPowerSupplyDevice }; } 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')); return if (!defined($self->{results}->{$oid_rPDUPowerSupplyDevice})); my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_rPDUPowerSupplyDevice}, instance => '0'); for (my $i = 1; $i <= 2; $i++) { next if (!defined($result->{'rPDUPowerSupply' . $i . 'Status'})); next if ($result->{'rPDUPowerSupply' . $i . 'Status'} !~ /notPresent/i && $self->absent_problem(section => 'psu', instance => $i)); next if ($self->check_filter(section => 'psu', instance => $i)); $self->{components}->{psu}->{total}++; $self->{output}->output_add(long_msg => sprintf("Power supply '%s' status is '%s' [instance: %s]", $i, $result->{'rPDUPowerSupply' . $i . 'Status'}, $i)); my $exit = $self->get_severity(section => 'psu', instance => $i, value => $result->{'rPDUPowerSupply' . $i . 'Status'}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Power supply '%s' status is '%s'", $i, $result->{'rPDUPowerSupply' . $i . 'Status'})); } } } 1; centreon-plugins-20220113/hardware/pdu/apc/snmp/mode/components/temperature.pm000066400000000000000000000122231417000230700273450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::apc::snmp::mode::components::temperature; use strict; use warnings; my %map_status = ( 1 => 'notPresent', 2 => 'belowMin', 3 => 'belowLow', 4 => 'normal', 5 => 'aboveHigh', 6 => 'aboveMax', ); my %map_type = ( 1 => 'temperatureOnly', 2 => 'temperatureHumidity', 3 => 'commsLost', 4 => 'notInstalled', ); # In MIB 'PowerNet-MIB' my $mapping = { rPDU2SensorTempHumidityStatusName => { oid => '.1.3.6.1.4.1.318.1.1.26.10.2.2.1.3' }, rPDU2SensorTempHumidityStatusNumber => { oid => '.1.3.6.1.4.1.318.1.1.26.10.2.2.1.4' }, rPDU2SensorTempHumidityStatusType => { oid => '.1.3.6.1.4.1.318.1.1.26.10.2.2.1.5', map => \%map_type }, rPDU2SensorTempHumidityStatusTempC => { oid => '.1.3.6.1.4.1.318.1.1.26.10.2.2.1.8' }, rPDU2SensorTempHumidityStatusTempStatus => { oid => '.1.3.6.1.4.1.318.1.1.26.10.2.2.1.9', map => \%map_status }, }; my $oid_rPDU2SensorTempHumidityStatusEntry = '.1.3.6.1.4.1.318.1.1.26.10.2.2.1'; sub load { my ($self) = @_; foreach (@{$self->{request}}) { return if ($_->{oid} eq $oid_rPDU2SensorTempHumidityStatusEntry); } push @{$self->{request}}, { oid => $oid_rPDU2SensorTempHumidityStatusEntry }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking temperatures"); $self->{components}->{temperature} = {name => 'temperatures', total => 0, skip => 0}; return if ($self->check_filter(section => 'temperature')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_rPDU2SensorTempHumidityStatusEntry}})) { next if ($oid !~ /^$mapping->{rPDU2SensorTempHumidityStatusTempStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_rPDU2SensorTempHumidityStatusEntry}, instance => $instance); next if ($result->{rPDU2SensorTempHumidityStatusType} !~ /temperatureOnly|temperatureHumidity/i); next if ($self->check_filter(section => 'temperature', instance => $result->{rPDU2SensorTempHumidityStatusNumber})); next if ($result->{rPDU2SensorTempHumidityStatusTempStatus} !~ /notPresent/i && $self->absent_problem(section => 'temperature', instance => $result->{rPDU2SensorTempHumidityStatusNumber})); $self->{components}->{temperature}->{total}++; $self->{output}->output_add(long_msg => sprintf("Temperature '%s' status is '%s' [instance: %s, value: %s]", $result->{rPDU2SensorTempHumidityStatusName}, $result->{rPDU2SensorTempHumidityStatusTempStatus}, $result->{rPDU2SensorTempHumidityStatusNumber}, $result->{rPDU2SensorTempHumidityStatusTempC} / 10)); my $exit = $self->get_severity(section => 'temperature', instance => $result->{rPDU2SensorTempHumidityStatusNumber}, value => $result->{rPDU2SensorTempHumidityStatusTempStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Temperature '%s' status is %s", $result->{rPDU2SensorTempHumidityStatusName}, $result->{rPDU2SensorTempHumidityStatusTempStatus})); } if (defined($result->{rPDU2SensorTempHumidityStatusTempC}) && $result->{rPDU2SensorTempHumidityStatusTempC} =~ /[0-9]/) { my $value = $result->{rPDU2SensorTempHumidityStatusTempC} / 10; my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $result->{rPDU2SensorTempHumidityStatusNumber}, value => $value); if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit2, short_msg => sprintf("Temperature '%s' value is %s C", $result->{rPDU2SensorTempHumidityStatusName}, $value)); } $self->{output}->perfdata_add( label => 'temp', unit => 'C', nlabel => 'hardware.sensor.temperature.celsius', instances => $result->{rPDU2SensorTempHumidityStatusName}, value => $value, warning => $warn, critical => $crit ); } } } 1; centreon-plugins-20220113/hardware/pdu/apc/snmp/mode/hardware.pm000066400000000000000000000066131417000230700244260ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::apc::snmp::mode::hardware; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^humidity|temperature$'; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { humidity => [ ['notPresent', 'OK'], ['belowMin', 'CRITICAL'], ['belowLow', 'WARNING'], ['normal', 'OK'], ['aboveHigh', 'WARNING'], ['aboveMax', 'CRITICAL'] ], temperature => [ ['notPresent', 'OK'], ['belowMin', 'CRITICAL'], ['belowLow', 'WARNING'], ['normal', 'OK'], ['aboveHigh', 'WARNING'], ['aboveMax', 'CRITICAL'] ], psu => [ ['ok', 'OK'], ['failed', 'CRITICAL'], ['notPresent', 'OK'] ] }; $self->{components_path} = 'hardware::pdu::apc::snmp::mode::components'; $self->{components_module} = ['psu', 'humidity', 'temperature']; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } 1; __END__ =head1 MODE Check components (humidity, temperature, power supplies). =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'psu', 'humidity', 'temperature'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=temperature --filter=humidity) Can also exclude specific instance: --filter=temperature,1 =item B<--absent-problem> Return an error if an entity is not 'present' (default is skipping) (comma seperated list) Can be specific or global: --absent-problem=psu =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='temperature,CRITICAL,^(?!(normal)$)' =item B<--warning> Set warning threshold for temperatures (syntax: type,instance,threshold) Example: --warning='temperature,.*,30' =item B<--critical> Set critical threshold for temperatures (syntax: type,instance,threshold) Example: --critical='temperature,.*,40' =back =cut centreon-plugins-20220113/hardware/pdu/apc/snmp/mode/load.pm000066400000000000000000000306411417000230700235460ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::apc::snmp::mode::load; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return 'status: ' . $self->{result_values}->{status}; } sub prefix_bank_output { my ($self, %options) = @_; return "Bank '" . $options{instance_value}->{display} . "' "; } sub prefix_phase_output { my ($self, %options) = @_; return "Phase '" . $options{instance_value}->{display} . "' "; } sub prefix_device_output { my ($self, %options) = @_; return "Device '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'device', type => 1, cb_prefix_output => 'prefix_device_output', message_multiple => 'All devices are ok', skipped_code => { -10 => 1 } }, { name => 'bank', type => 1, cb_prefix_output => 'prefix_bank_output', message_multiple => 'All banks are ok', skipped_code => { -10 => 1 } }, { name => 'phase', type => 1, cb_prefix_output => 'prefix_phase_output', message_multiple => 'All phases are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{bank} = [ { label => 'bank-status', type => 2, warning_default => '%{status} =~ /low|nearOverload/i', critical_default => '%{status} =~ /^overload/i', set => { key_values => [ { name => 'status' }, { name => 'display' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'current', nlabel => 'bank.current.ampere', set => { key_values => [ { name => 'current' }, { name => 'display' } ], output_template => 'current: %s A', perfdatas => [ { template => '%s', unit => 'A', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } } ]; $self->{maps_counters}->{phase} = [ { label => 'phase-status', type => 2, warning_default => '%{status} =~ /low|nearOverload/i', critical_default => '%{status} =~ /^overload/i', set => { key_values => [ { name => 'status' }, { name => 'display' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'current', nlabel => 'phase.current.ampere', set => { key_values => [ { name => 'current' }, { name => 'display' } ], output_template => 'current: %s A', perfdatas => [ { template => '%s', unit => 'A', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'power', nlabel => 'phase.power.watt', set => { key_values => [ { name => 'power' }, { name => 'display' } ], output_template => 'power: %s W', perfdatas => [ { template => '%s', unit => 'W', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } } ]; $self->{maps_counters}->{device} = [ { label => 'power', nlabel => 'device.power.watt', set => { key_values => [ { name => 'power' }, { name => 'display' } ], output_template => 'power: %s W', perfdatas => [ { template => '%s', unit => 'W', min => 0, label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } my $map_rpdu_status = { 1 => 'normal', 2 => 'low', 3 => 'nearOverload', 4 => 'overload', }; sub check_rpdu { my ($self, %options) = @_; return if (scalar(keys %{$self->{phase}}) > 0); my $mapping = { rPDULoadStatusLoad => { oid => '.1.3.6.1.4.1.318.1.1.12.2.3.1.1.2' }, rPDULoadStatusLoadState => { oid => '.1.3.6.1.4.1.318.1.1.12.2.3.1.1.3', map => $map_rpdu_status }, rPDULoadStatusPhaseNumber => { oid => '.1.3.6.1.4.1.318.1.1.12.2.3.1.1.4' }, rPDULoadStatusBankNumber => { oid => '.1.3.6.1.4.1.318.1.1.12.2.3.1.1.5' } # Bank 0 = no bank (phase total) }; my $oid_rPDULoadStatusEntry = '.1.3.6.1.4.1.318.1.1.12.2.3.1.1'; my $snmp_result = $options{snmp}->get_table(oid => $oid_rPDULoadStatusEntry, nothing_quit => 1); foreach my $oid (keys %{$snmp_result}) { next if ($oid !~ /^$mapping->{rPDULoadStatusLoadState}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); if ($result->{rPDULoadStatusBankNumber} == 0) { $self->{phase}->{$result->{rPDULoadStatusPhaseNumber}} = { display => $result->{rPDULoadStatusPhaseNumber}, status => $result->{rPDULoadStatusLoadState}, current => $result->{rPDULoadStatusLoad} / 10 }; } else { $self->{bank}->{$result->{rPDULoadStatusBankNumber}} = { display => $result->{rPDULoadStatusBankNumber}, current => 0 } if (!defined($self->{bank}->{$result->{rPDULoadStatusBankNumber}})); $self->{bank}->{$result->{rPDULoadStatusBankNumber}}->{status} = $result->{rPDULoadStatusLoadState}; $self->{bank}->{$result->{rPDULoadStatusBankNumber}}->{current} += $result->{rPDULoadStatusLoad} / 10; } } my $oid_rPDUIdentName = '.1.3.6.1.4.1.318.1.1.12.1.1.0'; my $oid_rPDUIdentDevicePowerWatts = '.1.3.6.1.4.1.318.1.1.12.1.16.0'; $snmp_result = $options{snmp}->get_leef(oids => [$oid_rPDUIdentName, $oid_rPDUIdentDevicePowerWatts]); $self->{device}->{0} = { display => $snmp_result->{$oid_rPDUIdentName}, power => $snmp_result->{$oid_rPDUIdentDevicePowerWatts} }; } my $map_rpdu2_status = { 1 => 'low', 2 => 'normal', 3 => 'nearOverload', 4 => 'overload', }; sub check_rpdu2 { my ($self, %options) = @_; my $mapping_phase = { rPDU2PhaseStatusModule => { oid => '.1.3.6.1.4.1.318.1.1.26.6.3.1.2' }, rPDU2PhaseStatusNumber => { oid => '.1.3.6.1.4.1.318.1.1.26.6.3.1.3' }, rPDU2PhaseStatusLoadState => { oid => '.1.3.6.1.4.1.318.1.1.26.6.3.1.4', map => $map_rpdu2_status }, rPDU2PhaseStatusCurrent => { oid => '.1.3.6.1.4.1.318.1.1.26.6.3.1.5' }, rPDU2PhaseStatusPower => { oid => '.1.3.6.1.4.1.318.1.1.26.6.3.1.7' } }; my $mapping_bank = { rPDU2BankStatusModule => { oid => '.1.3.6.1.4.1.318.1.1.26.8.3.1.2' }, rPDU2BankStatusNumber => { oid => '.1.3.6.1.4.1.318.1.1.26.8.3.1.3' }, rPDU2BankStatusLoadState => { oid => '.1.3.6.1.4.1.318.1.1.26.8.3.1.4', map => $map_rpdu2_status }, rPDU2BankStatusCurrent => { oid => '.1.3.6.1.4.1.318.1.1.26.8.3.1.5' } }; my $mapping_device = { rPDU2DeviceStatusName => { oid => '.1.3.6.1.4.1.318.1.1.26.4.3.1.3' }, rPDU2DeviceStatusPower => { oid => '.1.3.6.1.4.1.318.1.1.26.4.3.1.5' } }; my $oid_rPDU2DeviceStatusEntry = '.1.3.6.1.4.1.318.1.1.26.4.3.1'; my $oid_rPDU2PhaseStatusEntry = '.1.3.6.1.4.1.318.1.1.26.6.3.1'; my $oid_rPDU2BankStatusEntry = '.1.3.6.1.4.1.318.1.1.26.8.3.1'; my $snmp_result = $options{snmp}->get_multiple_table(oids => [ { oid => $oid_rPDU2PhaseStatusEntry, end => $mapping_phase->{rPDU2PhaseStatusPower}->{oid} }, { oid => $oid_rPDU2BankStatusEntry, end => $mapping_bank->{rPDU2BankStatusCurrent}->{oid} }, { oid => $oid_rPDU2DeviceStatusEntry, end => $mapping_device->{rPDU2DeviceStatusPower}->{oid} } ]); foreach my $oid (keys %{$snmp_result->{$oid_rPDU2PhaseStatusEntry}}) { next if ($oid !~ /^$mapping_phase->{rPDU2PhaseStatusLoadState}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping_phase, results => $snmp_result->{$oid_rPDU2PhaseStatusEntry}, instance => $instance); my $name = 'mod' . $result->{rPDU2PhaseStatusModule} . 'phase' . $result->{rPDU2PhaseStatusNumber}; $self->{phase}->{$name} = { display => $name, status => $result->{rPDU2PhaseStatusLoadState}, current => $result->{rPDU2PhaseStatusCurrent} / 10, power => defined($result->{rPDU2PhaseStatusPower}) ? $result->{rPDU2PhaseStatusPower} * 10 : undef # hundreth of kW. So * 10 for watt } } foreach my $oid (keys %{$snmp_result->{$oid_rPDU2BankStatusEntry}}) { next if ($oid !~ /^$mapping_bank->{rPDU2BankStatusLoadState}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping_bank, results => $snmp_result->{$oid_rPDU2BankStatusEntry}, instance => $instance); my $name = 'mod' . $result->{rPDU2BankStatusModule} . 'bank' . $result->{rPDU2BankStatusNumber}; $self->{bank}->{$name} = { display => $name, status => $result->{rPDU2BankStatusLoadState}, current => $result->{rPDU2BankStatusCurrent} / 10 } } foreach my $oid (keys %{$snmp_result->{$oid_rPDU2DeviceStatusEntry}}) { next if ($oid !~ /^$mapping_device->{rPDU2DeviceStatusName}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping_device, results => $snmp_result->{$oid_rPDU2DeviceStatusEntry}, instance => $instance); $self->{device}->{$result->{rPDU2DeviceStatusName}} = { display => $result->{rPDU2DeviceStatusName}, power => defined($result->{rPDU2DeviceStatusPower}) ? $result->{rPDU2DeviceStatusPower} * 10 : undef } } } sub manage_selection { my ($self, %options) = @_; $self->{bank} = {}; $self->{phase} = {}; $self->{device} = {}; $self->check_rpdu2(%options); $self->check_rpdu(%options); if (scalar(keys %{$self->{device}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No device found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check phase/bank load. =over 8 =item B<--unknown-bank-status> Set warning threshold for status. Can used special variables like: %{type}, %{status}, %{display} =item B<--warning-bank-status> Set warning threshold for status (Default: '%{status} =~ /low|nearOverload/i'). Can used special variables like: %{type}, %{status}, %{display} =item B<--critical-bank-status> Set critical threshold for status (Default: '%{status} =~ /^overload/'). Can used special variables like: %{type}, %{status}, %{display} =item B<--unknown-phase-status> Set warning threshold for status. Can used special variables like: %{status}, %{display} =item B<--warning-phase-status> Set warning threshold for status (Default: '%{status} =~ /low|nearOverload/i'). Can used special variables like: %{status}, %{display} =item B<--critical-phase-status> Set critical threshold for status (Default: '%{status} =~ /^overload/i'). Can used special variables like: %{status}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'current', 'power'. =back =cut centreon-plugins-20220113/hardware/pdu/apc/snmp/mode/ntp.pm000066400000000000000000000040311417000230700234220ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::apc::snmp::mode::ntp; use base qw(snmp_standard::mode::ntp); use strict; use warnings; use Date::Parse; sub get_target_time { my ($self, %options) = @_; my $oid_mconfigClockDate = '.1.3.6.1.4.1.318.2.1.6.1.0'; my $oid_mconfigClockTime = '.1.3.6.1.4.1.318.2.1.6.2.0'; my $snmp_result = $options{snmp}->get_leef(oids => [ $oid_mconfigClockDate, $oid_mconfigClockTime ], nothing_quit => 1); my $epoch = Date::Parse::str2time($snmp_result->{$oid_mconfigClockDate} . ' ' . $snmp_result->{$oid_mconfigClockTime}); return $self->get_from_epoch(date => $epoch); } 1; __END__ =head1 MODE Check time offset of server with ntp server. Use local time if ntp-host option is not set. SNMP gives a date with second precision (no milliseconds). Time precision is not very accurate. Use threshold with (+-) 2 seconds offset (minimum). =over 8 =item B<--warning-offset> Time offset warning threshold (in seconds). =item B<--critical-offset> Time offset critical Threshold (in seconds). =item B<--ntp-hostname> Set the ntp hostname (if not set, localtime is used). =item B<--ntp-port> Set the ntp port (Default: 123). =item B<--timezone> Set the timezone of distant server. For Windows, you need to set it. Can use format: 'Europe/London' or '+0100'. =back =cut centreon-plugins-20220113/hardware/pdu/apc/snmp/mode/outlet.pm000066400000000000000000000224701417000230700241440ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::apc::snmp::mode::outlet; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf( "status : '%s' %s%s", $self->{result_values}->{status}, $self->{result_values}->{bank} ne '' ? '[bank: ' . $self->{result_values}->{bank} . '] ' : '', '[phase: ' . $self->{result_values}->{phase} . ']', ); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; $self->{result_values}->{bank} = $options{new_datas}->{$self->{instance} . '_bank'}; $self->{result_values}->{phase} = $options{new_datas}->{$self->{instance} . '_phase'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'outlet', type => 1, cb_prefix_output => 'prefix_outlet_output', message_multiple => 'All outlets are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{outlet} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'bank' }, { name => 'phase' }, { 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 => \&catalog_status_threshold, } }, { label => 'current', nlabel => 'outlet.current.ampere', set => { key_values => [ { name => 'current', no_value => 0 }, { name => 'display' } ], output_template => 'current : %s A', perfdatas => [ { label => 'current', template => '%s', value => 'current', unit => 'A', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub prefix_outlet_output { my ($self, %options) = @_; return "Outlet '" . $options{instance_value}->{display} . "' "; } 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 => { 'unknown-status:s' => { name => 'unknown_status', default => '' }, 'warning-status:s' => { name => 'warning_status', default => '' }, 'critical-status:s' => { name => 'critical_status', default => '%{status} =~ /off/i' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => [ 'warning_status', 'critical_status', 'unknown_status', ]); } my %map_rpdu_status = ( 1 => 'on', 2 => 'off', ); my %map_rpdu_phase = ( 1 => 'phase1', 2 => 'phase2', 3 => 'phase3', 4 => 'phase1-2', 5 => 'phase2-3', 6 => 'phase3-1', ); sub check_rpdu { my ($self, %options) = @_; return if (scalar(keys %{$self->{outlet}}) > 0); my $mapping = { rPDUOutletStatusOutletName => { oid => '.1.3.6.1.4.1.318.1.1.12.3.5.1.1.2' }, rPDUOutletStatusOutletPhase => { oid => '.1.3.6.1.4.1.318.1.1.12.3.5.1.1.3', map => \%map_rpdu_phase }, rPDUOutletStatusOutletState => { oid => '.1.3.6.1.4.1.318.1.1.12.3.5.1.1.4', map => \%map_rpdu_status }, rPDUOutletStatusOutletBank => { oid => '.1.3.6.1.4.1.318.1.1.12.3.5.1.1.6' }, rPDUOutletStatusLoad => { oid => '.1.3.6.1.4.1.318.1.1.12.3.5.1.1.7' }, }; my $oid_rPDUOutletStatusEntry = '.1.3.6.1.4.1.318.1.1.12.3.5.1.1'; my $snmp_result = $options{snmp}->get_table(oid => $oid_rPDUOutletStatusEntry, nothing_quit => 1); my $duplicated = {}; foreach my $oid (keys %{$snmp_result}) { next if ($oid !~ /^$mapping->{rPDUOutletStatusOutletState}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); my $name = $result->{rPDUOutletStatusOutletName}; $name = $instance if (defined($duplicated->{$name})); if (defined($self->{outlet}->{$name})) { $duplicated->{$name} = 1; my $instance2 = $self->{outlet}->{$name}->{instance}; $self->{outlet}->{$instance2} = $self->{outlet}->{$name}; $self->{outlet}->{$instance2}->{display} = $instance2; delete $self->{outlet}->{$name}; $name = $instance; } $self->{outlet}->{$name} = { instance => $instance, display => $name, status => $result->{rPDUOutletStatusOutletState}, bank => $result->{rPDUOutletStatusOutletBank}, phase => $result->{rPDUOutletStatusOutletPhase}, current => $result->{rPDUOutletStatusLoad} / 10, }; } } sub check_rpdu2 { my ($self, %options) = @_; my $map_rpdu2_status = { 1 => 'off', 2 => 'on', }; my $map_rpdu2_phase = { 1 => 'seqPhase1ToNeutral', 2 => 'seqPhase2ToNeutral', 3 => 'seqPhase3ToNeutral', 4 => 'seqPhase1ToPhase2', 5 => 'seqPhase2ToPhase3', 6 => 'seqPhase3ToPhase1', }; my $mapping = { rPDU2OutletSwitchedPropertiesPhaseLayout => { oid => '.1.3.6.1.4.1.318.1.1.26.9.2.2.1.5', map => $map_rpdu2_phase }, rPDU2OutletSwitchedPropertiesBank => { oid => '.1.3.6.1.4.1.318.1.1.26.9.2.2.1.6' }, rPDU2OutletSwitchedStatusName => { oid => '.1.3.6.1.4.1.318.1.1.26.9.2.3.1.3' }, rPDU2OutletSwitchedStatusState => { oid => '.1.3.6.1.4.1.318.1.1.26.9.2.3.1.5', map => $map_rpdu2_status }, }; my $oid_rPDU2OutletSwitchedPropertiesEntry = '.1.3.6.1.4.1.318.1.1.26.9.2.2.1'; my $oid_rPDU2OutletSwitchedStatusEntry = '.1.3.6.1.4.1.318.1.1.26.9.2.3.1'; my $snmp_result = $options{snmp}->get_multiple_table( oids => [ { oid => $oid_rPDU2OutletSwitchedPropertiesEntry, start => $mapping->{rPDU2OutletSwitchedPropertiesPhaseLayout}->{oid}, end => $mapping->{rPDU2OutletSwitchedPropertiesBank}->{oid} }, { oid => $oid_rPDU2OutletSwitchedStatusEntry, start => $mapping->{rPDU2OutletSwitchedStatusName}->{oid}, end => $mapping->{rPDU2OutletSwitchedStatusState}->{oid} }, ], return_type => 1, ); my $duplicated = {}; foreach my $oid (keys %{$snmp_result}) { next if ($oid !~ /^$mapping->{rPDU2OutletSwitchedStatusState}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); my $name = $result->{rPDU2OutletSwitchedStatusName} . ' bank ' . $result->{rPDU2OutletSwitchedPropertiesBank}; $name = $instance if (defined($duplicated->{$name})); if (defined($self->{outlet}->{$name})) { $duplicated->{$name} = 1; my $instance2 = $self->{outlet}->{$name}->{instance}; $self->{outlet}->{$instance2} = $self->{outlet}->{$name}; $self->{outlet}->{$instance2}->{display} = $instance2; delete $self->{outlet}->{$name}; $name = $instance; } $self->{outlet}->{$name} = { instance => $instance, display => $name, status => $result->{rPDU2OutletSwitchedStatusState}, bank => '', phase => $result->{rPDU2OutletSwitchedPropertiesPhaseLayout}, }; } } sub manage_selection { my ($self, %options) = @_; $self->{outlet} = {}; $self->check_rpdu2(%options); $self->check_rpdu(%options); if (scalar(keys %{$self->{outlet}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No outlet found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check outlet. =over 8 =item B<--unknown-status> Set warning threshold for status. Can used special variables like: %{status}, %{display} =item B<--warning-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{phase}, %{bank}, %{display} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /off/'). Can used special variables like: %{status}, %{phase}, %{bank}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'current'. =back =cut centreon-plugins-20220113/hardware/pdu/apc/snmp/plugin.pm000066400000000000000000000027171417000230700232040ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::apc::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} = { 'load' => 'hardware::pdu::apc::snmp::mode::load', 'hardware' => 'hardware::pdu::apc::snmp::mode::hardware', 'outlet' => 'hardware::pdu::apc::snmp::mode::outlet', 'time' => 'hardware::pdu::apc::snmp::mode::ntp', 'uptime' => 'snmp_standard::mode::uptime' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check APC PDU in SNMP (PowerNet-MIB). =cut centreon-plugins-20220113/hardware/pdu/clever/000077500000000000000000000000001417000230700211015ustar00rootroot00000000000000centreon-plugins-20220113/hardware/pdu/clever/snmp/000077500000000000000000000000001417000230700220565ustar00rootroot00000000000000centreon-plugins-20220113/hardware/pdu/clever/snmp/mode/000077500000000000000000000000001417000230700230025ustar00rootroot00000000000000centreon-plugins-20220113/hardware/pdu/clever/snmp/mode/psusage.pm000066400000000000000000000061451417000230700250150ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::clever::snmp::mode::psusage; 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 }, ]; $self->{maps_counters}->{global} = [ { label => 'power', set => { key_values => [ { name => 'power' } ], output_template => 'Input power : %s W', perfdatas => [ { label => 'power', value => 'power', template => '%s', unit => 'W', min => 0 }, ], } }, { label => 'current', set => { key_values => [ { name => 'current' } ], output_template => 'Current : %s A', perfdatas => [ { label => 'current', value => 'current', template => '%s', unit => 'A', min => 0 }, ], } }, { label => 'voltage', set => { key_values => [ { name => 'voltage' } ], output_template => 'Voltage : %s V', perfdatas => [ { label => 'voltage', value => 'voltage', template => '%s', unit => 'V', min => 0 }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my $oid_current = '.1.3.6.1.4.1.30966.1.2.1.6.0'; my $oid_voltage = '.1.3.6.1.4.1.30966.1.2.1.9.0'; sub manage_selection { my ($self, %options) = @_; my $result = $options{snmp}->get_leef(oids => [ $oid_current, $oid_voltage ], nothing_quit => 1); $self->{global} = { current => $result->{$oid_current}, voltage => $result->{$oid_voltage}, power => $result->{$oid_current} * $result->{$oid_voltage} }; } 1; __END__ =head1 MODE Check power source usage. =over 8 =item B<--warning-*> Threshold warning. Can be: 'current', 'power', 'voltage'. =item B<--critical-*> Threshold critical. Can be: 'current', 'power', 'voltage'. =back =cut centreon-plugins-20220113/hardware/pdu/clever/snmp/plugin.pm000066400000000000000000000023421417000230700237130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::clever::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}} = ( 'ps-usage' => 'hardware::pdu::clever::snmp::mode::psusage', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check China Clever PDU in SNMP. =cut centreon-plugins-20220113/hardware/pdu/cyberpower/000077500000000000000000000000001417000230700220025ustar00rootroot00000000000000centreon-plugins-20220113/hardware/pdu/cyberpower/snmp/000077500000000000000000000000001417000230700227575ustar00rootroot00000000000000centreon-plugins-20220113/hardware/pdu/cyberpower/snmp/mode/000077500000000000000000000000001417000230700237035ustar00rootroot00000000000000centreon-plugins-20220113/hardware/pdu/cyberpower/snmp/mode/load.pm000066400000000000000000000270301417000230700251620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::cyberpower::snmp::mode::load; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return 'state: ' . $self->{result_values}->{state}; } sub device_long_output { my ($self, %options) = @_; return "checking device '" . $options{instance_value}->{display} . "'"; } sub prefix_device_output { my ($self, %options) = @_; return "Device '" . $options{instance_value}->{display} . "' "; } sub prefix_bank_output { my ($self, %options) = @_; return "bank '" . $options{instance_value}->{display} . "' "; } sub prefix_phase_output { my ($self, %options) = @_; return "phase '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'devices', type => 3, cb_prefix_output => 'prefix_device_output', cb_long_output => 'device_long_output', indent_long_output => ' ', message_multiple => 'All devices are ok', group => [ { name => 'banks', display_long => 1, cb_prefix_output => 'prefix_bank_output', message_multiple => 'banks are ok', type => 1, skipped_code => { -10 => 1 } }, { name => 'phases', display_long => 1, cb_prefix_output => 'prefix_phase_output', message_multiple => 'phases are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{banks} = [ { label => 'bank-status', type => 2, warning_default => '%{state} =~ /low|nearOverload/i', critical_default => '%{state} =~ /^overload/i', set => { key_values => [ { name => 'state' }, { name => 'display' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'bank-current', nlabel => 'bank.current.ampere', set => { key_values => [ { name => 'current' } ], output_template => 'current : %s A', perfdatas => [ { template => '%s', unit => 'A', min => 0, label_extra_instance => 1 } ] } } ]; $self->{maps_counters}->{phases} = [ { label => 'phase-status', type => 2, warning_default => '%{state} =~ /low|nearOverload/i', critical_default => '%{state} =~ /^overload/i', set => { key_values => [ { name => 'state' }, { name => 'display' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'phase-current', nlabel => 'phase.current.ampere', set => { key_values => [ { name => 'current' } ], output_template => 'current : %s A', perfdatas => [ { template => '%s', unit => 'A', min => 0, label_extra_instance => 1 } ] } }, { label => 'phase-power', nlabel => 'phase.power.watt', set => { key_values => [ { name => 'power' } ], output_template => 'power : %s W', perfdatas => [ { template => '%s', unit => 'W', min => 0, label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my $oid_ePDUIdentName = '.1.3.6.1.4.1.3808.1.1.3.1.1'; my $oid_ePDU2DeviceConfigName = '.1.3.6.1.4.1.3808.1.1.6.3.2.1.3'; my $map_pdu_status = { 1 => 'normal', 2 => 'low', 3 => 'nearOverload', 4 => 'overload' }; sub check_pdu { my ($self, %options) = @_; return if (scalar(keys %{$self->{devices}}) > 0); $self->{devices}->{ $options{device} } = { display => $options{device}, banks => {}, phases => {} }; my $mapping = { current => { oid => '.1.3.6.1.4.1.3808.1.1.3.2.3.1.1.2' }, # ePDULoadStatusLoad state => { oid => '.1.3.6.1.4.1.3808.1.1.3.2.3.1.1.3', map => $map_pdu_status }, # ePDULoadStatusLoadState phase => { oid => '.1.3.6.1.4.1.3808.1.1.3.2.3.1.1.4' }, # ePDULoadStatusPhaseNumber bank => { oid => '.1.3.6.1.4.1.3808.1.1.3.2.3.1.1.5' }, # ePDULoadStatusBankNumber [Bank 0 = no bank (phase total)] }; my $oid_ePDULoadStatusEntry = '.1.3.6.1.4.1.3808.1.1.3.2.3.1.1'; my $snmp_result = $options{snmp}->get_table( oid => $oid_ePDULoadStatusEntry, start => $mapping->{current}->{oid}, end => $mapping->{bank}->{oid}, nothing_quit => 1 ); foreach my $oid (keys %$snmp_result) { next if ($oid !~ /^$mapping->{state}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); $result->{current} /= 10; if ($result->{bank} == 0) { $self->{devices}->{ $options{device} }->{phases}->{ $result->{phase} } = { display => $result->{phase}, %$result }; } else { $self->{devices}->{ $options{device} }->{banks}->{ $result->{bank} } = { display => $result->{bank}, current => 0 } if (!defined($self->{devices}->{ $options{device} }->{banks}->{ $result->{bank} })); $self->{devices}->{ $options{device} }->{banks}->{ $result->{bank} }->{state} = $result->{state}; $self->{devices}->{ $options{device} }->{banks}->{ $result->{bank} }->{current} += ($result->{current} / 10); } } } sub check_pdu2 { my ($self, %options) = @_; my $mapping_phase = { module => { oid => '.1.3.6.1.4.1.3808.1.1.6.4.4.1.2' }, # ePDU2PhaseStatusModuleIndex number => { oid => '.1.3.6.1.4.1.3808.1.1.6.4.4.1.3' }, # ePDU2PhaseStatusNumber state => { oid => '.1.3.6.1.4.1.3808.1.1.6.4.4.1.4', map => $map_pdu_status }, # ePDU2PhaseStatusLoadState current => { oid => '.1.3.6.1.4.1.3808.1.1.6.4.4.1.5' }, # ePDU2PhaseStatusLoad power => { oid => '.1.3.6.1.4.1.3808.1.1.6.4.4.1.7' } # ePDU2PhaseStatusPower }; my $mapping_bank = { module => { oid => '.1.3.6.1.4.1.3808.1.1.6.5.4.1.2' }, # ePDU2BankStatusModuleIndex number => { oid => '.1.3.6.1.4.1.3808.1.1.6.5.4.1.3' }, # ePDU2BankStatusNumber state => { oid => '.1.3.6.1.4.1.3808.1.1.6.5.4.1.4', map => $map_pdu_status }, # ePDU2BankStatusLoadState current => { oid => '.1.3.6.1.4.1.3808.1.1.6.5.4.1.5' } # ePDU2BankStatusLoad }; my $oid_ePDU2PhaseStatusEntry = '.1.3.6.1.4.1.3808.1.1.6.4.4.1'; my $oid_ePDU2BankStatusEntry = '.1.3.6.1.4.1.3808.1.1.6.5.4.1'; my $snmp_result = $options{snmp}->get_multiple_table(oids => [ { oid => $oid_ePDU2PhaseStatusEntry, end => $mapping_phase->{power}->{oid} }, { oid => $oid_ePDU2BankStatusEntry, end => $mapping_bank->{current}->{oid} } ]); foreach (keys %{$snmp_result->{$oid_ePDU2PhaseStatusEntry}}) { next if (! /^$mapping_phase->{state}->{oid}\.(.*)$/); my $result = $options{snmp}->map_instance(mapping => $mapping_phase, results => $snmp_result->{$oid_ePDU2PhaseStatusEntry}, instance => $1); my $device_name = $options{devices}->{ $oid_ePDU2DeviceConfigName . '.' . $result->{module} }; if (!defined($self->{devices}->{$device_name})) { $self->{devices}->{$device_name} = { display => $device_name, banks => {}, phases => {} }; } $self->{devices}->{$device_name}->{phases}->{ $result->{number} } = { display => $result->{number}, state => $result->{state}, current => $result->{current} / 10, power => $result->{power} * 10 # hundreth of kW. So * 10 for watt } } foreach (keys %{$snmp_result->{$oid_ePDU2BankStatusEntry}}) { next if (! /^$mapping_bank->{state}->{oid}\.(.*)$/); my $result = $options{snmp}->map_instance(mapping => $mapping_bank, results => $snmp_result->{$oid_ePDU2BankStatusEntry}, instance => $1); my $device_name = $options{devices}->{ $oid_ePDU2DeviceConfigName . '.' . $result->{module} }; if (!defined($self->{devices}->{$device_name})) { $self->{devices}->{$device_name} = { display => $device_name, banks => {}, phases => {} }; } $self->{devices}->{$device_name}->{banks}->{ $result->{number} } = { display => $result->{number}, status => $result->{state}, current => $result->{current} / 10 } } } sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_multiple_table( oids => [ { oid => $oid_ePDUIdentName }, { oid => $oid_ePDU2DeviceConfigName } ], nothing_quit => 1 ); $self->{devices} = {}; $self->check_pdu2(snmp => $options{snmp}, devices => $snmp_result->{$oid_ePDU2DeviceConfigName}); $self->check_pdu( snmp => $options{snmp}, device => defined($snmp_result->{$oid_ePDUIdentName}->{$oid_ePDUIdentName . '.0'}) ? $snmp_result->{$oid_ePDUIdentName}->{$oid_ePDUIdentName . '.0'} : 'unknown' ); } 1; __END__ =head1 MODE Check phase/bank load. =over 8 =item B<--unknown-bank-status> Set unknown threshold for status. Can used special variables like: %{state}, %{display} =item B<--warning-bank-status> Set warning threshold for status (Default: '%{state} =~ /low|nearOverload/i'). Can used special variables like: %{state}, %{display} =item B<--critical-bank-status> Set critical threshold for status (Default: '%{state} =~ /^overload/'). Can used special variables like: %{state}, %{display} =item B<--unknown-phase-status> Set unknown threshold for status. Can used special variables like: %{state}, %{display} =item B<--warning-phase-status> Set warning threshold for status (Default: '%{state} =~ /low|nearOverload/i'). Can used special variables like: %{state}, %{display} =item B<--critical-phase-status> Set critical threshold for status (Default: '%{state} =~ /^overload/i'). Can used special variables like: %{state}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'phase-current', 'phase-power', 'bank-current'. =back =cut centreon-plugins-20220113/hardware/pdu/cyberpower/snmp/mode/outlets.pm000066400000000000000000000265141417000230700257500ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::cyberpower::snmp::mode::outlets; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf( "state: '%s' %s", $self->{result_values}->{state}, '[phase: ' . $self->{result_values}->{phase} . ']', ); } sub device_long_output { my ($self, %options) = @_; return "checking device '" . $options{instance_value}->{display} . "'"; } sub prefix_device_output { my ($self, %options) = @_; return "Device '" . $options{instance_value}->{display} . "' "; } sub prefix_outlet_output { my ($self, %options) = @_; return "outlet '" . $options{instance_value}->{display} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'devices', type => 3, cb_prefix_output => 'prefix_device_output', cb_long_output => 'device_long_output', indent_long_output => ' ', message_multiple => 'All devices are ok', group => [ { name => 'outlets', display_long => 1, cb_prefix_output => 'prefix_outlet_output', message_multiple => 'outlets are ok', type => 1, skipped_code => { -10 => 1 } } ] } ]; $self->{maps_counters}->{outlets} = [ { label => 'status', type => 2, critical_default => '%{state} =~ /off/i', set => { key_values => [ { name => 'state' }, { name => 'bank' }, { name => 'phase' }, { name => 'display' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'current', nlabel => 'outlet.current.ampere', set => { key_values => [ { name => 'current', no_value => 0 }, { name => 'display' } ], output_template => 'current : %s A', perfdatas => [ { template => '%s', unit => 'A', min => 0, label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my $map_pdu_status = { 1 => 'on', 2 => 'off' }; my $map_pdu_phase = { 1 => 'phase1', 2 => 'phase2', 3 => 'phase3', 4 => 'phase1-2', 5 => 'phase2-3', 6 => 'phase3-1' }; sub check_pdu { my ($self, %options) = @_; return if (scalar(keys %{$self->{devices}}) > 0); $self->{devices}->{ $options{device} } = { display => $options{device}, outlets => {} }; my $mapping = { name => { oid => '.1.3.6.1.4.1.3808.1.1.3.3.5.1.1.2' }, # ePDUOutletStatusOutletName phase => { oid => '.1.3.6.1.4.1.3808.1.1.3.3.5.1.1.3', map => $map_pdu_phase }, # ePDUOutletStatusOutletPhase state => { oid => '.1.3.6.1.4.1.3808.1.1.3.3.5.1.1.4', map => $map_pdu_status }, # ePDUOutletStatusOutletState bank => { oid => '.1.3.6.1.4.1.3808.1.1.3.3.5.1.1.6' }, # ePDUOutletStatusOutletBank current => { oid => '.1.3.6.1.4.1.3808.1.1.3.3.5.1.1.7' } # ePDUOutletStatusLoad }; my $oid_ePDUOutletStatusEntry = '.1.3.6.1.4.1.3808.1.1.3.3.5.1.1'; my $snmp_result = $options{snmp}->get_table( oid => $oid_ePDUOutletStatusEntry, start => $mapping->{name}->{oid}, end => $mapping->{current}->{oid} ); my $duplicated = {}; foreach my $oid (keys %$snmp_result) { next if ($oid !~ /^$mapping->{state}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); my $name = $result->{name} . ' bank ' . $result->{bank}; $name = $instance if (defined($duplicated->{$name})); if (defined($self->{devices}->{ $options{device} }->{outlets}->{$name})) { $duplicated->{$name} = 1; my $instance2 = $self->{devices}->{ $options{device} }->{outlets}->{$name}->{instance}; $self->{devices}->{ $options{device} }->{outlets}->{$instance2} = $self->{devices}->{ $options{device} }->{outlets}->{$name}; $self->{devices}->{ $options{device} }->{outlets}->{$instance2}->{display} = $instance2; delete $self->{devices}->{ $options{device} }->{outlets}->{$name}; $name = $instance; } $result->{current} /= 10; $self->{devices}->{ $options{device} }->{outlets}->{$name} = { instance => $instance, display => $name, %$result }; } } my $map_pdu2_status = { 1 => 'on', 2 => 'off', }; my $map_pdu2_phase = { 1 => 'seqPhase1ToNeutral', 2 => 'seqPhase2ToNeutral', 3 => 'seqPhase3ToNeutral', 4 => 'seqPhase1ToPhase2', 5 => 'seqPhase2ToPhase3', 6 => 'seqPhase3ToPhase1', }; my $oid_ePDUIdentName = '.1.3.6.1.4.1.3808.1.1.3.1.1'; my $oid_ePDU2DeviceConfigName = '.1.3.6.1.4.1.3808.1.1.6.3.2.1.3'; sub check_pdu2 { my ($self, %options) = @_; my $mapping_switched = { bank => { oid => '.1.3.6.1.4.1.3808.1.1.6.6.1.3.1.6' }, # ePDU2OutletSwitchedInfoBank module => { oid => '.1.3.6.1.4.1.3808.1.1.6.6.1.4.1.2' }, # ePDU2OutletSwitchedStatusModuleIndex number => { oid => '.1.3.6.1.4.1.3808.1.1.6.6.1.4.1.3' }, # ePDU2OutletSwitchedStatusNumber name => { oid => '.1.3.6.1.4.1.3808.1.1.6.6.1.4.1.4' }, # ePDU2OutletSwitchedStatusName state => { oid => '.1.3.6.1.4.1.3808.1.1.6.6.1.4.1.5', map => $map_pdu2_status } # ePDU2OutletSwitchedStatusState, }; my $mapping_metered = { module => { oid => '.1.3.6.1.4.1.3808.1.1.6.6.2.3.1.2' }, # ePDU2OutletMeteredInfoModuleIndex number => { oid => '.1.3.6.1.4.1.3808.1.1.6.6.2.3.1.3' }, # ePDU2OutletMeteredInfoNumber name => { oid => '.1.3.6.1.4.1.3808.1.1.6.6.2.3.1.4' }, # ePDU2OutletMeteredInfoName phase => { oid => '.1.3.6.1.4.1.3808.1.1.6.6.2.3.1.5', map => $map_pdu2_phase }, # ePDU2OutletMeteredInfoLayout bank => { oid => '.1.3.6.1.4.1.3808.1.1.6.6.2.3.1.7' }, # ePDU2OutletMeteredInfoBank current => { oid => '.1.3.6.1.4.1.3808.1.1.6.6.2.4.1.6' } # ePDU2OutletMeteredStatusLoad }; my $oid_ePDU2OutletSwitchedStatusEntry = '.1.3.6.1.4.1.3808.1.1.6.6.1.4.1'; my $snmp_result_switched = $options{snmp}->get_multiple_table( oids => [ { oid => $mapping_switched->{bank}->{oid} }, { oid => $oid_ePDU2OutletSwitchedStatusEntry, start => $mapping_switched->{module}->{oid}, end => $mapping_switched->{state}->{oid} } ], return_type => 1, ); my $oid_ePDU2OutletMeteredInfoEntry = '.1.3.6.1.4.1.3808.1.1.6.6.2.3.1'; my $oid_ePDU2OutletMeteredStatusEntry = '.1.3.6.1.4.1.3808.1.1.6.6.2.4.1'; my $snmp_result_metered = $options{snmp}->get_multiple_table( oids => [ { oid => $oid_ePDU2OutletMeteredInfoEntry, start => $mapping_metered->{module}->{oid}, end => $mapping_metered->{bank}->{oid} }, { oid => $oid_ePDU2OutletMeteredStatusEntry, start => $mapping_metered->{current}->{oid}, end => $mapping_metered->{current}->{oid} } ], return_type => 1, ); my $result_metered = {}; foreach (keys %$snmp_result_metered) { next if (! /^$mapping_metered->{module}->{oid}\.(.*)$/); my $result = $options{snmp}->map_instance(mapping => $mapping_metered, results => $snmp_result_metered, instance => $1); $result_metered->{ $result->{module} . ':' . $result->{bank} . ':' . $result->{number} } = $result; } my $duplicated = {}; foreach (keys %$snmp_result_switched) { next if (! /^$mapping_switched->{module}->{oid}\.(.*)$/); my $result = $options{snmp}->map_instance(mapping => $mapping_switched, results => $snmp_result_switched, instance => $1); my $device_name = $options{devices}->{ $oid_ePDU2DeviceConfigName . '.' . $result->{module} }; if (!defined($self->{devices}->{$device_name})) { $self->{devices}->{$device_name} = { display => $device_name, outlets => {} }; } my $instance = $result->{bank} . ':' . $result->{number}; my $name = $result->{name} . ' bank ' . $result->{bank}; $name = $instance if (defined($duplicated->{$name})); if (defined($self->{devices}->{$device_name}->{outlets}->{$name})) { $duplicated->{$name} = 1; my $instance2 = $self->{devices}->{$device_name}->{outlets}->{$name}->{instance}; $self->{devices}->{$device_name}->{outlets}->{$instance2} = $self->{devices}->{$device_name}->{outlets}->{$name}; $self->{devices}->{$device_name}->{outlets}->{$instance2}->{display} = $instance2; delete $self->{devices}->{$device_name}->{outlets}->{$name}; $name = $instance; } $result_metered->{ $result->{module} . ':' . $result->{bank} . ':' . $result->{number} }->{current} /= 10; $self->{devices}->{$device_name}->{outlets}->{$name} = { instance => $instance, display => $name, state => $result->{state}, %{$result_metered->{ $result->{module} . ':' . $result->{bank} . ':' . $result->{number} }} }; } } sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_multiple_table( oids => [ { oid => $oid_ePDUIdentName }, { oid => $oid_ePDU2DeviceConfigName } ], nothing_quit => 1 ); $self->{devices} = {}; $self->check_pdu2(snmp => $options{snmp}, devices => $snmp_result->{$oid_ePDU2DeviceConfigName}); $self->check_pdu( snmp => $options{snmp}, device => defined($snmp_result->{$oid_ePDUIdentName}->{$oid_ePDUIdentName . '.0'}) ? $snmp_result->{$oid_ePDUIdentName}->{$oid_ePDUIdentName . '.0'} : 'unknown' ); } 1; __END__ =head1 MODE Check outlets. =over 8 =item B<--unknown-status> Set unknown threshold for status. Can used special variables like: %%{state}, %{phase}, %{bank}, %{display} =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{state}, %{phase}, %{bank}, %{display} =item B<--critical-status> Set critical threshold for status (Default: '%{state} =~ /off/'). Can used special variables like: %{state}, %{phase}, %{bank}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'current'. =back =cut centreon-plugins-20220113/hardware/pdu/cyberpower/snmp/plugin.pm000066400000000000000000000024471417000230700246220ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::cyberpower::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} = { 'load' => 'hardware::pdu::cyberpower::snmp::mode::load', 'outlets' => 'hardware::pdu::cyberpower::snmp::mode::outlets' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check CyberPower PDU in SNMP. =cut centreon-plugins-20220113/hardware/pdu/eaton/000077500000000000000000000000001417000230700207275ustar00rootroot00000000000000centreon-plugins-20220113/hardware/pdu/eaton/snmp/000077500000000000000000000000001417000230700217045ustar00rootroot00000000000000centreon-plugins-20220113/hardware/pdu/eaton/snmp/mode/000077500000000000000000000000001417000230700226305ustar00rootroot00000000000000centreon-plugins-20220113/hardware/pdu/eaton/snmp/mode/environment.pm000066400000000000000000000242651417000230700255430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::eaton::snmp::mode::environment; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); sub custom_status_output { my ($self, %options) = @_; my $msg = "status '" . $self->{result_values}->{status} . "'"; return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'pdu', type => 3, cb_prefix_output => 'prefix_pdu_output', cb_long_output => 'pdu_long_output', indent_long_output => ' ', message_multiple => 'All pdu sensors are ok', group => [ { name => 'temperature', display_long => 1, cb_prefix_output => 'prefix_temperature_output', message_multiple => 'All temperature sensors are ok', type => 1, skipped_code => { -10 => 1 } }, { name => 'humidity', display_long => 1, cb_prefix_output => 'prefix_humidity_output', message_multiple => 'All humidity sensors are ok', type => 1, skipped_code => { -10 => 1 } }, ] } ]; $self->{maps_counters}->{temperature} = [ { label => 'temperature-status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'display' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold, } }, { label => 'temperature', nlabel => 'sensor.temperature.celsius', set => { key_values => [ { name => 'value' }, { name => 'display' } ], output_template => 'temperature %.1f C', perfdatas => [ { value => 'value', template => '%.1f', unit => 'C', label_extra_instance => 1 }, ], } }, ]; $self->{maps_counters}->{humidity} = [ { label => 'humidity-status', threshold => 0, set => { key_values => [ { name => 'status' }, { name => 'display' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold, } }, { label => 'humidity', nlabel => 'sensor.humidity.percentage', set => { key_values => [ { name => 'value' }, { name => 'display' } ], output_template => 'humidity %.2f %%', perfdatas => [ { value => 'value', template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1 }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'unknown-temperature-status:s' => { name => 'unknown_temperature_status', default => '' }, 'warning-temperature-status:s' => { name => 'warning_temperature_status', default => '' }, 'critical-temperature-status:s' => { name => 'critical_temperature_status', default => '%{status} eq "bad"' }, 'unknown-humidity-status:s' => { name => 'unknown_humidity_status', default => '' }, 'warning-humidity-status:s' => { name => 'warning_humidity_status', default => '' }, 'critical-humidity-status:s' => { name => 'critical_humidity_status', default => '%{status} eq "bad"' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros( macros => [ 'warning_temperature_status', 'critical_temperature_status', 'unknown_temperature_status', 'warning_humidity_status', 'critical_humidity_status', 'unknown_humidity_status', ] ); } sub prefix_pdu_output { my ($self, %options) = @_; return "PDU '" . $options{instance_value}->{display} . "' : "; } sub pdu_long_output { my ($self, %options) = @_; return "checking pdu '" . $options{instance_value}->{display} . "'"; } sub prefix_temperature_output { my ($self, %options) = @_; return "temperature '" . $options{instance_value}->{display} . "' "; } sub prefix_humidity_output { my ($self, %options) = @_; return "humidity '" . $options{instance_value}->{display} . "' "; } my $mapping_scale = { 0 => 'celsius', 1 => 'fahrenheit' }; my $mapping_probe = { -1 => 'bad', 0 => 'disconnected', 1 => 'connected' }; my $mapping = { serialNumber => { oid => '.1.3.6.1.4.1.534.6.6.7.1.2.1.4' }, temperatureScale => { oid => '.1.3.6.1.4.1.534.6.6.7.1.2.1.9' }, }; my $mapping2 = { temperatureName => { oid => '.1.3.6.1.4.1.534.6.6.7.7.1.1.2' }, temperatureProbeStatus => { oid => '.1.3.6.1.4.1.534.6.6.7.7.1.1.3', map => $mapping_probe }, temperatureValue => { oid => '.1.3.6.1.4.1.534.6.6.7.7.1.1.4' }, }; my $mapping3 = { humidityName => { oid => '.1.3.6.1.4.1.534.6.6.7.7.2.1.2' }, humidityProbeStatus => { oid => '.1.3.6.1.4.1.534.6.6.7.7.2.1.3', map => $mapping_probe }, humidityValue => { oid => '.1.3.6.1.4.1.534.6.6.7.7.2.1.4' }, }; my $oid_unitEntry = '.1.3.6.1.4.1.534.6.6.7.1.2.1'; my $oid_temperatureEntry = '.1.3.6.1.4.1.534.6.6.7.7.1.1'; my $oid_humidityEntry = '.1.3.6.1.4.1.534.6.6.7.7.2.1'; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_multiple_table( oids => [ { oid => $oid_unitEntry, start => $mapping->{serialNumber}->{oid}, end => $mapping->{temperatureScale}->{oid} }, { oid => $oid_temperatureEntry, start => $mapping2->{temperatureName}->{oid}, end => $mapping2->{temperatureValue}->{oid} }, { oid => $oid_humidityEntry, start => $mapping3->{humidityName}->{oid}, end => $mapping3->{humidityValue}->{oid} }, ], nothing_quit => 1 ); $self->{pdu} = {}; foreach my $oid (keys %{$snmp_result->{$oid_unitEntry}}) { next if ($oid !~ /^$mapping->{serialNumber}->{oid}\.(.*)$/); my $strapping_index = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result->{$oid_unitEntry}, instance => $strapping_index); my $temp_scale = $result->{temperatureScale}; my $pdu_serial = $result->{serialNumber}; $self->{pdu}->{$pdu_serial} = { display => $pdu_serial, temperature => {}, humidity => {}, }; foreach (keys %{$snmp_result->{$oid_temperatureEntry}}) { next if (! /^$mapping2->{temperatureProbeStatus}->{oid}\.$strapping_index\.(.*)$/); $result = $options{snmp}->map_instance(mapping => $mapping2, results => $snmp_result->{$oid_temperatureEntry}, instance => $strapping_index . '.' . $1); my $name = defined($result->{temperatureName}) && $result->{temperatureName} ne '' ? $result->{temperatureName} : $1; my $value = $result->{temperatureValue} / 10; $value = centreon::plugins::misc::convert_fahrenheit(value => $value) if ($temp_scale eq 'fahrenheit'); $self->{pdu}->{$pdu_serial}->{temperature}->{$name} = { display => $name, status => $result->{temperatureProbeStatus}, value => $value, }; } foreach (keys %{$snmp_result->{$oid_humidityEntry}}) { next if (! /^$mapping3->{humidityProbeStatus}->{oid}\.$strapping_index\.(.*)$/); $result = $options{snmp}->map_instance(mapping => $mapping3, results => $snmp_result->{$oid_humidityEntry}, instance => $strapping_index . '.' . $1); my $name = defined($result->{humidityName}) && $result->{humidityName} ne '' ? $result->{humidityName} : $1; $self->{pdu}->{$pdu_serial}->{humidity}->{$name} = { display => $name, status => $result->{humidityProbeStatus}, value => $result->{humidityValue} / 10, }; } } if (scalar(keys %{$self->{pdu}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No pdu found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check pdu environmental sensors. =over 8 =item B<--unknown-temperature-status> Set unknon threshold for status (Default: ''). Can used special variables like: %{status}, %{display} =item B<--warning-temperature-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{display} =item B<--critical-temperature-status> Set critical threshold for status (Default: '%{status} eq "bad"'). Can used special variables like: %{status}, %{display} =item B<--unknown-humidity-status> Set unknon threshold for status (Default: ''). Can used special variables like: %{status}, %{display} =item B<--warning-humidity-status> Set warning threshold for status (Default: ''). Can used special variables like: %{status}, %{display} =item B<--critical-humidity-status> Set critical threshold for status (Default: '%{status} eq "bad"'). Can used special variables like: %{status}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'humidity' (%), 'temperature' (C). =back =cut centreon-plugins-20220113/hardware/pdu/eaton/snmp/mode/group.pm000066400000000000000000000124721417000230700243300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::eaton::snmp::mode::group; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'group', type => 1, cb_prefix_output => 'prefix_group_output', message_multiple => 'All groups are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{group} = [ { label => 'current', nlabel => 'group.current.ampere', set => { key_values => [ { name => 'groupCurrent', no_value => 0 }, { name => 'display' } ], output_template => 'Current : %.2f A', perfdatas => [ { value => 'groupCurrent', template => '%.2f', min => 0, unit => 'A', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'voltage', nlabel => 'group.voltage.volt', set => { key_values => [ { name => 'groupVoltage', no_value => 0 }, { name => 'display' } ], output_template => 'Voltage : %.2f V', perfdatas => [ { value => 'groupVoltage', template => '%.2f', unit => 'V', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'power', nlabel => 'group.power.watt', set => { key_values => [ { name => 'groupWatts', no_value => 0 }, { name => 'display' } ], output_template => 'Power : %.2f W', perfdatas => [ { value => 'groupWatts', template => '%.2f', unit => 'W', label_extra_instance => 1, instance_use => 'display' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } sub prefix_group_output { my ($self, %options) = @_; return "Group '" . $options{instance_value}->{display} . "' "; } my $mapping = { groupName => { oid => '.1.3.6.1.4.1.534.6.6.7.5.1.1.3' }, groupVoltage => { oid => '.1.3.6.1.4.1.534.6.6.7.5.3.1.3' }, # in mVolt groupCurrent => { oid => '.1.3.6.1.4.1.534.6.6.7.5.4.1.3' }, # in mA groupWatts => { oid => '.1.3.6.1.4.1.534.6.6.7.5.5.1.3' }, # in Watt }; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_multiple_table( oids => [ { oid => $mapping->{groupName}->{oid} }, { oid => $mapping->{groupVoltage}->{oid} }, { oid => $mapping->{groupCurrent}->{oid} }, { oid => $mapping->{groupWatts}->{oid} }, ], return_type => 1, nothing_quit => 1 ); $self->{group} = {}; foreach my $oid (keys %{$snmp_result}) { $oid =~ /\.(\d+)\.(\d+)$/; my ($strapping_index, $group_index) = ($1, $2); next if (defined($self->{group}->{$strapping_index . '.' . $group_index})); my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $strapping_index . '.' . $group_index); $result->{groupVoltage} *= 0.001 if (defined($result->{groupVoltage})); $result->{groupCurrent} *= 0.001 if (defined($result->{groupCurrent})); my $display = $strapping_index . '.' . $group_index; if (defined($result->{groupName}) && $result->{groupName} ne '') { $display = $result->{groupName} . ' strapping ' . $strapping_index; } if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $display !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $display . "': no matching filter.", debug => 1); next; } $self->{group}->{$strapping_index . '.' . $group_index} = { display => $display, %$result }; } if (scalar(keys %{$self->{group}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No group found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check group metrics (voltage, current and power). =over 8 =item B<--filter-name> Filter group name (can be a regexp). =item B<--warning-*> Threshold warning. Can be: 'voltage', 'current', 'power'. =item B<--critical-*> Threshold critical. Can be: 'voltage', 'current', 'power'. =back =cut centreon-plugins-20220113/hardware/pdu/eaton/snmp/mode/outlet.pm000066400000000000000000000125561417000230700245130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::eaton::snmp::mode::outlet; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'outlet', type => 1, cb_prefix_output => 'prefix_outlet_output', message_multiple => 'All outlets are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{outlet} = [ { label => 'current', nlabel => 'outlet.current.ampere', set => { key_values => [ { name => 'outletCurrent', no_value => 0 }, { name => 'display' } ], output_template => 'Current : %.2f A', perfdatas => [ { value => 'outletCurrent', template => '%.2f', min => 0, unit => 'A', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'voltage', nlabel => 'outlet.voltage.volt', set => { key_values => [ { name => 'outletVoltage', no_value => 0 }, { name => 'display' } ], output_template => 'Voltage : %.2f V', perfdatas => [ { value => 'outletVoltage', template => '%.2f', unit => 'V', label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'power', nlabel => 'outlet.power.watt', set => { key_values => [ { name => 'outletWatts', no_value => 0 }, { name => 'display' } ], output_template => 'Power : %.2f W', perfdatas => [ { value => 'outletWatts', template => '%.2f', unit => 'W', label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } sub prefix_outlet_output { my ($self, %options) = @_; return "Outlet '" . $options{instance_value}->{display} . "' "; } my $mapping = { outletName => { oid => '.1.3.6.1.4.1.534.6.6.7.6.1.1.3' }, outletVoltage => { oid => '.1.3.6.1.4.1.534.6.6.7.6.3.1.2' }, # in mVolt outletCurrent => { oid => '.1.3.6.1.4.1.534.6.6.7.6.4.1.3' }, # in mA outletWatts => { oid => '.1.3.6.1.4.1.534.6.6.7.6.5.1.3' }, # in Watt }; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_multiple_table( oids => [ { oid => $mapping->{outletName}->{oid} }, { oid => $mapping->{outletVoltage}->{oid} }, { oid => $mapping->{outletCurrent}->{oid} }, { oid => $mapping->{outletWatts}->{oid} }, ], return_type => 1, nothing_quit => 1 ); $self->{outlet} = {}; foreach my $oid (keys %{$snmp_result}) { $oid =~ /\.(\d+)\.(\d+)$/; my ($strapping_index, $outlet_index) = ($1, $2); next if (defined($self->{outlet}->{$strapping_index . '.' . $outlet_index})); my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $strapping_index . '.' . $outlet_index); $result->{outletVoltage} *= 0.001 if (defined($result->{outletVoltage})); $result->{outletCurrent} *= 0.001 if (defined($result->{outletCurrent})); my $display = $strapping_index . '.' . $outlet_index; if (defined($result->{outletName}) && $result->{outletName} ne '') { $display = $result->{outletName} . ' strapping ' . $strapping_index; } if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $display !~ /$self->{option_results}->{filter_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $display . "': no matching filter.", debug => 1); next; } $self->{outlet}->{$strapping_index . '.' . $outlet_index} = { display => $display, %$result }; } if (scalar(keys %{$self->{outlet}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No outlet found."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check outlet metrics (voltage, current and power). =over 8 =item B<--filter-name> Filter outlet name (can be a regexp). =item B<--warning-*> Threshold warning. Can be: 'voltage', 'current', 'power'. =item B<--critical-*> Threshold critical. Can be: 'voltage', 'current', 'power'. =back =cut centreon-plugins-20220113/hardware/pdu/eaton/snmp/plugin.pm000066400000000000000000000025451417000230700235460ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::eaton::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}} = ( 'environment' => 'hardware::pdu::eaton::snmp::mode::environment', 'group' => 'hardware::pdu::eaton::snmp::mode::group', 'outlet' => 'hardware::pdu::eaton::snmp::mode::outlet', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Eaton PDU in SNMP. =cut centreon-plugins-20220113/hardware/pdu/emerson/000077500000000000000000000000001417000230700212715ustar00rootroot00000000000000centreon-plugins-20220113/hardware/pdu/emerson/snmp/000077500000000000000000000000001417000230700222465ustar00rootroot00000000000000centreon-plugins-20220113/hardware/pdu/emerson/snmp/mode/000077500000000000000000000000001417000230700231725ustar00rootroot00000000000000centreon-plugins-20220113/hardware/pdu/emerson/snmp/mode/globalstatus.pm000066400000000000000000000124501417000230700262360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::emerson::snmp::mode::globalstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = "status is '" . $self->{result_values}->{status} . "'"; return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'pdu', type => 1, cb_prefix_output => 'prefix_pdu_output', message_multiple => 'All PDU status are ok' } ]; $self->{maps_counters}->{pdu} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' }, { 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 => \&catalog_status_threshold, } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'warning-status:s' => { name => 'warning_status', default => '%{status} =~ /normalWithWarning/i' }, 'critical-status:s' => { name => 'critical_status', default => '%{status} =~ /normalWithAlarm|abnormalOperation/i' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['warning_status', 'critical_status']); } sub prefix_pdu_output { my ($self, %options) = @_; return "PDU '" . $options{instance_value}->{display} . "' "; } my %bitmap_status = ( 1 => 'normalOperation', 2 => 'startUp', 8 => 'normalWithWarning', 16 => 'normalWithAlarm', 32 => 'abnormalOperation', ); my $mapping = { lgpPduEntryUsrLabel => { oid => '.1.3.6.1.4.1.476.1.42.3.8.20.1.10' }, lgpPduEntrySysStatus => { oid => '.1.3.6.1.4.1.476.1.42.3.8.20.1.25' }, }; my $oid_lgpPduEntry = '.1.3.6.1.4.1.476.1.42.3.8.20.1'; sub manage_selection { my ($self, %options) = @_; $self->{pdu} = {}; $self->{results} = $options{snmp}->get_table( oid => $oid_lgpPduEntry, start => $mapping->{lgpPduEntryUsrLabel}->{oid}, end => $mapping->{lgpPduEntrySysStatus}->{oid}, nothing_quit => 1 ); foreach my $oid (keys %{$self->{results}}) { next if ($oid !~ /^$mapping->{lgpPduEntrySysStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $self->{results}, instance => $instance); my $name = defined($result->{lgpPduEntryUsrLabel}) && $result->{lgpPduEntryUsrLabel} ne '' ? $result->{lgpPduEntryUsrLabel} : $instance; my $status = 'unknown'; foreach (keys %bitmap_status) { if ((int($result->{lgpPduEntrySysStatus}) & $_)) { $status = $bitmap_status{$_}; last; } } 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->{pdu}->{$instance} = { display => $name, status => $status }; } if (scalar(keys %{$self->{pdu}}) <= 0) { $self->{output}->add_option_msg(short_msg => "Cannot found pdu."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check global status. =over 8 =item B<--filter-name> Filter PDU name (can be a regexp). =item B<--warning-status> Set warning threshold for status (Default: '%{status} =~ /normalWithWarning/i'). Can used special variables like: %{status}, %{display}. =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /normalWithAlarm|abnormalOperation/i'). Can used special variables like: %{status}, %{display} =back =cut centreon-plugins-20220113/hardware/pdu/emerson/snmp/mode/psusage.pm000066400000000000000000000235051417000230700252040ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::emerson::snmp::mode::psusage; 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 => 'ps', type => 3, cb_prefix_output => 'prefix_ps_output', cb_long_output => 'ps_long_output', indent_long_output => ' ', message_multiple => 'All power sources are ok', group => [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'line', display_long => 1, cb_prefix_output => 'prefix_line_output', message_multiple => 'All power source lines are ok', type => 1, skipped_code => { -10 => 1 } }, ] } ]; $self->{maps_counters}->{global} = [ { label => 'power', nlabel => 'powersource.total.input.power.watt', set => { key_values => [ { name => 'PwrTotal' } ], output_template => 'Total input power : %s W', output_error_template => "total input power : %s", perfdatas => [ { label => 'power', value => 'PwrTotal', template => '%s', unit => 'W', min => 0, label_extra_instance => 1 }, ], } }, { label => 'energy', nlabel => 'powersource.total.accumulated.energy.kilowatthour', set => { key_values => [ { name => 'EnergyAccum', diff => 1 } ], output_template => 'Total energy : %.3f kWh', output_error_template => "Total energy : %s", perfdatas => [ { label => 'energy', value => 'EnergyAccum', template => '%.3f', unit => 'kWh', min => 0, label_extra_instance => 1 }, ], } }, { label => 'current-neutral', nlabel => 'powersource.neutral.current.ampacrms', set => { key_values => [ { name => 'EcNeutral' } ], output_template => 'Current neutral : %s Amp AC RMS', output_error_template => "Current neutral : %s", perfdatas => [ { label => 'current_neutral', value => 'EcNeutral', template => '%s', unit => 'AmpAcRMS', min => 0, label_extra_instance => 1 }, ], } }, ]; $self->{maps_counters}->{line} = [ { label => 'line-load', nlabel => 'line.load.percentage', set => { key_values => [ { name => 'load' } ], output_template => 'Load : %.2f %%', output_error_template => "Load : %s", perfdatas => [ { label => 'line_load', value => 'load', template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1 }, ], } }, { label => 'line-current', nlabel => 'line.neutral.current.ampere', set => { key_values => [ { name => 'current' }], output_template => 'Current : %.2f A', output_error_template => "Current : %s", perfdatas => [ { label => 'line_current', value => 'current', template => '%.2f', unit => 'A', min => 0, label_extra_instance => 1 }, ], } }, ]; } sub prefix_ps_output { my ($self, %options) = @_; return "Power source '" . $options{instance_value}->{display} . "' "; } sub ps_long_output { my ($self, %options) = @_; return "checking power source '" . $options{instance_value}->{display} . "'"; } sub prefix_line_output { my ($self, %options) = @_; return "Power source line '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, }); return $self; } my %map_phase = (1 => 'phase1', 2 => 'phase2', 3 => 'phase3'); my $mapping = { lgpPduEntryUsrLabel => { oid => '.1.3.6.1.4.1.476.1.42.3.8.20.1.10' }, lgpPduEntrySysAssignLabel => { oid => '.1.3.6.1.4.1.476.1.42.3.8.20.1.15' }, }; my $mapping2 = { lgpPduPsEntrySysAssignLabel => { oid => '.1.3.6.1.4.1.476.1.42.3.8.30.20.1.15' }, lgpPduPsEntryEnergyAccum => { oid => '.1.3.6.1.4.1.476.1.42.3.8.30.20.1.50' }, # 0.1 Kilowatt-Hour lgpPduPsEntryPwrTotal => { oid => '.1.3.6.1.4.1.476.1.42.3.8.30.20.1.65' }, # Watt lgpPduPsEntryEcNeutral => { oid => '.1.3.6.1.4.1.476.1.42.3.8.30.20.1.70' }, # 0.1 Amp-AC-RMS }; my $mapping3 = { lgpPduPsLineEntryLine => { oid => '.1.3.6.1.4.1.476.1.42.3.8.30.40.1.15', map => \%map_phase }, lgpPduPsLineEntryEcHundredths => { oid => '.1.3.6.1.4.1.476.1.42.3.8.30.40.1.22' }, # 0.01 A lgpPduPsLineEntryEcUsedBeforeAlarm => { oid => '.1.3.6.1.4.1.476.1.42.3.8.30.40.1.39' }, # % }; my $oid_lgpPduEntry = '.1.3.6.1.4.1.476.1.42.3.8.20.1'; my $oid_lgpPduPsEntry = '.1.3.6.1.4.1.476.1.42.3.8.30.20.1'; my $oid_lgpPduPsLineEntry = '.1.3.6.1.4.1.476.1.42.3.8.30.40.1'; sub manage_selection { my ($self, %options) = @_; $self->{cache_name} = "pdu_emerson_" . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . $self->{mode} . '_' . (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); $self->{ps} = {}; my $snmp_result = $options{snmp}->get_multiple_table( oids => [ { oid => $oid_lgpPduEntry, start => $mapping->{lgpPduEntryUsrLabel}->{oid}, end => $mapping->{lgpPduEntrySysAssignLabel}->{oid} }, { oid => $oid_lgpPduPsEntry, start => $mapping2->{lgpPduPsEntrySysAssignLabel}->{oid}, end => $mapping2->{lgpPduPsEntryEcNeutral}->{oid} }, { oid => $oid_lgpPduPsLineEntry, start => $mapping3->{lgpPduPsLineEntryLine}->{oid}, end => $mapping3->{lgpPduPsLineEntryEcUsedBeforeAlarm}->{oid} }, ], nothing_quit => 1 ); foreach my $oid (keys %{$snmp_result->{$oid_lgpPduPsEntry}}) { next if ($oid !~ /^$mapping2->{lgpPduPsEntrySysAssignLabel}->{oid}\.(\d+)\.(\d+)/); my ($pdu_index, $ps_index) = ($1, $2); my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result->{$oid_lgpPduEntry}, instance => $pdu_index); my $result2 = $options{snmp}->map_instance(mapping => $mapping2, results => $snmp_result->{$oid_lgpPduPsEntry}, instance => $pdu_index . '.' . $ps_index); my $name = (defined($result->{lgpPduEntryUsrLabel}) && $result->{lgpPduEntryUsrLabel} ne '' ? $result->{lgpPduEntryUsrLabel} : $result->{lgpPduEntrySysAssignLabel}); $name .= '~' . $result2->{lgpPduPsEntrySysAssignLabel}; 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->{ps}->{$name} = { display => $name, global => { display => $name, EnergyAccum => $result2->{lgpPduPsEntryEnergyAccum} * 0.1, PwrTotal => $result2->{lgpPduPsEntryPwrTotal}, EcNeutral => defined($result2->{lgpPduPsEntryEcNeutral}) ? $result2->{lgpPduPsEntryEcNeutral} * 0.1 : undef, }, line => {}, }; foreach my $oid (keys %{$snmp_result->{$oid_lgpPduPsLineEntry}}) { next if ($oid !~ /^$mapping3->{lgpPduPsLineEntryEcUsedBeforeAlarm}->{oid}\.$pdu_index\.$ps_index\.(\d+)/); my $line_index = $1; my $result3 = $options{snmp}->map_instance(mapping => $mapping3, results => $snmp_result->{$oid_lgpPduPsLineEntry}, instance => $pdu_index . '.' . $ps_index . '.' . $line_index); $self->{ps}->{$name}->{line}->{$result3->{lgpPduPsLineEntryLine}} = { display => $result3->{lgpPduPsLineEntryLine}, current => defined($result3->{lgpPduPsLineEntryEcHundredths}) ? $result3->{lgpPduPsLineEntryEcHundredths} * 0.01 : undef, load => $result3->{lgpPduPsLineEntryEcUsedBeforeAlarm}, }; } } if (scalar(keys %{$self->{ps}}) <= 0) { $self->{output}->add_option_msg(short_msg => "Cannot found power sources."); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check power source usage. =over 8 =item B<--filter-name> Filter power source name (can be a regexp). =item B<--filter-counters> Only display some counters (regexp can be used). Example: --filter-counters='^(power|energy)$' =item B<--warning-*> Threshold warning. Can be: 'power', 'energy', 'current-neutral', 'line-load', 'line-current'. =item B<--critical-*> Threshold critical. Can be: 'power', 'energy', 'current-neutral', 'line-load', 'line-current'. =back =cut centreon-plugins-20220113/hardware/pdu/emerson/snmp/mode/receptacles.pm000066400000000000000000000301311417000230700260200ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::emerson::snmp::mode::receptacles; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); use Digest::MD5 qw(md5_hex); sub custom_rcp_status_output { my ($self, %options) = @_; my $msg = sprintf( "operational state '%s' [power state: %s]", $self->{result_values}->{oper_state}, $self->{result_values}->{power_state} ); return $msg; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'rb', type => 3, cb_prefix_output => 'prefix_rb_output', cb_long_output => 'rb_long_output', indent_long_output => ' ', message_multiple => 'All receptacle branches are ok', group => [ { name => 'global', type => 0, skipped_code => { -10 => 1 } }, { name => 'rcp', display_long => 1, cb_prefix_output => 'prefix_rcp_output', message_multiple => 'All receptacles are ok', type => 1, skipped_code => { -10 => 1 } }, ] } ]; $self->{maps_counters}->{global} = [ { label => 'total-accumulated-energy', nlabel => 'receptaclebranch.total.accumulated.energy.kilowatthour', set => { key_values => [ { name => 'lgpPduRbEntryEnergyAccum', diff => 1 } ], output_template => 'total input power : %s kWh', perfdatas => [ { template => '%s', value => 'lgpPduRbEntryEnergyAccum', unit => 'kWh', min => 0, label_extra_instance => 1 }, ], } }, { label => 'line2neutral-real-power', nlabel => 'receptaclebranch.line2neutral.real.power.watt', set => { key_values => [ { name => 'lgpPduRbEntryPwr' } ], output_template => 'line-to-neutral real power : %s W', perfdatas => [ { template => '%s', value => 'lgpPduRbEntryPwr', unit => 'W', min => 0, label_extra_instance => 1 }, ], } }, { label => 'line2neutral-apparent-power', nlabel => 'receptaclebranch.line2neutral.apparent.power.voltampere', set => { key_values => [ { name => 'lgpPduRbEntryAp' } ], output_template => 'line-to-neutral apparent power : %s VA', perfdatas => [ { template => '%s', value => 'lgpPduRbEntryAp', unit => 'VA', min => 0, label_extra_instance => 1 }, ], } }, { label => 'current-neutral', nlabel => 'receptaclebranch.line2neutral.current.ampacrms', set => { key_values => [ { name => 'lgpPduRbEntryEcHundredths' } ], output_template => 'line-to-neutral current : %s Amp AC RMS', perfdatas => [ { value => 'lgpPduRbEntryEcHundredths', template => '%s', unit => 'AmpAcRMS', min => 0, label_extra_instance => 1 }, ], } }, { label => 'potential-neutral', nlabel => 'receptaclebranch.line2neutral.potential.voltrms', set => { key_values => [ { name => 'lgpPduRbEntryEpLNTenths' } ], output_template => 'line-to-neutral potential : %s VoltRMS', perfdatas => [ { value => 'lgpPduRbEntryEpLNTenths', template => '%s', unit => 'VoltRMS', min => 0, label_extra_instance => 1 }, ], } }, ]; $self->{maps_counters}->{rcp} = [ { label => 'rcp-status', threshold => 0, set => { key_values => [ { name => 'oper_state' }, { name => 'power_state' }, { name => 'display' } ], closure_custom_calc => \&catalog_status_calc, closure_custom_output => $self->can('custom_rcp_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold, } }, ]; } sub prefix_rb_output { my ($self, %options) = @_; return "Receptacle branch '" . $options{instance_value}->{display} . "' : "; } sub rb_long_output { my ($self, %options) = @_; return "checking receptacle branch '" . $options{instance_value}->{display} . "'"; } sub prefix_rcp_output { my ($self, %options) = @_; return "receptacle '" . $options{instance_value}->{display} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1, statefile => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-rb:s' => { name => 'filter_rb' }, 'unknown-rcp-status:s' => { name => 'unknown_rcp_status', default => '' }, 'warning-rcp-status:s' => { name => 'warning_rcp_status', default => '%{oper_state} =~ /warning|alarm/' }, 'critical-rcp-status:s' => { name => 'critical_rcp_status', default => '%{oper_state} =~ /abnormal/' }, }); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => ['unknown_rcp_status', 'warning_rcp_status', 'critical_rcp_status']); } my $rcp_power_state = { 0 => 'unknown', 1 => 'off', 2 => 'on', 3 => 'off-pending-on-delay' }; my $rcp_oper = { 1 => 'normal', 2 => 'warning', 3 => 'alarm', 4 => 'abnormal' }; sub manage_selection { my ($self, %options) = @_; my $mapping = { lgpPduEntryUsrLabel => { oid => '.1.3.6.1.4.1.476.1.42.3.8.20.1.10' }, lgpPduEntrySysAssignLabel => { oid => '.1.3.6.1.4.1.476.1.42.3.8.20.1.15' }, }; my $mapping2 = { lgpPduRbEntryUsrLabel => { oid => '.1.3.6.1.4.1.476.1.42.3.8.40.20.1.8' }, lgpPduRbEntrySysAssignLabel => { oid => '.1.3.6.1.4.1.476.1.42.3.8.40.20.1.20' }, lgpPduRbEntryEnergyAccum => { oid => '.1.3.6.1.4.1.476.1.42.3.8.40.20.1.85' }, # 0.1 Kilowatt-Hour lgpPduRbEntryEpLNTenths => { oid => '.1.3.6.1.4.1.476.1.42.3.8.40.20.1.100' }, lgpPduRbEntryPwr => { oid => '.1.3.6.1.4.1.476.1.42.3.8.40.20.1.115' }, # Watt lgpPduRbEntryAp => { oid => '.1.3.6.1.4.1.476.1.42.3.8.40.20.1.120' }, # VA lgpPduRbEntryEcHundredths => { oid => '.1.3.6.1.4.1.476.1.42.3.8.40.20.1.130' }, }; my $mapping3 = { lgpPduRcpEntryUsrLabel => { oid => '.1.3.6.1.4.1.476.1.42.3.8.50.20.1.10' }, lgpPduRcpEntrySysAssignLabel => { oid => '.1.3.6.1.4.1.476.1.42.3.8.50.20.1.25' }, lgpPduRcpEntryPwrState => { oid => '.1.3.6.1.4.1.476.1.42.3.8.50.20.1.95', map => $rcp_power_state }, lgpPduRcpEntryOperationCondition => { oid => '.1.3.6.1.4.1.476.1.42.3.8.50.20.1.210', map => $rcp_oper }, }; my $oid_lgpPduEntry = '.1.3.6.1.4.1.476.1.42.3.8.20.1'; my $oid_lgpPduRbEntry = '.1.3.6.1.4.1.476.1.42.3.8.40.20.1'; my $oid_lgpPduRcpEntry = '.1.3.6.1.4.1.476.1.42.3.8.50.20.1'; my $snmp_result = $options{snmp}->get_multiple_table( oids => [ { oid => $oid_lgpPduEntry, start => $mapping->{lgpPduEntryUsrLabel}->{oid}, end => $mapping->{lgpPduEntrySysAssignLabel}->{oid} }, { oid => $oid_lgpPduRbEntry, start => $mapping2->{lgpPduRbEntryUsrLabel}->{oid}, end => $mapping2->{lgpPduRbEntryEcHundredths}->{oid} }, { oid => $oid_lgpPduRcpEntry, start => $mapping3->{lgpPduRcpEntryUsrLabel}->{oid}, end => $mapping3->{lgpPduRcpEntryOperationCondition}->{oid} }, ], nothing_quit => 1, ); $self->{rb} = {}; foreach my $oid (keys %{$snmp_result->{$oid_lgpPduRbEntry}}) { next if ($oid !~ /^$mapping2->{lgpPduRbEntrySysAssignLabel}->{oid}\.(.*?)\.(.*)$/); my ($pdu_index, $rb_index) = ($1, $2); my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result->{$oid_lgpPduEntry}, instance => $pdu_index); my $result2 = $options{snmp}->map_instance(mapping => $mapping2, results => $snmp_result->{$oid_lgpPduRbEntry}, instance => $pdu_index . '.' . $rb_index); my $name = (defined($result->{lgpPduEntryUsrLabel}) && $result->{lgpPduEntryUsrLabel} ne '' ? $result->{lgpPduEntryUsrLabel} : $result->{lgpPduEntrySysAssignLabel}); $name .= '~' . (defined($result2->{lgpPduRbEntryUsrLabel}) && $result2->{lgpPduRbEntryUsrLabel} ne '' ? $result2->{lgpPduRbEntryUsrLabel} : $result2->{lgpPduRbEntrySysAssignLabel}); 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 receptacle branch '" . $name . "'.", debug => 1); next; } $result2->{lgpPduRbEntryEnergyAccum} /= 10; $result2->{lgpPduRbEntryEcHundredths} *= 0.01 if (defined($result2->{lgpPduRbEntryEcHundredths})); $result2->{lgpPduRbEntryEpLNTenths} *= 0.1 if (defined($result2->{lgpPduRbEntryEpLNTenths})); $self->{rb}->{$name} = { display => $name, global => { %$result2 }, rcp => {}, }; foreach (keys %{$snmp_result->{$oid_lgpPduRcpEntry}}) { next if (!/^$mapping3->{lgpPduRcpEntrySysAssignLabel}->{oid}\.$pdu_index\.$rb_index\.(.*)$/); my $rcp_index = $1; my $result3 = $options{snmp}->map_instance(mapping => $mapping3, results => $snmp_result->{$oid_lgpPduRcpEntry}, instance => $pdu_index . '.' . $rb_index . '.' . $rcp_index); my $rcp_name = (defined($result3->{lgpPduRcpEntryUsrLabel}) && $result3->{lgpPduRcpEntryUsrLabel} ne '' ? $result3->{lgpPduRcpEntryUsrLabel} : $result3->{lgpPduRcpEntrySysAssignLabel}); $self->{rb}->{$name}->{rcp}->{$rcp_name} = { display => $rcp_name, power_state => $result3->{lgpPduRcpEntryPwrState}, oper_state => $result3->{lgpPduRcpEntryOperationCondition}, }; } } if (scalar(keys %{$self->{rb}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No receptacle branch found."); $self->{output}->option_exit(); } $self->{cache_name} = "pdu_liebert_" . $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_rb}) ? md5_hex($self->{option_results}->{filter_rb}) : md5_hex('all')); } 1; __END__ =head1 MODE Check receptacles. =over 8 =item B<--filter-rb> Filter receptable branch name (can be a regexp). =item B<--unknown-rcp-status> Set warning threshold for status (Default: ''). Can used special variables like: %{oper_state}, %{power_state}, %{display} =item B<--warning-rcp-status> Set warning threshold for status (Default: '%{oper_state} =~ /warning|alarm/'). Can used special variables like: %{oper_state}, %{power_state}, %{display} =item B<--critical-rcp-status> Set critical threshold for status (Default: '%{oper_state} =~ /abnormal/'). Can used special variables like: %{oper_state}, %{power_state}, %{display} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'total-accumulated-energy', 'line2neutral-real-power', 'line2neutral-apparent-power'. =back =cut centreon-plugins-20220113/hardware/pdu/emerson/snmp/plugin.pm000066400000000000000000000026051417000230700241050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::emerson::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}} = ( 'global-status' => 'hardware::pdu::emerson::snmp::mode::globalstatus', 'ps-usage' => 'hardware::pdu::emerson::snmp::mode::psusage', 'receptacles' => 'hardware::pdu::emerson::snmp::mode::receptacles', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Emerson Liebert PDU in SNMP. =cut centreon-plugins-20220113/hardware/pdu/gude/000077500000000000000000000000001417000230700205455ustar00rootroot00000000000000centreon-plugins-20220113/hardware/pdu/gude/epc/000077500000000000000000000000001417000230700213145ustar00rootroot00000000000000centreon-plugins-20220113/hardware/pdu/gude/epc/snmp/000077500000000000000000000000001417000230700222715ustar00rootroot00000000000000centreon-plugins-20220113/hardware/pdu/gude/epc/snmp/mode/000077500000000000000000000000001417000230700232155ustar00rootroot00000000000000centreon-plugins-20220113/hardware/pdu/gude/epc/snmp/mode/listsppowerchannels.pm000066400000000000000000000063761417000230700276760ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::gude::epc::snmp::mode::listsppowerchannels; use base qw(centreon::plugins::mode); use strict; use warnings; use hardware::pdu::gude::epc::snmp::mode::resources; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); } sub manage_selection { my ($self, %options) = @_; my $branch = hardware::pdu::gude::epc::snmp::mode::resources::find_gude_branch($self, snmp => $options{snmp}); my $oid_entry = $branch . '.1.3.1.2.1'; my $port_status_mapping = { 0 => 'off', 1 => 'on' }; my $sp_mapping = { name => { oid => $branch . '.1.3.1.2.1.2' }, state => { oid => $branch . '.1.3.1.2.1.3', map => $port_status_mapping } }; my $snmp_result = $options{snmp}->get_table(oid => $oid_entry); my $ports = {}; foreach my $port_oid (keys %$snmp_result) { next if ($port_oid !~ /^$sp_mapping->{name}->{oid}\.(.*)$/); my $instance = $1; $ports->{$instance} = $options{snmp}->map_instance(mapping => $sp_mapping, results => $snmp_result, instance => $instance); }; return $ports; } sub run { my ($self, %options) = @_; my $ports = $self->manage_selection(%options); foreach my $instance (sort keys %$ports) { $self->{output}->output_add( long_msg => sprintf( "[id: %s][name: %s][state: %s]", $instance, $ports->{$instance}->{name}, $ports->{$instance}->{state} ) ); } $self->{output}->output_add( severity => 'OK', short_msg => 'List single port power channel interfaces:' ); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } sub disco_format { my ($self, %options) = @_; $self->{output}->add_disco_format(elements => ['id', 'name', 'state']); } sub disco_show { my ($self, %options) = @_; my $ports = $self->manage_selection(%options); foreach my $instance (sort keys %$ports) { $self->{output}->add_disco_entry( id => $instance, name => $ports->{$instance}->{name}, state => $ports->{$instance}->{state} ); } } 1; __END__ =head1 MODE List single port power channel interfaces. =over 8 =back =cut centreon-plugins-20220113/hardware/pdu/gude/epc/snmp/mode/powerchannels.pm000066400000000000000000000262011417000230700264240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::gude::epc::snmp::mode::powerchannels; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use hardware::pdu::gude::epc::snmp::mode::resources; sub prefix_channels_output { my ($self, %options) = @_; return "Power channel interface '" . $options{instance_value}->{name} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'channels', type => 1, cb_prefix_output => 'prefix_channels_output', message_multiple => 'All power channel interfaces are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'active-channels', nlabel => 'pdu.power_channels.active.count', set => { key_values => [ { name => 'active_channels' } ], output_template => '%s active power channel(s)', perfdatas => [ { template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{channels} = [ { label => 'status', type => 2, critical_default => '%{status} !~ /valid/i', set => { key_values => [ { name => 'status' }, { name => 'name' } ], output_template => 'status: %s', closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'ovp-status', type => 2, critical_default => '%{ovp_status} !~ /ok/i', set => { key_values => [ { name => 'ovp_status' }, { name => 'name' } ], output_template => 'ovp status: %s', closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'ps-status', type => 2, critical_default => '%{ps_status} !~ /up/i', set => { key_values => [ { name => 'ps_status' }, { name => 'name' } ], output_template => 'power supply status: %s', closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'current', nlabel => 'pdu.interface.power_channel.current.ampere', set => { key_values => [ { name => 'current', no_value => 0 }, { name => 'name' } ], output_template => 'current: %.2f A', perfdatas => [ { template => '%.2f', min => 0, unit => 'A', label_extra_instance => 1, instance_use => 'name' } ] } }, { label => 'energy', nlabel => 'pdu.interface.power_channel.energy.active.kilowatthour', set => { key_values => [ { name => 'abs_energy_active', no_value => 0 }, { name => 'name' } ], output_template => 'absolute energy active: %.2f kWh', perfdatas => [ { template => '%.2f', min => 0, unit => 'kWh', label_extra_instance => 1, instance_use => 'name' } ] } }, { label => 'frequency', nlabel => 'pdu.interface.power_channel.frequency.hertz', set => { key_values => [ { name => 'frequency', no_value => 0 }, { name => 'name' } ], output_template => 'frequency: %.2f Hz', perfdatas => [ { template => '%.2f', min => 0, unit => 'Hz', label_extra_instance => 1, instance_use => 'name' } ] } }, { label => 'phase-angle', nlabel => 'pdu.interface.power_channel.phase.angle.degree', set => { key_values => [ { name => 'phase_angle', no_value => 0 }, { name => 'name' } ], output_template => 'phase angle: %.2f°', perfdatas => [ { template => '%.2f', min => 0, label_extra_instance => 1, instance_use => 'name' } ] } }, { label => 'power-active', nlabel => 'pdu.interface.power_channel.active.watt', set => { key_values => [ { name => 'power_active', no_value => 0 }, { name => 'name' } ], output_template => 'active power: %.2f W', perfdatas => [ { template => '%.2f', unit => 'W', label_extra_instance => 1, instance_use => 'name' } ] } }, { label => 'power-apparent', nlabel => 'pdu.interface.power_channel.power.apparent.voltampere', set => { key_values => [ { name => 'power_apparent', no_value => 0 }, { name => 'name' } ], output_template => 'apparent power: %.2f VA', perfdatas => [ { template => '%.2f', unit => 'VA', label_extra_instance => 1, instance_use => 'name' } ] } }, { label => 'power-factor', nlabel => 'pdu.interface.power_channel.power.factor.count', set => { key_values => [ { name => 'power_factor', no_value => 0 }, { name => 'name' } ], output_template => 'power factor: %.2f', perfdatas => [ { template => '%.2f', min => 0, unit => '', label_extra_instance => 1, instance_use => 'name' } ] } }, { label => 'power-reactive', nlabel => 'pdu.interface.power_channel.power.reactive.voltampere', set => { key_values => [ { name => 'power_reactive', no_value => 0 }, { name => 'name' } ], output_template => 'reactive power: %.2f Var', perfdatas => [ { template => '%.2f', unit => 'Var', label_extra_instance => 1, instance_use => 'name' } ] } }, { label => 'voltage', nlabel => 'pdu.interface.power_channel.voltage.volt', set => { key_values => [ { name => 'voltage', no_value => 0 }, { name => 'name' } ], output_template => 'voltage: %.2f V', perfdatas => [ { template => '%.2f', min => 0, unit => 'V', label_extra_instance => 1, instance_use => 'name' } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $branch = hardware::pdu::gude::epc::snmp::mode::resources::find_gude_branch($self, snmp => $options{snmp}); my $channel_status_mapping = { 0 => 'not active', 1 => 'valid' }; my $ovp_status_mapping = { 0 => 'failure', 1 => 'ok', 2 => 'unknown' }; my $ps_status_mapping = { 0 => 'down', 1 => 'up' }; my $mapping = { status => { oid => $branch .'.1.5.1.2.1.2', map => $channel_status_mapping }, abs_energy_active => { oid => $branch .'.1.5.1.2.1.3' }, power_active => { oid => $branch .'.1.5.1.2.1.4' }, current => { oid => $branch .'.1.5.1.2.1.5' }, voltage => { oid => $branch .'.1.5.1.2.1.6' }, frequency => { oid => $branch .'.1.5.1.2.1.7' }, power_factor => { oid => $branch .'.1.5.1.2.1.8' }, phase_angle => { oid => $branch .'.1.5.1.2.1.9' }, power_apparent => { oid => $branch .'.1.5.1.2.1.10' }, power_reactive => { oid => $branch .'.1.5.1.2.1.11' }, ovp_status => { oid => $branch .'.1.5.2.1.2', map => $ovp_status_mapping }, ps_status => { oid => $branch .'.1.5.13.1.2', map => $ps_status_mapping } }; my $oid_name = $branch . '.1.5.1.2.1.100'; my $snmp_result = $options{snmp}->get_table(oid => $oid_name, nothing_quit => 1); $self->{global} = { active_channels => 0 }; $self->{channels} = {}; foreach (keys %$snmp_result) { /^$oid_name\.(.*)$/; my $instance = $1; my $name = defined($snmp_result->{$_}) && $snmp_result->{$_} ne '' ? $snmp_result->{$_} : $instance; $self->{global}->{active_channels}++; next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $name !~ /$self->{option_results}->{filter_name}/); $self->{channels}->{$instance} = { name => $name }; } return if (scalar(keys %{$self->{channels}}) <= 0); $options{snmp}->load( oids => [ map($_->{oid}, values(%$mapping)) ], instances => [ map($_, keys %{$self->{channels}}) ], instance_regexp => '^(.*)$' ); $snmp_result = $options{snmp}->get_leef(); foreach (keys %{$self->{channels}}) { my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $_); $result->{current} *= 0.001 if (defined($result->{current})); $result->{power_factor} *= 0.001 if (defined($result->{power_factor})); $result->{frequency} *= 0.01 if (defined($result->{frequency})); $result->{abs_energy_active} *= 0.01 if (defined($result->{abs_energy_active})); $self->{channels}->{$_} = { %$result, %{$self->{channels}->{$_}} }; } } 1; __END__ =head1 MODE Check power channel interfaces. =over 8 =item B<--filter-name> Filter power channel interfaces by name (can be a regexp). =item B<--warning-status> Warning threshold for channel status. =item B<--critical-status> Critical threshold for channel status (Default: '%{status} !~ /valid/i') =item B<--warning-ovp-status> Warning threshold for OVP (OverVoltage Protection) status. =item B<--critical-ovp-status> Critical threshold for OVP (OverVoltage Protection) status (Default: '%{ovp_status} !~ /ok/i') =item B<--warning-ps-status> Warning threshold for power supply status. =item B<--critical-ps-status> Critical threshold for power supply status (Default: '%{ps_status} !~ /up/i') =item B<--warning-*> Threshold warning. Can be: 'active-channels', 'current', 'energy', 'frequency', 'phase-angle', 'power-active', 'power-apparent', 'power-factor', 'power-reactive', 'voltage' =item B<--critical-*> Can be: 'active-channels', 'current', 'energy', 'frequency', 'phase-angle', 'power-active', 'power-apparent', 'power-factor', 'power-reactive', 'voltage' =back =cut centreon-plugins-20220113/hardware/pdu/gude/epc/snmp/mode/resources.pm000066400000000000000000000040661417000230700255730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::gude::epc::snmp::mode::resources; use strict; use warnings; use Exporter; our @ISA = qw(Exporter); our @EXPORT_OK = qw(find_gude_version); my $regexp_gude_branch = { '1104' => '.1.3.6.1.4.1.28507.68', '1105' => '.1.3.6.1.4.1.28507.69', '1202' => '.1.3.6.1.4.1.28507.43', '8021' => '.1.3.6.1.4.1.28507.77', '8025' => '.1.3.6.1.4.1.28507.79', '8031' => '.1.3.6.1.4.1.28507.81', '8035' => '.1.3.6.1.4.1.28507.83', '8041' => '.1.3.6.1.4.1.28507.85', '8045' => '.1.3.6.1.4.1.28507.87', '8101' => '.1.3.6.1.4.1.28507.89', '8221' => '.1.3.6.1.4.1.28507.56', '8226' => '.1.3.6.1.4.1.28507.58', '8316' => '.1.3.6.1.4.1.28507.64' }; sub find_gude_branch { my ($self, %options) = @_; my $oid_sysDescr = '.1.3.6.1.2.1.1.1.0'; my $snmp_result = $options{snmp}->get_leef( oids => [ $oid_sysDescr ], nothing_quit => 1 ); my $branch; foreach my $re (keys %$regexp_gude_branch) { if ($snmp_result->{$oid_sysDescr} =~ /$re/) { $branch = $regexp_gude_branch->{$re}; last; } } if (!defined($branch)) { $self->{output}->add_option_msg(short_msg => 'unsupported device: ' . $snmp_result->{$oid_sysDescr}); $self->{output}->option_exit(); } return $branch; } 1; __END__ centreon-plugins-20220113/hardware/pdu/gude/epc/snmp/mode/sppowerchannels.pm000066400000000000000000000250231417000230700267700ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::gude::epc::snmp::mode::sppowerchannels; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use hardware::pdu::gude::epc::snmp::mode::resources; sub prefix_sp_output { my ($self, %options) = @_; return "Single port power channel interface '" . $options{instance} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0 }, { name => 'sp', type => 1, cb_prefix_output => 'prefix_sp_output', message_multiple => 'All single port power channel interfaces are ok', skipped_code => { -10 => 1 } } ]; $self->{maps_counters}->{global} = [ { label => 'total-singleports', nlabel => 'pdu.singleport_power_channels.total.count', set => { key_values => [ { name => 'total' } ], output_template => '%s single port(s)', perfdatas => [ { template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{sp} = [ { label => 'state', type => 2, set => { key_values => [ { name => 'state' }, { name => 'name' } ], output_template => 'state: %s', closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'status', type => 2, set => { key_values => [ { name => 'status' }, { name => 'name' } ], output_template => 'status: %s', closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'current', nlabel => 'pdu.interface.singleport_power_channel.current.ampere', set => { key_values => [ { name => 'current', no_value => 0 } ], output_template => 'current: %.2f A', perfdatas => [ { template => '%.2f', min => 0, unit => 'A', label_extra_instance => 1 } ] } }, { label => 'energy', nlabel => 'pdu.interface.singleport_power_channel.energy.active.kilowatthour', set => { key_values => [ { name => 'abs_energy_active', no_value => 0 } ], output_template => 'absolute energy active: %.2f kWh', perfdatas => [ { template => '%.2f', min => 0, unit => 'kWh', label_extra_instance => 1 } ] } }, { label => 'frequency', nlabel => 'pdu.interface.singleport_power_channel.frequency.hertz', set => { key_values => [ { name => 'frequency', no_value => 0 } ], output_template => 'frequency: %.2f Hz', perfdatas => [ { template => '%.2f', min => 0, unit => 'Hz', label_extra_instance => 1 } ] } }, { label => 'phase-angle', nlabel => 'pdu.interface.singleport_power_channel.phase.angle.degree', set => { key_values => [ { name => 'phase_angle', no_value => 0 } ], output_template => 'phase angle: %.2f°', perfdatas => [ { template => '%.2f', min => 0, label_extra_instance => 1 } ] } }, { label => 'power-active', nlabel => 'pdu.power_channel.active.watt', set => { key_values => [ { name => 'power_active', no_value => 0 } ], output_template => 'active power: %.2f W', perfdatas => [ { template => '%.2f', unit => 'W', label_extra_instance => 1 } ] } }, { label => 'power-apparent', nlabel => 'pdu.interface.singleport_power_channel.power.apparent.voltampere', set => { key_values => [ { name => 'power_apparent', no_value => 0 } ], output_template => 'apparent power: %.2f VA', perfdatas => [ { template => '%.2f', unit => 'VA', label_extra_instance => 1 } ] } }, { label => 'power-factor', nlabel => 'pdu.interface.singleport_power_channel.power.factor.count', set => { key_values => [ { name => 'power_factor', no_value => 0 } ], output_template => 'power factor: %.2f', perfdatas => [ { template => '%.2f', min => 0, unit => '', label_extra_instance => 1 } ] } }, { label => 'power-reactive', nlabel => 'pdu.interface.singleport_power_channel.power.reactive.voltampere', set => { key_values => [ { name => 'power_reactive', no_value => 0 } ], output_template => 'reactive power: %.2f Var', perfdatas => [ { template => '%.2f', unit => 'Var', label_extra_instance => 1 } ] } }, { label => 'voltage', nlabel => 'pdu.interface.singleport_power_channel.voltage.volt', set => { key_values => [ { name => 'voltage', no_value => 0 } ], output_template => 'voltage: %.2f V', perfdatas => [ { template => '%.2f', min => 0, unit => 'V', label_extra_instance => 1 } ] } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-name:s' => { name => 'filter_name' }, 'skip-poweredoff' => { name => 'skip_poweredoff' } }); return $self; } sub manage_selection { my ($self, %options) = @_; my $branch = hardware::pdu::gude::epc::snmp::mode::resources::find_gude_branch($self, snmp => $options{snmp}); my $sp_state_mapping = { 0 => 'off', 1 => 'on' }; my $sp_status_mapping = { 0 => 'not active', 1 => 'valid' }; my $mapping = { state => { oid => $branch .'.1.3.1.2.1.3', map => $sp_state_mapping }, status => { oid => $branch .'.1.5.5.2.1.2', map => $sp_status_mapping }, abs_energy_active => { oid => $branch .'.1.5.5.2.1.3' }, power_active => { oid => $branch .'.1.5.5.2.1.4' }, current => { oid => $branch .'.1.5.5.2.1.5' }, voltage => { oid => $branch .'.1.5.5.2.1.6' }, frequency => { oid => $branch .'.1.5.5.2.1.7' }, power_factor => { oid => $branch .'.1.5.5.2.1.8' }, phase_angle => { oid => $branch .'.1.5.5.2.1.9' }, power_apparent => { oid => $branch .'.1.5.5.2.1.10' }, power_reactive => { oid => $branch .'.1.5.5.2.1.11' } }; my $oid_name = $branch . '.1.3.1.2.1.2'; my $snmp_result = $options{snmp}->get_table(oid => $oid_name, nothing_quit => 1); $self->{global} = { total => 0 }; $self->{sp} = {}; my $duplicated = {}; foreach (keys %$snmp_result) { /^$oid_name\.(.*)$/; my $id = $1; my $name = $snmp_result->{$_}; $name = $snmp_result->{$_} . ':' . $id if (defined($duplicated->{$name})); if (defined($self->{sp}->{$name})) { $duplicated->{$name} = 1; my $instance = $self->{sp}->{$name}->{name} . ':' . $self->{sp}->{$name}->{instance}; $self->{sp}->{$instance} = delete $self->{sp}->{$name}; $name = $snmp_result->{$_} . ':' . $id; } next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $name !~ /$self->{option_results}->{filter_name}/); $self->{global}->{total}++; $self->{sp}->{$name} = { name => $name, instance => $id }; } return if (scalar(keys %{$self->{sp}}) <= 0); $options{snmp}->load( oids => [ map($_->{oid}, values(%$mapping)) ], instances => [ map($_->{instance}, values %{$self->{sp}}) ], instance_regexp => '^(.*)$' ); $snmp_result = $options{snmp}->get_leef(); foreach (keys %{$self->{sp}}) { my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $self->{sp}->{$_}->{instance}); if (defined($self->{option_results}->{skip_poweredoff}) && $result->{state} eq 'off') { $self->{global}->{total}--; delete $self->{sp}->{$_}; next; } $result->{current} *= 0.001 if (defined($result->{current})); $result->{power_factor} *= 0.001 if (defined($result->{power_factor})); $result->{frequency} *= 0.01 if (defined($result->{frequency})); $result->{abs_energy_active} *= 0.01 if (defined($result->{abs_energy_active})); $self->{sp}->{$_} = { %$result, %{$self->{sp}->{$_}} }; } } 1; __END__ =head1 MODE Check single port power channels. =over 8 =item B<--filter-name> Filter single port power channels by name (can be a regexp). =item B<--skip-poweredoff> Exclude the single ports that have been powered off. =item B<--warning-state> Warning threshold for single port state. =item B<--critical-state> Critical threshold for single port state. =item B<--warning-status> Warning threshold for for single port status. =item B<--critical-status> Critical threshold for for single port status. =item B<--warning-*> Threshold warning. Can be: 'active-channels', 'current', 'energy', 'frequency', 'phase-angle', 'power-active', 'power-apparent', 'power-factor', 'power-reactive', 'voltage' =item B<--critical-*> Can be: 'active-channels', 'current', 'energy', 'frequency', 'phase-angle', 'power-active', 'power-apparent', 'power-factor', 'power-reactive', 'voltage' =back =cut centreon-plugins-20220113/hardware/pdu/gude/epc/snmp/plugin.pm000066400000000000000000000027101417000230700241250ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::gude::epc::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}} = ( 'list-sp-power-channels' => 'hardware::pdu::gude::epc::snmp::mode::listsppowerchannels', 'power-channels' => 'hardware::pdu::gude::epc::snmp::mode::powerchannels', 'sp-power-channels' => 'hardware::pdu::gude::epc::snmp::mode::sppowerchannels' ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Gude Export Power Control (EPC) PDU in SNMP. =cut centreon-plugins-20220113/hardware/pdu/raritan/000077500000000000000000000000001417000230700212615ustar00rootroot00000000000000centreon-plugins-20220113/hardware/pdu/raritan/snmp/000077500000000000000000000000001417000230700222365ustar00rootroot00000000000000centreon-plugins-20220113/hardware/pdu/raritan/snmp/mode/000077500000000000000000000000001417000230700231625ustar00rootroot00000000000000centreon-plugins-20220113/hardware/pdu/raritan/snmp/mode/components/000077500000000000000000000000001417000230700253475ustar00rootroot00000000000000centreon-plugins-20220113/hardware/pdu/raritan/snmp/mode/components/resources.pm000066400000000000000000000224551417000230700277270ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::raritan::snmp::mode::components::resources; use strict; use warnings; use Exporter; our $thresholds; our $mapping; our %raritan_type; our %map_type; our @ISA = qw(Exporter); our @EXPORT_OK = qw($thresholds $mapping %raritan_type %map_type); my %map_units = ( -1 => { unit => '' }, # none 0 => { unit => 'other', nunit => 'count' }, 1 => { unit => 'V', nunit => 'volt' }, # volt, 2 => { unit => 'A', nunit => 'ampere' }, # amp, 3 => { unit => 'W', nunit => 'watt' }, # watt 4 => { unit => 'voltamp' }, 5 => { unit => 'wattHour' }, 6 => { unit => 'voltampHour' }, 7 => { unit => 'C', nunit => 'celsius' }, # degreeC 8 => { unit => 'Hz', nunit => 'hertz' }, # hertz 9 => { unit => '%', nunit => 'percentage' }, # percent 10 => { unit => 'meterpersec' }, 11 => { unit => 'pascal' }, 12 => { unit => 'psi' }, 13 => { unit => 'g' }, 14 => { unit => 'degreeF', nunit => 'fahrenheit' }, 15 => { unit => 'feet' }, 16 => { unit => 'inches' }, 17 => { unit => 'cm' }, 18 => { unit => 'meters' }, 19 => { unit => 'rpm' }, 20 => { unit => 'degrees' }, 21 => { unit => 'lux' }, ); my %map_state = ( -1 => 'unavailable', 0 => 'open', 1 => 'closed', 2 => 'belowLowerCritical', 3 => 'belowLowerWarning', 4 => 'normal', 5 => 'aboveUpperWarning', 6 => 'aboveUpperCritical', 7 => 'on', 8 => 'off', 9 => 'detected', 10 => 'notDetected', 11 => 'alarmed', 12 => 'ok', 14 => 'fail', 15 => 'yes', 16 => 'no', 17 => 'standby', 18 => 'one', 19 => 'two', 20 => 'inSync', 21 => 'outOfSync', 22 => 'i1OpenFault', 23 => 'i1ShortFault', 24 => 'i2OpenFault', 25 => 'i2ShortFault', 26 => 'fault', 27 => 'warning', 28 => 'critical', 29 => 'selfTest', ); $mapping = { inlet_label => { Label => { oid => '.1.3.6.1.4.1.13742.6.3.3.3.1.2' }, # inletLabel }, inlet => { Unit => { oid => '.1.3.6.1.4.1.13742.6.3.3.4.1.6', map => \%map_units }, # inletSensorUnits Decimal => { oid => '.1.3.6.1.4.1.13742.6.3.3.4.1.7' }, # inletSensorDecimalDigits EnabledThresholds => { oid => '.1.3.6.1.4.1.13742.6.3.3.4.1.25' }, # inletSensorEnabledThresholds LowerCriticalThreshold => { oid => '.1.3.6.1.4.1.13742.6.3.3.4.1.21' }, # inletSensorLowerCriticalThreshold LowerWarningThreshold => { oid => '.1.3.6.1.4.1.13742.6.3.3.4.1.22' }, # inletSensorLowerWarningThreshold UpperCriticalThreshold => { oid => '.1.3.6.1.4.1.13742.6.3.3.4.1.23' }, # inletSensorUpperCriticalThreshold UpperWarningThreshold => { oid => '.1.3.6.1.4.1.13742.6.3.3.4.1.24' }, # inletSensorUpperWarningThreshold State => { oid => '.1.3.6.1.4.1.13742.6.5.2.3.1.3', map => \%map_state }, # measurementsInletSensorState Value => { oid => '.1.3.6.1.4.1.13742.6.5.2.3.1.4' }, # measurementsInletSensorValue }, outlet_label => { Label => { oid => '.1.3.6.1.4.1.13742.6.3.5.3.1.2' }, # outletLabel }, outlet => { Unit => { oid => '.1.3.6.1.4.1.13742.6.3.5.4.1.6', map => \%map_units }, # outletSensorUnits Decimal => { oid => '.1.3.6.1.4.1.13742.6.3.5.4.1.7' }, # outletSensorDecimalDigits EnabledThresholds => { oid => '.1.3.6.1.4.1.13742.6.3.5.4.1.25' }, # outletSensorEnabledThresholds LowerCriticalThreshold => { oid => '.1.3.6.1.4.1.13742.6.3.5.4.1.21' }, # outletSensorLowerCriticalThreshold LowerWarningThreshold => { oid => '.1.3.6.1.4.1.13742.6.3.5.4.1.22' }, # outletSensorLowerWarningThreshold UpperCriticalThreshold => { oid => '.1.3.6.1.4.1.13742.6.3.5.4.1.23' }, # outletSensorUpperCriticalThreshold UpperWarningThreshold => { oid => '.1.3.6.1.4.1.13742.6.3.5.4.1.24' }, # outletSensorUpperWarningThreshold State => { oid => '.1.3.6.1.4.1.13742.6.5.4.3.1.3', map => \%map_state }, # measurementsOutletSensorState Value => { oid => '.1.3.6.1.4.1.13742.6.5.4.3.1.4' }, # measurementsOutletSensorValue }, ocprot_label => { Label => { oid => '.1.3.6.1.4.1.13742.6.3.4.3.1.2' }, # overCurrentProtectorLabel }, ocprot => { Unit => { oid => '.1.3.6.1.4.1.13742.6.3.4.4.1.6', map => \%map_units }, # overCurrentProtectorSensorUnits Decimal => { oid => '.1.3.6.1.4.1.13742.6.3.4.4.1.7' }, # overCurrentProtectorSensorDecimalDigits EnabledThresholds => { oid => '.1.3.6.1.4.1.13742.6.3.4.4.1.25' }, # overCurrentProtectorSensorEnabledThresholds LowerCriticalThreshold => { oid => '.1.3.6.1.4.1.13742.6.3.4.4.1.21' }, # overCurrentProtectorSensorLowerCriticalThreshold LowerWarningThreshold => { oid => '.1.3.6.1.4.1.13742.6.3.4.4.1.22' }, # overCurrentProtectorSensorLowerWarningThreshold UpperCriticalThreshold => { oid => '.1.3.6.1.4.1.13742.6.3.4.4.1.23' }, # overCurrentProtectorSensorUpperCriticalThreshold UpperWarningThreshold => { oid => '.1.3.6.1.4.1.13742.6.3.4.4.1.24' }, # overCurrentProtectorSensorUpperWarningThreshold State => { oid => '.1.3.6.1.4.1.13742.6.5.3.3.1.3', map => \%map_state }, # measurementsOverCurrentProtectorSensorState Value => { oid => '.1.3.6.1.4.1.13742.6.5.3.3.1.4' }, # measurementsOverCurrentProtectorSensorValue }, }; %raritan_type = ( rmsCurrent => 1, peakCurrent => 2, unbalancedCurrent => 3, rmsVoltage => 4, activePower => 5, apparentPower => 6, powerFactor => 7, activeEnergy => 8, apparentEnergy => 9, temperature => 10, humidity => 11, airFlow => 12, airPressure => 13, onOff => 14, trip => 15, vibration => 16, waterDetection => 17, smokeDetection => 18, binary => 19, contact => 20, fanSpeed => 21, surgeProtectorStatus => 22, frequency => 23, phaseAngle => 24, rmsVoltageLN => 25, residualCurrent => 26, rcmState => 27, other => 30, none => 31, powerQuality => 32, overloadStatus => 33, overheatStatus => 34, fanStatus => 37, inletPhaseSyncAngle => 38, inletPhaseSync => 39, operatingState => 40, activeInlet => 41, illuminance => 42, doorContact => 43, tamperDetection => 44, motionDetection => 45, i1smpsStatus => 46, i2smpsStatus => 47, switchStatus => 48, ); %map_type = ( 1 => 'numeric', 2 => 'numeric', 3 => 'numeric', 4 => 'numeric', 5 => 'numeric', 6 => 'numeric', 7 => 'numeric', 8 => 'numeric', 9 => 'numeric', 10 => 'numeric', 11 => 'numeric', 12 => 'numeric', 13 => 'numeric', 14 => 'onoff', 15 => 'contact', 16 => 'alarm', 17 => 'alarm', 18 => 'alarm', 19 => 'alarm', 20 => 'alarm', 21 => 'numeric', 22 => 'fault', 23 => 'numeric', 24 => 'numeric', 25 => 'numeric', 26 => 'numeric', 27 => 'alarm', 30 => 'numeric', 31 => 'numeric', 32 => 'powerQuality', 33 => 'fault', 34 => 'fault', 37 => 'fault', 38 => 'numeric', 39 => 'inletPhaseSync', 40 => 'operatingState', 41 => 'activeInlet', 42 => 'numeric', 43 => 'contact', 44 => 'alarm', 45 => 'motionDetection', 46 => 'fault', 47 => 'fault', 48 => 'switchStatus', ); $thresholds = { numeric => [ ['unavailable', 'UNKNOWN'], ['normal', 'OK'], ['belowLowerCritical', 'CRITICAL'], ['belowLowerWarning', 'WARNING'], ['aboveUpperWarning', 'WARNING'], ['aboveUpperCritical', 'CRITICAL'], ], onoff => [ ['unavailable', 'UNKNOWN'], ['on', 'OK'], ['off', 'OK'], ], contact => [ ['unavailable', 'UNKNOWN'], ['open', 'OK'], ['closed', 'OK'], ], alarm => [ ['unavailable', 'UNKNOWN'], ['normal', 'OK'], ['alarmed', 'CRITICAL'], ['selfTest', 'OK'], ['fail', 'CRITICAL'], ], fault => [ ['unavailable', 'UNKNOWN'], ['ok', 'OK'], ['fault', 'CRITICAL'], ], powerQuality => [ ['unavailable', 'UNKNOWN'], ['normal', 'OK'], ['warning', 'WARNING'], ['critical', 'CRITICAL'], ], inletPhaseSync => [ ['unavailable', 'UNKNOWN'], ['inSync', 'OK'], ['outOfSync', 'CRITICAL'], ], operatingState => [ ['unavailable', 'UNKNOWN'], ['normal', 'OK'], ['standby', 'OK'], ['off', 'CRITICAL'], ], activeInlet => [ ['unavailable', 'UNKNOWN'], ['one', 'OK'], ['two', 'OK'], ['none', 'WARNING'], ], motionDetection => [ ['unavailable', 'UNKNOWN'], ], switchStatus => [ ['unavailable', 'UNKNOWN'], ['ok', 'OK'], ['i1OpenFault', 'WARNING'], ['i1ShortFault', 'WARNING'], ['i2OpenFault', 'WARNING'], ['i2ShortFault', 'WARNING'], ], }; 1; centreon-plugins-20220113/hardware/pdu/raritan/snmp/mode/components/sensor.pm000066400000000000000000000165371417000230700272320ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::raritan::snmp::mode::components::sensor; use strict; use warnings; use hardware::pdu::raritan::snmp::mode::components::resources qw($mapping %raritan_type %map_type); sub load { my ($self, %options) = @_; push @{$self->{request}}, { oid => $mapping->{$options{type} . '_label'}->{Label}->{oid} }, { oid => $mapping->{$options{type}}->{Unit}->{oid} }, { oid => $mapping->{$options{type}}->{Decimal}->{oid} }, { oid => $mapping->{$options{type}}->{EnabledThresholds}->{oid} }, { oid => $mapping->{$options{type}}->{LowerCriticalThreshold}->{oid} }, { oid => $mapping->{$options{type}}->{LowerWarningThreshold}->{oid} }, { oid => $mapping->{$options{type}}->{UpperCriticalThreshold}->{oid} }, { oid => $mapping->{$options{type}}->{UpperWarningThreshold}->{oid} }, { oid => $mapping->{$options{type}}->{State}->{oid} }, { oid => $mapping->{$options{type}}->{Value}->{oid} }; } sub check { my ($self, %options) = @_; foreach my $component (sort keys %raritan_type) { my $long_msg = 0; next if ($component !~ /$options{component}/); $self->{components}->{$component} = {name => $component, total => 0, skip => 0}; next if ($self->check_filter(section => $component)); my $instance_type = $raritan_type{$component}; my $value_type = $map_type{$instance_type}; foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}})) { next if ($oid !~ /^$mapping->{$options{type}}->{State}->{oid}\.(\d+)\.(\d+)\.$instance_type$/); my $instance = $1 . '.' . $2 . '.' . $instance_type; my $result = $self->{snmp}->map_instance(mapping => $mapping->{$options{type}}, results => $self->{results}, instance => $instance); my $result2 = $self->{snmp}->map_instance(mapping => $mapping->{$options{type} . '_label'}, results => $self->{results}, instance => $1 . '.' . $2); $instance = defined($result2->{Label}) && $result2->{Label} ne '' ? $result2->{Label} : $1 . '.' . $2; next if ($self->check_filter(section => $component, instance => $instance)); if ($long_msg == 0) { $self->{output}->output_add(long_msg => "Checking " . $component); $long_msg = 1; } $self->{components}->{$component}->{total}++; my $value = (defined($result->{Value}) && $result->{Value} ne '') ? $result->{Value} : '-'; if ($value =~ /[0-9]/) { $value *= 10 ** -int($result->{Decimal}); } $self->{output}->output_add( long_msg => sprintf( "'%s' %s state is '%s' [instance: %s, value: %s, unit: %s, label: %s]", $instance, $component, $result->{State}, $instance, $value, $result->{Unit}->{unit}, $result2->{Label} ) ); my $exit = $self->get_severity( section => $component, label => $value_type, instance => $instance, value => $result->{State} ); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "'%s' %s state is '%s'", $instance, $component, $result->{State} ) ); } if ($value =~ /[0-9]/) { next if ($value =~ /^0$/ && $result->{Unit}->{unit} eq ''); my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => $component, instance => $instance, value => $value); if ($checked == 0) { $result->{EnabledThresholds} = oct("0b". unpack('b*', $result->{EnabledThresholds})); my $warn_th; $warn_th = ($result->{LowerWarningThreshold} * 10 ** -int($result->{Decimal})) . ':' if (($result->{EnabledThresholds} & (1 << 1))); if (($result->{EnabledThresholds} & (1 << 2))) { if (defined($warn_th)) { $warn_th .= ($result->{UpperWarningThreshold} * 10 ** -int($result->{Decimal})); } else { $warn_th = '~:' . ($result->{UpperWarningThreshold} * 10 ** -int($result->{Decimal})); } } my $crit_th; $crit_th = ($result->{LowerCriticalThreshold} * 10 ** -int($result->{Decimal})) . ':' if (($result->{EnabledThresholds} & (1 << 0))); if (($result->{EnabledThresholds} & (1 << 3))) { if (defined($crit_th)) { $crit_th .= ($result->{UpperCriticalThreshold} * 10 ** -int($result->{Decimal})); } else { $crit_th = '~:' . ($result->{UpperCriticalThreshold} * 10 ** -int($result->{Decimal})); } } $self->{perfdata}->threshold_validate(label => 'warning-' . $component . '-instance-' . $instance, value => $warn_th); $self->{perfdata}->threshold_validate(label => 'critical-' . $component . '-instance-' . $instance, value => $crit_th); $warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $component . '-instance-' . $instance); $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $component . '-instance-' . $instance); } if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit2, short_msg => sprintf( "'%s' %s value is %s %s", $instance, $component, $value, $result->{Unit}->{unit} ) ); } my $nunit = (defined($result->{Unit}->{nunit}) ? $result->{Unit}->{nunit} : lc($result->{Unit}->{unit})); $self->{output}->perfdata_add( label => $component, unit => $result->{Unit}->{unit}, nlabel => 'hardware.sensor.' . $options{type} . '.' . lc($component) . '.' . $nunit, instances => $instance, value => $value, warning => $warn, critical => $crit ); } } } } 1; centreon-plugins-20220113/hardware/pdu/raritan/snmp/mode/inletsensors.pm000066400000000000000000000071751417000230700262620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::raritan::snmp::mode::inletsensors; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; use hardware::pdu::raritan::snmp::mode::components::resources qw($thresholds %raritan_type); sub set_system { my ($self, %options) = @_; $self->{cb_threshold_numeric_check_section_option} = 'check_numeric_section_option'; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = $thresholds; $self->{components_path} = 'hardware::pdu::raritan::snmp::mode::components'; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}, return_type => 1); } sub check_numeric_section_option { my ($self, %options) = @_; if (!defined($raritan_type{$options{section}})) { $self->{output}->add_option_msg(short_msg => "Wrong $options{option_name} option '" . $options{option_value} . "'."); $self->{output}->option_exit(); } } sub load_components { my ($self, %options) = @_; my $mod_name = $self->{components_path} . "::sensor"; 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->($self, type => 'inlet'); $self->{loaded} = 1; } sub exec_components { my ($self, %options) = @_; my $mod_name = $self->{components_path} . "::sensor"; my $func = $mod_name->can('check'); $func->($self, component => $self->{option_results}->{component}, type => 'inlet'); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_absent => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } 1; __END__ =head1 MODE Check inlet sensors. =over 8 =item B<--component> Which component to check (Default: '.*'). =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=airPressure --filter=rmsVoltage) Can also exclude specific instance: --filter=rmsVoltage,I1 =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='powerQuality,CRITICAL,^(?!(normal)$)' =item B<--warning> Set warning threshold for temperatures (syntax: type,instance,threshold) Example: --warning='powerQuality,.*,30' =item B<--critical> Set critical threshold for temperatures (syntax: type,instance,threshold) Example: --critical='powerQuality,.*,40' =back =cutcentreon-plugins-20220113/hardware/pdu/raritan/snmp/mode/ocprotsensors.pm000066400000000000000000000071261417000230700264510ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::raritan::snmp::mode::ocprotsensors; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; use hardware::pdu::raritan::snmp::mode::components::resources qw($thresholds %raritan_type); sub set_system { my ($self, %options) = @_; $self->{cb_threshold_numeric_check_section_option} = 'check_numeric_section_option'; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = $thresholds; $self->{components_path} = 'hardware::pdu::raritan::snmp::mode::components'; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}, return_type => 1); } sub check_numeric_section_option { my ($self, %options) = @_; if (!defined($raritan_type{$options{section}})) { $self->{output}->add_option_msg(short_msg => "Wrong $options{option_name} option '" . $options{option_value} . "'."); $self->{output}->option_exit(); } } sub load_components { my ($self, %options) = @_; my $mod_name = $self->{components_path} . "::sensor"; 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->($self, type => 'ocprot'); $self->{loaded} = 1; } sub exec_components { my ($self, %options) = @_; my $mod_name = $self->{components_path} . "::sensor"; my $func = $mod_name->can('check'); $func->($self, component => $self->{option_results}->{component}, type => 'ocprot'); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_absent => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } 1; __END__ =head1 MODE Check overcurrent protectors sensors. =over 8 =item B<--component> Which component to check (Default: '.*'). =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=airPressure --filter=rmsVoltage) Can also exclude specific instance: --filter=rmsVoltage,C1 =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='powerQuality,CRITICAL,^(?!(normal)$)' =item B<--warning> Set warning threshold for temperatures (syntax: type,instance,threshold) Example: --warning='powerQuality,.*,30' =item B<--critical> Set critical threshold for temperatures (syntax: type,instance,threshold) Example: --critical='powerQuality,.*,40' =back =cut centreon-plugins-20220113/hardware/pdu/raritan/snmp/mode/outletsensors.pm000066400000000000000000000070661417000230700264620ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::raritan::snmp::mode::outletsensors; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; use hardware::pdu::raritan::snmp::mode::components::resources qw($thresholds %raritan_type); sub set_system { my ($self, %options) = @_; $self->{cb_threshold_numeric_check_section_option} = 'check_numeric_section_option'; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = $thresholds; $self->{components_path} = 'hardware::pdu::raritan::snmp::mode::components'; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}, return_type => 1); } sub check_numeric_section_option { my ($self, %options) = @_; if (!defined($raritan_type{$options{section}})) { $self->{output}->add_option_msg(short_msg => "Wrong $options{option_name} option '" . $options{option_value} . "'."); $self->{output}->option_exit(); } } sub load_components { my ($self, %options) = @_; my $mod_name = $self->{components_path} . "::sensor"; 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->($self, type => 'outlet'); $self->{loaded} = 1; } sub exec_components { my ($self, %options) = @_; my $mod_name = $self->{components_path} . "::sensor"; my $func = $mod_name->can('check'); $func->($self, component => $self->{option_results}->{component}, type => 'outlet'); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } 1; __END__ =head1 MODE Check outlet sensors. =over 8 =item B<--component> Which component to check (Default: '.*'). =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=airPressure --filter=rmsVoltage) Can also exclude specific instance: --filter=rmsVoltage,I1 =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='powerQuality,CRITICAL,^(?!(normal)$)' =item B<--warning> Set warning threshold for temperatures (syntax: type,instance,threshold) Example: --warning='powerQuality,.*,30' =item B<--critical> Set critical threshold for temperatures (syntax: type,instance,threshold) Example: --critical='powerQuality,.*,40' =back =cut centreon-plugins-20220113/hardware/pdu/raritan/snmp/plugin.pm000066400000000000000000000026161417000230700240770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::raritan::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}} = ( 'inlet-sensors' => 'hardware::pdu::raritan::snmp::mode::inletsensors', 'outlet-sensors' => 'hardware::pdu::raritan::snmp::mode::outletsensors', 'ocprot-sensors' => 'hardware::pdu::raritan::snmp::mode::ocprotsensors', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Raritan PDU in SNMP. =cut centreon-plugins-20220113/hardware/pdu/schleifenbauer/000077500000000000000000000000001417000230700226005ustar00rootroot00000000000000centreon-plugins-20220113/hardware/pdu/schleifenbauer/gateway/000077500000000000000000000000001417000230700242415ustar00rootroot00000000000000centreon-plugins-20220113/hardware/pdu/schleifenbauer/gateway/snmp/000077500000000000000000000000001417000230700252165ustar00rootroot00000000000000centreon-plugins-20220113/hardware/pdu/schleifenbauer/gateway/snmp/mode/000077500000000000000000000000001417000230700261425ustar00rootroot00000000000000centreon-plugins-20220113/hardware/pdu/schleifenbauer/gateway/snmp/mode/components/000077500000000000000000000000001417000230700303275ustar00rootroot00000000000000centreon-plugins-20220113/hardware/pdu/schleifenbauer/gateway/snmp/mode/components/contact.pm000066400000000000000000000066171417000230700323320ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::schleifenbauer::gateway::snmp::mode::components::contact; use strict; use warnings; use hardware::pdu::schleifenbauer::gateway::snmp::mode::components::resources qw($oid_pdumeasuresEntry $oid_deviceName $mapping); sub load {} sub check_contact { my ($self, %options) = @_; my $description = $options{device_name}; $description .= '.' . ((defined($options{sensor_name}) && $options{sensor_name} ne '') ? $options{sensor_name} : $options{num}); next if ($self->check_filter(section => 'contact', instance => $options{instance}, name => $description)); $self->{components}->{contact}->{total}++; $self->{output}->output_add(long_msg => sprintf("contact '%s' is %s [instance = %s]", $description, $options{value}, $options{instance})); my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'contact', instance => $options{instance}, name => $description, value => $options{value}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Contact '%s' is %s %%", $description, $options{value})); } $self->{output}->perfdata_add( label => 'contact', nlabel => 'hardware.sensor.contact.count', instances => [$options{device_name}, (defined($options{sensor_name}) && $options{sensor_name} ne '') ? $options{sensor_name} : $options{num}], value => $options{value}, warning => $warn, critical => $crit, min => 0, max => 100 ); } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking contact"); $self->{components}->{contact} = { name => 'contact', total => 0, skip => 0 }; return if ($self->check_filter(section => 'contact')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_deviceName}})) { $oid =~ /^$oid_deviceName.(.*)$/; my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_pdumeasuresEntry}, instance => $instance); for (my $i = 1; $i <= 16; $i++) { next if (!defined($result->{'sensor' . $i . 'Type'}) || $result->{'sensor' . $i . 'Type'} !~ /I/); check_contact($self, instance => $instance, device_name => $self->{results}->{$oid_deviceName}->{$oid}, num => $i, value => $result->{'sensor' . $i . 'Value'}, sensor_name => $result->{'sensor' . $i . 'Name'}, ); } } } 1; centreon-plugins-20220113/hardware/pdu/schleifenbauer/gateway/snmp/mode/components/humidity.pm000066400000000000000000000066611417000230700325320ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::schleifenbauer::gateway::snmp::mode::components::humidity; use strict; use warnings; use hardware::pdu::schleifenbauer::gateway::snmp::mode::components::resources qw($oid_pdumeasuresEntry $oid_deviceName $mapping); sub load {} sub check_humidity { my ($self, %options) = @_; my $description = $options{device_name}; $description .= '.' . ((defined($options{sensor_name}) && $options{sensor_name} ne '') ? $options{sensor_name} : $options{num}); next if ($self->check_filter(section => 'humidity', instance => $options{instance}, name => $description)); $self->{components}->{humidity}->{total}++; $self->{output}->output_add(long_msg => sprintf("humidity '%s' is %s %% [instance = %s]", $description, $options{value}, $options{instance})); my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'humidity', instance => $options{instance}, name => $description, value => $options{value}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Humdity '%s' is %s %%", $description, $options{value})); } $self->{output}->perfdata_add( label => 'humidity', unit => '%', nlabel => 'hardware.sensor.humidity.percentage', instances => [$options{device_name}, (defined($options{sensor_name}) && $options{sensor_name} ne '') ? $options{sensor_name} : $options{num}], value => $options{value}, warning => $warn, critical => $crit, min => 0, max => 100 ); } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking humidity"); $self->{components}->{humidity} = { name => 'humidity', total => 0, skip => 0 }; return if ($self->check_filter(section => 'humidity')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_deviceName}})) { $oid =~ /^$oid_deviceName.(.*)$/; my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_pdumeasuresEntry}, instance => $instance); for (my $i = 1; $i <= 16; $i++) { next if (!defined($result->{'sensor' . $i . 'Type'}) || $result->{'sensor' . $i . 'Type'} !~ /H/); check_humidity($self, instance => $instance, device_name => $self->{results}->{$oid_deviceName}->{$oid}, num => $i, value => $result->{'sensor' . $i . 'Value'}, sensor_name => $result->{'sensor' . $i . 'Name'}, ); } } } 1; centreon-plugins-20220113/hardware/pdu/schleifenbauer/gateway/snmp/mode/components/resources.pm000066400000000000000000000111511417000230700326760ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::schleifenbauer::gateway::snmp::mode::components::resources; use strict; use warnings; use Exporter; our $oid_pdumeasuresEntry; our $oid_deviceName; our $mapping; our @ISA = qw(Exporter); our @EXPORT_OK = qw($oid_pdumeasuresEntry $oid_deviceName $mapping); $oid_pdumeasuresEntry = '.1.3.6.1.4.1.31034.1.1.8.1'; $oid_deviceName = '.1.3.6.1.4.1.31034.1.1.4.1.3'; $mapping = { pduIntTemperature => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.3' }, pduExtTemperature => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.4' }, sensor1Type => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.7' }, sensor1Value => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.8' }, sensor1Name => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.9' }, sensor2Type => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.10' }, sensor2Value => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.11' }, sensor2Name => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.12' }, sensor3Type => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.13' }, sensor3Value => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.14' }, sensor3Name => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.15' }, sensor4Type => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.16' }, sensor4Value => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.17' }, sensor4Name => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.18' }, sensor5Type => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.19' }, sensor5Value => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.20' }, sensor5Name => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.21' }, sensor6Type => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.22' }, sensor6Value => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.23' }, sensor6Name => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.24' }, sensor7Type => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.25' }, sensor7Value => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.26' }, sensor7Name => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.27' }, sensor8Type => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.28' }, sensor8Value => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.29' }, sensor8Name => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.30' }, sensor9Type => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.31' }, sensor9Value => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.32' }, sensor9Name => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.33' }, sensor10Type => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.34' }, sensor10Value => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.35' }, sensor10Name => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.36' }, sensor11Type => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.37' }, sensor11Value => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.38' }, sensor11Name => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.39' }, sensor12Type => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.40' }, sensor12Value => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.41' }, sensor12Name => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.42' }, sensor13Type => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.43' }, sensor13Value => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.44' }, sensor13Name => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.45' }, sensor14Type => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.46' }, sensor14Value => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.47' }, sensor14Name => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.48' }, sensor15Type => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.49' }, sensor15Value => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.50' }, sensor15Name => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.51' }, sensor16Type => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.52' }, sensor16Value => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.53' }, sensor16Name => { oid => '.1.3.6.1.4.1.31034.1.1.8.1.54' }, }; 1; centreon-plugins-20220113/hardware/pdu/schleifenbauer/gateway/snmp/mode/components/temperature.pm000066400000000000000000000100311417000230700332150ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::schleifenbauer::gateway::snmp::mode::components::temperature; use strict; use warnings; use hardware::pdu::schleifenbauer::gateway::snmp::mode::components::resources qw($oid_pdumeasuresEntry $oid_deviceName $mapping); sub load {} sub check_temperature { my ($self, %options) = @_; my $description = $options{device_name}; $description .= '.' . ((defined($options{sensor_name}) && $options{sensor_name} ne '') ? $options{sensor_name} : $options{num}); next if ($self->check_filter(section => 'temperature', instance => $options{instance}, name => $description)); $self->{components}->{temperature}->{total}++; $self->{output}->output_add(long_msg => sprintf("temperature '%s' is %s C [instance = %s]", $description, $options{value}, $options{instance})); my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $options{instance}, name => $description, value => $options{value}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Temperature '%s' is %s C", $description, $options{value})); } $self->{output}->perfdata_add( label => 'temperature', unit => 'C', nlabel => 'hardware.sensor.temperature.celsius', instances => [$options{device_name}, (defined($options{sensor_name}) && $options{sensor_name} ne '') ? $options{sensor_name} : $options{num}], value => $options{value}, warning => $warn, critical => $crit, ); } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking temperature"); $self->{components}->{temperature} = { name => 'temperature', total => 0, skip => 0 }; return if ($self->check_filter(section => 'temperature')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_deviceName}})) { $oid =~ /^$oid_deviceName.(.*)$/; my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_pdumeasuresEntry}, instance => $instance); for (my $i = 1; $i <= 16; $i++) { next if (!defined($result->{'sensor' . $i . 'Type'}) || $result->{'sensor' . $i . 'Type'} !~ /T/); check_temperature($self, instance => $instance, device_name => $self->{results}->{$oid_deviceName}->{$oid}, num => $i, value => $result->{'sensor' . $i . 'Value'}, sensor_name => $result->{'sensor' . $i . 'Name'}, ); } check_temperature($self, instance => $instance, device_name => $self->{results}->{$oid_deviceName}->{$oid}, num => 0, value => $result->{pduIntTemperature}, sensor_name => 'Internal', ) if ($result->{pduIntTemperature} != 0); check_temperature($self, instance => $instance, device_name => $self->{results}->{$oid_deviceName}->{$oid}, num => 0, value => $result->{pduExtTemperature}, sensor_name => 'External', ) if ($result->{pduExtTemperature} != 0); } } 1; centreon-plugins-20220113/hardware/pdu/schleifenbauer/gateway/snmp/mode/sensors.pm000066400000000000000000000051721417000230700302010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::schleifenbauer::gateway::snmp::mode::sensors; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; use hardware::pdu::schleifenbauer::gateway::snmp::mode::components::resources qw($oid_pdumeasuresEntry $oid_deviceName); sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^(temperature|humidity|contact)$'; $self->{cb_hook2} = 'snmp_execute'; $self->{components_path} = 'hardware::pdu::schleifenbauer::gateway::snmp::mode::components'; $self->{components_module} = ['humidity', 'temperature', 'contact']; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{results} = $self->{snmp}->get_multiple_table(oids => [ { oid => $oid_deviceName }, { oid => $oid_pdumeasuresEntry } ]); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_absent => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } 1; __END__ =head1 MODE Check sensors. =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'temperature', 'humidity', 'contact'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=temperature --filter=contact) Can also exclude specific instance: --filter=temperature,1 =item B<--no-component> Return an error if no compenents are checked. If total (with skipped) is 0. (Default: 'critical' returns). =item B<--warning> Set warning threshold for 'temperature', 'humidity', 'contact' (syntax: type,regexp,threshold) Example: --warning='temperature,.*,30' =item B<--critical> Set critical threshold for 'temperature', 'humidity', 'contact' (syntax: type,regexp,threshold) Example: --warning='temperature,.*,50' =back =cut centreon-plugins-20220113/hardware/pdu/schleifenbauer/gateway/snmp/plugin.pm000066400000000000000000000024061417000230700270540ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::pdu::schleifenbauer::gateway::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}} = ( 'sensors' => 'hardware::pdu::schleifenbauer::gateway::snmp::mode::sensors', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Schleifenbauwer gateway in SNMP. =cut centreon-plugins-20220113/hardware/printers/000077500000000000000000000000001417000230700206775ustar00rootroot00000000000000centreon-plugins-20220113/hardware/printers/standard/000077500000000000000000000000001417000230700224775ustar00rootroot00000000000000centreon-plugins-20220113/hardware/printers/standard/rfc3805/000077500000000000000000000000001417000230700235715ustar00rootroot00000000000000centreon-plugins-20220113/hardware/printers/standard/rfc3805/mode/000077500000000000000000000000001417000230700245155ustar00rootroot00000000000000centreon-plugins-20220113/hardware/printers/standard/rfc3805/mode/coverstatus.pm000066400000000000000000000072331417000230700274420ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::printers::standard::rfc3805::mode::coverstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub prefix_cover_output { my ($self, %options) = @_; return "Cover '" . $options{instance_value}->{description} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'covers', type => 1, cb_prefix_output => 'prefix_cover_output', message_multiple => 'All covers are ok' } ]; $self->{maps_counters}->{covers} = [ { label => 'status', type => 2, unknown_default => '%{status} =~ /other|unknown/', warning_default => '%{status} =~ /coverOpen|interlockOpen/', set => { key_values => [ { name => 'status' }, { name => 'description' } ], output_template => "status is '%s'", closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my $map_status = { 1 => 'other', 2 => 'unknown', 3 => 'coverOpen', 4 => 'coverClosed', 5 => 'interlockOpen', 6 => 'interlockClosed' }; my $mapping = { description => { oid => '.1.3.6.1.2.1.43.6.1.1.2' }, # prtCoverDescription status => { oid => '.1.3.6.1.2.1.43.6.1.1.3', map => $map_status } # prtCoverStatus }; sub manage_selection { my ($self, %options) = @_; my $oid_prtCoverTable = '.1.3.6.1.2.1.43.6.1'; my $snmp_result = $options{snmp}->get_table( oid => $oid_prtCoverTable, start => $mapping->{description}->{oid}, nothing_quit => 1 ); $self->{covers} = {}; foreach my $oid (keys %$snmp_result) { next if ($oid !~ /^$mapping->{status}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); $result->{description} = centreon::plugins::misc::trim($result->{description}); $self->{covers}->{$instance} = $result; } } 1; __END__ =head1 MODE Check covers of the printer. =over 8 =item B<--unknown-status> Set unknown threshold for status (Default: '%%{status} =~ /other|unknown/'). Can used special variables like: %{status}, %{description} =item B<--warning-status> Set warning threshold for status (Default: '%%{status} =~ /coverOpen|interlockOpen/'). Can used special variables like: %{status}, %{description} =item B<--critical-status> Set critical threshold for status. Can used special variables like: %{status}, %{description} =back =cut centreon-plugins-20220113/hardware/printers/standard/rfc3805/mode/markerimpression.pm000066400000000000000000000137141417000230700304530ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::printers::standard::rfc3805::mode::markerimpression; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::statefile; my %unit_managed = ( 7 => 'impressions', 8 => 'sheets', ); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning:s" => { name => 'warning' }, "critical:s" => { name => 'critical' }, }); $self->{statefile_value} = centreon::plugins::statefile->new(%options); 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(); } $self->{statefile_value}->check_options(%options); } sub run { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{hostname} = $self->{snmp}->get_hostname(); $self->{snmp_port} = $self->{snmp}->get_port(); my $new_datas = {}; $new_datas->{last_timestamp} = time(); $self->{statefile_value}->read(statefile => "snmpstandard_" . $self->{hostname} . '_' . $self->{snmp_port} . '_' . $self->{mode}); my $old_timestamp = $self->{statefile_value}->get(name => 'last_timestamp'); my $oid_prtMarkerCounterUnit = '.1.3.6.1.2.1.43.10.2.1.3'; my $oid_prtMarkerLifeCount = '.1.3.6.1.2.1.43.10.2.1.4'; my $result = $self->{snmp}->get_table(oid => $oid_prtMarkerLifeCount, nothing_quit => 1); $self->{snmp}->load(oids => [$oid_prtMarkerCounterUnit], instances => [keys %$result], instance_regexp => '(\d+\.\d+)$'); $self->{output}->output_add(severity => 'OK', short_msg => "Marker impressions/sheets are ok."); my $perf_label = {}; my $result2 = $self->{snmp}->get_leef(); foreach my $key ($self->{snmp}->oid_lex_sort(keys %$result)) { $key =~ /(\d+).(\d+)$/; my ($hrDeviceIndex, $prtMarkerIndex) = ($1, $2); my $instance = $hrDeviceIndex . '.' . $prtMarkerIndex; my $counter_unit = $result2->{$oid_prtMarkerCounterUnit . '.' . $instance}; $new_datas->{'lifecount_' . $instance} = $result->{$key}; if (!defined($unit_managed{$counter_unit})) { $self->{output}->output_add(long_msg => "Skipping marker '" . $hrDeviceIndex . '#' . $prtMarkerIndex . "': unit not managed."); next; } my $old_life_count = $self->{statefile_value}->get(name => 'lifecount_' . $instance); if (!defined($old_timestamp) || !defined($old_life_count)) { next; } if ($old_life_count > $new_datas->{'lifecount_' . $instance}) { $old_life_count = 0; } my $value = $new_datas->{'lifecount_' . $instance} - $old_life_count; my $exit = $self->{perfdata}->threshold_check(value => $value, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(long_msg => sprintf("Marker %s '%s': %s", $unit_managed{$counter_unit}, $hrDeviceIndex . '#' . $prtMarkerIndex, $value)); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Marker %s '%s': %s", $unit_managed{$counter_unit}, $hrDeviceIndex . '#' . $prtMarkerIndex, $value)); } my $label = $unit_managed{$counter_unit}; if (defined($perf_label->{$label})) { $label .= '#' . $hrDeviceIndex . '#' . $prtMarkerIndex; } $perf_label->{$label} = 1; $self->{output}->perfdata_add(label => $label, value => $value, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0); } $self->{statefile_value}->write(data => $new_datas); if (!defined($old_timestamp)) { $self->{output}->output_add(severity => 'OK', short_msg => "Buffer creation..."); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check marker impressions/sheets. =over 8 =item B<--warning> Threshold warning. =item B<--critical> Threshold critical. =back =cut centreon-plugins-20220113/hardware/printers/standard/rfc3805/mode/markersupply.pm000066400000000000000000000163271417000230700276220ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::printers::standard::rfc3805::mode::markersupply; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::misc; # 1 means: do percent calc 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), 15 => 1, # tenthsOfMilliliters(15) 19 => 0 # percent(19) ); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { 'warning:s' => { name => 'warning' }, 'critical:s' => { name => 'critical' }, 'filter:s' => { name => 'filter' } }); 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 $oid_prtMarkerSuppliesColorantIndex = '.1.3.6.1.2.1.43.11.1.1.3'; my $oid_prtMarkerSuppliesDescription = '.1.3.6.1.2.1.43.11.1.1.6'; my $oid_prtMarkerSuppliesSupplyUnit = '.1.3.6.1.2.1.43.11.1.1.7'; my $oid_prtMarkerSuppliesMaxCapacity = '.1.3.6.1.2.1.43.11.1.1.8'; my $oid_prtMarkerSuppliesLevel = '.1.3.6.1.2.1.43.11.1.1.9'; my $oid_prtMarkerColorantValue = '.1.3.6.1.2.1.43.12.1.1.4'; my $result = $options{snmp}->get_table(oid => $oid_prtMarkerSuppliesColorantIndex, nothing_quit => 1); $options{snmp}->load( oids => [ $oid_prtMarkerSuppliesDescription, $oid_prtMarkerSuppliesSupplyUnit, $oid_prtMarkerSuppliesMaxCapacity, $oid_prtMarkerSuppliesLevel ], instances => [keys %$result], instance_regexp => '(\d+\.\d+)$' ); foreach (keys %$result) { if ($result->{$_} != 0) { /(\d+)\.(\d+)$/; # $1 = hrDeviceIndex $options{snmp}->load(oids => [$oid_prtMarkerColorantValue . '.' . $1 . '.' . $result->{$_}]); } } $self->{output}->output_add( severity => 'OK', short_msg => 'Marker supply usages are ok.' ); my $perf_label = {}; my $result2 = $options{snmp}->get_leef(); foreach my $key ($options{snmp}->oid_lex_sort(keys %$result)) { $key =~ /(\d+).(\d+)$/; my ($hrDeviceIndex, $prtMarkerSuppliesIndex) = ($1, $2); my $instance = $hrDeviceIndex . '.' . $prtMarkerSuppliesIndex; my $unit = $result2->{$oid_prtMarkerSuppliesSupplyUnit . '.' . $instance}; my $descr = centreon::plugins::misc::trim($result2->{$oid_prtMarkerSuppliesDescription . '.' . $instance}); my $current_value = $result2->{$oid_prtMarkerSuppliesLevel . '.' . $instance}; my $max_value = $result2->{$oid_prtMarkerSuppliesMaxCapacity . '.' . $instance}; if (!defined($unit) || !defined($unit_managed{$unit})) { $self->{output}->output_add(long_msg => "Skipping marker supply '$descr': no unit or not managed."); next; } if ($current_value == -1) { $self->{output}->output_add(long_msg => "Skipping marker supply '$descr': no level."); next; } elsif ($current_value == -2) { $self->{output}->output_add(long_msg => "Skipping marker supply '$descr': level unknown."); next; } elsif ($current_value == -3) { $self->{output}->output_add(long_msg => "Marker supply '$descr': no level but some space remaining."); next; } if (defined($self->{option_results}->{filter}) && $self->{option_results}->{filter} ne '' && $instance !~ /$self->{option_results}->{filter}/) { $self->{output}->output_add(long_msg => "Skipping marker supply '$descr' (instance: $instance): filter."); next; } my $prct_value = $current_value; if ($unit_managed{$unit} == 1 && $max_value > 0) { $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' } ]); $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, short_msg => sprintf("Marker supply '%s': %.2f %%", $descr, $prct_value) ); } my $label = $descr; 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; } } $perf_label->{$label} = 1; $self->{output}->perfdata_add( label => $label, unit => '%', value => sprintf("%.2f", $prct_value), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0, max => 100 ); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check marker supply usages. =over 8 =item B<--warning> Threshold warning in percent. =item B<--critical> Threshold critical in percent. =item B<--filter> Filter maker supply instance. =back =cut centreon-plugins-20220113/hardware/printers/standard/rfc3805/mode/papertray.pm000066400000000000000000000137501417000230700270700ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::printers::standard::rfc3805::mode::papertray; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::misc; my %unit_managed = ( 8 => 1, # sheets(8) ); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "warning:s" => { name => 'warning' }, "critical:s" => { name => 'critical' }, "filter-tray:s" => { name => 'filter_tray' }, }); 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) = @_; $self->{snmp} = $options{snmp}; my $oid_prtInputCurrentLevel = '.1.3.6.1.2.1.43.8.2.1.10'; my $oid_prtInputMaxCapacity = '.1.3.6.1.2.1.43.8.2.1.9'; my $oid_prtInputCapacityUnit = '.1.3.6.1.2.1.43.8.2.1.8'; my $oid_prtInputDescription = '.1.3.6.1.2.1.43.8.2.1.18'; my $result = $self->{snmp}->get_table(oid => $oid_prtInputCurrentLevel, nothing_quit => 1); $self->{snmp}->load(oids => [$oid_prtInputMaxCapacity, $oid_prtInputCapacityUnit, $oid_prtInputDescription], instances => [keys %$result], instance_regexp => '(\d+\.\d+)$'); $self->{output}->output_add(severity => 'OK', short_msg => "Paper tray usages are ok."); my $result2 = $self->{snmp}->get_leef(); foreach my $key ($self->{snmp}->oid_lex_sort(keys %$result)) { $key =~ /(\d+).(\d+)$/; my ($hrDeviceIndex, $prtInputIndex) = ($1, $2); my $instance = $hrDeviceIndex . '.' . $prtInputIndex; my $unit = $result2->{$oid_prtInputCapacityUnit . '.' . $instance}; my $descr = centreon::plugins::misc::trim($result2->{$oid_prtInputDescription . '.' . $instance}); my $current_value = $result->{$key}; my $max_value = $result2->{$oid_prtInputMaxCapacity . '.' . $instance}; if (!defined($descr) || $descr eq '') { $descr = $hrDeviceIndex . '#' . $prtInputIndex; } if (defined($self->{option_results}->{filter_tray}) && $self->{option_results}->{filter_tray} ne '' && $descr !~ /$self->{option_results}->{filter_tray}/) { $self->{output}->output_add(long_msg => "Skipping tray '$descr': not matching filter."); next; } if (!defined($unit_managed{$unit})) { $self->{output}->output_add(long_msg => "Skipping input '$descr': unit not managed."); next; } if ($current_value == -1) { $self->{output}->output_add(long_msg => "Skipping tray '$descr': no level."); next; } elsif ($current_value == -2) { $self->{output}->output_add(long_msg => "Skippinp tray '$descr': level unknown."); next; } elsif ($current_value == -3) { $self->{output}->output_add(long_msg => "Tray '$descr': no level but some space remaining."); next; } my $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' } ]); $self->{output}->output_add(long_msg => sprintf("Paper tray '%s': %.2f %%", $descr, $prct_value)); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Paper tray '%s': %.2f %%", $descr, $prct_value)); } my $label = 'tray_' . $descr; $self->{output}->perfdata_add(label => $label, unit => '%', value => sprintf("%.2f", $prct_value), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0, max => 100); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check paper trays usages. =over 8 =item B<--warning> Threshold warning in percent. =item B<--critical> Threshold critical in percent. =item B<--filter-tray> Filter tray to check (can use a regexp). =back =cut centreon-plugins-20220113/hardware/printers/standard/rfc3805/plugin.pm000066400000000000000000000034741417000230700254350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::printers::standard::rfc3805::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} = { 'cover-status' => 'hardware::printers::standard::rfc3805::mode::coverstatus', 'hardware-device' => 'snmp_standard::mode::hardwaredevice', 'markersupply-usage' => 'hardware::printers::standard::rfc3805::mode::markersupply', 'marker-impression' => 'hardware::printers::standard::rfc3805::mode::markerimpression', 'papertray-usage' => 'hardware::printers::standard::rfc3805::mode::papertray', 'printer-error' => 'snmp_standard::mode::printererror' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check printers compatible RFC3805 (Printer MIB v2) in SNMP. Don't know if you can have multiple printer devices at once. So it's not managed yet. =cut centreon-plugins-20220113/hardware/sensors/000077500000000000000000000000001417000230700205255ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/akcp/000077500000000000000000000000001417000230700214435ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/akcp/snmp/000077500000000000000000000000001417000230700224205ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/akcp/snmp/mode/000077500000000000000000000000001417000230700233445ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/akcp/snmp/mode/components/000077500000000000000000000000001417000230700255315ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/akcp/snmp/mode/components/humidity.pm000066400000000000000000000161761417000230700277360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::akcp::snmp::mode::components::humidity; use strict; use warnings; use hardware::sensors::akcp::snmp::mode::components::resources qw(%map_default1_status %map_online); my $mapping = { HumidityDescription => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.17.1.1' }, # hhmsSensorArrayHumidityDescription HumidityPercent => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.17.1.3' }, # hhmsSensorArrayHumidityPercent HumidityStatus => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.17.1.4', map => \%map_default1_status }, # hhmsSensorArrayHumidityStatus HumidityOnline => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.17.1.5', map => \%map_online }, # hhmsSensorArrayHumidityOnline HumidityHighWarning => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.17.1.7' }, # hhmsSensorArrayHumidityHighWarning HumidityHighCritical => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.17.1.8' }, # hhmsSensorArrayHumidityHighCritical HumidityLowWarning => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.17.1.9' }, # hhmsSensorArrayHumidityLowWarning HumidityLowCritical => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.17.1.10' }, # hhmsSensorArrayHumidityLowCritical }; my $mapping2 = { HumidityDescription => { oid => '.1.3.6.1.4.1.3854.3.5.3.1.2' }, # humidityDescription HumidityPercent => { oid => '.1.3.6.1.4.1.3854.3.5.3.1.4' }, # humidityPercent HumidityStatus => { oid => '.1.3.6.1.4.1.3854.3.5.3.1.6', map => \%map_default1_status }, # humidityStatus HumidityOnline => { oid => '.1.3.6.1.4.1.3854.3.5.3.1.8', map => \%map_online }, # humidityGoOffline HumidityHighWarning => { oid => '.1.3.6.1.4.1.3854.3.5.3.1.11' }, # humidityHighWarning HumidityHighCritical => { oid => '.1.3.6.1.4.1.3854.3.5.3.1.12' }, # humidityHighCritical HumidityLowWarning => { oid => '.1.3.6.1.4.1.3854.3.5.3.1.10' }, # humidityLowWarning HumidityLowCritical => { oid => '.1.3.6.1.4.1.3854.3.5.3.1.9' }, # humidityLowCritical }; my $oid_hhmsSensorArrayHumidityEntry = '.1.3.6.1.4.1.3854.1.2.2.1.17.1'; my $oid_humidityEntry = '.1.3.6.1.4.1.3854.3.5.3.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_hhmsSensorArrayHumidityEntry }, { oid => $oid_humidityEntry, end => $mapping2->{HumidityHighCritical}->{oid} }; } sub check_humidity { my ($self, %options) = @_; foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$options{entry}}})) { next if ($oid !~ /^$options{mapping}->{HumidityOnline}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $options{mapping}, results => $self->{results}->{$options{entry}}, instance => $instance); next if ($self->check_filter(section => 'humidity', instance => $instance)); if ($result->{HumidityOnline} eq 'offline') { $self->{output}->output_add(long_msg => sprintf("skipping '%s': is offline", $result->{HumidityDescription})); next; } $self->{components}->{humidity}->{total}++; $self->{output}->output_add(long_msg => sprintf("humidity '%s' status is '%s' [instance = %s] [value = %s]", $result->{HumidityDescription}, $result->{HumidityStatus}, $instance, $result->{HumidityPercent})); my $exit = $self->get_severity(label => 'default1', section => 'humidity', value => $result->{HumidityStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Humdity '%s' status is '%s'", $result->{HumidityDescription}, $result->{HumidityStatus})); } my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'humidity', instance => $instance, value => $result->{HumidityPercent}); if ($checked == 0) { $result->{HumidityLowWarning} = (defined($result->{HumidityLowWarning}) && $result->{HumidityLowWarning} =~ /[0-9]/) ? $result->{HumidityLowWarning} : ''; $result->{HumidityLowCritical} = (defined($result->{HumidityLowCritical}) && $result->{HumidityLowCritical} =~ /[0-9]/) ? $result->{HumidityLowCritical} : ''; $result->{HumidityHighWarning} = (defined($result->{HumidityHighWarning}) && $result->{HumidityHighWarning} =~ /[0-9]/) ? $result->{HumidityHighWarning} : ''; $result->{HumidityHighCritical} = (defined($result->{HumidityHighCritical}) && $result->{HumidityHighCritical} =~ /[0-9]/) ? $result->{HumidityHighCritical} : ''; my $warn_th = $result->{HumidityLowWarning} . ':' . $result->{HumidityHighWarning}; my $crit_th = $result->{HumidityLowCritical} . ':' . $result->{HumidityHighCritical}; $self->{perfdata}->threshold_validate(label => 'warning-humidity-instance-' . $instance, value => $warn_th); $self->{perfdata}->threshold_validate(label => 'critical-humidity-instance-' . $instance, value => $crit_th); $warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-humidity-instance-' . $instance); $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-humidity-instance-' . $instance); } if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit2, short_msg => sprintf("Humdity '%s' is %s %%", $result->{HumidityDescription}, $result->{HumidityPercent})); } $self->{output}->perfdata_add( label => 'humidity', unit => '%', nlabel => 'hardware.sensor.humidity.percentage', instances => $result->{HumidityDescription}, value => $result->{HumidityPercent}, warning => $warn, critical => $crit, min => 0, max => 100 ); } } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking humidities"); $self->{components}->{humidity} = {name => 'humidities', total => 0, skip => 0}; return if ($self->check_filter(section => 'humidity')); check_humidity($self, entry => $oid_hhmsSensorArrayHumidityEntry, mapping => $mapping); check_humidity($self, entry => $oid_humidityEntry, mapping => $mapping2); } 1; centreon-plugins-20220113/hardware/sensors/akcp/snmp/mode/components/resources.pm000066400000000000000000000032661417000230700301100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::akcp::snmp::mode::components::resources; use strict; use warnings; use Exporter; our %map_default1_status; our %map_default2_status; our %map_online; our %map_degree_type; our @ISA = qw(Exporter); our @EXPORT_OK = qw(%map_default1_status %map_default2_status %map_online %map_degree_type); %map_default1_status = ( 1 => 'noStatus', 2 => 'normal', 3 => 'highWarning', 4 => 'highCritical', 5 => 'lowWarning', 6 => 'lowCritical', 7 => 'sensorError', 8 => 'relayOn', 9 => 'relayOff', ); %map_default2_status = ( 1 => 'noStatus', 2 => 'normal', 4 => 'critical', 7 => 'sensorError', ); %map_online = ( 1 => 'online', 2 => 'offline', ); %map_degree_type = ( 0 => { unit => 'F', unit_long => 'fahrenheit' }, F => { unit => 'F', unit_long => 'fahrenheit' }, 1 => { unit => 'C', unit_long => 'celsius' }, C => { unit => 'C', unit_long => 'celsius' }, ); 1; centreon-plugins-20220113/hardware/sensors/akcp/snmp/mode/components/serial.pm000066400000000000000000000062511417000230700273520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::akcp::snmp::mode::components::serial; use strict; use warnings; use hardware::sensors::akcp::snmp::mode::components::resources qw(%map_default2_status %map_online); my $mapping = { hhmsSensorArraySerialDescription => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.19.1.1' }, hhmsSensorArraySerialStatus => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.19.1.3', map => \%map_default2_status }, hhmsSensorArraySerialOnline => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.19.1.4', map => \%map_online }, }; my $oid_hhmsSensorArraySwitchEntry = '.1.3.6.1.4.1.3854.1.2.2.1.18.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_hhmsSensorArraySwitchEntry }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking serials"); $self->{components}->{serial} = {name => 'serials', total => 0, skip => 0}; return if ($self->check_filter(section => 'serial')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_hhmsSensorArraySwitchEntry}})) { next if ($oid !~ /^$mapping->{hhmsSensorArraySerialOnline}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_hhmsSensorArraySwitchEntry}, instance => $instance); next if ($self->check_filter(section => 'serial', instance => $instance)); if ($result->{hhmsSensorArraySerialOnline} eq 'offline') { $self->{output}->output_add(long_msg => sprintf("skipping '%s': is offline", $result->{hhmsSensorArraySerialDescription})); next; } $self->{components}->{serial}->{total}++; $self->{output}->output_add(long_msg => sprintf("serial '%s' status is '%s' [instance = %s]", $result->{hhmsSensorArraySerialDescription}, $result->{hhmsSensorArraySerialStatus}, $instance, )); my $exit = $self->get_severity(label => 'default2', section => 'serial', value => $result->{hhmsSensorArraySerialStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Serial '%s' status is '%s'", $result->{hhmsSensorArraySerialDescription}, $result->{hhmsSensorArraySerialStatus})); } } } 1; centreon-plugins-20220113/hardware/sensors/akcp/snmp/mode/components/switch.pm000066400000000000000000000062531417000230700273760ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::akcp::snmp::mode::components::switch; use strict; use warnings; use hardware::sensors::akcp::snmp::mode::components::resources qw(%map_default2_status %map_online); my $mapping = { hhmsSensorArraySwitchDescription => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.18.1.1' }, hhmsSensorArraySwitchStatus => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.18.1.3', map => \%map_default2_status }, hhmsSensorArraySwitchOnline => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.18.1.4', map => \%map_online }, }; my $oid_hhmsSensorArraySwitchEntry = '.1.3.6.1.4.1.3854.1.2.2.1.18.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_hhmsSensorArraySwitchEntry }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking switches"); $self->{components}->{switch} = {name => 'switches', total => 0, skip => 0}; return if ($self->check_filter(section => 'switch')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_hhmsSensorArraySwitchEntry}})) { next if ($oid !~ /^$mapping->{hhmsSensorArraySwitchOnline}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_hhmsSensorArraySwitchEntry}, instance => $instance); next if ($self->check_filter(section => 'switch', instance => $instance)); if ($result->{hhmsSensorArraySwitchOnline} eq 'offline') { $self->{output}->output_add(long_msg => sprintf("skipping '%s': is offline", $result->{hhmsSensorArraySwitchDescription})); next; } $self->{components}->{switch}->{total}++; $self->{output}->output_add(long_msg => sprintf("switch '%s' status is '%s' [instance = %s]", $result->{hhmsSensorArraySwitchDescription}, $result->{hhmsSensorArraySwitchStatus}, $instance, )); my $exit = $self->get_severity(label => 'default2', section => 'switch', value => $result->{hhmsSensorArraySwitchStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Switch '%s' status is '%s'", $result->{hhmsSensorArraySwitchDescription}, $result->{hhmsSensorArraySwitchStatus})); } } } 1; centreon-plugins-20220113/hardware/sensors/akcp/snmp/mode/components/temperature.pm000066400000000000000000000166671417000230700304440ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::akcp::snmp::mode::components::temperature; use strict; use warnings; use hardware::sensors::akcp::snmp::mode::components::resources qw(%map_default1_status %map_online %map_degree_type); my $mapping = { TempDescription => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.16.1.1' }, # hhmsSensorArrayTempDescription TempDegree => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.16.1.3' }, # hhmsSensorArrayTempDegree TempStatus => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.16.1.4', map => \%map_default1_status }, # hhmsSensorArrayTempStatus TempOnline => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.16.1.5', map => \%map_online }, # hhmsSensorArrayTempOnline TempHighWarning => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.16.1.7' }, # hhmsSensorArrayTempHighWarning TempHighCritical => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.16.1.8' }, # hhmsSensorArrayTempHighCritical TempLowWarning => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.16.1.9' }, # hhmsSensorArrayTempLowWarning TempLowCritical => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.16.1.10' }, # hhmsSensorArrayTempLowCritical TempDegreeType => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.16.1.12', map => \%map_degree_type }, # hhmsSensorArrayTempDegreeType }; my $mapping2 = { TempDescription => { oid => '.1.3.6.1.4.1.3854.3.5.2.1.2' }, # temperatureDescription TempDegree => { oid => '.1.3.6.1.4.1.3854.3.5.2.1.4' }, # temperatureDegree TempStatus => { oid => '.1.3.6.1.4.1.3854.3.5.2.1.6', map => \%map_default1_status }, # temperatureStatus TempOnline => { oid => '.1.3.6.1.4.1.3854.3.5.2.1.8', map => \%map_online }, # temperatureGoOffline TempHighWarning => { oid => '.1.3.6.1.4.1.3854.3.5.2.1.11' }, # temperatureHighWarning TempHighCritical => { oid => '.1.3.6.1.4.1.3854.3.5.2.1.12' }, # temperatureHighCritical TempLowWarning => { oid => '.1.3.6.1.4.1.3854.3.5.2.1.10' }, # temperatureLowWarning TempLowCritical => { oid => '.1.3.6.1.4.1.3854.3.5.2.1.9' }, # temperatureLowCritical TempDegreeType => { oid => '.1.3.6.1.4.1.3854.3.5.2.1.5', map => \%map_degree_type }, # temperatureUnit }; my $oid_hhmsSensorArrayTempEntry = '.1.3.6.1.4.1.3854.1.2.2.1.16.1'; my $oid_temperatureEntry = '.1.3.6.1.4.1.3854.3.5.2.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_hhmsSensorArrayTempEntry }, { oid => $oid_temperatureEntry, end => $mapping2->{TempHighCritical}->{oid} }; } sub check_temperature { my ($self, %options) = @_; foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$options{entry}}})) { next if ($oid !~ /^$options{mapping}->{TempOnline}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $options{mapping}, results => $self->{results}->{$options{entry}}, instance => $instance); next if ($self->check_filter(section => 'temperature', instance => $instance)); if ($result->{TempOnline} eq 'offline') { $self->{output}->output_add(long_msg => sprintf("skipping '%s': is offline", $result->{TempDescription})); next; } $self->{components}->{temperature}->{total}++; $self->{output}->output_add(long_msg => sprintf("temperature '%s' status is '%s' [instance = %s] [value = %s]", $result->{TempDescription}, $result->{TempStatus}, $instance, $result->{TempDegree})); my $exit = $self->get_severity(label => 'default1', section => 'temperature', value => $result->{TempStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Temperature '%s' status is '%s'", $result->{TempDescription}, $result->{TempStatus})); } my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $instance, value => $result->{TempDegree}); if ($checked == 0) { $result->{TempLowWarning} = (defined($result->{TempLowWarning}) && $result->{TempLowWarning} =~ /[0-9]/) ? $result->{TempLowWarning} * $options{threshold_mult} : ''; $result->{TempLowCritical} = (defined($result->{TempLowCritical}) && $result->{TempLowCritical} =~ /[0-9]/) ? $result->{TempLowCritical} * $options{threshold_mult} : ''; $result->{TempHighWarning} = (defined($result->{TempHighWarning}) && $result->{TempHighWarning} =~ /[0-9]/) ? $result->{TempHighWarning} * $options{threshold_mult} : ''; $result->{TempHighCritical} = (defined($result->{TempHighCritical}) && $result->{TempHighCritical} =~ /[0-9]/) ? $result->{TempHighCritical} * $options{threshold_mult} : ''; my $warn_th = $result->{TempLowWarning} . ':' . $result->{TempHighWarning}; my $crit_th = $result->{TempLowCritical} . ':' . $result->{TempHighCritical}; $self->{perfdata}->threshold_validate(label => 'warning-temperature-instance-' . $instance, value => $warn_th); $self->{perfdata}->threshold_validate(label => 'critical-temperature-instance-' . $instance, value => $crit_th); $warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-temperature-instance-' . $instance); $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-temperature-instance-' . $instance); } if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit2, short_msg => sprintf("Temperature '%s' is %s %s", $result->{TempDescription}, $result->{TempDegree}, $result->{TempDegreeType}->{unit})); } $self->{output}->perfdata_add( label => 'temperature', unit => $result->{TempDegreeType}->{unit}, nlabel => 'hardware.sensor.temperature.' . $result->{TempDegreeType}->{unit_long}, instances => $result->{TempDescription}, value => $result->{TempDegree}, warning => $warn, critical => $crit, ); } } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking temperatures"); $self->{components}->{temperature} = {name => 'temperatures', total => 0, skip => 0}; return if ($self->check_filter(section => 'temperature')); check_temperature($self, entry => $oid_hhmsSensorArrayTempEntry, mapping => $mapping, threshold_mult => 1); check_temperature($self, entry => $oid_temperatureEntry, mapping => $mapping2, threshold_mult => 0.1); } 1; centreon-plugins-20220113/hardware/sensors/akcp/snmp/mode/components/water.pm000066400000000000000000000057211417000230700272160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::akcp::snmp::mode::components::water; use strict; use warnings; use hardware::sensors::akcp::snmp::mode::components::resources qw(%map_default1_status %map_online); my $mapping = { waterDescription => { oid => '.1.3.6.1.4.1.3854.3.5.9.1.2' }, waterStatus => { oid => '.1.3.6.1.4.1.3854.3.5.9.1.6', map => \%map_default1_status }, waterGoOffline => { oid => '.1.3.6.1.4.1.3854.3.5.9.1.8', map => \%map_online }, }; my $oid_waterEntry = '.1.3.6.1.4.1.3854.3.5.9.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_waterEntry, end => $mapping->{waterGoOffline}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking waters"); $self->{components}->{water} = {name => 'waters', total => 0, skip => 0}; return if ($self->check_filter(section => 'water')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_waterEntry}})) { next if ($oid !~ /^$mapping->{waterGoOffline}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_waterEntry}, instance => $instance); next if ($self->check_filter(section => 'water', instance => $instance)); if ($result->{waterGoOffline} eq 'offline') { $self->{output}->output_add(long_msg => sprintf("skipping '%s': is offline", $result->{waterDescription})); next; } $self->{components}->{water}->{total}++; $self->{output}->output_add(long_msg => sprintf("water '%s' status is '%s' [instance = %s]", $result->{waterDescription}, $result->{waterStatus}, $instance, )); my $exit = $self->get_severity(label => 'default1', section => 'water', value => $result->{waterStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Water '%s' status is '%s'", $result->{waterDescription}, $result->{waterStatus})); } } } 1; centreon-plugins-20220113/hardware/sensors/akcp/snmp/mode/sensors.pm000066400000000000000000000062511417000230700254020ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::akcp::snmp::mode::sensors; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^(temperature|humidity)$'; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { default1 => [ ['noStatus', 'OK'], ['normal', 'OK'], ['highWarning', 'WARNING'], ['highCritical', 'CRITICAL'], ['lowWarning', 'WARNING'], ['lowCritical', 'CRITICAL'], ['sensorError', 'CRITICAL'], ['relayOn', 'OK'], ['relayOff', 'OK'] ], default2 => [ ['noStatus', 'OK'], ['normal', 'OK'], ['critical', 'CRITICAL'], ['sensorError', 'CRITICAL'] ] }; $self->{components_path} = 'hardware::sensors::akcp::snmp::mode::components'; $self->{components_module} = ['temperature', 'humidity', 'switch', 'serial', 'water']; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $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; $options{options}->add_options(arguments => {}); return $self; } 1; __END__ =head1 MODE Check sensors. =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'temperature', 'humidity', 'switch', 'serial', 'water'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=temperature --filter=humidity) Can also exclude specific instance: --filter=fan,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='temperature,CRITICAL,^(?!(normal)$)' =item B<--warning> Set warning threshold for 'temperature', 'humidity' (syntax: type,regexp,threshold) Example: --warning='temperature,.*,30' =item B<--critical> Set critical threshold for 'temperature', 'humidity' (syntax: type,regexp,threshold) Example: --warning='temperature,.*,50' =back =cut centreon-plugins-20220113/hardware/sensors/akcp/snmp/plugin.pm000066400000000000000000000023351417000230700242570ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::akcp::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}} = ( 'sensors' => 'hardware::sensors::akcp::snmp::mode::sensors', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check AKCP sensors in SNMP. =cut centreon-plugins-20220113/hardware/sensors/comet/000077500000000000000000000000001417000230700216345ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/comet/p8000/000077500000000000000000000000001417000230700224035ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/comet/p8000/snmp/000077500000000000000000000000001417000230700233605ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/comet/p8000/snmp/mode/000077500000000000000000000000001417000230700243045ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/comet/p8000/snmp/mode/sensors.pm000066400000000000000000000161151417000230700263420ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::comet::p8000::snmp::mode::sensors; use base qw(centreon::plugins::templates::counter); use strict; use warnings; sub custom_temperature_perfdata { my ($self, %options) = @_; my ($extra_label, $unit) = ('', 'C'); if (!defined($options{extra_instance}) || $options{extra_instance} != 0) { $extra_label .= '_' . $self->{result_values}->{display}; } $self->{output}->perfdata_add( label => $self->{label} . $extra_label, unit => $unit, value => $self->{result_values}->{$self->{label} }, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label} . '_' . $self->{result_values}->{display}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label} . '_' . $self->{result_values}->{display}), ); } sub custom_humidity_perfdata { my ($self, %options) = @_; my ($extra_label, $unit) = ('', '%'); if (!defined($options{extra_instance}) || $options{extra_instance} != 0) { $extra_label .= '_' . $self->{result_values}->{display}; } $self->{output}->perfdata_add( label => $self->{label} . $extra_label, unit => $unit, value => $self->{result_values}->{$self->{label} }, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label} . '_' . $self->{result_values}->{display}), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label} . '_' . $self->{result_values}->{display}), min => 0, max => 100, ); } sub custom_sensor_threshold { my ($self, %options) = @_; my $warn_limit; if (defined($self->{instance_mode}->{option_results}->{'warning-' . $self->{label}}) && $self->{instance_mode}->{option_results}->{'warning-' . $self->{label}} ne '') { $warn_limit = $self->{instance_mode}->{option_results}->{'warning-' . $self->{label}}; } $self->{perfdata}->threshold_validate(label => 'warning-' . $self->{label} . '_' . $self->{result_values}->{display}, value => $warn_limit); my $crit_limit = $self->{result_values}->{limit_lo} . ':' . $self->{result_values}->{limit_hi}; if (defined($self->{instance_mode}->{option_results}->{'critical-' . $self->{label}}) && $self->{instance_mode}->{option_results}->{'critical-' . $self->{label}} ne '') { $crit_limit = $self->{instance_mode}->{option_results}->{'critical-' . $self->{label}}; } $self->{perfdata}->threshold_validate(label => 'critical-' . $self->{label} . '_' . $self->{result_values}->{display}, value => $crit_limit); my $exit = $self->{perfdata}->threshold_check(value => $self->{result_values}->{$self->{label} }, threshold => [ { label => 'critical-' . $self->{label} . '_' . $self->{result_values}->{display}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{label} . '_' . $self->{result_values}->{display}, exit_litteral => 'warning' } ]); return $exit; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'channel', type => 1, cb_prefix_output => 'prefix_channel_output', message_multiple => 'All channels are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{channel} = [ { label => 'temperature', set => { key_values => [ { name => 'temperature' }, { name => 'limit_hi' }, { name => 'limit_lo' }, { name => 'display' } ], output_template => 'Temperature: %.2f C', closure_custom_perfdata => $self->can('custom_temperature_perfdata'), closure_custom_threshold_check => $self->can('custom_sensor_threshold'), } }, { label => 'humidity', set => { key_values => [ { name => 'humidity' }, { name => 'limit_hi' }, { name => 'limit_lo' }, { name => 'display' } ], output_template => 'Humidity: %.2f %%', closure_custom_perfdata => $self->can('custom_humidity_perfdata'), closure_custom_threshold_check => $self->can('custom_sensor_threshold'), } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub prefix_channel_output { my ($self, %options) = @_; return "Channel '" . $options{instance_value}->{display} . "' "; } sub manage_selection { my ($self, %options) = @_; my $oid_channels = '.1.3.6.1.4.1.22626.1.5.2'; my $chName_suffix = '1.0'; my $chVal_suffix = '2.0'; my $chLimHi_suffix = '5.0'; my $chLimLo_suffix = '6.0'; my $chUnit_suffix = '9.0'; my $snmp_result = $options{snmp}->get_table(oid => $oid_channels, nothing_quit => 1); $self->{channel} = {}; for my $channel ((1, 2, 3, 4)) { next if (!defined($snmp_result->{$oid_channels . '.' . $channel . '.' . $chName_suffix})); my $value = $snmp_result->{$oid_channels . '.' . $channel . '.' . $chVal_suffix}; # sensor not configured (n/a) next if ($value !~ /[0-9\.]/); my $name = $snmp_result->{$oid_channels . '.' . $channel . '.' . $chName_suffix}; my $unit = $snmp_result->{$oid_channels . '.' . $channel . '.' . $chUnit_suffix}; my $limit_hi = $snmp_result->{$oid_channels . '.' . $channel . '.' . $chLimHi_suffix}; my $limit_lo = $snmp_result->{$oid_channels . '.' . $channel . '.' . $chLimLo_suffix}; $limit_hi /= 10; $limit_lo /= 10; if ($unit =~ /F/i) { $value = sprintf("%.2f", ($value - 32) / 1.8); $limit_hi = sprintf("%.2f", ($limit_hi - 32) / 1.8); $limit_lo = sprintf("%.2f", ($limit_lo - 32) / 1.8); } $self->{channel}->{$channel} = { display => $name, humidity => ($unit =~ /RH/) ? $value : undef, temperature => ($unit =~ /F|C/) ? $value : undef, limit_hi => $limit_hi, limit_lo => $limit_lo, }; } } 1; __END__ =head1 MODE Check environment channels. =over 8 =item B<--warning-*> Threshold warning. Can be: 'temperature', 'humidity'. =item B<--critical-*> Threshold critical. Can be: 'temperature', 'humidity'. =back =cut centreon-plugins-20220113/hardware/sensors/comet/p8000/snmp/plugin.pm000066400000000000000000000024641417000230700252220ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::comet::p8000::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}} = ( 'sensors' => 'hardware::sensors::comet::p8000::snmp::mode::sensors', ); return $self; } 1; __END__ =head1 PLUGIN DESCRITPION Check Comet P8000 (P8510, P8511, P8541, P8610, P8611, p8631, P8641, P8552, P8652) sensors in SNMP. =cut centreon-plugins-20220113/hardware/sensors/geist/000077500000000000000000000000001417000230700216405ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/geist/snmp/000077500000000000000000000000001417000230700226155ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/geist/snmp/mode/000077500000000000000000000000001417000230700235415ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/geist/snmp/mode/sensors.pm000066400000000000000000000225751417000230700256060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::geist::snmp::mode::sensors; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'internal', type => 1, cb_prefix_output => 'prefix_internal_output', message_multiple => 'All internal sensors are ok', skipped_code => { -10 => 1 } }, { name => 'climate', type => 1, cb_prefix_output => 'prefix_climate_output', message_multiple => 'All climate sensors are ok', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{climate} = [ { label => 'climate-temperature', nlabel => 'sensor.climate.temperature.celsius', set => { key_values => [ { name => 'climateTempC', no_value => 0, } ], output_template => 'temperature %s C', perfdatas => [ { value => 'climateTempC', template => '%s', unit => 'C', label_extra_instance => 1 }, ], } }, { label => 'climate-humidity', nlabel => 'sensor.climate.humidity.percentage', set => { key_values => [ { name => 'climateHumidity', no_value => 0 } ], output_template => 'humidity %.2f %%', perfdatas => [ { value => 'climateHumidity', template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1 }, ], } }, { label => 'climate-light', nlabel => 'sensor.climate.ambientlight.percentage', set => { key_values => [ { name => 'climateLight', no_value => 0 } ], output_template => 'ambient light %.2f %%', perfdatas => [ { value => 'climateLight', template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1 }, ], } }, { label => 'climate-airflow', nlabel => 'sensor.climate.airflow.percentage', set => { key_values => [ { name => 'climateAirflow', no_value => 0 } ], output_template => 'airflow %.2f %%', perfdatas => [ { value => 'climateAirflow', template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1 }, ], } }, { label => 'climate-sound', nlabel => 'sensor.climate.sound.percentage', set => { key_values => [ { name => 'climateSound', no_value => 0 } ], output_template => 'sound %.2f %%', perfdatas => [ { value => 'climateSound', template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1 }, ], } }, { label => 'climate-dewpoint', nlabel => 'sensor.climate.dewpoint.celsius', set => { key_values => [ { name => 'climateDewPointC', no_value => 0 } ], output_template => 'dew point %s C', perfdatas => [ { value => 'climateDewPointC', template => '%s', unit => 'C', label_extra_instance => 1 }, ], } }, ]; $self->{maps_counters}->{internal} = [ { label => 'internal-temperature', nlabel => 'sensor.internal.temperature.celsius', set => { key_values => [ { name => 'internalTemp', no_value => 0, } ], output_template => 'temperature %s C', perfdatas => [ { value => 'internalTemp', template => '%s', unit => 'C', label_extra_instance => 1 }, ], } }, { label => 'internal-humidity', nlabel => 'sensor.internal.humidity.percentage', set => { key_values => [ { name => 'internalHumidity', no_value => 0 } ], output_template => 'humidity %.2f %%', perfdatas => [ { value => 'internalHumidity', template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1 }, ], } }, { label => 'internal-dewpoint', nlabel => 'sensor.internal.dewpoint.celsius', set => { key_values => [ { name => 'internalDewPoint', no_value => 0 } ], output_template => 'dew point %s C', perfdatas => [ { value => 'internalDewPoint', template => '%s', unit => 'C', label_extra_instance => 1 }, ], } }, ]; } sub prefix_climate_output { my ($self, %options) = @_; return "Climate '" . $options{instance_value}->{climateName} . "' "; } sub prefix_internal_output { my ($self, %options) = @_; return "Internal '" . $options{instance_value}->{internalName} . "' "; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } sub get_climate_v3 { my ($self, %options) = @_; return if (!defined($options{count}) || $options{count} == 0); my $mapping = { climateName => { oid => '.1.3.6.1.4.1.21239.2.2.1.3' }, climateTempC => { oid => '.1.3.6.1.4.1.21239.2.2.1.5' }, climateHumidity => { oid => '.1.3.6.1.4.1.21239.2.2.1.7' }, climateLight => { oid => '.1.3.6.1.4.1.21239.2.2.1.8' }, climateAirflow => { oid => '.1.3.6.1.4.1.21239.2.2.1.9' }, climateDewPointC => { oid => '.1.3.6.1.4.1.21239.2.2.1.31' }, }; my $oid_climateEntry = '.1.3.6.1.4.1.21239.2.2.1'; my $snmp_result = $options{snmp}->get_table( oid => $oid_climateEntry, start => $mapping->{climateName}->{oid}, ); $self->{climate} = {}; foreach my $oid (keys %$snmp_result) { next if ($oid !~ /^$mapping->{climateName}->{oid}\.(.*)/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); $self->{climate}->{$result->{climateName}} = { %$result }; } } sub geist_v3 { my ($self, %options) = @_; my $oid_climateCount = '.1.3.6.1.4.1.21239.2.1.8.1.2.0'; my $oid_tempSensorCount = '.1.3.6.1.4.1.21239.2.1.8.1.4.0'; my $oid_airflowSensorCount = '.1.3.6.1.4.1.21239.2.1.8.1.5.0'; my $snmp_result = $options{snmp}->get_leef( oids => [$oid_climateCount, $oid_tempSensorCount, $oid_airflowSensorCount], ); return 1 if (!defined($snmp_result->{$oid_climateCount})); $self->get_climate_v3(%options, count => $snmp_result->{$oid_climateCount}); return 0; } sub get_internal_v4 { my ($self, %options) = @_; my $mapping = { internalName => { oid => '.1.3.6.1.4.1.21239.5.1.2.1.3' }, internalTemp => { oid => '.1.3.6.1.4.1.21239.5.1.2.1.5' }, internalHumidity => { oid => '.1.3.6.1.4.1.21239.5.1.2.1.6' }, internalDewPoint => { oid => '.1.3.6.1.4.1.21239.5.1.2.1.7' }, }; my $oid_internalEntry = '.1.3.6.1.4.1.21239.5.1.2.1'; my $snmp_result = $options{snmp}->get_table( oid => $oid_internalEntry, start => $mapping->{internalName}->{oid}, ); $self->{internal} = {}; foreach my $oid (keys %$snmp_result) { next if ($oid !~ /^$mapping->{internalName}->{oid}\.(.*)/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); if ($options{temp_unit} eq 'F') { $result->{internalTemp} = centreon::plugins::misc::convert_fahrenheit(value => $result->{internalTemp}); $result->{internalDewPoint} = centreon::plugins::misc::convert_fahrenheit(value => $result->{internalDewPoint}); } $result->{internalTemp} /= 10; $result->{internalDewPoint} /= 10; $self->{internal}->{$result->{internalName}} = { %$result }; } } sub geist_v4 { my ($self, %options) = @_; my $oid_temperatureUnits = '.1.3.6.1.4.1.21239.5.1.1.7.0'; my $snmp_result = $options{snmp}->get_leef( oids => [$oid_temperatureUnits], nothing_quit => 1 ); my $temp_unit = $snmp_result->{$oid_temperatureUnits} == 1 ? 'C' : 'F'; $self->get_internal_v4(%options, temp_unit => $temp_unit); } sub manage_selection { my ($self, %options) = @_; if ($self->geist_v3(%options)) { $self->geist_v4(%options) } } 1; __END__ =head1 MODE Check sensors. =over 8 =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'climate-temperature', 'climate-humidity', 'climate-light', 'climate-airflow', 'climate-sound', 'climate-dewpoint', 'internal-temperature', 'internal-humidity', 'internal-dewpoint'. =back =cut centreon-plugins-20220113/hardware/sensors/geist/snmp/plugin.pm000066400000000000000000000023401417000230700244500ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::geist::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}} = ( 'sensors' => 'hardware::sensors::geist::snmp::mode::sensors', ); return $self; } 1; __END__ =head1 PLUGIN DESCRITPION Check Geist sensors in SNMP. =cut centreon-plugins-20220113/hardware/sensors/hwgste/000077500000000000000000000000001417000230700220265ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/hwgste/snmp/000077500000000000000000000000001417000230700230035ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/hwgste/snmp/mode/000077500000000000000000000000001417000230700237275ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/hwgste/snmp/mode/components/000077500000000000000000000000001417000230700261145ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/hwgste/snmp/mode/components/humidity.pm000066400000000000000000000067641417000230700303230ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::hwgste::snmp::mode::components::humidity; use strict; use warnings; use hardware::sensors::hwgste::snmp::mode::components::resources qw($mapping); sub load {} sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking humidity"); $self->{components}->{humidity} = {name => 'humidity', total => 0, skip => 0}; return if ($self->check_filter(section => 'humidity')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{ $mapping->{branch_sensors}->{$self->{branch}} }})) { next if ($oid !~ /^$mapping->{$self->{branch}}->{sensState}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping->{$self->{branch}}, results => $self->{results}->{ $mapping->{branch_sensors}->{$self->{branch}} }, instance => $instance); next if (!(defined($result->{sensUnit}) && $result->{sensUnit} eq '%')); next if ($self->check_filter(section => 'humidity', instance => $instance)); $self->{components}->{humidity}->{total}++; $result->{sensValue} /= 10 if ($result->{sensValue} =~ /\d+/); $self->{output}->output_add(long_msg => sprintf("humidity '%s' state is '%s' [instance: %s, value: %s]", $result->{sensName}, $result->{sensState}, $instance, $result->{sensValue})); my $exit = $self->get_severity(section => 'humidity', label => 'default', instance => $instance, value => $result->{sensState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("humidity '%s' state is '%s'", $result->{sensName}, $result->{sensState})); } if ($result->{sensValue} =~ /\d+/) { my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'humidity', instance => $instance, value => $result->{sensValue}); if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit2, short_msg => sprintf("humidity '%s' value is %s %s", $result->{sensName}, $result->{sensValue}, $result->{sensUnit})); } $self->{output}->perfdata_add( label => 'sensor', unit => '%', nlabel => 'hardware.sensor.humidity.percentage', instances => $result->{sensName}, value => $result->{sensValue}, warning => $warn, critical => $crit, min => 0, max => 100 ); } } } 1; centreon-plugins-20220113/hardware/sensors/hwgste/snmp/mode/components/resources.pm000066400000000000000000000037651417000230700304770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::hwgste::snmp::mode::components::resources; use strict; use warnings; use Exporter; our %map_sens_unit; our %map_sens_state; our $mapping; our @ISA = qw(Exporter); our @EXPORT_OK = qw($mapping); %map_sens_state = ( 0 => 'invalid', 1 => 'normal', 2 => 'outOfRangeLo', 3 => 'outOfRangeHi', 4 => 'alarmLo', 5 => 'alarmHi', ); %map_sens_unit = ( 0 => '', # none 1 => 'C', 2 => 'F', 3 => 'K', 4 => '%', ); $mapping = { branch_sensors => { hwgste => '.1.3.6.1.4.1.21796.4.1.3', hwgste2 => '.1.3.6.1.4.1.21796.4.9.3', }, hwgste => { sensName => { oid => '.1.3.6.1.4.1.21796.4.1.3.1.2' }, sensState => { oid => '.1.3.6.1.4.1.21796.4.1.3.1.3', map => \%map_sens_state }, sensValue => { oid => '.1.3.6.1.4.1.21796.4.1.3.1.5' }, sensUnit => { oid => '.1.3.6.1.4.1.21796.4.1.3.1.7', map => \%map_sens_unit }, }, hwgste2 => { sensName => { oid => '.1.3.6.1.4.1.21796.4.9.3.1.2' }, sensState => { oid => '.1.3.6.1.4.1.21796.4.9.3.1.3', map => \%map_sens_state }, sensValue => { oid => '.1.3.6.1.4.1.21796.4.9.3.1.5' }, sensUnit => { oid => '.1.3.6.1.4.1.21796.4.9.3.1.7', map => \%map_sens_unit }, }, }; 1; centreon-plugins-20220113/hardware/sensors/hwgste/snmp/mode/components/temperature.pm000066400000000000000000000073151417000230700310150ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::hwgste::snmp::mode::components::temperature; use strict; use warnings; use hardware::sensors::hwgste::snmp::mode::components::resources qw($mapping); sub load {} sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking temperature"); $self->{components}->{temperature} = {name => 'temperature', total => 0, skip => 0}; return if ($self->check_filter(section => 'temperature')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{ $mapping->{branch_sensors}->{$self->{branch}} }})) { next if ($oid !~ /^$mapping->{$self->{branch}}->{sensState}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping->{$self->{branch}}, results => $self->{results}->{ $mapping->{branch_sensors}->{$self->{branch}} }, instance => $instance); next if (!(defined($result->{sensUnit}) && $result->{sensUnit} =~ /C|F|K/i)); next if ($self->check_filter(section => 'temperature', instance => $instance)); $self->{components}->{temperature}->{total}++; $result->{sensValue} /= 10 if ($result->{sensValue} =~ /\d+/); $self->{output}->output_add(long_msg => sprintf("temperature '%s' state is '%s' [instance: %s, value: %s]", $result->{sensName}, $result->{sensState}, $instance, $result->{sensValue})); my $exit = $self->get_severity(section => 'temperature', label => 'default', instance => $instance, value => $result->{sensState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("temperature '%s' state is '%s'", $result->{sensName}, $result->{sensState})); } if ($result->{sensValue} =~ /\d+/) { my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $instance, value => $result->{sensValue}); if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit2, short_msg => sprintf("temperature '%s' value is %s %s", $result->{sensName}, $result->{sensValue}, $result->{sensUnit})); } my $nunit = 'celsius'; $nunit = 'fahrenheit' if ($result->{sensUnit} =~ /F/i); $nunit = 'kelvin' if ($result->{sensUnit} =~ /K/i); $self->{output}->perfdata_add( label => 'sensor', unit => $result->{sensUnit}, nlabel => 'hardware.sensor.temperature.' . $nunit, instances => $result->{sensName}, value => $result->{sensValue}, warning => $warn, critical => $crit ); } } } 1; centreon-plugins-20220113/hardware/sensors/hwgste/snmp/mode/sensors.pm000066400000000000000000000060641417000230700257670ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. package hardware::sensors::hwgste::snmp::mode::sensors; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; use hardware::sensors::hwgste::snmp::mode::components::resources qw($mapping); sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^(temperature|humidity)$'; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { default => [ ['invalid', 'UNKNOWN'], ['normal', 'OK'], ['outOfRangeLo', 'WARNING'], ['outOfRangeHi', 'WARNING'], ['alarmLo', 'CRITICAL'], ['alarmHi', 'CRITICAL'] ] }; $self->{components_path} = 'hardware::sensors::hwgste::snmp::mode::components'; $self->{components_module} = ['temperature', 'humidity']; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{results} = $self->{snmp}->get_multiple_table( oids => [{ oid => $mapping->{branch_sensors}->{hwgste} }, { oid => $mapping->{branch_sensors}->{hwgste2} }] ); $self->{branch} = 'hwgste'; if (defined($self->{results}->{ $mapping->{branch_sensors}->{hwgste2} }) && scalar(keys %{$self->{results}->{ $mapping->{branch_sensors}->{hwgste2} }}) > 0) { $self->{branch} = 'hwgste2'; } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_absent => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } 1; __END__ =head1 MODE Check HWg-STE sensors. =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'temperature', 'humidity'. =item B<--filter> Exclude some parts. Can also exclude specific instance: --filter=sensor,10 =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,CRITICAL,^(?!(normal)$)' =item B<--warning> Set warning threshold for temperature, humidity (syntax: type,instance,threshold) Example: --warning='temperature,.*,30' =item B<--critical> Set critical threshold for temperature, humidity (syntax: type,instance,threshold) Example: --critical='humidty,.*,40' =back =cut centreon-plugins-20220113/hardware/sensors/hwgste/snmp/plugin.pm000066400000000000000000000023441417000230700246420ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::hwgste::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.9'; %{$self->{modes}} = ( 'sensors' => 'hardware::sensors::hwgste::snmp::mode::sensors', ); return $self; } 1; __END__ =head1 PLUGIN DESCRITPION Check HWg-STE sensors in SNMP. =cut centreon-plugins-20220113/hardware/sensors/jacarta/000077500000000000000000000000001417000230700221325ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/jacarta/snmp/000077500000000000000000000000001417000230700231075ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/jacarta/snmp/mode/000077500000000000000000000000001417000230700240335ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/jacarta/snmp/mode/components/000077500000000000000000000000001417000230700262205ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/jacarta/snmp/mode/components/humidity.pm000066400000000000000000000151341417000230700304160ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::jacarta::snmp::mode::components::humidity; use strict; use warnings; use hardware::sensors::jacarta::snmp::mode::components::resources qw(%map_default_status %map_state); my $mapping = { isDeviceMonitorHumidityName => { oid => '.1.3.6.1.4.1.19011.1.3.2.1.3.1.2.1.2' }, isDeviceMonitorHumidity => { oid => '.1.3.6.1.4.1.19011.1.3.2.1.3.1.2.1.3' }, isDeviceMonitorHumidityAlarm => { oid => '.1.3.6.1.4.1.19011.1.3.2.1.3.1.2.1.4', map => \%map_default_status }, }; my $mapping2 = { isDeviceConfigHumidityLowWarning => { oid => '.1.3.6.1.4.1.19011.1.3.2.1.3.2.3.1.3' }, isDeviceConfigHumidityLowCritical => { oid => '.1.3.6.1.4.1.19011.1.3.2.1.3.2.3.1.4' }, isDeviceConfigHumidityHighWarning => { oid => '.1.3.6.1.4.1.19011.1.3.2.1.3.2.3.1.5' }, isDeviceConfigHumidityHighCritical => { oid => '.1.3.6.1.4.1.19011.1.3.2.1.3.2.3.1.6' }, isDeviceConfigHumidityLowWarningState => { oid => '.1.3.6.1.4.1.19011.1.3.2.1.3.2.3.1.9', map => \%map_state }, isDeviceConfigHumidityLowCriticalState => { oid => '.1.3.6.1.4.1.19011.1.3.2.1.3.2.3.1.10', map => \%map_state }, isDeviceConfigHumidityHighWarningState => { oid => '.1.3.6.1.4.1.19011.1.3.2.1.3.2.3.1.11', map => \%map_state }, isDeviceConfigHumidityHighCriticalState => { oid => '.1.3.6.1.4.1.19011.1.3.2.1.3.2.3.1.12', map => \%map_state }, }; my $oid_isDeviceMonitorHumidityEntry = '.1.3.6.1.4.1.19011.1.3.2.1.3.1.2.1'; my $oid_isDeviceConfigHumidityEntry = '.1.3.6.1.4.1.19011.1.3.2.1.3.2.3.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_isDeviceMonitorHumidityEntry }, { oid => $oid_isDeviceConfigHumidityEntry }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking humidities"); $self->{components}->{humidity} = {name => 'humidities', total => 0, skip => 0}; return if ($self->check_filter(section => 'humidity')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_isDeviceMonitorHumidityEntry}})) { next if ($oid !~ /^$mapping->{isDeviceMonitorHumidityAlarm}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_isDeviceMonitorHumidityEntry}, instance => $instance); my $result2 = $self->{snmp}->map_instance(mapping => $mapping2, results => $self->{results}->{$oid_isDeviceConfigHumidityEntry}, instance => $instance); next if ($self->check_filter(section => 'humidity', instance => $instance)); $self->{components}->{humidity}->{total}++; $result->{isDeviceMonitorHumidity} *= 0.01; $self->{output}->output_add(long_msg => sprintf("humidity '%s' status is '%s' [instance = %s] [value = %s]", $result->{isDeviceMonitorHumidityName}, $result->{isDeviceMonitorHumidityAlarm}, $instance, $result->{isDeviceMonitorHumidity})); my $exit = $self->get_severity(label => 'default', section => 'humidity', value => $result->{isDeviceMonitorHumidityAlarm}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Humdity '%s' status is '%s'", $result->{isDeviceMonitorHumidityName}, $result->{isDeviceMonitorHumidityAlarm})); } my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'humidity', instance => $instance, value => $result->{isDeviceMonitorHumidity}); if ($checked == 0) { $result2->{isDeviceConfigHumidityLowWarning} = ($result2->{isDeviceConfigHumidityLowWarningState} eq 'enabled') ? $result2->{isDeviceConfigHumidityLowWarning} * 0.01 : ''; $result2->{isDeviceConfigHumidityLowCritical} = ($result2->{isDeviceConfigHumidityLowCriticalState} eq 'enabled') ? $result2->{isDeviceConfigHumidityLowCritical} * 0.01 : ''; $result2->{isDeviceConfigHumidityHighWarning} = ($result2->{isDeviceConfigHumidityHighWarningState} eq 'enabled') ? $result2->{isDeviceConfigHumidityHighWarning} * 0.01 : ''; $result2->{isDeviceConfigHumidityHighCritical} = ($result2->{isDeviceConfigHumidityHighCriticalState} eq 'enabled') ? $result2->{isDeviceConfigHumidityHighCritical} * 0.01 : ''; my $warn_th = $result2->{isDeviceConfigHumidityLowWarning} . ':' . $result2->{isDeviceConfigHumidityHighWarning}; my $crit_th = $result2->{isDeviceConfigHumidityLowCritical} . ':' . $result2->{isDeviceConfigHumidityHighCritical}; $self->{perfdata}->threshold_validate(label => 'warning-humidity-instance-' . $instance, value => $warn_th); $self->{perfdata}->threshold_validate(label => 'critical-humidity-instance-' . $instance, value => $crit_th); $warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-humidity-instance-' . $instance); $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-humidity-instance-' . $instance); } if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit2, short_msg => sprintf("Humdity '%s' is %s %%", $result->{isDeviceMonitorHumidityName}, $result->{isDeviceMonitorHumidity})); } $self->{output}->perfdata_add( label => 'humidity', unit => '%', nlabel => 'hardware.humidity.percentage', instances => $result->{isDeviceMonitorHumidityName}, value => $result->{isDeviceMonitorHumidity}, warning => $warn, critical => $crit, min => 0, max => 100 ); } } 1; centreon-plugins-20220113/hardware/sensors/jacarta/snmp/mode/components/input.pm000066400000000000000000000056531417000230700277260ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::jacarta::snmp::mode::components::input; use strict; use warnings; use hardware::sensors::jacarta::snmp::mode::components::resources qw(%map_input_status); my $mapping = { isDeviceMonitorDigitalInName => { oid => '.1.3.6.1.4.1.19011.1.3.2.1.3.1.3.1.2' }, isDeviceMonitorDigitalIn => { oid => '.1.3.6.1.4.1.19011.1.3.2.1.3.1.3.1.3' }, isDeviceMonitorDigitalInAlarm => { oid => '.1.3.6.1.4.1.19011.1.3.2.1.3.1.3.1.4', map => \%map_input_status }, }; my $oid_isDeviceMonitorDigitalInEntry = '.1.3.6.1.4.1.19011.1.3.2.1.3.1.3.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_isDeviceMonitorDigitalInEntry }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking digital inputs"); $self->{components}->{input} = {name => 'inputs', total => 0, skip => 0}; return if ($self->check_filter(section => 'input')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_isDeviceMonitorDigitalInEntry}})) { next if ($oid !~ /^$mapping->{isDeviceMonitorDigitalInAlarm}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_isDeviceMonitorDigitalInEntry}, instance => $instance); next if ($self->check_filter(section => 'input', instance => $instance)); $self->{components}->{input}->{total}++; $self->{output}->output_add(long_msg => sprintf("input '%s' status is '%s' [instance = %s]", $result->{isDeviceMonitorDigitalInName}, $result->{isDeviceMonitorDigitalInAlarm}, $instance, )); my $exit = $self->get_severity(section => 'input', value => $result->{isDeviceMonitorDigitalInAlarm}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Input '%s' status is '%s'", $result->{isDeviceMonitorDigitalInName}, $result->{isDeviceMonitorDigitalInAlarm})); next; } } } 1;centreon-plugins-20220113/hardware/sensors/jacarta/snmp/mode/components/resources.pm000066400000000000000000000025371417000230700305770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::jacarta::snmp::mode::components::resources; use strict; use warnings; use Exporter; our %map_default_status; our %map_input_status; our %map_state; our @ISA = qw(Exporter); our @EXPORT_OK = qw(%map_default_status %map_input_status %map_state); %map_default_status = ( 1 => 'unknown', 2 => 'disable', 3 => 'normal', 4 => 'below-low-warning', 5 => 'below-low-critical', 6 => 'above-high-warning', 7 => 'above-high-critical', ); %map_input_status = ( 1 => 'normal', 2 => 'triggered', ); %map_state = ( 1 => 'enabled', 2 => 'disabled', ); 1;centreon-plugins-20220113/hardware/sensors/jacarta/snmp/mode/components/temperature.pm000066400000000000000000000155501417000230700311210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::jacarta::snmp::mode::components::temperature; use strict; use warnings; use hardware::sensors::jacarta::snmp::mode::components::resources qw(%map_default_status %map_state); my $mapping = { isDeviceMonitorTemperatureName => { oid => '.1.3.6.1.4.1.19011.1.3.2.1.3.1.1.1.2' }, isDeviceMonitorTemperature => { oid => '.1.3.6.1.4.1.19011.1.3.2.1.3.1.1.1.3' }, isDeviceMonitorTemperatureAlarm => { oid => '.1.3.6.1.4.1.19011.1.3.2.1.3.1.1.1.4', map => \%map_default_status }, }; my $mapping2 = { isDeviceConfigTemperatureLowWarning => { oid => '.1.3.6.1.4.1.19011.1.3.2.1.3.2.2.1.3' }, isDeviceConfigTemperatureLowCritical => { oid => '.1.3.6.1.4.1.19011.1.3.2.1.3.2.2.1.4' }, isDeviceConfigTemperatureHighWarning => { oid => '.1.3.6.1.4.1.19011.1.3.2.1.3.2.2.1.5' }, isDeviceConfigTemperatureHighCritical => { oid => '.1.3.6.1.4.1.19011.1.3.2.1.3.2.2.1.6' }, isDeviceConfigTemperatureLowWarningState => { oid => '.1.3.6.1.4.1.19011.1.3.2.1.3.2.2.1.9', map => \%map_state }, isDeviceConfigTemperatureLowCriticalState => { oid => '.1.3.6.1.4.1.19011.1.3.2.1.3.2.2.1.10', map => \%map_state }, isDeviceConfigTemperatureHighWarningState => { oid => '.1.3.6.1.4.1.19011.1.3.2.1.3.2.2.1.11', map => \%map_state }, isDeviceConfigTemperatureHighCriticalState => { oid => '.1.3.6.1.4.1.19011.1.3.2.1.3.2.2.1.12', map => \%map_state }, }; my $oid_isDeviceMonitorTemperatureEntry = '.1.3.6.1.4.1.19011.1.3.2.1.3.1.1.1'; my $oid_isDeviceConfigTemperatureEntry = '.1.3.6.1.4.1.19011.1.3.2.1.3.2.2.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_isDeviceMonitorTemperatureEntry }, { oid => $oid_isDeviceConfigTemperatureEntry }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking temperatures"); $self->{components}->{temperature} = {name => 'temperatures', total => 0, skip => 0}; return if ($self->check_filter(section => 'temperature')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_isDeviceMonitorTemperatureEntry}})) { next if ($oid !~ /^$mapping->{isDeviceMonitorTemperatureAlarm}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_isDeviceMonitorTemperatureEntry}, instance => $instance); my $result2 = $self->{snmp}->map_instance(mapping => $mapping2, results => $self->{results}->{$oid_isDeviceConfigTemperatureEntry}, instance => $instance); next if ($self->check_filter(section => 'temperature', instance => $instance)); $self->{components}->{temperature}->{total}++; $result->{isDeviceMonitorTemperature} *= 0.01; $self->{output}->output_add(long_msg => sprintf("temperature '%s' status is '%s' [instance = %s] [value = %s]", $result->{isDeviceMonitorTemperatureName}, $result->{isDeviceMonitorTemperatureAlarm}, $instance, $result->{isDeviceMonitorTemperature})); my $exit = $self->get_severity(label => 'default', section => 'temperature', value => $result->{isDeviceMonitorTemperatureAlarm}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Temperature '%s' status is '%s'", $result->{isDeviceMonitorTemperatureName}, $result->{isDeviceMonitorTemperatureAlarm})); } my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $instance, value => $result->{isDeviceMonitorTemperature}); if ($checked == 0) { $result2->{isDeviceConfigTemperatureLowWarning} = ($result2->{isDeviceConfigTemperatureLowWarningState} eq 'enabled') ? $result2->{isDeviceConfigTemperatureLowWarning} * 0.01 : ''; $result2->{isDeviceConfigTemperatureLowCritical} = ($result2->{isDeviceConfigTemperatureLowCriticalState} eq 'enabled') ? $result2->{isDeviceConfigTemperatureLowCritical} * 0.01 : ''; $result2->{isDeviceConfigTemperatureHighWarning} = ($result2->{isDeviceConfigTemperatureHighWarningState} eq 'enabled') ? $result2->{isDeviceConfigTemperatureHighWarning} * 0.01 : ''; $result2->{isDeviceConfigTemperatureHighCritical} = ($result2->{isDeviceConfigTemperatureHighCriticalState} eq 'enabled') ? $result2->{isDeviceConfigTemperatureHighCritical} * 0.01 : ''; my $warn_th = $result2->{isDeviceConfigTemperatureLowWarning} . ':' . $result2->{isDeviceConfigTemperatureHighWarning}; my $crit_th = $result2->{isDeviceConfigTemperatureLowCritical} . ':' . $result2->{isDeviceConfigTemperatureHighCritical}; $self->{perfdata}->threshold_validate(label => 'warning-temperature-instance-' . $instance, value => $warn_th); $self->{perfdata}->threshold_validate(label => 'critical-temperature-instance-' . $instance, value => $crit_th); $warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-temperature-instance-' . $instance); $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-temperature-instance-' . $instance); } if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit2, short_msg => sprintf("Temperature '%s' is %s %s", $result->{isDeviceMonitorTemperatureName}, $result->{isDeviceMonitorTemperature}, $self->{temperature_unit})); } $self->{output}->perfdata_add( label => 'temperature', unit => $self->{temperature_unit}, nlabel => 'hardware.temperature.' . (($self->{temperature_unit} eq 'C') ? 'celsius' : 'fahrenheit'), instances => $result->{isDeviceMonitorTemperatureName}, value => $result->{isDeviceMonitorTemperature}, warning => $warn, critical => $crit, ); } } 1; centreon-plugins-20220113/hardware/sensors/jacarta/snmp/mode/sensors.pm000066400000000000000000000067371417000230700261020ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::jacarta::snmp::mode::sensors; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^(temperature|humidity)$'; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { default => [ ['unknown', 'UNKNOWN'], ['disable', 'OK'], ['normal', 'OK'], ['below-low-warning', 'WARNING'], ['below-low-critical', 'CRITICAL'], ['above-high-warning', 'WARNING'], ['above-high-critical', 'CRITICAL'], ['sensorError', 'CRITICAL'] ], input => [ ['normal', 'OK'], ['triggered', 'CRITICAL'] ] }; $self->{components_path} = 'hardware::sensors::jacarta::snmp::mode::components'; $self->{components_module} = ['temperature', 'humidity', 'input']; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; my $oid_isConfigTemperatureUnit = '.1.3.6.1.4.1.19011.1.3.2.1.2.16'; # .0 push @{$self->{request}}, { oid => $oid_isConfigTemperatureUnit }; $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); $self->{temperature_unit} = defined($self->{results}->{$oid_isConfigTemperatureUnit}->{$oid_isConfigTemperatureUnit . '.0'}) && $self->{results}->{$oid_isConfigTemperatureUnit}->{$oid_isConfigTemperatureUnit . '.0'} == 1 ? 'C' : 'F'; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_absent => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } 1; __END__ =head1 MODE Check sensors. =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'temperature', 'humidity', 'input'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=temperature --filter=input) Can also exclude specific instance: --filter=temperature,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='temperature,CRITICAL,^(?!(normal)$)' =item B<--warning> Set warning threshold for 'temperature', 'humidity' (syntax: type,regexp,threshold) Example: --warning='temperature,.*,30' =item B<--critical> Set critical threshold for 'temperature', 'humidity' (syntax: type,regexp,threshold) Example: --warning='temperature,.*,50' =back =cut centreon-plugins-20220113/hardware/sensors/jacarta/snmp/plugin.pm000066400000000000000000000023461417000230700247500ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::jacarta::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}} = ( 'sensors' => 'hardware::sensors::jacarta::snmp::mode::sensors', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Jacarta sensors in SNMP. =cut centreon-plugins-20220113/hardware/sensors/netbotz/000077500000000000000000000000001417000230700222125ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/netbotz/snmp/000077500000000000000000000000001417000230700231675ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/netbotz/snmp/mode/000077500000000000000000000000001417000230700241135ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/netbotz/snmp/mode/components/000077500000000000000000000000001417000230700263005ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/netbotz/snmp/mode/components/airflow.pm000066400000000000000000000105611417000230700303040ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::netbotz::snmp::mode::components::airflow; use strict; use warnings; use hardware::sensors::netbotz::snmp::mode::components::resources qw($map_status); sub load { my ($self) = @_; $self->{mapping_airflow} = { airFlowSensorId => { oid => '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.1.5.1.1' }, airFlowSensorValue => { oid => '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.1.5.1.2' }, airFlowSensorErrorStatus => { oid => '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.1.5.1.3', map => $map_status }, airFlowSensorLabel => { oid => '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.1.5.1.4' } }; $self->{oid_airFlowSensorEntry} = '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.1.5.1'; push @{$self->{request}}, { oid => $self->{oid_airFlowSensorEntry}, end => $self->{mapping_airflow}->{airFlowSensorLabel}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking air flows"); $self->{components}->{airflow} = { name => 'air flows', total => 0, skip => 0 }; return if ($self->check_filter(section => 'airflow')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{ $self->{oid_airFlowSensorEntry} }})) { next if ($oid !~ /^$self->{mapping_airflow}->{airFlowSensorErrorStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance( mapping => $self->{mapping_airflow}, results => $self->{results}->{ $self->{oid_airFlowSensorEntry} }, instance => $instance ); next if ($self->check_filter(section => 'airflow', instance => $instance)); $self->{components}->{airflow}->{total}++; $result->{airFlowSensorValue} *= 0.1; my $label = defined($result->{airFlowSensorLabel}) && $result->{airFlowSensorLabel} ne '' ? $result->{airFlowSensorLabel} : $result->{airFlowSensorId}; $self->{output}->output_add( long_msg => sprintf( "air flow '%s' status is '%s' [instance = %s] [value = %s]", $label, $result->{airFlowSensorErrorStatus}, $instance, $result->{airFlowSensorValue} ) ); my $exit = $self->get_severity(label => 'default', section => 'airflow', value => $result->{airFlowSensorErrorStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Air flow '%s' status is '%s'", $label, $result->{airFlowSensorErrorStatus} ) ); } my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'airflow', instance => $instance, value => $result->{airFlowSensorValue}); if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit2, short_msg => sprintf( "Air flow '%s' is %s m/min", $label, $result->{airFlowSensorValue} ) ); } $self->{output}->perfdata_add( label => 'airflow', unit => 'm/min', nlabel => 'hardware.sensor.airflow.cubicmeterperminute', instances => $label, value => $result->{airFlowSensorValue}, warning => $warn, critical => $crit, min => 0 ); } } 1; centreon-plugins-20220113/hardware/sensors/netbotz/snmp/mode/components/camera.pm000066400000000000000000000071501417000230700300710ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::netbotz::snmp::mode::components::camera; use strict; use warnings; use hardware::sensors::netbotz::snmp::mode::components::resources qw($map_status $map_camera_value); sub load { my ($self) = @_; $self->{mapping_camera} = { cameraMotionSensorId => { oid => '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.2.3.1.1' }, cameraMotionSensorValue => { oid => '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.2.3.1.2', map => $map_camera_value }, cameraMotionSensorErrorStatus => { oid => '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.2.3.1.3', map => $map_status }, cameraMotionSensorLabel => { oid => '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.2.3.1.4' } }; $self->{oid_cameraMotionSensorEntry} = '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.2.3.1'; push @{$self->{request}}, { oid => $self->{oid_cameraMotionSensorEntry}, end => $self->{mapping_camera}->{cameraMotionSensorLabel}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking cameras"); $self->{components}->{camera} = { name => 'cameras', total => 0, skip => 0 }; return if ($self->check_filter(section => 'camera')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{ $self->{oid_cameraMotionSensorEntry} }})) { next if ($oid !~ /^$self->{mapping_camera}->{cameraMotionSensorErrorStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance( mapping => $self->{mapping_camera}, results => $self->{results}->{ $self->{oid_cameraMotionSensorEntry} }, instance => $instance ); next if ($self->check_filter(section => 'camera', instance => $instance)); $self->{components}->{camera}->{total}++; my $label = defined($result->{cameraMotionSensorLabel}) && $result->{cameraMotionSensorLabel} ne '' ? $result->{cameraMotionSensorLabel} : $result->{cameraMotionSensorId}; $self->{output}->output_add( long_msg => sprintf( "camera motion '%s' status is '%s' [instance = %s] [value = %s]", $label, $result->{cameraMotionSensorErrorStatus}, $instance, $result->{cameraMotionSensorValue} ) ); my $exit = $self->get_severity(label => 'default', section => 'camera', value => $result->{cameraMotionSensorErrorStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Camera motion '%s' status is '%s'", $label, $result->{cameraMotionSensorErrorStatus} ) ); } } } 1; centreon-plugins-20220113/hardware/sensors/netbotz/snmp/mode/components/dewpoint.pm000066400000000000000000000105741417000230700304760ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::netbotz::snmp::mode::components::dewpoint; use strict; use warnings; use hardware::sensors::netbotz::snmp::mode::components::resources qw($map_status); sub load { my ($self) = @_; $self->{mapping_dewpoint} = { dewPointSensorId => { oid => '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.1.3.1.1' }, dewPointSensorValue => { oid => '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.1.3.1.2' }, dewPointSensorErrorStatus => { oid => '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.1.3.1.3', map => $map_status }, dewPointSensorLabel => { oid => '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.1.3.1.4' } }; $self->{oid_dewPointSensorEntry} = '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.1.3.1'; push @{$self->{request}}, { oid => $self->{oid_dewPointSensorEntry}, end => $self->{mapping_dewpoint}->{dewPointSensorLabel}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking dew points"); $self->{components}->{dewpoint} = { name => 'dew points', total => 0, skip => 0 }; return if ($self->check_filter(section => 'dewpoint')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{ $self->{oid_dewPointSensorEntry} }})) { next if ($oid !~ /^$self->{mapping_dewpoint}->{dewPointSensorErrorStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance( mapping => $self->{mapping_dewpoint}, results => $self->{results}->{ $self->{oid_dewPointSensorEntry} }, instance => $instance ); next if ($self->check_filter(section => 'dewpoint', instance => $instance)); $self->{components}->{dewpoint}->{total}++; $result->{dewPointSensorValue} *= 0.1; my $label = defined($result->{dewPointSensorLabel}) && $result->{dewPointSensorLabel} ne '' ? $result->{dewPointSensorLabel} : $result->{dewPointSensorId}; $self->{output}->output_add( long_msg => sprintf( "dew point '%s' status is '%s' [instance = %s] [value = %s]", $label, $result->{dewPointSensorErrorStatus}, $instance, $result->{dewPointSensorValue} ) ); my $exit = $self->get_severity(label => 'default', section => 'dewpoint', value => $result->{dewPointSensorErrorStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Dew point '%s' status is '%s'", $label, $result->{dewPointSensorErrorStatus} ) ); } my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'dewpoint', instance => $instance, value => $result->{dewPointSensorValue}); if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit2, short_msg => sprintf( "Dew point '%s' is %s C", $label, $result->{dewPointSensorValue} ) ); } $self->{output}->perfdata_add( label => 'dewpoint', unit => 'C', nlabel => 'hardware.sensor.dewpoint.celsius', instances => $label, value => $result->{dewPointSensorValue}, warning => $warn, critical => $crit, ); } } 1; centreon-plugins-20220113/hardware/sensors/netbotz/snmp/mode/components/doorswitch.pm000066400000000000000000000071571417000230700310350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::netbotz::snmp::mode::components::doorswitch; use strict; use warnings; use hardware::sensors::netbotz::snmp::mode::components::resources qw($map_status $map_door_value); sub load { my ($self) = @_; $self->{mapping_doorswitch} = { doorSwitchSensorId => { oid => '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.2.2.1.1' }, doorSwitchSensorValue => { oid => '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.2.2.1.2', map => $map_door_value }, doorSwitchSensorErrorStatus => { oid => '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.2.2.1.3', map => $map_status }, doorSwitchSensorLabel => { oid => '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.2.2.1.4' } }; $self->{oid_doorSwitchSensorEntry} = '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.2.2.1'; push @{$self->{request}}, { oid => $self->{oid_doorSwitchSensorEntry}, end => $self->{mapping_doorswitch}->{doorSwitchSensorLabel}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking door switches"); $self->{components}->{doorswitch} = { name => 'door switches', total => 0, skip => 0 }; return if ($self->check_filter(section => 'doorswitch')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{ $self->{oid_doorSwitchSensorEntry} }})) { next if ($oid !~ /^$self->{mapping_doorswitch}->{doorSwitchSensorErrorStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance( mapping => $self->{mapping_doorswitch}, results => $self->{results}->{ $self->{oid_doorSwitchSensorEntry} }, instance => $instance ); next if ($self->check_filter(section => 'doorswitch', instance => $instance)); $self->{components}->{doorswitch}->{total}++; my $label = defined($result->{doorSwitchSensorLabel}) && $result->{doorSwitchSensorLabel} ne '' ? $result->{doorSwitchSensorLabel} : $result->{doorSwitchSensorId}; $self->{output}->output_add( long_msg => sprintf( "door switch '%s' status is '%s' [instance = %s] [value = %s]", $label, $result->{doorSwitchSensorErrorStatus}, $instance, $result->{doorSwitchSensorValue} ) ); my $exit = $self->get_severity(label => 'default', section => 'doorswitch', value => $result->{doorSwitchSensorErrorStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Door switch '%s' status is '%s'", $label, $result->{doorSwitchSensorErrorStatus} ) ); } } } 1; centreon-plugins-20220113/hardware/sensors/netbotz/snmp/mode/components/humidity.pm000066400000000000000000000105001417000230700304660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::netbotz::snmp::mode::components::humidity; use strict; use warnings; use hardware::sensors::netbotz::snmp::mode::components::resources qw($map_status); sub load { my ($self) = @_; $self->{mapping_humidity} = { humiSensorId => { oid => '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.1.2.1.1' }, humiSensorValue => { oid => '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.1.2.1.2' }, humiSensorErrorStatus => { oid => '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.1.2.1.3', map => $map_status }, humiSensorLabel => { oid => '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.1.2.1.4' } }; $self->{oid_humiSensorEntry} = '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.1.2.1'; push @{$self->{request}}, { oid => $self->{oid_humiSensorEntry}, end => $self->{mapping_humidity}->{humiSensorLabel}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking humidities"); $self->{components}->{humidity} = { name => 'humidity', total => 0, skip => 0 }; return if ($self->check_filter(section => 'humidity')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{ $self->{oid_humiSensorEntry} }})) { next if ($oid !~ /^$self->{mapping_humidity}->{humiSensorErrorStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance( mapping => $self->{mapping_humidity}, results => $self->{results}->{ $self->{oid_humiSensorEntry} }, instance => $instance ); next if ($self->check_filter(section => 'humidity', instance => $instance)); $self->{components}->{humidity}->{total}++; $result->{humiSensorValue} *= 0.1; my $label = defined($result->{humiSensorLabel}) && $result->{humiSensorLabel} ne '' ? $result->{humiSensorLabel} : $result->{humiSensorId}; $self->{output}->output_add( long_msg => sprintf( "humidity '%s' status is '%s' [instance = %s] [value = %s]", $label, $result->{humiSensorErrorStatus}, $instance, $result->{humiSensorValue} ) ); my $exit = $self->get_severity(label => 'default', section => 'humidity', value => $result->{humiSensorErrorStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Humidity '%s' status is '%s'", $label, $result->{humiSensorErrorStatus} ) ); } my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'humidity', instance => $instance, value => $result->{humiSensorValue}); if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit2, short_msg => sprintf( "Humidity '%s' is %s %%", $label, $result->{humiSensorValue} ) ); } $self->{output}->perfdata_add( label => 'humidity', unit => '%', nlabel => 'hardware.sensor.humidity.percentage', instances => $label, value => $result->{humiSensorValue}, warning => $warn, critical => $crit, min => 0, max => 100 ); } } 1; centreon-plugins-20220113/hardware/sensors/netbotz/snmp/mode/components/otherstate.pm000066400000000000000000000067631417000230700310340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::netbotz::snmp::mode::components::otherstate; use strict; use warnings; use hardware::sensors::netbotz::snmp::mode::components::resources qw($map_status); sub load { my ($self) = @_; $self->{mapping_otherstate} = { otherStateSensorId => { oid => '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.2.10.1.1' }, otherStateSensorErrorStatus => { oid => '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.2.10.1.3', map => $map_status }, otherStateSensorLabel => { oid => '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.2.10.1.4' }, otherStateSensorValueStr => { oid => '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.2.10.1.7' } }; $self->{oid_otherStateSensorEntry} = '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.2.10.1'; push @{$self->{request}}, { oid => $self->{oid_otherStateSensorEntry} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking other state"); $self->{components}->{otherstate} = { name => 'other state', total => 0, skip => 0 }; return if ($self->check_filter(section => 'otherstate')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{ $self->{oid_otherStateSensorEntry} }})) { next if ($oid !~ /^$self->{mapping_otherstate}->{otherStateSensorErrorStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance( mapping => $self->{mapping_otherstate}, results => $self->{results}->{ $self->{oid_otherStateSensorEntry} }, instance => $instance ); next if ($self->check_filter(section => 'otherstate', instance => $instance)); $self->{components}->{otherstate}->{total}++; my $label = defined($result->{otherStateSensorLabel}) && $result->{otherStateSensorLabel} ne '' ? $result->{otherStateSensorLabel} : $result->{otherStateSensorId}; $self->{output}->output_add( long_msg => sprintf( "other state '%s' status is '%s' [instance = %s] [value = %s]", $label, $result->{otherStateSensorErrorStatus}, $instance, $result->{otherStateSensorValueStr} ) ); my $exit = $self->get_severity(label => 'default', section => 'otherstate', value => $result->{otherStateSensorErrorStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Other state '%s' status is '%s'", $label, $result->{otherStateSensorErrorStatus} ) ); } } } 1; centreon-plugins-20220113/hardware/sensors/netbotz/snmp/mode/components/resources.pm000066400000000000000000000024661417000230700306600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::netbotz::snmp::mode::components::resources; use strict; use warnings; use Exporter; our $map_status; our $map_door_value; our $map_camera_value; our @ISA = qw(Exporter); our @EXPORT_OK = qw($map_status $map_door_value $map_camera_value); $map_status = { 0 => 'normal', 1 => 'info', 2 => 'warning', 3 => 'error', 4 => 'critical', 5 => 'failure' }; $map_door_value = { -1 => 'null', 0 => 'open', 1 => 'closed' }; $map_camera_value = { -1 => 'null', 0 => 'noMotion', 1 => 'motionDetected' }; 1; centreon-plugins-20220113/hardware/sensors/netbotz/snmp/mode/components/temperature.pm000066400000000000000000000105531417000230700311770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::netbotz::snmp::mode::components::temperature; use strict; use warnings; use hardware::sensors::netbotz::snmp::mode::components::resources qw($map_status); sub load { my ($self) = @_; $self->{mapping_temperature} = { tempSensorId => { oid => '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.1.1.1.1' }, tempSensorValue => { oid => '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.1.1.1.2' }, tempSensorErrorStatus => { oid => '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.1.1.1.3', map => $map_status }, tempSensorLabel => { oid => '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.1.1.1.4' }, }; $self->{oid_tempSensorEntry} = '.1.3.6.1.4.1.' . $self->{netbotz_branch} . '.4.1.1.1'; push @{$self->{request}}, { oid => $self->{oid_tempSensorEntry}, end => $self->{mapping_temperature}->{tempSensorLabel}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking temperatures"); $self->{components}->{temperature} = { name => 'temperatures', total => 0, skip => 0 }; return if ($self->check_filter(section => 'temperature')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{ $self->{oid_tempSensorEntry} }})) { next if ($oid !~ /^$self->{mapping_temperature}->{tempSensorErrorStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance( mapping => $self->{mapping_temperature}, results => $self->{results}->{ $self->{oid_tempSensorEntry} }, instance => $instance ); next if ($self->check_filter(section => 'temperature', instance => $instance)); $self->{components}->{temperature}->{total}++; $result->{tempSensorValue} *= 0.1; my $label = defined($result->{tempSensorLabel}) && $result->{tempSensorLabel} ne '' ? $result->{tempSensorLabel} : $result->{tempSensorId}; $self->{output}->output_add( long_msg => sprintf( "temperature '%s' status is '%s' [instance = %s] [value = %s]", $label, $result->{tempSensorErrorStatus}, $instance, $result->{tempSensorValue} ) ); my $exit = $self->get_severity(label => 'default', section => 'temperature', value => $result->{tempSensorErrorStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Temperature '%s' status is '%s'", $label, $result->{tempSensorErrorStatus} ) ); } my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $instance, value => $result->{tempSensorValue}); if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit2, short_msg => sprintf( "Temperature '%s' is %s C", $label, $result->{tempSensorValue} ) ); } $self->{output}->perfdata_add( label => 'temperature', unit => 'C', nlabel => 'hardware.sensor.temperature.celsius', instances => $label, value => $result->{tempSensorValue}, warning => $warn, critical => $crit, ); } } 1; centreon-plugins-20220113/hardware/sensors/netbotz/snmp/mode/sensors.pm000066400000000000000000000074321417000230700261530ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::netbotz::snmp::mode::sensors; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^(temperature|humidity|dewpoint|airflow)$'; $self->{cb_hook1} = 'get_version'; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { default => [ ['normal', 'OK'], ['info', 'OK'], ['warning', 'WARNING'], ['error', 'CRITICAL'], ['critical', 'CRITICAL'], ['failure', 'CRITICAL'] ] }; $self->{components_path} = 'hardware::sensors::netbotz::snmp::mode::components'; $self->{components_module} = [ 'temperature', 'humidity', 'dewpoint', 'airflow', 'doorswitch', 'camera', 'otherstate' ]; } sub get_version { my ($self, %options) = @_; my $v1_netBotzErrorStatus = '.1.3.6.1.4.1.5528.100.100'; my $v5_netBotzErrorStatus = '.1.3.6.1.4.1.52674.500.100.0'; my $result = $options{snmp}->get_leef( oids => [$v1_netBotzErrorStatus, $v1_netBotzErrorStatus . '.0', $v5_netBotzErrorStatus] ); $self->{is_v5} = 0; $self->{netbotz_branch} = '5528.100'; if (defined($result->{$v5_netBotzErrorStatus})) { $self->{is_v5} = 1; $self->{netbotz_branch} = '52674.500'; } elsif (!defined($result->{$v1_netBotzErrorStatus}) && !defined($result->{$v1_netBotzErrorStatus . '.0'})) { $self->{output}->add_option_msg(short_msg => 'cannot find netbotz version'); $self->{output}->option_exit(); } } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $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; $options{options}->add_options(arguments => {}); return $self; } 1; __END__ =head1 MODE Check sensors. =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'temperature', 'humidity', 'dewpoint', 'airflow', 'doorswitch', 'camera', 'otherstate'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=temperature --filter=humidity) Can also exclude specific instance: --filter=temperature,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='temperature,CRITICAL,^(?!(normal)$)' =item B<--warning> Set warning threshold for 'temperature', 'humidity' (syntax: type,regexp,threshold) Example: --warning='temperature,.*,30' =item B<--critical> Set critical threshold for 'temperature', 'humidity' (syntax: type,regexp,threshold) Example: --warning='temperature,.*,50' =back =cut centreon-plugins-20220113/hardware/sensors/netbotz/snmp/plugin.pm000066400000000000000000000023461417000230700250300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::netbotz::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}} = ( 'sensors' => 'hardware::sensors::netbotz::snmp::mode::sensors', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check NetBotz sensors in SNMP. =cut centreon-plugins-20220113/hardware/sensors/sensorip/000077500000000000000000000000001417000230700223675ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/sensorip/snmp/000077500000000000000000000000001417000230700233445ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/sensorip/snmp/mode/000077500000000000000000000000001417000230700242705ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/sensorip/snmp/mode/components/000077500000000000000000000000001417000230700264555ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/sensorip/snmp/mode/components/humidity.pm000066400000000000000000000140621417000230700306520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::sensorip::snmp::mode::components::humidity; use strict; use warnings; my %map_hum_status = ( 1 => 'noStatus', 2 => 'normal', 3 => 'highWarning', 4 => 'highCritical', 5 => 'lowWarning', 6 => 'lowCritical', 7 => 'sensorError', ); my %map_hum_online = ( 1 => 'online', 2 => 'offline', ); my $mapping = { sensorProbeHumidityDescription => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.17.1.1' }, sensorProbeHumidityPercent => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.17.1.3' }, sensorProbeHumidityStatus => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.17.1.4', map => \%map_hum_status }, sensorProbeHumidityOnline => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.17.1.5', map => \%map_hum_online }, sensorProbeHumidityHighWarning => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.17.1.7' }, sensorProbeHumidityHighCritical => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.17.1.8' }, sensorProbeHumidityLowWarning => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.17.1.9' }, sensorProbeHumidityLowCritical => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.17.1.10' }, }; my $oid_sensorProbeHumidityEntry = '.1.3.6.1.4.1.3854.1.2.2.1.17.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_sensorProbeHumidityEntry, end => $mapping->{sensorProbeHumidityLowCritical}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking humidity"); $self->{components}->{humidity} = {name => 'humidity', total => 0, skip => 0}; return if ($self->check_filter(section => 'humidity')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_sensorProbeHumidityEntry}})) { next if ($oid !~ /^$mapping->{sensorProbeHumidityPercent}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_sensorProbeHumidityEntry}, instance => $instance); next if ($self->check_filter(section => 'humidity', instance => $instance)); if ($result->{sensorProbeHumidityOnline} =~ /Offline/i) { $self->absent_problem(section => 'humidity', instance => $instance); next; } $self->{components}->{humidity}->{total}++; if ($result->{sensorProbeHumidityStatus} =~ /sensorError/i) { my $exit = $self->get_severity(section => 'humidity', value => $result->{sensorProbeHumidityStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Humidity sensor '%s' status is '%s'", $result->{sensorProbeHumidityDescription}, $result->{sensorProbeTempStatus})); next; } } $self->{output}->output_add(long_msg => sprintf("Humidity sensor '%s' status is '%s' [instance = %s, value = %s %%]", $result->{sensorProbeHumidityDescription}, $result->{sensorProbeHumidityStatus}, $instance, $result->{sensorProbeHumidityPercent})); if (defined($result->{sensorProbeHumidityPercent}) && $result->{sensorProbeHumidityPercent} =~ /[0-9]/) { my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'humidity', instance => $instance, value => $result->{sensorProbeHumidityPercent}); if ($checked == 0) { my $warn_th = $result->{sensorProbeHumidityLowWarning} . ':' . $result->{sensorProbeHumidityHighWarning}; my $crit_th = $result->{sensorProbeHumidityLowCritical} . ':' . $result->{sensorProbeHumidityHighCritical}; $self->{perfdata}->threshold_validate(label => 'warning-humidity-instance-' . $instance, value => $warn_th); $self->{perfdata}->threshold_validate(label => 'critical-humidity-instance-' . $instance, value => $crit_th); $exit = $self->{perfdata}->threshold_check(value => $result->{sensorProbeHumidityPercent}, threshold => [ { label => 'critical-humidity-instance-' . $instance, exit_litteral => 'critical' }, { label => 'warning-humidity-instance-' . $instance, exit_litteral => 'warning' } ]); $warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-humidity-instance-' . $instance); $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-humidity-instance-' . $instance) } if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Humidity sensor '%s' is %s %%", $result->{sensorProbeHumidityDescription}, $result->{sensorProbeHumidityPercent})); } $self->{output}->perfdata_add( label => 'humdity', unit => '%', nlabel => 'hardware.sensor.humidity.percentage', instances => $instance, value => $result->{sensorProbeHumidityPercent}, warning => $warn, critical => $crit, min => 0, max => 100 ); } } } 1; centreon-plugins-20220113/hardware/sensors/sensorip/snmp/mode/components/sp.pm000066400000000000000000000045641417000230700274460ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::sensorip::snmp::mode::components::sp; use strict; use warnings; my %map_sp_status = ( 1 => 'noStatus', 2 => 'normal', 3 => 'warning', 4 => 'critical', 5 => 'sensorError', ); my $oid_spStatus = '.1.3.6.1.4.1.3854.1.1.2'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_spStatus }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking sp"); $self->{components}->{sp} = { name => 'sp', total => 0, skip => 0 }; return if ($self->check_filter(section => 'sp')); return if (scalar(keys %{$self->{results}->{$oid_spStatus}}) <= 0); my $instance = 0; my $sp_status = defined($map_sp_status{$self->{results}->{$oid_spStatus}->{$oid_spStatus . '.' . $instance}}) ? $map_sp_status{$self->{results}->{$oid_spStatus}->{$oid_spStatus . '.' . $instance}} : 'unknown'; return if ($self->check_filter(section => 'sp', instance => $instance)); return if ($sp_status =~ /noStatus/i && $self->absent_problem(section => 'sp', instance => $instance)); $self->{components}->{sp}->{total}++; $self->{output}->output_add(long_msg => sprintf("Sensor probe '%s' status is '%s'", $instance, $sp_status)); my $exit = $self->get_severity(section => 'sp', value => $sp_status); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Sensor probe '%s' status is '%s'", $instance, $sp_status)); } } 1; centreon-plugins-20220113/hardware/sensors/sensorip/snmp/mode/components/switch.pm000066400000000000000000000062751417000230700303260ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::sensorip::snmp::mode::components::switch; use strict; use warnings; my %map_sw_status = ( 1 => 'noStatus', 2 => 'normal', 4 => 'highCritical', 6 => 'lowCritical', 7 => 'sensorError', 8 => 'relayOn', 9 => 'relayOff', ); my %map_sw_online = ( 1 => 'online', 2 => 'offline', ); my $mapping = { sensorProbeSwitchDescription => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.18.1.1' }, sensorProbeSwitchStatus => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.18.1.3', map => \%map_sw_status }, sensorProbeSwitchOnline => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.18.1.4', map => \%map_sw_online }, }; my $oid_sensorProbeSwitchEntry = '.1.3.6.1.4.1.3854.1.2.2.1.18.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_sensorProbeSwitchEntry, end => $mapping->{sensorProbeSwitchOnline}->{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')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_sensorProbeSwitchEntry}})) { next if ($oid !~ /^$mapping->{sensorProbeSwitchStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_sensorProbeSwitchEntry}, instance => $instance); next if ($self->check_filter(section => 'switch', instance => $instance)); if ($result->{sensorProbeSwitchOnline} =~ /Offline/i) { $self->absent_problem(section => 'switch', instance => $instance); next; } $self->{components}->{switch}->{total}++; $self->{output}->output_add(long_msg => sprintf("Switch sensor '%s' status is '%s' [instance : %s]", $result->{sensorProbeSwitchDescription}, $result->{sensorProbeSwitchStatus}, $instance)); my $exit = $self->get_severity(section => 'switch', value => $result->{sensorProbeSwitchStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Switch sensor '%s' status is '%s'", $result->{sensorProbeSwitchDescription}, $result->{sensorProbeSwitchStatus})); } } } 1; centreon-plugins-20220113/hardware/sensors/sensorip/snmp/mode/components/temperature.pm000066400000000000000000000137021417000230700313530ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::sensorip::snmp::mode::components::temperature; use strict; use warnings; my %map_temp_status = ( 1 => 'noStatus', 2 => 'normal', 3 => 'highWarning', 4 => 'highCritical', 5 => 'lowWarning', 6 => 'lowCritical', 7 => 'sensorError', ); my %map_temp_online = ( 1 => 'online', 2 => 'offline', ); my $mapping = { sensorProbeTempDescription => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.16.1.1' }, sensorProbeTempDegree => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.16.1.3' }, sensorProbeTempStatus => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.16.1.4', map => \%map_temp_status }, sensorProbeTempOnline => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.16.1.5', map => \%map_temp_online }, sensorProbeTempHighWarning => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.16.1.7' }, sensorProbeTempHighCritical => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.16.1.8' }, sensorProbeTempLowWarning => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.16.1.9' }, sensorProbeTempLowCritical => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.16.1.10' }, }; my $oid_sensorProbeTempEntry = '.1.3.6.1.4.1.3854.1.2.2.1.16.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_sensorProbeTempEntry, end => $mapping->{sensorProbeTempLowCritical}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking temperatures"); $self->{components}->{temperature} = {name => 'temperatures', total => 0, skip => 0}; return if ($self->check_filter(section => 'temperature')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_sensorProbeTempEntry}})) { next if ($oid !~ /^$mapping->{sensorProbeTempDegree}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_sensorProbeTempEntry}, instance => $instance); next if ($self->check_filter(section => 'temperature', instance => $instance)); if ($result->{sensorProbeTempOnline} =~ /Offline/i) { $self->absent_problem(section => 'temperature', instance => $instance); next; } $self->{components}->{temperature}->{total}++; if ($result->{sensorProbeTempStatus} =~ /sensorError/i) { my $exit = $self->get_severity(section => 'temperature', value => $result->{sensorProbeTempStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Temperature sensor '%s' status is '%s'", $result->{sensorProbeTempDescription}, $result->{sensorProbeTempStatus})); next; } } $self->{output}->output_add(long_msg => sprintf("Temperature sensor '%s' status is '%s' [instance = %s, value = %s]", $result->{sensorProbeTempDescription}, $result->{sensorProbeTempStatus}, $instance, $result->{sensorProbeTempDegree})); if (defined($result->{sensorProbeTempDegree}) && $result->{sensorProbeTempDegree} =~ /[0-9]/) { my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $instance, value => $result->{sensorProbeTempDegree}); if ($checked == 0) { my $warn_th = $result->{sensorProbeTempLowWarning} . ':' . $result->{sensorProbeTempHighWarning}; my $crit_th = $result->{sensorProbeTempLowCritical} . ':' . $result->{sensorProbeTempHighCritical}; $self->{perfdata}->threshold_validate(label => 'warning-temperature-instance-' . $instance, value => $warn_th); $self->{perfdata}->threshold_validate(label => 'critical-temperature-instance-' . $instance, value => $crit_th); $exit = $self->{perfdata}->threshold_check(value => $result->{sensorProbeTempDegree}, threshold => [ { label => 'critical-temperature-instance-' . $instance, exit_litteral => 'critical' }, { label => 'warning-temperature-instance-' . $instance, exit_litteral => 'warning' } ]); $warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-temperature-instance-' . $instance); $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-temperature-instance-' . $instance); } if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Temperature sensor '%s' is %s degree centigrade", $result->{sensorProbeTempDescription}, $result->{sensorProbeTempDegree})); } $self->{output}->perfdata_add( label => 'temp', unit => 'C', nlabel => 'hardware.sensor.temperature.celsius', instances => $instance, value => $result->{sensorProbeTempDegree}, warning => $warn, critical => $crit, ); } } } 1; centreon-plugins-20220113/hardware/sensors/sensorip/snmp/mode/sensors.pm000066400000000000000000000064371417000230700263340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::sensorip::snmp::mode::sensors; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^humidity|temperature$'; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { sp => [ ['noStatus', 'UNKNOWN'], ['normal', 'OK'], ['warning', 'WARNING'], ['critical', 'CRITICAL'], ['sensorError', 'CRITICAL'] ], switch => [ ['noStatus', 'UNKNOWN'], ['normal', 'OK'], ['highCritical', 'CRITICAL'], ['lowCritical', 'CRITICAL'], ['sensorError', 'CRITICAL'], ['relayOn', 'OK'], ['relayOff', 'OK'] ] }; $self->{components_path} = 'hardware::sensors::sensorip::snmp::mode::components'; $self->{components_module} = ['sp', 'temperature', 'humidity', 'switch']; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } 1; __END__ =head1 MODE Check sensor components. =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'sp', 'temperature', 'humidity', 'switch'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=psu) Can also exclude specific instance: --filter=humidty,0 =item B<--absent-problem> Return an error if an entity is not 'present' (default is skipping) (comma seperated list) Can be specific or global: --absent-problem=temperature#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,status,regexp) It used before default thresholds (order stays). Example: --threshold-overload='temperature,CRITICAL,^(?!(normal)$)' =item B<--warning> Set warning threshold for temperatures and humidity (syntax: type,regexp,threshold) Example: --warning='temperature,.*,30' --warning='humidity,.*,90' =item B<--critical> Set critical threshold for temperature and humidity (syntax: type,regexp,threshold) Example: --critical='temperature,.*,40' =back =cut centreon-plugins-20220113/hardware/sensors/sensorip/snmp/plugin.pm000066400000000000000000000023521417000230700252020ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::sensorip::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}} = ( 'sensors' => 'hardware::sensors::sensorip::snmp::mode::sensors', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Sensor-IP sensors in SNMP. =cut centreon-plugins-20220113/hardware/sensors/sensormetrix/000077500000000000000000000000001417000230700232675ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/sensormetrix/em01/000077500000000000000000000000001417000230700240315ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/sensormetrix/em01/web/000077500000000000000000000000001417000230700246065ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/sensormetrix/em01/web/mode/000077500000000000000000000000001417000230700255325ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/sensormetrix/em01/web/mode/contact.pm000066400000000000000000000105041417000230700275230ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::sensormetrix::em01::web::mode::contact; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::http; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "hostname:s" => { name => 'hostname' }, "port:s" => { name => 'port', }, "proto:s" => { name => 'proto' }, "urlpath:s" => { name => 'url_path', default => "/index.htm?eL" }, "credentials" => { name => 'credentials' }, "basic" => { name => 'basic' }, "username:s" => { name => 'username' }, "password:s" => { name => 'password' }, "warning" => { name => 'warning' }, "critical" => { name => 'critical' }, "closed" => { name => 'closed' }, "timeout:s" => { name => 'timeout' }, }); $self->{status} = { closed => 'ok', opened => 'ok' }; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); my $label = 'opened'; $label = 'closed' if (defined($self->{option_results}->{closed})); if (defined($self->{option_results}->{critical})) { $self->{status}->{$label} = 'critical'; } elsif (defined($self->{option_results}->{warning})) { $self->{status}->{$label} = 'warning'; } $self->{http}->set_options(%{$self->{option_results}}); } sub run { my ($self, %options) = @_; my $webcontent = $self->{http}->request(); my $contact; if ($webcontent !~ /(.*)<\/body>/msi || $1 !~ /([NW]).*?:/) { $self->{output}->add_option_msg(short_msg => "Could not find door contact information."); $self->{output}->option_exit(); } $contact = $1; if ($contact eq 'N') { $self->{output}->output_add(severity => $self->{status}->{opened}, short_msg => sprintf("Door is opened.")); } else { $self->{output}->output_add(severity => $self->{status}->{closed}, short_msg => sprintf("Door is closed.")); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check sensor contact. =over 8 =item B<--hostname> IP Addr/FQDN of the webserver host =item B<--port> Port used by Apache =item B<--proto> Specify https if needed =item B<--urlpath> Set path to get server-status page in auto mode (Default: '/index.htm?eL') =item B<--credentials> Specify this option if you access server-status page with authentication =item B<--username> Specify username for authentication (Mandatory if --credentials is specified) =item B<--password> Specify password for authentication (Mandatory if --credentials is specified) =item B<--basic> Specify this option if you access server-status page over basic authentication and don't want a '401 UNAUTHORIZED' error to be logged on your webserver. Specify this option if you access server-status page over hidden basic authentication or you'll get a '404 NOT FOUND' error. (Use with --credentials) =item B<--timeout> Threshold for HTTP timeout =item B<--warning> Warning if door is opened (can set --close for closed door) =item B<--critical> Critical if door is opened (can set --close for closed door) =item B<--closed> Threshold is on closed door (default: opened) =back =cut centreon-plugins-20220113/hardware/sensors/sensormetrix/em01/web/mode/flood.pm000066400000000000000000000103731417000230700271770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::sensormetrix::em01::web::mode::flood; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::http; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "hostname:s" => { name => 'hostname' }, "port:s" => { name => 'port', }, "proto:s" => { name => 'proto' }, "urlpath:s" => { name => 'url_path' }, "credentials" => { name => 'credentials' }, "basic" => { name => 'basic' }, "username:s" => { name => 'username' }, "password:s" => { name => 'password' }, "warning" => { name => 'warning' }, "critical" => { name => 'critical' }, "dry" => { name => 'dry' }, "timeout:s" => { name => 'timeout' }, }); $self->{status} = { dry => 'ok', wet => 'ok' }; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); my $label = 'wet'; $label = 'dry' if (defined($self->{option_results}->{dry})); if (defined($self->{option_results}->{critical})) { $self->{status}->{$label} = 'critical'; } elsif (defined($self->{option_results}->{warning})) { $self->{status}->{$label} = 'warning'; } $self->{http}->set_options(%{$self->{option_results}}); } sub run { my ($self, %options) = @_; my $webcontent = $self->{http}->request(); my $flood; if ($webcontent !~ /(.*)<\/body>/msi || $1 !~ /(dry|wet)/i) { $self->{output}->add_option_msg(short_msg => "Could not find flood information (need to set good --urlpath option)."); $self->{output}->option_exit(); } $flood = lc($1); if ($flood eq 'dry') { $self->{output}->output_add(severity => $self->{status}->{dry}, short_msg => sprintf("Flood sensor is dry.")); } else { $self->{output}->output_add(severity => $self->{status}->{wet}, short_msg => sprintf("Flood sensor is wet.")); } $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check sensor flood. =over 8 =item B<--hostname> IP Addr/FQDN of the webserver host =item B<--port> Port used by Apache =item B<--proto> Specify https if needed =item B<--urlpath> Set path to get server-status page in auto mode (Default: '/') =item B<--credentials> Specify this option if you access server-status page with authentication =item B<--username> Specify username for authentication (Mandatory if --credentials is specified) =item B<--password> Specify password for authentication (Mandatory if --credentials is specified) =item B<--basic> Specify this option if you access server-status page over basic authentication and don't want a '401 UNAUTHORIZED' error to be logged on your webserver. Specify this option if you access server-status page over hidden basic authentication or you'll get a '404 NOT FOUND' error. (Use with --credentials) =item B<--timeout> Threshold for HTTP timeout =item B<--warning> Warning if flood sensor is wet (can set --dry for dry sensor) =item B<--critical> Critical if flood sensor is wet (can set --dry for dry sensor) =item B<--closed> Threshold is on dry sensor (default: wet) =back =cut centreon-plugins-20220113/hardware/sensors/sensormetrix/em01/web/mode/humidity.pm000066400000000000000000000113751417000230700277330ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::sensormetrix::em01::web::mode::humidity; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::http; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "hostname:s" => { name => 'hostname' }, "port:s" => { name => 'port', }, "proto:s" => { name => 'proto' }, "urlpath:s" => { name => 'url_path', default => "/index.htm?em" }, "credentials" => { name => 'credentials' }, "basic" => { name => 'basic' }, "username:s" => { name => 'username' }, "password:s" => { name => 'password' }, "warning:s" => { name => 'warning' }, "critical:s" => { name => 'critical' }, "timeout:s" => { name => 'timeout' }, }); $self->{http} = centreon::plugins::http->new(%options); 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(); } $self->{http}->set_options(%{$self->{option_results}}); } sub run { my ($self, %options) = @_; my $webcontent = $self->{http}->request(); my $humidity; if ($webcontent !~ /(.*)<\/body>/msi || $1 !~ /HU:\s*([0-9\.]+)/i) { $self->{output}->add_option_msg(short_msg => "Could not find humidity information."); $self->{output}->option_exit(); } $humidity = $1; $humidity = '0' . $humidity if ($humidity =~ /^\./); my $exit = $self->{perfdata}->threshold_check(value => $humidity, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit, short_msg => sprintf("Humidity: %.2f %%", $humidity)); $self->{output}->perfdata_add(label => "humidity", unit => '%', value => sprintf("%.2f", $humidity), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), ); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check sensor Humidity. =over 8 =item B<--hostname> IP Addr/FQDN of the webserver host =item B<--port> Port used by Apache =item B<--proto> Specify https if needed =item B<--urlpath> Set path to get server-status page in auto mode (Default: '/index.htm?em') =item B<--credentials> Specify this option if you access server-status page with authentication =item B<--username> Specify username for authentication (Mandatory if --credentials is specified) =item B<--password> Specify password for authentication (Mandatory if --credentials is specified) =item B<--basic> Specify this option if you access server-status page over basic authentication and don't want a '401 UNAUTHORIZED' error to be logged on your webserver. Specify this option if you access server-status page over hidden basic authentication or you'll get a '404 NOT FOUND' error. (Use with --credentials) =item B<--timeout> Threshold for HTTP timeout =item B<--warning> Warning Threshold for Humidity =item B<--critical> Critical Threshold for Humidity =back =cut centreon-plugins-20220113/hardware/sensors/sensormetrix/em01/web/mode/illumination.pm000066400000000000000000000115401417000230700305750ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::sensormetrix::em01::web::mode::illumination; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::http; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "hostname:s" => { name => 'hostname' }, "port:s" => { name => 'port', }, "proto:s" => { name => 'proto' }, "urlpath:s" => { name => 'url_path', default => "/index.htm?em" }, "credentials" => { name => 'credentials' }, "basic" => { name => 'basic' }, "username:s" => { name => 'username' }, "password:s" => { name => 'password' }, "warning:s" => { name => 'warning' }, "critical:s" => { name => 'critical' }, "timeout:s" => { name => 'timeout' }, }); $self->{http} = centreon::plugins::http->new(%options); 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(); } $self->{http}->set_options(%{$self->{option_results}}); } sub run { my ($self, %options) = @_; my $webcontent = $self->{http}->request(); my $illumination; if ($webcontent !~ /(.*)<\/body>/msi || $1 !~ /IL(?:\s*:\s*|\s*)([0-9\.]+)/i) { $self->{output}->add_option_msg(short_msg => "Could not find illumination information."); $self->{output}->option_exit(); } $illumination = $1; $illumination = '0' . $illumination if ($illumination =~ /^\./); my $exit = $self->{perfdata}->threshold_check(value => $illumination, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit, short_msg => sprintf("Illumination: %.1f", $illumination)); $self->{output}->perfdata_add(label => "illumination", value => sprintf("%.1f", $illumination), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), ); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check sensor Illumination. =over 8 =item B<--hostname> IP Addr/FQDN of the webserver host =item B<--port> Port used by Apache =item B<--proto> Specify https if needed =item B<--urlpath> Set path to get server-status page in auto mode (Default: '/index.htm?em') =item B<--credentials> Specify this option if you access server-status page with authentication =item B<--username> Specify username for authentication (Mandatory if --credentials is specified) =item B<--password> Specify password for authentication (Mandatory if --credentials is specified) =item B<--basic> Specify this option if you access server-status page over basic authentication and don't want a '401 UNAUTHORIZED' error to be logged on your webserver. Specify this option if you access server-status page over hidden basic authentication or you'll get a '404 NOT FOUND' error. (Use with --credentials) =item B<--timeout> Threshold for HTTP timeout =item B<--warning> Warning Threshold for Illumination =item B<--critical> Critical Threshold for Illumination =back =cut centreon-plugins-20220113/hardware/sensors/sensormetrix/em01/web/mode/temperature.pm000066400000000000000000000114651417000230700304340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::sensormetrix::em01::web::mode::temperature; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::http; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "hostname:s" => { name => 'hostname' }, "port:s" => { name => 'port', }, "proto:s" => { name => 'proto' }, "urlpath:s" => { name => 'url_path', default => "/index.htm?em" }, "credentials" => { name => 'credentials' }, "basic" => { name => 'basic' }, "username:s" => { name => 'username' }, "password:s" => { name => 'password' }, "warning:s" => { name => 'warning' }, "critical:s" => { name => 'critical' }, "timeout:s" => { name => 'timeout' }, }); $self->{http} = centreon::plugins::http->new(%options); 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(); } $self->{http}->set_options(%{$self->{option_results}}); } sub run { my ($self, %options) = @_; my $webcontent = $self->{http}->request(); if ($webcontent !~ /(.*)<\/body>/msi || $1 !~ /T([CF]):\s*([0-9\.]+)/i) { $self->{output}->add_option_msg(short_msg => "Could not find temperature information."); $self->{output}->option_exit(); } my ($temperature, $unit) = ($2, $1); $temperature = '0' . $temperature if ($temperature =~ /^\./); my $exit = $self->{perfdata}->threshold_check(value => $temperature, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit, short_msg => sprintf("Temperature: %.2f %s", $temperature, $unit)); $self->{output}->perfdata_add(label => "temperature", unit => $unit, value => sprintf("%.2f", $temperature), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), ); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check sensor Temperature. =over 8 =item B<--hostname> IP Addr/FQDN of the webserver host =item B<--port> Port used by Apache =item B<--proto> Specify https if needed =item B<--urlpath> Set path to get server-status page in auto mode (Default: '/index.htm?em') =item B<--credentials> Specify this option if you access server-status page with authentication =item B<--username> Specify username for authentication (Mandatory if --credentials is specified) =item B<--password> Specify password for authentication (Mandatory if --credentials is specified) =item B<--basic> Specify this option if you access server-status page over basic authentication and don't want a '401 UNAUTHORIZED' error to be logged on your webserver. Specify this option if you access server-status page over hidden basic authentication or you'll get a '404 NOT FOUND' error. (Use with --credentials) =item B<--timeout> Threshold for HTTP timeout =item B<--warning> Warning Threshold for Temperature =item B<--critical> Critical Threshold for Temperature =back =cut centreon-plugins-20220113/hardware/sensors/sensormetrix/em01/web/mode/thermistor.pm000066400000000000000000000115371417000230700302770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::sensormetrix::em01::web::mode::thermistor; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::http; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "hostname:s" => { name => 'hostname' }, "port:s" => { name => 'port', }, "proto:s" => { name => 'proto' }, "urlpath:s" => { name => 'url_path', default => "/index.htm?eR" }, "credentials" => { name => 'credentials' }, "basic" => { name => 'basic' }, "username:s" => { name => 'username' }, "password:s" => { name => 'password' }, "warning:s" => { name => 'warning' }, "critical:s" => { name => 'critical' }, "timeout:s" => { name => 'timeout' }, }); $self->{http} = centreon::plugins::http->new(%options); 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(); } $self->{http}->set_options(%{$self->{option_results}}); } sub run { my ($self, %options) = @_; my $webcontent = $self->{http}->request(); if ($webcontent !~ /(.*)<\/body>/msi || $1 !~ /R([CF])\s*([0-9\.]+)/i) { $self->{output}->add_option_msg(short_msg => "Could not find thermistor temperature information."); $self->{output}->option_exit(); } my ($temperature, $unit) = ($2, $1); $temperature = '0' . $temperature if ($temperature =~ /^\./); my $exit = $self->{perfdata}->threshold_check(value => $temperature, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit, short_msg => sprintf("Temperature: %.2f %s", $temperature, $unit)); $self->{output}->perfdata_add(label => "temperature", unit => $unit, value => sprintf("%.2f", $temperature), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), ); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check sensor thermistor temperature. =over 8 =item B<--hostname> IP Addr/FQDN of the webserver host =item B<--port> Port used by Apache =item B<--proto> Specify https if needed =item B<--urlpath> Set path to get server-status page in auto mode (Default: '/index.htm?eR') =item B<--credentials> Specify this option if you access server-status page with authentication =item B<--username> Specify username for authentication (Mandatory if --credentials is specified) =item B<--password> Specify password for authentication (Mandatory if --credentials is specified) =item B<--basic> Specify this option if you access server-status page over basic authentication and don't want a '401 UNAUTHORIZED' error to be logged on your webserver. Specify this option if you access server-status page over hidden basic authentication or you'll get a '404 NOT FOUND' error. (Use with --credentials) =item B<--timeout> Threshold for HTTP timeout =item B<--warning> Warning Threshold for Thermistor Temperature =item B<--critical> Critical Threshold for Thermistor Temperature =back =cut centreon-plugins-20220113/hardware/sensors/sensormetrix/em01/web/mode/voltage.pm000066400000000000000000000113541417000230700275350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::sensormetrix::em01::web::mode::voltage; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::http; sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "hostname:s" => { name => 'hostname' }, "port:s" => { name => 'port', }, "proto:s" => { name => 'proto' }, "urlpath:s" => { name => 'url_path', default => "/index.htm?ev" }, "credentials" => { name => 'credentials' }, "basic" => { name => 'basic' }, "username:s" => { name => 'username' }, "password:s" => { name => 'password' }, "warning:s" => { name => 'warning' }, "critical:s" => { name => 'critical' }, "timeout:s" => { name => 'timeout' }, }); $self->{http} = centreon::plugins::http->new(%options); 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(); } $self->{http}->set_options(%{$self->{option_results}}); } sub run { my ($self, %options) = @_; my $webcontent = $self->{http}->request(); my $voltage; if ($webcontent !~ /(.*)<\/body>/msi || $1 !~ /CV\s*([0-9\.]+)/i) { $self->{output}->add_option_msg(short_msg => "Could not find voltage information."); $self->{output}->option_exit(); } $voltage = $1; $voltage = '0' . $voltage if ($voltage =~ /^\./); my $exit = $self->{perfdata}->threshold_check(value => $voltage, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit, short_msg => sprintf("Voltage: %.2f V", $voltage)); $self->{output}->perfdata_add(label => "voltage", unit => 'V', value => sprintf("%.2f", $voltage), warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), ); $self->{output}->display(); $self->{output}->exit(); } 1; __END__ =head1 MODE Check sensor voltage. =over 8 =item B<--hostname> IP Addr/FQDN of the webserver host =item B<--port> Port used by Apache =item B<--proto> Specify https if needed =item B<--urlpath> Set path to get server-status page in auto mode (Default: '/index.htm?ev') =item B<--credentials> Specify this option if you access server-status page with authentication =item B<--username> Specify username for authentication (Mandatory if --credentials is specified) =item B<--password> Specify password for authentication (Mandatory if --credentials is specified) =item B<--basic> Specify this option if you access server-status page over basic authentication and don't want a '401 UNAUTHORIZED' error to be logged on your webserver. Specify this option if you access server-status page over hidden basic authentication or you'll get a '404 NOT FOUND' error. (Use with --credentials) =item B<--timeout> Threshold for HTTP timeout =item B<--warning> Warning Threshold for Voltage =item B<--critical> Critical Threshold for Voltage =back =cut centreon-plugins-20220113/hardware/sensors/sensormetrix/em01/web/plugin.pm000066400000000000000000000034351417000230700264470ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::sensormetrix::em01::web::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} = '0.1'; %{$self->{modes}} = ( 'contact' => 'hardware::sensors::sensormetrix::em01::web::mode::contact', 'temperature' => 'hardware::sensors::sensormetrix::em01::web::mode::temperature', 'humidity' => 'hardware::sensors::sensormetrix::em01::web::mode::humidity', 'illumination' => 'hardware::sensors::sensormetrix::em01::web::mode::illumination', 'flood' => 'hardware::sensors::sensormetrix::em01::web::mode::flood', 'thermistor' => 'hardware::sensors::sensormetrix::em01::web::mode::thermistor', 'voltage' => 'hardware::sensors::sensormetrix::em01::web::mode::voltage', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Sensormetrix em01 sensors through webpage. =cut centreon-plugins-20220113/hardware/sensors/serverscheck/000077500000000000000000000000001417000230700232145ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/serverscheck/sensorgateway/000077500000000000000000000000001417000230700261075ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/serverscheck/sensorgateway/snmp/000077500000000000000000000000001417000230700270645ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/serverscheck/sensorgateway/snmp/mode/000077500000000000000000000000001417000230700300105ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/serverscheck/sensorgateway/snmp/mode/components/000077500000000000000000000000001417000230700321755ustar00rootroot00000000000000sensors.pm000066400000000000000000000056571417000230700341650ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/serverscheck/sensorgateway/snmp/mode/components# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::serverscheck::sensorgateway::snmp::mode::components::sensors; use strict; use warnings; my $oid_control = '.1.3.6.1.4.1.17095.3'; my $list_oids = { 1 => 1, 2 => 5, 3 => 9, 4 => 13, 5 => 17, }; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_control }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking sensors"); $self->{components}->{sensors} = {name => 'sensors', total => 0, skip => 0}; return if ($self->check_filter(section => 'sensors')); foreach my $i (sort keys %{$list_oids}) { if (!defined($self->{results}->{$oid_control}->{'.1.3.6.1.4.1.17095.3.' . ($list_oids->{$i} + 1) . '.0'}) || $self->{results}->{$oid_control}->{'.1.3.6.1.4.1.17095.3.' . ($list_oids->{$i} + 1) . '.0'} !~ /([0-9\.]+)/) { $self->{output}->output_add(long_msg => sprintf("skip sensor '%s': no values", $i)); next; } my $name = $self->{results}->{$oid_control}->{'.1.3.6.1.4.1.17095.3.' . ($list_oids->{$i}) . '.0'}; my $value = $self->{results}->{$oid_control}->{'.1.3.6.1.4.1.17095.3.' . ($list_oids->{$i} + 1) . '.0'}; next if ($self->check_filter(section => 'sensors', instance => $name)); $self->{components}->{sensors}->{total}++; $self->{output}->output_add(long_msg => sprintf("sensor '%s' value is %s.", $name, $value)); my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'sensors', instance => $name, value => $value); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("sensor '%s' value is %s", $name, $value)); } $self->{output}->perfdata_add( label => $name, value => $value, warning => $warn, critical => $crit ); } } 1; centreon-plugins-20220113/hardware/sensors/serverscheck/sensorgateway/snmp/mode/sensors.pm000066400000000000000000000053701417000230700320470ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::serverscheck::sensorgateway::snmp::mode::sensors; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^sensors$'; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { output => [ ['open', 'CRITICAL'], ['close', 'OK'] ] }; $self->{components_path} = 'hardware::sensors::serverscheck::sensorgateway::snmp::mode::components'; $self->{components_module} = ['sensors']; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } 1; __END__ =head1 MODE Check sensors components (Sensor Probes). =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'sensors'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=sensors) Can also exclude specific instance: --filter=sensors,Inter =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,status,regexp) It used before default thresholds (order stays). Example: --threshold-overload='output,CRITICAL,^(?!(off)$)' =item B<--warning> Set warning threshold for temperatures and humidity (syntax: type,regexp,threshold) Example: --warning='sensors,Int. Temp,30' --warning='sensors,Fuel Level,50:' =item B<--critical> Set critical threshold for temperature and humidity (syntax: type,regexp,threshold) Example: --warning='sensors,Int. Temp,35' --warning='sensors,Fuel Level,40:' =back =cut centreon-plugins-20220113/hardware/sensors/serverscheck/sensorgateway/snmp/plugin.pm000066400000000000000000000024241417000230700307220ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::serverscheck::sensorgateway::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}} = ( 'sensors' => 'hardware::sensors::serverscheck::sensorgateway::snmp::mode::sensors', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Sensorgateway sensors in SNMP. =cut centreon-plugins-20220113/hardware/sensors/temperhum/000077500000000000000000000000001417000230700225335ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/temperhum/local/000077500000000000000000000000001417000230700236255ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/temperhum/local/mode/000077500000000000000000000000001417000230700245515ustar00rootroot00000000000000centreon-plugins-20220113/hardware/sensors/temperhum/local/mode/environment.pm000066400000000000000000000151211417000230700274530ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::temperhum::local::mode::environment; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'drive', type => 1, cb_prefix_output => 'prefix_device_output', message_multiple => 'All measures are OK' }, ]; $self->{maps_counters}->{drive} = [ { label => 'humidity', set => { key_values => [ { name => 'humidity' }, { name => 'display' } ], output_template => 'Humidity: %.2f%%', perfdatas => [ { label => 'humidity', value => 'humidity', template => '%.2f', unit => '%', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], }, }, { label => 'temperature', set => { key_values => [ { name => 'temperature' }, { name => 'dewpoint' }, { name => 'display' } ], output_template => 'Temperature: %.2f C', perfdatas => [ { label => 'temperature', value => 'temperature', template => '%.2f', unit => 'C', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], }, }, { label => 'dew-point', set => { key_values => [ { name => 'dewpoint' }, { name => 'display' } ], output_template => 'Dew Point : %.2f C', perfdatas => [ { label => 'dew_point', value => 'dewpoint', template => '%.2f', unit => 'C', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, { label => 'delta', set => { key_values => [ { name => 'delta' }, { name => 'display' } ], output_template => 'Delta (Temp - Dew) : %.2f C', perfdatas => [ { label => 'delta', value => 'delta', template => '%.2f', unit => 'C', min => 0, label_extra_instance => 1, instance_use => 'display' }, ], } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "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 => 'tempered' }, "command-path:s" => { name => 'command_path', default => '/opt/PCsensor/TEMPered/utils/' }, "command-options:s" => { name => 'command_options' }, "filter-drive:s" => { name => 'filter_drive', default => '.*' }, }); return $self; } sub prefix_device_output { my ($self, %options) = @_; return "'" . $options{instance_value}->{display} . "' "; } sub manage_selection { my ($self, %options) = @_; $self->{drive} = {}; 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}); foreach (split(/\n/, $stdout)) { next if !/(\/dev\/[a-z0-9]+).*temperature\s(\d*\.?\d+).*relative\shumidity\s(\d*\.?\d+).*dew\spoint\s(\d*\.?\d+)/; my ($drive, $temp, $hum, $dew) = ($1, $2, $3, $4); next if ($drive !~ /$self->{option_results}->{filter_drive}/); $self->{drive}->{$drive} = { humidity => $hum, temperature => $temp, dewpoint => $dew, delta => ($temp - $dew), display => $drive }; } if (scalar(keys %{$self->{drive}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No informations gathered, please check your filters"); $self->{output}->option_exit(); } } 1; __END__ =head1 MODE Check metrics from TemPerHum sensors =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: 'tempered'). Can be changed if you have output in a file. =item B<--command-path> Command path (Default: '/usr/sbin'). =item B<--command-options> Command options (Default: '-u'). =item B<--filter-drive> Filter by drive name (e.g --filter-drive raw4) =item B<--warning-*> Threshold Warning Can be: 'temperature', 'humidity', 'dew-point', 'delta' =item B<--critical-*> Threshold Critical Can be: 'temperature', 'humidity', 'dew-point', 'delta' =back =cut centreon-plugins-20220113/hardware/sensors/temperhum/local/plugin.pm000066400000000000000000000024261417000230700254650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::sensors::temperhum::local::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); $self->{version} = '0.1'; %{$self->{modes}} = ( 'environment' => 'hardware::sensors::temperhum::local::mode::environment', ); return $self;} 1; __END__ =head1 PLUGIN DESCRIPTION Check temperature, humidity and dew point for TemPerHum Sensors (the plugin can use SSH). =cut centreon-plugins-20220113/hardware/server/000077500000000000000000000000001417000230700203375ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/cisco/000077500000000000000000000000001417000230700214375ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/cisco/ucs/000077500000000000000000000000001417000230700222315ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/cisco/ucs/snmp/000077500000000000000000000000001417000230700232065ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/cisco/ucs/snmp/mode/000077500000000000000000000000001417000230700241325ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/cisco/ucs/snmp/mode/auditlogs.pm000066400000000000000000000173611417000230700264730ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::cisco::ucs::snmp::mode::auditlogs; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::statefile; use POSIX; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); my $map_severity = { 0 => 'cleared', 1 => 'info', 2 => 'condition', 3 => 'warning', 4 => 'minor', 5 => 'major', 6 => 'critical' }; sub custom_status_output { my ($self, %options) = @_; return sprintf( 'audit [severity: %s] [dn: %s] [description: %s] %s', $self->{result_values}->{severity}, $self->{result_values}->{dn}, $self->{result_values}->{description}, scalar(localtime($self->{result_values}->{created})) ); } sub prefix_global_output { my ($self, %options) = @_; return 'Audit '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', }, { name => 'alarms', type => 2, message_multiple => '0 problem(s) detected', display_counter_problem => { nlabel => 'audit.problems.current.count', min => 0 }, group => [ { name => 'alarm', skipped_code => { -11 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'audit-total', nlabel => 'audit.total.count', display_ok => 0, set => { key_values => [ { name => 'total' } ], output_template => 'total: %s', perfdatas => [ { template => '%s', min => 0 } ] } } ]; foreach (values %$map_severity) { push @{$self->{maps_counters}->{global}}, { label => 'audit-' . $_, nlabel => 'audit.' . $_ . '.count', display_ok => 0, set => { key_values => [ { name => $_ }, { name => 'total' } ], output_template => $_ . ': %s', perfdatas => [ { template => '%s', min => 0, max => 'total' } ] } }; } $self->{maps_counters}->{alarm} = [ { label => 'status', type => 2, warning_default => '%{severity} =~ /minor|warning/', critical_default => '%{severity} =~ /major|critical/', set => { key_values => [ { name => 'dn' }, { name => 'severity' }, { name => 'description' }, { name => 'created' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-message:s' => { name => 'filter_message' }, 'retention:s' => { name => 'retention' }, 'memory' => { name => 'memory' } }); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->check_options(%options); } } sub get_timestamp { my ($self, %options) = @_; my $value = unpack('H*', $options{value}); $value =~ /^([0-9a-z]{4})([0-9a-z]{2})([0-9a-z]{2})([0-9a-z]{2})([0-9a-z]{2})([0-9a-z]{2})/; my $currentTmsp = mktime(hex($6), hex($5), hex($4), hex($3), hex($2) - 1, hex($1) - 1900); return $currentTmsp; } my $mapping = { dn => { oid => '.1.3.6.1.4.1.9.9.719.1.2.17.1.2' }, # cucsAaaModLRDn description => { oid => '.1.3.6.1.4.1.9.9.719.1.2.17.1.9' }, # cucsAaaModLRDescr created => { oid => '.1.3.6.1.4.1.9.9.719.1.2.17.1.8' }, # cucsAaaModLRCreated severity => { oid => '.1.3.6.1.4.1.9.9.719.1.2.17.1.12', map => $map_severity } # cucsAaaModLRSeverity }; sub manage_selection { my ($self, %options) = @_; my $datas = {}; my ($start, $last_instance); if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->read(statefile => 'cache_ciscoucs_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . $self->{mode}); $start = $self->{statefile_cache}->get(name => 'start'); $start = $start - 1 if (defined($start)); } my $snmp_result = $options{snmp}->get_multiple_table( oids => [ map({ oid => $_->{oid}, start => $_->{oid} . (defined($start) ? '.' . $start : '') }, values(%$mapping)) ], return_type => 1 ); $self->{global} = { total => 0, cleared => 0, info => 0, condition => 0, warning => 0, minor => 0, major => 0, critical => 0 }; $self->{alarms} = { global => { alarm => {} } }; my ($i, $current_time) = (1, time()); foreach my $oid ($options{snmp}->oid_lex_sort(keys %$snmp_result)) { next if ($oid !~ /^$mapping->{dn}->{oid}\.(\d+)$/); my $instance = $1; if (defined($self->{option_results}->{memory})) { $last_instance = $instance; next if (defined($start) && ($start + 1) >= $instance); # we skip last one from previous check) } my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); $result->{description} = centreon::plugins::misc::trim($result->{description}); $result->{created} = $self->get_timestamp(value => $result->{created}); if (defined($self->{option_results}->{retention})) { next if ($current_time - $result->{created} > $self->{option_results}->{retention}); } $self->{global}->{total}++; next if (defined($self->{option_results}->{filter_message}) && $self->{option_results}->{filter_message} ne '' && $result->{description} !~ /$self->{option_results}->{filter_message}/); $self->{alarms}->{global}->{alarm}->{$i} = $result; $self->{global}->{ $result->{severity} }++; $i++; } if (defined($self->{option_results}->{memory})) { $datas->{start} = $last_instance; $self->{statefile_cache}->write(data => $datas); } } 1; __END__ =head1 MODE Check audit logs. =over 8 =item B<--warning-status> Set warning threshold for status (Default: '%{severity} =~ /minor|warning/') Can used special variables like: %{severity}, %{description}, %{dn} =item B<--critical-status> Set critical threshold for status (Default: '%{severity} =~ /major|critical/'). Can used special variables like: %{severity}, %{description}, %{dn} =item B<--memory> Only check new audit. =item B<--filter-message> Filter on event message. (Default: none) =item B<--retention> Event older (current time - retention time) is not checked (in seconds). =back =cut centreon-plugins-20220113/hardware/server/cisco/ucs/snmp/mode/components/000077500000000000000000000000001417000230700263175ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/cisco/ucs/snmp/mode/components/blade.pm000066400000000000000000000075631417000230700277370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::cisco::ucs::snmp::mode::components::blade; use strict; use warnings; use hardware::server::cisco::ucs::snmp::mode::components::resources qw(%mapping_presence %mapping_overall_status); # In MIB 'CISCO-UNIFIED-COMPUTING-EQUIPMENT-MIB' my $mapping1 = { cucsComputeBladePresence => { oid => '.1.3.6.1.4.1.9.9.719.1.9.2.1.45', map => \%mapping_presence } }; my $mapping2 = { cucsComputeBladeOperState => { oid => '.1.3.6.1.4.1.9.9.719.1.9.2.1.42', map => \%mapping_overall_status } }; my $oid_cucsComputeBladeDn = '.1.3.6.1.4.1.9.9.719.1.9.2.1.2'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping1->{cucsComputeBladePresence}->{oid} }, { oid => $mapping2->{cucsComputeBladeOperState}->{oid} }, { oid => $oid_cucsComputeBladeDn }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking blades"); $self->{components}->{blade} = {name => 'blades', total => 0, skip => 0}; return if ($self->check_filter(section => 'blade')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_cucsComputeBladeDn}})) { $oid =~ /\.(\d+)$/; my $instance = $1; my $blade_dn = $self->{results}->{$oid_cucsComputeBladeDn}->{$oid}; my $result = $self->{snmp}->map_instance(mapping => $mapping1, results => $self->{results}->{$mapping1->{cucsComputeBladePresence}->{oid}}, instance => $instance); my $result2 = $self->{snmp}->map_instance(mapping => $mapping2, results => $self->{results}->{$mapping2->{cucsComputeBladeOperState}->{oid}}, instance => $instance); next if ($self->absent_problem(section => 'blade', instance => $blade_dn)); next if ($self->check_filter(section => 'blade', instance => $blade_dn)); $self->{output}->output_add( long_msg => sprintf( "blade '%s' state is '%s' [presence: %s].", $blade_dn, $result2->{cucsComputeBladeOperState}, $result->{cucsComputeBladePresence} ) ); my $exit = $self->get_severity(section => 'blade.presence', label => 'default.presence', value => $result->{cucsComputeBladePresence}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "blade '%s' presence is: '%s'", $blade_dn, $result->{cucsComputeBladePresence} ) ); next; } $self->{components}->{blade}->{total}++; $exit = $self->get_severity(section => 'blade.overall_status', label => 'default.overall_status', value => $result2->{cucsComputeBladeOperState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "blade '%s' state is '%s'", $blade_dn, $result2->{cucsComputeBladeOperState} ) ); } } } 1; centreon-plugins-20220113/hardware/server/cisco/ucs/snmp/mode/components/chassis.pm000066400000000000000000000060221417000230700303120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::cisco::ucs::snmp::mode::components::chassis; use strict; use warnings; use hardware::server::cisco::ucs::snmp::mode::components::resources qw(%mapping_operability); # In MIB 'CISCO-UNIFIED-COMPUTING-EQUIPMENT-MIB' # Don't do the 'presence'. Is 'unknown' ??!!! my $mapping1 = { cucsEquipmentChassisOperState => { oid => '.1.3.6.1.4.1.9.9.719.1.15.7.1.27', map => \%mapping_operability } }; my $oid_cucsEquipmentChassisDn = '.1.3.6.1.4.1.9.9.719.1.15.7.1.2'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping1->{cucsEquipmentChassisOperState}->{oid} }, { oid => $oid_cucsEquipmentChassisDn }; } 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')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_cucsEquipmentChassisDn}})) { $oid =~ /\.(\d+)$/; my $instance = $1; my $chassis_dn = $self->{results}->{$oid_cucsEquipmentChassisDn}->{$oid}; my $result = $self->{snmp}->map_instance(mapping => $mapping1, results => $self->{results}->{$mapping1->{cucsEquipmentChassisOperState}->{oid}}, instance => $instance); next if ($self->absent_problem(section => 'chassis', instance => $chassis_dn)); next if ($self->check_filter(section => 'chassis', instance => $chassis_dn)); $self->{components}->{chassis}->{total}++; $self->{output}->output_add( long_msg => sprintf( "chassis '%s' state is '%s'.", $chassis_dn, $result->{cucsEquipmentChassisOperState} ) ); my $exit = $self->get_severity(section => 'chassis.operability', label => 'default.operability', value => $result->{cucsEquipmentChassisOperState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "chassis '%s' state is '%s'", $chassis_dn, $result->{cucsEquipmentChassisOperState} ) ); } } } 1; centreon-plugins-20220113/hardware/server/cisco/ucs/snmp/mode/components/cpu.pm000066400000000000000000000075131417000230700274520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::cisco::ucs::snmp::mode::components::cpu; use strict; use warnings; use hardware::server::cisco::ucs::snmp::mode::components::resources qw(%mapping_presence %mapping_operability); # In MIB 'CISCO-UNIFIED-COMPUTING-PROCESSOR-MIB' my $mapping1 = { cucsProcessorUnitPresence => { oid => '.1.3.6.1.4.1.9.9.719.1.41.9.1.13', map => \%mapping_presence } }; my $mapping2 = { cucsProcessorUnitOperState => { oid => '.1.3.6.1.4.1.9.9.719.1.41.9.1.9', map => \%mapping_operability } }; my $oid_cucsProcessorUnitDn = '.1.3.6.1.4.1.9.9.719.1.41.9.1.2'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping1->{cucsProcessorUnitPresence}->{oid} }, { oid => $mapping2->{cucsProcessorUnitOperState}->{oid} }, { oid => $oid_cucsProcessorUnitDn }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking cpus"); $self->{components}->{cpu} = {name => 'cpus', total => 0, skip => 0}; return if ($self->check_filter(section => 'cpu')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_cucsProcessorUnitDn}})) { $oid =~ /\.(\d+)$/; my $instance = $1; my $cpu_dn = $self->{results}->{$oid_cucsProcessorUnitDn}->{$oid}; my $result = $self->{snmp}->map_instance(mapping => $mapping1, results => $self->{results}->{$mapping1->{cucsProcessorUnitPresence}->{oid}}, instance => $instance); my $result2 = $self->{snmp}->map_instance(mapping => $mapping2, results => $self->{results}->{$mapping2->{cucsProcessorUnitOperState}->{oid}}, instance => $instance); next if ($self->absent_problem(section => 'cpu', instance => $cpu_dn)); next if ($self->check_filter(section => 'cpu', instance => $cpu_dn)); $self->{output}->output_add( long_msg => sprintf( "cpu '%s' state is '%s' [presence: %s].", $cpu_dn, $result2->{cucsProcessorUnitOperState}, $result->{cucsProcessorUnitPresence} ) ); my $exit = $self->get_severity(section => 'cpu.presence', label => 'default.presence', value => $result->{cucsProcessorUnitPresence}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "cpu '%s' presence is: '%s'", $cpu_dn, $result->{cucsProcessorUnitPresence} ) ); next; } $self->{components}->{cpu}->{total}++; $exit = $self->get_severity(section => 'cpu.operability', label => 'default.operability', value => $result2->{cucsProcessorUnitOperState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "cpu '%s' state is '%s'", $cpu_dn, $result2->{cucsProcessorUnitOperState} ) ); } } } 1; centreon-plugins-20220113/hardware/server/cisco/ucs/snmp/mode/components/fan.pm000066400000000000000000000075101417000230700274240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::cisco::ucs::snmp::mode::components::fan; use strict; use warnings; use hardware::server::cisco::ucs::snmp::mode::components::resources qw(%mapping_presence %mapping_operability); # In MIB 'CISCO-UNIFIED-COMPUTING-EQUIPMENT-MIB' my $mapping1 = { cucsEquipmentFanPresence => { oid => '.1.3.6.1.4.1.9.9.719.1.15.12.1.13', map => \%mapping_presence }, }; my $mapping2 = { cucsEquipmentFanOperState => { oid => '.1.3.6.1.4.1.9.9.719.1.15.12.1.9', map => \%mapping_operability }, }; my $oid_cucsEquipmentFanDn = '.1.3.6.1.4.1.9.9.719.1.15.12.1.2'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping1->{cucsEquipmentFanPresence}->{oid} }, { oid => $mapping2->{cucsEquipmentFanOperState}->{oid} }, { oid => $oid_cucsEquipmentFanDn }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking fans"); $self->{components}->{fan} = {name => 'fans', total => 0, skip => 0}; return if ($self->check_filter(section => 'fan')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_cucsEquipmentFanDn}})) { $oid =~ /\.(\d+)$/; my $instance = $1; my $fan_dn = $self->{results}->{$oid_cucsEquipmentFanDn}->{$oid}; my $result = $self->{snmp}->map_instance(mapping => $mapping1, results => $self->{results}->{$mapping1->{cucsEquipmentFanPresence}->{oid}}, instance => $instance); my $result2 = $self->{snmp}->map_instance(mapping => $mapping2, results => $self->{results}->{$mapping2->{cucsEquipmentFanOperState}->{oid}}, instance => $instance); next if ($self->absent_problem(section => 'fan', instance => $fan_dn)); next if ($self->check_filter(section => 'fan', instance => $fan_dn)); $self->{output}->output_add( long_msg => sprintf( "fan '%s' state is '%s' [presence: %s].", $fan_dn, $result2->{cucsEquipmentFanOperState}, $result->{cucsEquipmentFanPresence} ) ); my $exit = $self->get_severity(section => 'fan.presence', label => 'default.presence', value => $result->{cucsEquipmentFanPresence}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "fan '%s' presence is: '%s'", $fan_dn, $result->{cucsEquipmentFanPresence} ) ); next; } $self->{components}->{fan}->{total}++; $exit = $self->get_severity(section => 'fan.operability', label => 'default.operability', value => $result2->{cucsEquipmentFanOperState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "fan '%s' state is '%s'", $fan_dn, $result2->{cucsEquipmentFanOperState} ) ); } } } 1; centreon-plugins-20220113/hardware/server/cisco/ucs/snmp/mode/components/fex.pm000066400000000000000000000076031417000230700274450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::cisco::ucs::snmp::mode::components::fex; use strict; use warnings; use hardware::server::cisco::ucs::snmp::mode::components::resources qw(%mapping_presence %mapping_operability); # In MIB 'CISCO-UNIFIED-COMPUTING-EQUIPMENT-MIB' my $mapping1 = { cucsEquipmentFexPresence => { oid => '.1.3.6.1.4.1.9.9.719.1.15.19.1.24', map => \%mapping_presence }, }; my $mapping2 = { cucsEquipmentFexOperState => { oid => '.1.3.6.1.4.1.9.9.719.1.15.19.1.21', map => \%mapping_operability }, }; my $oid_cucsEquipmentFexDn = '.1.3.6.1.4.1.9.9.719.1.15.19.1.2'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping1->{cucsEquipmentFexPresence}->{oid} }, { oid => $mapping2->{cucsEquipmentFexOperState}->{oid} }, { oid => $oid_cucsEquipmentFexDn }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking fabric extenders"); $self->{components}->{fex} = {name => 'fabric extenders', total => 0, skip => 0}; return if ($self->check_filter(section => 'fex')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_cucsEquipmentFexDn}})) { $oid =~ /\.(\d+)$/; my $instance = $1; my $fex_dn = $self->{results}->{$oid_cucsEquipmentFexDn}->{$oid}; my $result = $self->{snmp}->map_instance(mapping => $mapping1, results => $self->{results}->{$mapping1->{cucsEquipmentFexPresence}->{oid}}, instance => $instance); my $result2 = $self->{snmp}->map_instance(mapping => $mapping2, results => $self->{results}->{$mapping2->{cucsEquipmentFexOperState}->{oid}}, instance => $instance); next if ($self->absent_problem(section => 'fex', instance => $fex_dn)); next if ($self->check_filter(section => 'fex', instance => $fex_dn)); $self->{output}->output_add( long_msg => sprintf( "Fabric extender '%s' state is '%s' [presence: %s].", $fex_dn, $result2->{cucsEquipmentFexOperState}, $result->{cucsEquipmentFexPresence} ) ); my $exit = $self->get_severity(section => 'fex.presence', label => 'default.presence', value => $result->{cucsEquipmentFexPresence}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Fabric extender '%s' presence is: '%s'", $fex_dn, $result->{cucsEquipmentFexPresence} ) ); next; } $self->{components}->{fex}->{total}++; $exit = $self->get_severity(section => 'fex.presence', label => 'default.operability', value => $result2->{cucsEquipmentFexOperState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Fabric extender '%s' state is '%s'.", $fex_dn, $result2->{cucsEquipmentFexOperState} ) ); } } } 1; centreon-plugins-20220113/hardware/server/cisco/ucs/snmp/mode/components/iocard.pm000066400000000000000000000077701417000230700301310ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::cisco::ucs::snmp::mode::components::iocard; use strict; use warnings; use hardware::server::cisco::ucs::snmp::mode::components::resources qw(%mapping_presence %mapping_operability); # In MIB 'CISCO-UNIFIED-COMPUTING-EQUIPMENT-MIB' my $mapping1 = { cucsEquipmentIOCardPresence => { oid => '.1.3.6.1.4.1.9.9.719.1.15.30.1.31', map => \%mapping_presence }, }; my $mapping2 = { cucsEquipmentIOCardOperState => { oid => '.1.3.6.1.4.1.9.9.719.1.15.30.1.25', map => \%mapping_operability }, }; my $oid_cucsEquipmentIOCardDn = '.1.3.6.1.4.1.9.9.719.1.15.30.1.2'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping1->{cucsEquipmentIOCardPresence}->{oid} }, { oid => $mapping2->{cucsEquipmentIOCardOperState}->{oid} }, { oid => $oid_cucsEquipmentIOCardDn }; } sub check { my ($self) = @_; # In MIB 'CISCO-UNIFIED-COMPUTING-EQUIPMENT-MIB' $self->{output}->output_add(long_msg => "Checking io cards"); $self->{components}->{iocard} = {name => 'io cards', total => 0, skip => 0}; return if ($self->check_filter(section => 'iocard')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_cucsEquipmentIOCardDn}})) { $oid =~ /\.(\d+)$/; my $instance = $1; my $iocard_dn = $self->{results}->{$oid_cucsEquipmentIOCardDn}->{$oid}; my $result = $self->{snmp}->map_instance(mapping => $mapping1, results => $self->{results}->{$mapping1->{cucsEquipmentIOCardPresence}->{oid}}, instance => $instance); my $result2 = $self->{snmp}->map_instance(mapping => $mapping2, results => $self->{results}->{$mapping2->{cucsEquipmentIOCardOperState}->{oid}}, instance => $instance); next if ($self->absent_problem(section => 'iocard', instance => $iocard_dn)); next if ($self->check_filter(section => 'iocard', instance => $iocard_dn)); $self->{output}->output_add( long_msg => sprintf( "IO cards '%s' state is '%s' [presence: %s].", $iocard_dn, $result2->{cucsEquipmentIOCardOperState}, $result->{cucsEquipmentIOCardPresence} ) ); my $exit = $self->get_severity(section => 'iocard.presence', label => 'default.presence', value => $result->{cucsEquipmentIOCardPresence}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "IO cards '%s' presence is: '%s'", $iocard_dn, $result->{cucsEquipmentIOCardPresence} ) ); next; } $self->{components}->{iocard}->{total}++; $exit = $self->get_severity(section => 'iocard.operability', label => 'default.operability', value => $result2->{cucsEquipmentIOCardOperState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "IO cards '%s' state is '%s'.", $iocard_dn, $result2->{cucsEquipmentIOCardOperState} ) ); } } } 1; centreon-plugins-20220113/hardware/server/cisco/ucs/snmp/mode/components/localdisk.pm000066400000000000000000000077371417000230700306400ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::cisco::ucs::snmp::mode::components::localdisk; use strict; use warnings; use hardware::server::cisco::ucs::snmp::mode::components::resources qw(%mapping_presence %mapping_operability); # In MIB 'CISCO-UNIFIED-COMPUTING-STORAGE-MIB' my $mapping1 = { cucsStorageLocalDiskPresence => { oid => '.1.3.6.1.4.1.9.9.719.1.45.4.1.10', map => \%mapping_presence } }; my $mapping2 = { cucsStorageLocalDiskOperability => { oid => '.1.3.6.1.4.1.9.9.719.1.45.4.1.9', map => \%mapping_operability } }; my $oid_cucsStorageLocalDiskDn = '.1.3.6.1.4.1.9.9.719.1.45.4.1.2'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping1->{cucsStorageLocalDiskPresence}->{oid} }, { oid => $mapping2->{cucsStorageLocalDiskOperability}->{oid} }, { oid => $oid_cucsStorageLocalDiskDn }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking local disks"); $self->{components}->{localdisk} = {name => 'local disks', total => 0, skip => 0}; return if ($self->check_filter(section => 'localdisk')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_cucsStorageLocalDiskDn}})) { $oid =~ /\.(\d+)$/; my $instance = $1; my $localdisk_dn = $self->{results}->{$oid_cucsStorageLocalDiskDn}->{$oid}; my $result = $self->{snmp}->map_instance(mapping => $mapping1, results => $self->{results}->{$mapping1->{cucsStorageLocalDiskPresence}->{oid}}, instance => $instance); my $result2 = $self->{snmp}->map_instance(mapping => $mapping2, results => $self->{results}->{$mapping2->{cucsStorageLocalDiskOperability}->{oid}}, instance => $instance); next if ($self->absent_problem(section => 'localdisk', instance => $localdisk_dn)); next if ($self->check_filter(section => 'localdisk', instance => $localdisk_dn)); $self->{output}->output_add( long_msg => sprintf( "local disk '%s' state is '%s' [presence: %s].", $localdisk_dn, $result2->{cucsStorageLocalDiskOperability}, $result->{cucsStorageLocalDiskPresence} ) ); my $exit = $self->get_severity(section => 'localdisk.presence', label => 'default.presence', value => $result->{cucsStorageLocalDiskPresence}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "local disk '%s' presence is: '%s'", $localdisk_dn, $result->{cucsStorageLocalDiskPresence}) ); next; } $self->{components}->{localdisk}->{total}++; $exit = $self->get_severity(section => 'localdisk.operability', label => 'default.operability', value => $result2->{cucsStorageLocalDiskOperability}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "local disk '%s' state is '%s'", $localdisk_dn, $result2->{cucsStorageLocalDiskOperability} ) ); } } } 1; centreon-plugins-20220113/hardware/server/cisco/ucs/snmp/mode/components/memory.pm000066400000000000000000000076021417000230700301720ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::cisco::ucs::snmp::mode::components::memory; use strict; use warnings; use hardware::server::cisco::ucs::snmp::mode::components::resources qw(%mapping_presence %mapping_operability); # In MIB 'CISCO-UNIFIED-COMPUTING-MEMORY-MIB' my $mapping1 = { cucsMemoryUnitPresence => { oid => '.1.3.6.1.4.1.9.9.719.1.30.11.1.17', map => \%mapping_presence }, }; my $mapping2 = { cucsMemoryUnitOperState => { oid => '.1.3.6.1.4.1.9.9.719.1.30.11.1.13', map => \%mapping_operability }, }; my $oid_cucsMemoryUnitDn = '.1.3.6.1.4.1.9.9.719.1.30.11.1.2'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping1->{cucsMemoryUnitPresence}->{oid} }, { oid => $mapping2->{cucsMemoryUnitOperState}->{oid} }, { oid => $oid_cucsMemoryUnitDn }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking memories"); $self->{components}->{memory} = {name => 'memories', total => 0, skip => 0}; return if ($self->check_filter(section => 'memory')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_cucsMemoryUnitDn}})) { $oid =~ /\.(\d+)$/; my $instance = $1; my $memory_dn = $self->{results}->{$oid_cucsMemoryUnitDn}->{$oid}; $memory_dn =~ s/\n$//ms; my $result = $self->{snmp}->map_instance(mapping => $mapping1, results => $self->{results}->{$mapping1->{cucsMemoryUnitPresence}->{oid}}, instance => $instance); my $result2 = $self->{snmp}->map_instance(mapping => $mapping2, results => $self->{results}->{$mapping2->{cucsMemoryUnitOperState}->{oid}}, instance => $instance); next if ($self->absent_problem(section => 'memory', instance => $memory_dn)); next if ($self->check_filter(section => 'memory', instance => $memory_dn)); $self->{output}->output_add( long_msg => sprintf( "memory '%s' state is '%s' [presence: %s].", $memory_dn, $result2->{cucsMemoryUnitOperState}, $result->{cucsMemoryUnitPresence} ) ); my $exit = $self->get_severity(section => 'memory.presence', label => 'default.presence', value => $result->{cucsMemoryUnitPresence}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "memory '%s' presence is: '%s'", $memory_dn, $result->{cucsMemoryUnitPresence} ) ); next; } $self->{components}->{memory}->{total}++; $exit = $self->get_severity(section => 'memory.operability', label => 'default.operability', value => $result2->{cucsMemoryUnitOperState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "memory '%s' state is '%s'", $memory_dn, $result2->{cucsMemoryUnitOperState} ) ); } } } 1; centreon-plugins-20220113/hardware/server/cisco/ucs/snmp/mode/components/psu.pm000066400000000000000000000076471417000230700275020ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::cisco::ucs::snmp::mode::components::psu; use strict; use warnings; use hardware::server::cisco::ucs::snmp::mode::components::resources qw(%mapping_presence %mapping_operability); # In MIB 'CISCO-UNIFIED-COMPUTING-EQUIPMENT-MIB' my $mapping1 = { cucsEquipmentPsuPresence => { oid => '.1.3.6.1.4.1.9.9.719.1.15.56.1.11', map => \%mapping_presence }, }; my $mapping2 = { cucsEquipmentPsuOperState => { oid => '.1.3.6.1.4.1.9.9.719.1.15.56.1.7', map => \%mapping_operability }, }; my $oid_cucsEquipmentPsuDn = '.1.3.6.1.4.1.9.9.719.1.15.56.1.2'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping1->{cucsEquipmentPsuPresence}->{oid} }, { oid => $mapping2->{cucsEquipmentPsuOperState}->{oid} }, { oid => $oid_cucsEquipmentPsuDn }; } sub check { my ($self) = @_; # In MIB 'CISCO-UNIFIED-COMPUTING-EQUIPMENT-MIB' $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')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_cucsEquipmentPsuDn}})) { $oid =~ /\.(\d+)$/; my $instance = $1; my $psu_dn = $self->{results}->{$oid_cucsEquipmentPsuDn}->{$oid}; my $result = $self->{snmp}->map_instance(mapping => $mapping1, results => $self->{results}->{$mapping1->{cucsEquipmentPsuPresence}->{oid}}, instance => $instance); my $result2 = $self->{snmp}->map_instance(mapping => $mapping2, results => $self->{results}->{$mapping2->{cucsEquipmentPsuOperState}->{oid}}, instance => $instance); next if ($self->absent_problem(section => 'psu', instance => $psu_dn)); next if ($self->check_filter(section => 'psu', instance => $psu_dn)); $self->{output}->output_add( long_msg => sprintf( "power supply '%s' state is '%s' [presence: %s].", $psu_dn, $result2->{cucsEquipmentPsuOperState}, $result->{cucsEquipmentPsuPresence} ) ); my $exit = $self->get_severity(section => 'psu.presence', label => 'default.presence', value => $result->{cucsEquipmentPsuPresence}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "power supply '%s' presence is: '%s'", $psu_dn, $result->{cucsEquipmentPsuPresence} ) ); next; } $self->{components}->{psu}->{total}++; $exit = $self->get_severity(section => 'psu.operability', label => 'default.operability', value => $result2->{cucsEquipmentPsuOperState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "power supply '%s' state is '%s'.", $psu_dn, $result2->{cucsEquipmentPsuOperState} ) ); } } } 1; centreon-plugins-20220113/hardware/server/cisco/ucs/snmp/mode/components/resources.pm000066400000000000000000000146451417000230700307010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::cisco::ucs::snmp::mode::components::resources; use strict; use warnings; use Exporter; our $thresholds; our %mapping_presence; our %mapping_operability; our %mapping_overall_status; our %mapping_drive_status; our @ISA = qw(Exporter); our @EXPORT_OK = qw($thresholds %mapping_presence %mapping_operability %mapping_overall_status %mapping_drive_status); %mapping_drive_status = ( 0 => 'unknown', 1 => 'online', 2 => 'unconfiguredGood', 3 => 'globalHotSpare', 4 => 'dedicatedHotSpare', 5 => 'jbod', 6 => 'offline', 7 => 'rebuilding', 8 => 'copyback', 9 => 'failed', 10 => 'unconfiguredBad', 11 => 'predictiveFailure', 12 => 'disabledForRemoval', 13 => 'foreignConfiguration' ); %mapping_presence = ( 0 => 'unknown', 1 => 'empty', 10 => 'equipped', 11 => 'missing', 12 => 'mismatch', 13 => 'equippedNotPrimary', 20 => 'equippedIdentityUnestablishable', 21 => 'mismatchIdentityUnestablishable', 30 => 'inaccessible', 40 => 'unauthorized', 100 => 'notSupported' ); %mapping_operability = ( 0 => 'unknown', 1 => 'operable', 2 => 'inoperable', 3 => 'degraded', 4 => 'poweredOff', 5 => 'powerProblem', 6 => 'removed', 7 => 'voltageProblem', 8 => 'thermalProblem', 9 => 'performanceProblem', 10 => 'accessibilityProblem', 11 => 'identityUnestablishable', 12 => 'biosPostTimeout', 13 => 'disabled', 51 => 'fabricConnProblem', 52 => 'fabricUnsupportedConn', 81 => 'config', 82 => 'equipmentProblem', 83 => 'decomissioning', 84 => 'chassisLimitExceeded', 100 => 'notSupported', 101 => 'discovery', 102 => 'discoveryFailed', 104 => 'postFailure', 105 => 'upgradeProblem', 106 => 'peerCommProblem', 107 => 'autoUpgrade', 108 => 'linkActivateBlocked' ); %mapping_overall_status = ( 0 => 'indeterminate', 1 => 'unassociated', 10 => 'ok', 11 => 'discovery', 12 => 'config', 13 => 'unconfig', 14 => 'power-off', 15 => 'restart', 20 => 'maintenance', 21 => 'test', 29 => 'compute-mismatch', 30 => 'compute-failed', 31 => 'degraded', 32 => 'discovery-failed', 33 => 'config-failure', 34 => 'unconfig-failed', 35 => 'test-failed', 36 => 'maintenance-failed', 40 => 'removed', 41 => 'disabled', 50 => 'inaccessible', 60 => 'thermal-problem', 61 => 'power-problem', 62 => 'voltage-problem', 63 => 'inoperable', 101 => 'decommissioning', 201 => 'bios-restore', 202 => 'cmos-reset', 203 => 'diagnostics', 204 => 'diagnostic-failed' ); $thresholds = { 'default.drivestatus' => [ ['unknown', 'UNKNOWN'], ['online', 'OK'], ['unconfiguredGood', 'OK'], ['globalHotSpare', 'OK'], ['dedicatedHotSpare', 'OK'], ['jbod', 'OK'], ['offline', 'OK'], ['rebuilding', 'WARNING'], ['copyback', 'OK'], ['failed', 'CRITICAL'], ['unconfiguredBad', 'CRITICAL'], ['predictiveFailure', 'WARNING'], ['disabledForRemoval', 'OK'], ['foreignConfiguration', 'OK'], ], 'default.presence' => [ ['unknown', 'UNKNOWN'], ['empty', 'OK'], ['equipped', 'OK'], ['missing', 'WARNING'], ['mismatch', 'WARNING'], ['equippedNotPrimary', 'OK'], ['equippedIdentityUnestablishable', 'WARNING'], ['mismatchIdentityUnestablishable', 'WARNING'], ['inaccessible', 'UNKNOWN'], ['unauthorized', 'UNKNOWN'], ['notSupported', 'WARNING'] ], 'default.operability' => [ ['unknown', 'UNKNOWN'], ['operable', 'OK'], ['inoperable', 'CRITICAL'], ['degraded', 'WARNING'], ['poweredOff', 'WARNING'], ['powerProblem', 'CRITICAL'], ['removed', 'WARNING'], ['voltageProblem', 'CRITICAL'], ['thermalProblem', 'CRITICAL'], ['performanceProblem', 'CRITICAL'], ['accessibilityProblem', 'WARNING'], ['identityUnestablishable', 'WARNING'], ['biosPostTimeout', 'WARNING'], ['disabled', 'OK'], ['fabricConnProblem', 'WARNING'], ['fabricUnsupportedConn', 'WARNING'], ['config', 'OK'], ['equipmentProblem', 'CRITICAL'], ['decomissioning', 'WARNING'], ['chassisLimitExceeded', 'WARNING'], ['notSupported', 'WARNING'], ['discovery', 'OK'], ['discoveryFailed', 'WARNING'], ['postFailure', 'WARNING'], ['upgradeProblem', 'WARNING'], ['peerCommProblem', 'WARNING'], ['autoUpgrade', 'OK'] ], 'default.overall_status' => [ ['indeterminate', 'UNKNOWN'], ['unassociated', 'OK'], ['ok', 'OK'], ['discovery', 'OK'], ['config', 'OK'], ['unconfig', 'OK'], ['power-off', 'WARNING'], ['restart', 'WARNING'], ['maintenance', 'OK'], ['test', 'OK'], ['compute-mismatch', 'WARNING'], ['compute-failed', 'WARNING'], ['degraded', 'WARNING'], ['discovery-failed', 'WARNING'], ['config-failure', 'WARNING'], ['unconfig-failed', 'WARNING'], ['test-failed', 'WARNING'], ['maintenance-failed', 'WARNING'], ['removed', 'WARNING'], ['disabled', 'OK'], ['inaccessible', 'WARNING'], ['thermal-problem', 'CRITICAL'], ['power-problem', 'CRITICAL'], ['voltage-problem', 'CRITICAL'], ['inoperable', 'CRITICAL'], ['decommissioning', 'WARNING'], ['bios-restore', 'WARNING'], ['cmos-reset', 'WARNING'], ['diagnostics', 'OK'], ['diagnostic-failed', 'WARNING'] ] }; 1; centreon-plugins-20220113/hardware/server/cisco/ucs/snmp/mode/equipment.pm000066400000000000000000000055031417000230700265020ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::cisco::ucs::snmp::mode::equipment; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; use hardware::server::cisco::ucs::snmp::mode::components::resources qw($thresholds); sub set_system { my ($self, %options) = @_; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = $thresholds; $self->{components_path} = 'hardware::server::cisco::ucs::snmp::mode::components'; $self->{components_module} = ['fan', 'psu', 'chassis', 'iocard', 'blade', 'fex', 'cpu', 'memory', 'localdisk']; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_performance => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } 1; __END__ =head1 MODE Check Hardware (Fans, Power supplies, chassis, io cards, blades, fabric extenders). =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'fan', 'psu', 'chassis', 'iocard', 'blade', 'fex', 'cpu', 'memory', 'localdisk'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=fan --filter=psu) Can also exclude specific instance: --filter=fan,/sys/chassis-7/fan-module-1-7/fan-1 =item B<--absent-problem> Return an error if an entity is not 'present' (default is skipping) (comma seperated list) Can be specific or global: --absent-problem=fan,/sys/chassis-7/fan-module-1-7/fan-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). Eg: --threshold-overload='fan.operability,OK,poweredOff|removed' --threshold-overload='presence,OK,missing' --threshold-overload='operability,OK,removed' =back =cut centreon-plugins-20220113/hardware/server/cisco/ucs/snmp/mode/faults.pm000066400000000000000000000177071417000230700260020ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::cisco::ucs::snmp::mode::faults; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; use centreon::plugins::statefile; use POSIX; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); my $map_severity = { 0 => 'cleared', 1 => 'info', 2 => 'condition', 3 => 'warning', 4 => 'minor', 5 => 'major', 6 => 'critical' }; sub custom_status_output { my ($self, %options) = @_; return sprintf( 'fault [severity: %s] [dn: %s] [description: %s] %s', $self->{result_values}->{severity}, $self->{result_values}->{dn}, $self->{result_values}->{description}, scalar(localtime($self->{result_values}->{created})) ); } sub prefix_global_output { my ($self, %options) = @_; return 'Faults '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', }, { name => 'faults', type => 2, message_multiple => '0 problem(s) detected', display_counter_problem => { nlabel => 'faults.problems.current.count', min => 0 }, group => [ { name => 'fault', skipped_code => { -11 => 1 } } ] } ]; $self->{maps_counters}->{global} = [ { label => 'faults-total', nlabel => 'faults.total.count', display_ok => 0, set => { key_values => [ { name => 'total' } ], output_template => 'total: %s', perfdatas => [ { template => '%s', min => 0 } ] } } ]; foreach (values %$map_severity) { push @{$self->{maps_counters}->{global}}, { label => 'faults-' . $_, nlabel => 'faults.' . $_ . '.count', display_ok => 0, set => { key_values => [ { name => $_ }, { name => 'total' } ], output_template => $_ . ': %s', perfdatas => [ { template => '%s', min => 0, max => 'total' } ] } }; } $self->{maps_counters}->{fault} = [ { label => 'status', type => 2, warning_default => '%{severity} =~ /minor|warning/', critical_default => '%{severity} =~ /major|critical/', set => { key_values => [ { name => 'dn' }, { name => 'severity' }, { name => 'description' }, { name => 'created' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'filter-message:s' => { name => 'filter_message' }, 'retention:s' => { name => 'retention' }, 'memory' => { name => 'memory' } }); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); return $self; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->check_options(%options); } } sub get_timestamp { my ($self, %options) = @_; my $currentTmsp = 0; my $value = $options{value}; if ($value =~ /^([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})/) { $currentTmsp = mktime($6, $5, $4, $3, $2 - 1, $1 - 1900); } else { $value = unpack('H*', $value); $value =~ /^([0-9a-z]{4})([0-9a-z]{2})([0-9a-z]{2})([0-9a-z]{2})([0-9a-z]{2})([0-9a-z]{2})/; $currentTmsp = mktime(hex($6), hex($5), hex($4), hex($3), hex($2) - 1, hex($1) - 1900); } return $currentTmsp; } my $mapping = { dn => { oid => '.1.3.6.1.4.1.9.9.719.1.1.1.1.2' }, # cucsFaultDn created => { oid => '.1.3.6.1.4.1.9.9.719.1.1.1.1.10' }, # cucsFaultCreationTime description => { oid => '.1.3.6.1.4.1.9.9.719.1.1.1.1.11' }, # cucsFaultDescription severity => { oid => '.1.3.6.1.4.1.9.9.719.1.1.1.1.20', map => $map_severity } # cucsFaultSeverity }; sub manage_selection { my ($self, %options) = @_; my $datas = {}; my ($start, $last_instance); if (defined($self->{option_results}->{memory})) { $self->{statefile_cache}->read(statefile => 'cache_ciscoucs_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . $self->{mode}); $start = $self->{statefile_cache}->get(name => 'start'); $start = $start - 1 if (defined($start)); } my $snmp_result = $options{snmp}->get_multiple_table( oids => [ map({ oid => $_->{oid}, start => $_->{oid} . (defined($start) ? '.' . $start : '') }, values(%$mapping)) ], return_type => 1 ); $self->{global} = { total => 0, cleared => 0, info => 0, condition => 0, warning => 0, minor => 0, major => 0, critical => 0 }; $self->{faults} = { global => { fault => {} } }; my ($i, $current_time) = (1, time()); foreach my $oid ($options{snmp}->oid_lex_sort(keys %$snmp_result)) { next if ($oid !~ /^$mapping->{dn}->{oid}\.(\d+)$/); my $instance = $1; if (defined($self->{option_results}->{memory})) { $last_instance = $instance; next if (defined($start) && ($start + 1) >= $instance); # we skip last one from previous check) } my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); $result->{description} = centreon::plugins::misc::trim($result->{description}); $result->{created} = $self->get_timestamp(value => $result->{created}); if (defined($self->{option_results}->{retention})) { next if ($current_time - $result->{created} > $self->{option_results}->{retention}); } $self->{global}->{total}++; next if (defined($self->{option_results}->{filter_message}) && $self->{option_results}->{filter_message} ne '' && $result->{description} !~ /$self->{option_results}->{filter_message}/); $self->{faults}->{global}->{fault}->{$i} = $result; $self->{global}->{ $result->{severity} }++; $i++; } if (defined($self->{option_results}->{memory})) { $datas->{start} = $last_instance; $self->{statefile_cache}->write(data => $datas); } } 1; __END__ =head1 MODE Check faults. =over 8 =item B<--warning-status> Set warning threshold for status (Default: '%{severity} =~ /minor|warning/') Can used special variables like: %{severity}, %{description}, %{dn} =item B<--critical-status> Set critical threshold for status (Default: '%{severity} =~ /major|critical/'). Can used special variables like: %{severity}, %{description}, %{dn} =item B<--memory> Only check new fault. =item B<--filter-message> Filter on event message. (Default: none) =item B<--retention> Event older (current time - retention time) is not checked (in seconds). =back =cut centreon-plugins-20220113/hardware/server/cisco/ucs/snmp/mode/mgmtentities.pm000066400000000000000000000125321417000230700272040ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::cisco::ucs::snmp::mode::mgmtentities; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf( 'status: %s [role: %s][services status: %s]', $self->{result_values}->{status}, $self->{result_values}->{role}, $self->{result_values}->{services_status} ); } sub prefix_mgmt_output { my ($self, %options) = @_; return sprintf( "Management entity '%s' ", $options{instance_value}->{dn} ); } sub prefix_global_output { my ($self, %options) = @_; return 'Management entities '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', cb_prefix_output => 'prefix_global_output', type => 0 }, { name => 'mgmt', type => 1, cb_prefix_output => 'prefix_mgmt_output', message_multiple => 'All management entities are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'total', nlabel => 'management_entities.total.count', display_ok => 0, set => { key_values => [ { name => 'total' } ], output_template => 'total: %s', perfdatas => [ { template => '%s', min => 0 } ] } } ]; $self->{maps_counters}->{mgmt} = [ { label => 'status', type => 2, unknown_default => '%{role} =~ /unknown/ or %{status} eq "unknown" or %{services_status} eq "unknown"', critical_default => '%{role} =~ /electionFailed|inapplicable/ or %{status} eq "down" or %{services_status} eq "down"', set => { key_values => [ { name => 'dn' }, { name => 'role' }, { name => 'services_status' }, { name => 'status' }, ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my $map_role = { 0 => 'unknown', 1 => 'primary', 2 => 'subordinate', 3 => 'inapplicable', 4 => 'electionInProgress', 5 => 'electionFailed' }; my $map_state = { 0 => 'unknown', 1 => 'up', 2 => 'down' }; my $map_services_state = { 0 => 'unknown', 1 => 'up', 2 => 'unresponsive', 3 => 'down', 4 => 'switchoverInProgress' }; my $mapping = { dn => { oid => '.1.3.6.1.4.1.9.9.719.1.31.8.1.2' }, # cucsMgmtEntityDn role => { oid => '.1.3.6.1.4.1.9.9.719.1.31.8.1.14', map => $map_role }, # cucsMgmtEntityLeadership services_status => { oid => '.1.3.6.1.4.1.9.9.719.1.31.8.1.15', map => $map_services_state }, # cucsMgmtEntityMgmtServicesState status => { oid => '.1.3.6.1.4.1.9.9.719.1.31.8.1.17', map => $map_state } # cucsMgmtEntityState }; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_multiple_table( oids => [ map({ oid => $_->{oid} }, values(%$mapping)) ], return_type => 1, nothing_quit => 1 ); $self->{global} = { total => 0, online => 0, offline => 0 }; $self->{mgmt} = {}; foreach my $oid (keys %$snmp_result) { next if ($oid !~ /^$mapping->{dn}->{oid}\.(.*)$/); my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $1); $self->{mgmt}->{ $result->{dn} } = $result; $self->{global}->{total}++; } } 1; __END__ =head1 MODE Check management entities. =over 8 =item B<--unknown-status> Set unknown threshold for status (Default: '%{role} =~ /unknown/ or %{status} eq "unknown" or %{services_status} eq "unknown"') Can used special variables like: %{dn}, %{role}, %{services_status}, %{status} =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{dn}, %{role}, %{services_status}, %{status} =item B<--critical-status> Set critical threshold for status (Default: '%{role} =~ /electionFailed|inapplicable/ or %{status} eq "down" or %{services_status} eq "down"'). Can used special variables like: %{dn}, %{role}, %{services_status}, %{status} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'total'. =back =cut centreon-plugins-20220113/hardware/server/cisco/ucs/snmp/mode/serviceprofile.pm000066400000000000000000000114471417000230700275200ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::cisco::ucs::snmp::mode::serviceprofile; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); sub custom_status_output { my ($self, %options) = @_; return sprintf( 'status: %s', $self->{result_values}->{status} ); } sub prefix_sp_output { my ($self, %options) = @_; return sprintf( "Service profile '%s' ", $options{instance_value}->{dn} ); } sub prefix_global_output { my ($self, %options) = @_; return 'Service profiles '; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', cb_prefix_output => 'prefix_global_output', type => 0 }, { name => 'sp', type => 1, cb_prefix_output => 'prefix_sp_output', message_multiple => 'All service profiles are ok' } ]; $self->{maps_counters}->{global} = [ { label => 'total', nlabel => 'serviceprofiles.total.count', display_ok => 0, set => { key_values => [ { name => 'total' } ], output_template => 'total: %s', perfdatas => [ { template => '%s', min => 0 } ] } }, { label => 'online', nlabel => 'serviceprofiles.online.count', display_ok => 0, set => { key_values => [ { name => 'online' }, { name => 'total' } ], output_template => 'online: %s', perfdatas => [ { template => '%s', min => 0, max => 'total' } ] } }, { label => 'offline', nlabel => 'serviceprofiles.offline.count', display_ok => 0, set => { key_values => [ { name => 'offline' }, { name => 'total' } ], output_template => 'offline: %s', perfdatas => [ { template => '%s', min => 0, max => 'total' } ] } } ]; $self->{maps_counters}->{sp} = [ { label => 'status', type => 2, critical_default => '%{status} eq "offline"', set => { key_values => [ { name => 'dn' }, { name => 'status' } ], closure_custom_output => $self->can('custom_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold_ng } } ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { }); return $self; } my $map_status = { 1 => 'online', 2 => 'offline' }; my $mapping = { dn => { oid => '.1.3.6.1.4.1.9.9.719.1.26.2.1.2' }, # cucsLsBindingDn status => { oid => '.1.3.6.1.4.1.9.9.719.1.26.2.1.10', map => $map_status } # cucsLsBindingOperState }; sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_multiple_table( oids => [ map({ oid => $_->{oid} }, values(%$mapping)) ], return_type => 1, nothing_quit => 1 ); $self->{global} = { total => 0, online => 0, offline => 0 }; $self->{sp} = {}; foreach my $oid (keys %$snmp_result) { next if ($oid !~ /^$mapping->{dn}->{oid}\.(.*)$/); my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $1); $self->{sp}->{ $result->{dn} } = $result; $self->{global}->{ $result->{status} }++; $self->{global}->{total}++; } } 1; __END__ =head1 MODE Check service profiles. =over 8 =item B<--warning-status> Set warning threshold for status. Can used special variables like: %{dn}, %{status} =item B<--critical-status> Set critical threshold for status (Default: '%{status} eq "offline"'). Can used special variables like: %{dn}, %{status} =item B<--warning-*> B<--critical-*> Thresholds. Can be: 'total', 'online', 'offline'. =back =cut centreon-plugins-20220113/hardware/server/cisco/ucs/snmp/plugin.pm000066400000000000000000000031241417000230700250420ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::cisco::ucs::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} = { 'audit-logs' => 'hardware::server::cisco::ucs::snmp::mode::auditlogs', 'equipment' => 'hardware::server::cisco::ucs::snmp::mode::equipment', 'faults' => 'hardware::server::cisco::ucs::snmp::mode::faults', 'mgmt-entities' => 'hardware::server::cisco::ucs::snmp::mode::mgmtentities', 'service-profile' => 'hardware::server::cisco::ucs::snmp::mode::serviceprofile' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Cisco UCS Manager Informations in SNMP. =cut centreon-plugins-20220113/hardware/server/dell/000077500000000000000000000000001417000230700212575ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/dell/cmc/000077500000000000000000000000001417000230700220215ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/dell/cmc/snmp/000077500000000000000000000000001417000230700227765ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/dell/cmc/snmp/mode/000077500000000000000000000000001417000230700237225ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/dell/cmc/snmp/mode/components/000077500000000000000000000000001417000230700261075ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/dell/cmc/snmp/mode/components/chassis.pm000066400000000000000000000072111417000230700301030ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::cmc::snmp::mode::components::chassis; use strict; use warnings; # In MIB 'DELL-RAC-MIB' my $mapping = { drsWattsReading => { oid => '.1.3.6.1.4.1.674.10892.2.4.1.1.13', section => 'power', label => 'power', unit => 'watt' }, drsAmpsReading => { oid => '.1.3.6.1.4.1.674.10892.2.4.1.1.14', section => 'current', label => 'current', unit => 'ampere' } }; my $oid_drsCMCPowerTableEntrydrsCMCPowerTableEntry = '.1.3.6.1.4.1.674.10892.2.4.1.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_drsCMCPowerTableEntrydrsCMCPowerTableEntry }; } 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')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_drsCMCPowerTableEntrydrsCMCPowerTableEntry}})) { next if ($oid !~ /^$mapping->{drsWattsReading}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_drsCMCPowerTableEntrydrsCMCPowerTableEntry}, instance => $instance); next if ($self->check_filter(section => 'chassis', instance => $instance)); $self->{components}->{chassis}->{total}++; $self->{output}->output_add( long_msg => sprintf( "chassis '%s': power %s W, current %s A [instance: %s].", $instance, $result->{drsWattsReading}, $result->{drsAmpsReading}, $instance ) ); foreach my $probe (('drsWattsReading', 'drsAmpsReading')) { next if (!defined($result->{$probe})); my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'chassis.' . $mapping->{$probe}->{section}, instance => $instance, value => $result->{$probe}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Chassis '%s' %s is %s%s", $instance, $mapping->{$probe}->{section}, $result->{$probe}, $mapping->{$probe}->{unit} ) ); } $self->{output}->perfdata_add( label => 'chassis_' . $mapping->{$probe}->{label}, unit => $mapping->{$probe}->{unit}, nlabel => 'hardware.chassis.' . $mapping->{$probe}->{label} . '.' . $mapping->{$probe}->{unit}, instances => $instance, value => $result->{$probe}, warning => $warn, critical => $crit ); } } } 1; centreon-plugins-20220113/hardware/server/dell/cmc/snmp/mode/components/disk.pm000066400000000000000000000053131417000230700274010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::cmc::snmp::mode::components::disk; use strict; use warnings; use hardware::server::dell::cmc::snmp::mode::components::resources qw($map_status); my $mapping = { name => { oid => '.1.3.6.1.4.1.674.10892.2.6.1.20.130.4.1.2' }, # physicalDiskName status => { oid => '.1.3.6.1.4.1.674.10892.2.6.1.20.130.4.1.24', map => $map_status } # physicalDiskComponentStatus }; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping->{name}->{oid} }, { oid => $mapping->{status}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking disks"); $self->{components}->{disk} = { name => 'disks', total => 0, skip => 0 }; return if ($self->check_filter(section => 'disk')); my $snmp_result = { %{$self->{results}->{ $mapping->{name}->{oid} }}, %{$self->{results}->{ $mapping->{status}->{oid} }} }; foreach my $oid ($self->{snmp}->oid_lex_sort(keys %$snmp_result)) { next if ($oid !~ /^$mapping->{name}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); next if ($self->check_filter(section => 'disk', instance => $instance)); $self->{components}->{disk}->{total}++; $self->{output}->output_add( long_msg => sprintf( "disk '%s' status is '%s' [instance: %s]", $result->{name}, $result->{status}, $instance ) ); my $exit = $self->get_severity(label => 'default', section => 'disk', value => $result->{status}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("disk '%s' status is '%s'", $result->{name}, $result->{status}) ); } } } 1; centreon-plugins-20220113/hardware/server/dell/cmc/snmp/mode/components/health.pm000066400000000000000000000067601417000230700277230ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::cmc::snmp::mode::components::health; use strict; use warnings; use hardware::server::dell::cmc::snmp::mode::components::resources qw($map_status); # In MIB 'DELL-RAC-MIB' my $mapping = { drsIOMCurrStatus => { oid => '.1.3.6.1.4.1.674.10892.2.3.1.2', map => $map_status, descr => 'IOM status' }, drsKVMCurrStatus => { oid => '.1.3.6.1.4.1.674.10892.2.3.1.3', map => $map_status, descr => 'iKVM status' }, drsRedCurrStatus => { oid => '.1.3.6.1.4.1.674.10892.2.3.1.4', map => $map_status, descr => 'Redundancy status' }, drsPowerCurrStatus => { oid => '.1.3.6.1.4.1.674.10892.2.3.1.5', map => $map_status, descr => 'Power status' }, drsFanCurrStatus => { oid => '.1.3.6.1.4.1.674.10892.2.3.1.6', map => $map_status, descr => 'Fan status' }, drsBladeCurrStatus => { oid => '.1.3.6.1.4.1.674.10892.2.3.1.7', map => $map_status, descr => 'Blade status' }, drsTempCurrStatus => { oid => '.1.3.6.1.4.1.674.10892.2.3.1.8', map => $map_status, descr => 'Temperature status' }, drsCMCCurrStatus => { oid => '.1.3.6.1.4.1.674.10892.2.3.1.9', map => $map_status, descr => 'CMC status' } }; my $oid_drsStatusNowGroup = '.1.3.6.1.4.1.674.10892.2.3.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_drsStatusNowGroup, start => $mapping->{drsIOMCurrStatus}->{oid}, end => $mapping->{drsCMCCurrStatus}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking health"); $self->{components}->{health} = {name => 'health', total => 0, skip => 0}; return if ($self->check_filter(section => 'health')); my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_drsStatusNowGroup}, instance => 0); foreach my $probe (keys %{$mapping}) { next if (!defined($result->{$probe})); $mapping->{$probe}->{oid} =~ /\.(\d+)$/; my $instance = $1; next if ($self->check_filter(section => 'health', instance => $instance)); $self->{components}->{health}->{total}++; $self->{output}->output_add( long_msg => sprintf( "%s is %s [instance: %s].", $mapping->{$probe}->{descr}, $result->{$probe}, $instance ) ); my $exit = $self->get_severity(label => 'default', section => 'health', value => $result->{$probe}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "%s is %s", $mapping->{$probe}->{descr}, $result->{$probe} ) ); } } } 1; centreon-plugins-20220113/hardware/server/dell/cmc/snmp/mode/components/psu.pm000066400000000000000000000101251417000230700272530ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::cmc::snmp::mode::components::psu; use strict; use warnings; my %map_psu_capable = ( 1 => 'absent', 2 => 'none', 3 => 'basic' ); # In MIB 'DELL-RAC-MIB' my $mapping = { drsPSULocation => { oid => '.1.3.6.1.4.1.674.10892.2.4.2.1.3' }, drsPSUMonitoringCapable => { oid => '.1.3.6.1.4.1.674.10892.2.4.2.1.4', map => \%map_psu_capable }, drsPSUVoltsReading => { oid => '.1.3.6.1.4.1.674.10892.2.4.2.1.5', section => 'voltage', label => 'voltage', unit => 'volt' }, drsPSUAmpsReading => { oid => '.1.3.6.1.4.1.674.10892.2.4.2.1.6', section => 'current', label => 'current', unit => 'ampere' }, drsPSUWattsReading => { oid => '.1.3.6.1.4.1.674.10892.2.4.2.1.7', section => 'power', label => 'power', unit => 'watt' } }; my $oid_drsCMCPSUTableEntry = '.1.3.6.1.4.1.674.10892.2.4.2.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_drsCMCPSUTableEntry }; } 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')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_drsCMCPSUTableEntry}})) { next if ($oid !~ /^$mapping->{drsPSUMonitoringCapable}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_drsCMCPSUTableEntry}, instance => $instance); next if ($self->check_filter(section => 'psu', instance => $instance)); next if ($result->{drsPSUMonitoringCapable} !~ /basic/i); $self->{components}->{psu}->{total}++; $self->{output}->output_add( long_msg => sprintf( "power supply '%s': power %s W, current %s A, voltage %s V [instance: %s].", $result->{drsPSULocation}, $result->{drsPSUWattsReading}, $result->{drsPSUAmpsReading}, $result->{drsPSUVoltsReading}, $instance ) ); foreach my $probe (('drsPSUVoltsReading', 'drsPSUAmpsReading', 'drsPSUWattsReading')) { next if (!defined($result->{$probe})); my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'psu.' . $mapping->{$probe}->{section}, instance => $instance, value => $result->{$probe}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Power supply '%s' %s is %s%s", $result->{drsPSULocation}, $mapping->{$probe}->{section}, $result->{$probe}, $mapping->{$probe}->{unit} ) ); } $self->{output}->perfdata_add( label => 'psu_' . $mapping->{$probe}->{label}, unit => $mapping->{$probe}->{unit}, nlabel => 'hardware.' . $mapping->{$probe}->{label} . '.' . $mapping->{$probe}->{unit}, instances => $instance, value => $result->{$probe}, warning => $warn, critical => $crit ); } } } 1; centreon-plugins-20220113/hardware/server/dell/cmc/snmp/mode/components/resources.pm000066400000000000000000000021201417000230700304520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::cmc::snmp::mode::components::resources; use strict; use warnings; use Exporter; our $map_status; our @ISA = qw(Exporter); our @EXPORT_OK = qw($map_status); $map_status = { 1 => 'other', 2 => 'unknown', 3 => 'ok', 4 => 'nonCritical', 5 => 'critical', 6 => 'nonRecoverable' }; 1; centreon-plugins-20220113/hardware/server/dell/cmc/snmp/mode/components/temperature.pm000066400000000000000000000064141417000230700310070ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::cmc::snmp::mode::components::temperature; use strict; use warnings; # In MIB 'DELL-RAC-MIB' my $mapping = { drsChassisFrontPanelAmbientTemperature => { oid => '.1.3.6.1.4.1.674.10892.2.3.1.10', instance => 'chassis', descr => 'Chassis Ambient temperature' }, drsCMCAmbientTemperature => { oid => '.1.3.6.1.4.1.674.10892.2.3.1.11', instance => 'ambient', descr => 'CMC Ambient temperarture' }, drsCMCProcessorTemperature => { oid => '.1.3.6.1.4.1.674.10892.2.3.1.12', instance => 'processor', descr => 'Processor temperature' } }; my $oid_drsChassisStatusGroup = '.1.3.6.1.4.1.674.10892.2.3'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_drsChassisStatusGroup, start => $mapping->{drsChassisFrontPanelAmbientTemperature}->{oid}, end => $mapping->{drsCMCProcessorTemperature}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking temperatures"); $self->{components}->{temperature} = {name => 'temperatures', total => 0, skip => 0}; return if ($self->check_filter(section => 'temperature')); my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_drsChassisStatusGroup}, instance => 0); foreach my $probe (keys %{$mapping}) { next if (!defined($result->{$probe})); next if ($self->check_filter(section => 'temperature', instance => $mapping->{$probe}->{instance})); $self->{components}->{temperature}->{total}++; $self->{output}->output_add( long_msg => sprintf( "%s is %dC [instance: %s].", $mapping->{$probe}->{descr}, $result->{$probe}, $mapping->{$probe}->{instance} ) ); my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $mapping->{$probe}->{instance}, value => $result->{$probe}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("%s is %sC", $mapping->{$probe}->{descr}, $result->{$probe}) ); } $self->{output}->perfdata_add( label => 'temp', unit => 'C', nlabel => 'hardware.temperature.celsius', instances => $mapping->{$probe}->{instance}, value => $result->{$probe}, warning => $warn, critical => $crit ); } } 1; centreon-plugins-20220113/hardware/server/dell/cmc/snmp/mode/components/vdisk.pm000066400000000000000000000053541417000230700275740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::cmc::snmp::mode::components::vdisk; use strict; use warnings; my $map_vdisk_status = { 1 => 'unknown', 2 => 'online', 3 => 'failed', 4 => 'degraded' }; my $mapping = { name => { oid => '.1.3.6.1.4.1.674.10892.2.6.1.20.140.1.1.2' }, # virtualDiskName status => { oid => '.1.3.6.1.4.1.674.10892.2.6.1.20.140.1.1.4', map => $map_vdisk_status } # virtualDiskState }; my $oid_vdisk_table = '.1.3.6.1.4.1.674.10892.2.6.1.20.140.1'; # virtualDiskTable sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_vdisk_table, start => $mapping->{name}->{oid}, end => $mapping->{status}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking vdisks"); $self->{components}->{vdisk} = { name => 'vdisks', total => 0, skip => 0 }; return if ($self->check_filter(section => 'vdisk')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_vdisk_table}})) { next if ($oid !~ /^$mapping->{name}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_vdisk_table}, instance => $instance); next if ($self->check_filter(section => 'vdisk', instance => $instance)); $self->{components}->{vdisk}->{total}++; $self->{output}->output_add( long_msg => sprintf( "vdisk '%s' status is '%s' [instance: %s]", $result->{name}, $result->{status}, $instance ) ); my $exit = $self->get_severity(section => 'vdisk', value => $result->{status}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("vdisk '%s' status is '%s'", $result->{name}, $result->{status}) ); } } } 1; centreon-plugins-20220113/hardware/server/dell/cmc/snmp/mode/hardware.pm000066400000000000000000000100331417000230700260520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::cmc::snmp::mode::hardware; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; use centreon::plugins::misc; sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^(temperature|psu\.(voltage|power|current)|chassis\.(power|current))$'; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { default => [ ['other', 'UNKNOWN'], ['unknown', 'UNKNOWN'], ['ok', 'OK'], ['nonCritical', 'WARNING'], ['critical', 'CRITICAL'], ['nonRecoverable', 'CRITICAL'] ], vdisk => [ ['online', 'OK'], ['degraded', 'WARNING'], ['failed', 'CRITICAL'], ['unknown', 'UNKNOWN'] ] }; $self->{components_path} = 'hardware::server::dell::cmc::snmp::mode::components'; $self->{components_module} = ['chassis', 'disk', 'health', 'psu', 'temperature', 'vdisk']; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); $self->display_system_information(); } sub display_system_information { my ($self, %options) = @_; my $oid_drsProductShortName = '.1.3.6.1.4.1.674.10892.2.1.1.2.0'; my $oid_drsChassisServiceTag = '.1.3.6.1.4.1.674.10892.2.1.1.6.0'; my $oid_drsFirmwareVersion = '.1.3.6.1.4.1.674.10892.2.1.2.1.0'; my $snmp_result = $self->{snmp}->get_leef(oids => [$oid_drsProductShortName, $oid_drsChassisServiceTag, $oid_drsFirmwareVersion]); $self->{output}->output_add( long_msg => sprintf("Product Name: %s, Service Tag: %s, Firmware Version: %s", defined($snmp_result->{$oid_drsProductShortName}) ? centreon::plugins::misc::trim($snmp_result->{$oid_drsProductShortName}) : 'unknown', defined($snmp_result->{$oid_drsChassisServiceTag}) ? $snmp_result->{$oid_drsChassisServiceTag} : 'unknown', defined($snmp_result->{$oid_drsFirmwareVersion}) ? $snmp_result->{$oid_drsFirmwareVersion} : 'unknown' ) ); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $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: 'chassis', 'disk', 'health', 'psu', 'temperature', 'vdisk'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=fan) Can also exclude specific instance: --filter=health,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,status,regexp) It used before default thresholds (order stays). Example: --threshold-overload='health,CRITICAL,^(?!(ok)$)' =item B<--warning> Set warning threshold for temperatures (syntax: type,regexp,threshold) Example: --warning='temperature,.*,30' =item B<--critical> Set critical threshold for temperatures (syntax: type,regexp,threshold) Example: --critical='temperature,.*,40' =back =cut centreon-plugins-20220113/hardware/server/dell/cmc/snmp/plugin.pm000066400000000000000000000025211417000230700246320ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::cmc::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}} = ( 'hardware' => 'hardware::server::dell::cmc::snmp::mode::hardware', 'uptime' => 'snmp_standard::mode::uptime', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Dell Chassis Management Controller (CMC) in SNMP (Dell m1000e, VRTX, FX2). =cut centreon-plugins-20220113/hardware/server/dell/idrac/000077500000000000000000000000001417000230700223415ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/dell/idrac/snmp/000077500000000000000000000000001417000230700233165ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/dell/idrac/snmp/mode/000077500000000000000000000000001417000230700242425ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/dell/idrac/snmp/mode/components/000077500000000000000000000000001417000230700264275ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/dell/idrac/snmp/mode/components/amperage.pm000066400000000000000000000205421417000230700305510ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::idrac::snmp::mode::components::amperage; use strict; use warnings; use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_probe_status %map_state %map_amperage_type); my $mapping = { amperageProbeStateSettings => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.30.1.4', map => \%map_state }, amperageProbeStatus => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.30.1.5', map => \%map_probe_status }, amperageProbeReading => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.30.1.6' }, amperageProbeType => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.30.1.7', map => \%map_amperage_type }, amperageProbeLocationName => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.30.1.8' }, amperageProbeUpperCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.30.1.10' }, amperageProbeUpperNonCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.30.1.11' }, amperageProbeLowerNonCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.30.1.12' }, amperageProbeLowerCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.30.1.13' } }; my $oid_amperageProbeTableEntry = '.1.3.6.1.4.1.674.10892.5.4.600.30.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_amperageProbeTableEntry, start => $mapping->{amperageProbeStateSettings}->{oid}, end => $mapping->{amperageProbeLowerCriticalThreshold}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking amperages"); $self->{components}->{amperage} = {name => 'amperages', total => 0, skip => 0}; return if ($self->check_filter(section => 'amperage')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_amperageProbeTableEntry}})) { next if ($oid !~ /^$mapping->{amperageProbeStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_amperageProbeTableEntry}, instance => $instance); next if ($self->check_filter(section => 'amperage', instance => $instance, name => $result->{amperageProbeLocationName})); $self->{components}->{amperage}->{total}++; my ($divisor, $unit) = (1000, 'A'); if ($result->{amperageProbeType} =~ /amperageProbeTypeIsPowerSupplyAmps|amperageProbeTypeIsSystemAmps/) { $divisor = 10; } elsif ($result->{amperageProbeType} =~ /amperageProbeTypeIsPowerSupplyWatts|amperageProbeTypeIsSystemWatts/) { $unit = 'W'; $divisor = 1; } $result->{amperageProbeReading} = (defined($result->{amperageProbeReading})) ? $result->{amperageProbeReading} / $divisor : 'unknown'; $self->{output}->output_add( long_msg => sprintf( "amperage '%s' status is '%s' [instance = %s] [state = %s] [value = %s]", $result->{amperageProbeLocationName}, $result->{amperageProbeStatus}, $instance, $result->{amperageProbeStateSettings}, $result->{amperageProbeReading} ) ); my $exit = $self->get_severity(label => 'default.state', section => 'amperage.state', value => $result->{amperageProbeStateSettings}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Amperage '%s' state is '%s'", $result->{amperageProbeLocationName}, $result->{amperageProbeStateSettings}) ); next; } $exit = $self->get_severity(label => 'probe.status', section => 'amperage.status', value => $result->{amperageProbeStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Amperage '%s' status is '%s'", $result->{amperageProbeLocationName}, $result->{amperageProbeStatus}) ); } next if ($result->{amperageProbeType} =~ /amperageProbeTypeIsDiscrete/); if (defined($result->{amperageProbeReading}) && $result->{amperageProbeReading} =~ /[0-9]/) { my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric( section => 'amperage', instance => $instance, name => $result->{amperageProbeLocationName}, value => $result->{amperageProbeReading} ); if ($checked == 0) { $result->{amperageProbeLowerNonCriticalThreshold} = (defined($result->{amperageProbeLowerNonCriticalThreshold}) && $result->{amperageProbeLowerNonCriticalThreshold} =~ /[0-9]/) ? $result->{amperageProbeLowerNonCriticalThreshold} / $divisor : ''; $result->{amperageProbeLowerCriticalThreshold} = (defined($result->{amperageProbeLowerCriticalThreshold}) && $result->{amperageProbeLowerCriticalThreshold} =~ /[0-9]/) ? $result->{amperageProbeLowerCriticalThreshold} / $divisor : ''; $result->{amperageProbeUpperNonCriticalThreshold} = (defined($result->{amperageProbeUpperNonCriticalThreshold}) && $result->{amperageProbeUpperNonCriticalThreshold} =~ /[0-9]/) ? $result->{amperageProbeUpperNonCriticalThreshold} / $divisor : ''; $result->{amperageProbeUpperCriticalThreshold} = (defined($result->{amperageProbeUpperCriticalThreshold}) && $result->{amperageProbeUpperCriticalThreshold} =~ /[0-9]/) ? $result->{amperageProbeUpperCriticalThreshold} / $divisor : ''; my $warn_th = $result->{amperageProbeLowerNonCriticalThreshold} . ':' . $result->{amperageProbeUpperNonCriticalThreshold}; my $crit_th = $result->{amperageProbeLowerCriticalThreshold} . ':' . $result->{amperageProbeUpperCriticalThreshold}; $self->{perfdata}->threshold_validate(label => 'warning-amperage-instance-' . $instance, value => $warn_th); $self->{perfdata}->threshold_validate(label => 'critical-amperage-instance-' . $instance, value => $crit_th); $exit = $self->{perfdata}->threshold_check( value => $result->{amperageProbeReading}, threshold => [ { label => 'critical-amperage-instance-' . $instance, exit_litteral => 'critical' }, { label => 'warning-amperage-instance-' . $instance, exit_litteral => 'warning' } ] ); $warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-amperage-instance-' . $instance); $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-amperage-instance-' . $instance); } if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Amperage '%s' is %s %s", $result->{amperageProbeLocationName}, $result->{amperageProbeReading}, $unit) ); } $self->{output}->perfdata_add( label => 'amperage', unit => $unit, nlabel => 'hardware.probe.amperage.' . ($unit eq 'A' ? 'ampere' : 'watt'), instances => $result->{amperageProbeLocationName}, value => $result->{amperageProbeReading}, warning => $warn, critical => $crit ); } } } 1; centreon-plugins-20220113/hardware/server/dell/idrac/snmp/mode/components/coolingdevice.pm000066400000000000000000000174021417000230700316030ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::idrac::snmp::mode::components::coolingdevice; use strict; use warnings; use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_probe_status %map_state); my $mapping = { coolingDeviceStateSettings => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.12.1.4', map => \%map_state }, coolingDeviceStatus => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.12.1.5', map => \%map_probe_status }, coolingDeviceReading => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.12.1.6' }, coolingDeviceLocationName => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.12.1.8' }, coolingDeviceUpperCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.20.1.10' }, coolingDeviceUpperNonCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.20.1.11' }, coolingDeviceLowerNonCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.20.1.12' }, coolingDeviceLowerCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.12.1.13' } }; my $oid_coolingDeviceTableEntry = '.1.3.6.1.4.1.674.10892.5.4.700.12.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_coolingDeviceTableEntry, start => $mapping->{coolingDeviceStateSettings}->{oid}, end => $mapping->{coolingDeviceLowerCriticalThreshold}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking cooling devices"); $self->{components}->{coolingdevice} = {name => 'cooling devices', total => 0, skip => 0}; return if ($self->check_filter(section => 'coolingdevice')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_coolingDeviceTableEntry}})) { next if ($oid !~ /^$mapping->{coolingDeviceStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_coolingDeviceTableEntry}, instance => $instance); next if ($self->check_filter(section => 'coolingdevice', instance => $instance, name => $result->{coolingDeviceLocationName})); $self->{components}->{coolingdevice}->{total}++; $result->{coolingDeviceReading} = (defined($result->{coolingDeviceReading})) ? $result->{coolingDeviceReading} : 'unknown'; $self->{output}->output_add( long_msg => sprintf( "cooling device '%s' status is '%s' [instance = %s] [state = %s] [value = %s]", $result->{coolingDeviceLocationName}, $result->{coolingDeviceStatus}, $instance, $result->{coolingDeviceStateSettings}, $result->{coolingDeviceReading} ) ); my $exit = $self->get_severity(label => 'default.state', section => 'coolingdevice.state', value => $result->{coolingDeviceStateSettings}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Cooling device '%s' state is '%s'", $result->{coolingDeviceLocationName}, $result->{coolingDeviceStateSettings}) ); next; } $exit = $self->get_severity(label => 'probe.status', section => 'coolingdevice.status', value => $result->{coolingDeviceStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Cooling device '%s' status is '%s'", $result->{coolingDeviceLocationName}, $result->{coolingDeviceStatus}) ); } if (defined($result->{coolingDeviceReading}) && $result->{coolingDeviceReading} =~ /[0-9]/) { my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric( section => 'coolingdevice', instance => $instance, name => $result->{coolingDeviceLocationName}, value => $result->{coolingDeviceReading} ); if ($checked == 0) { $result->{coolingDeviceLowerNonCriticalThreshold} = (defined($result->{coolingDeviceLowerNonCriticalThreshold}) && $result->{coolingDeviceLowerNonCriticalThreshold} =~ /[0-9]/) ? $result->{coolingDeviceLowerNonCriticalThreshold} / 10 : ''; $result->{coolingDeviceLowerCriticalThreshold} = (defined($result->{coolingDeviceLowerCriticalThreshold}) && $result->{coolingDeviceLowerCriticalThreshold} =~ /[0-9]/) ? $result->{coolingDeviceLowerCriticalThreshold} / 10 : ''; $result->{coolingDeviceUpperNonCriticalThreshold} = (defined($result->{coolingDeviceUpperNonCriticalThreshold}) && $result->{coolingDeviceUpperNonCriticalThreshold} =~ /[0-9]/) ? $result->{coolingDeviceUpperNonCriticalThreshold} / 10 : ''; $result->{coolingDeviceUpperCriticalThreshold} = (defined($result->{coolingDeviceUpperCriticalThreshold}) && $result->{coolingDeviceUpperCriticalThreshold} =~ /[0-9]/) ? $result->{coolingDeviceUpperCriticalThreshold} : ''; my $warn_th = $result->{coolingDeviceLowerNonCriticalThreshold} . ':' . $result->{coolingDeviceUpperNonCriticalThreshold}; my $crit_th = $result->{coolingDeviceLowerCriticalThreshold} . ':' . $result->{coolingDeviceUpperCriticalThreshold}; $self->{perfdata}->threshold_validate(label => 'warning-coolingdevice-instance-' . $instance, value => $warn_th); $self->{perfdata}->threshold_validate(label => 'critical-coolingdevice-instance-' . $instance, value => $crit_th); $exit = $self->{perfdata}->threshold_check( value => $result->{coolingDeviceReading}, threshold => [ { label => 'critical-coolingdevice-instance-' . $instance, exit_litteral => 'critical' }, { label => 'warning-coolingdevice-instance-' . $instance, exit_litteral => 'warning' } ] ); $warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-coolingdevice-instance-' . $instance); $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-coolingdevice-instance-' . $instance); } if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Cooling device '%s' is %s rpm", $result->{coolingDeviceLocationName}, $result->{coolingDeviceReading}) ); } $self->{output}->perfdata_add( label => 'fan', unit => 'rpm', nlabel => 'hardware.fan.speed.rpm', instances => $result->{coolingDeviceLocationName}, value => $result->{coolingDeviceReading}, warning => $warn, critical => $crit, ); } } } 1; centreon-plugins-20220113/hardware/server/dell/idrac/snmp/mode/components/coolingunit.pm000066400000000000000000000071301417000230700313200ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::idrac::snmp::mode::components::coolingunit; use strict; use warnings; use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_status %map_state); my $mapping = { coolingUnitStateSettings => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.10.1.4', map => \%map_state }, coolingUnitName => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.10.1.7' }, coolingUnitStatus => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.10.1.8', map => \%map_status } }; my $oid_coolingUnitTableEntry = '.1.3.6.1.4.1.674.10892.5.4.700.10.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_coolingUnitTableEntry, start => $mapping->{coolingUnitStateSettings}->{oid}, end => $mapping->{coolingUnitStatus}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking cooling units"); $self->{components}->{coolingunit} = {name => 'cooling units', total => 0, skip => 0}; return if ($self->check_filter(section => 'coolingunit')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_coolingUnitTableEntry}})) { next if ($oid !~ /^$mapping->{coolingUnitStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_coolingUnitTableEntry}, instance => $instance); next if ($self->check_filter(section => 'coolingunit', instance => $instance, name => $result->{coolingUnitName})); $self->{components}->{coolingunit}->{total}++; $self->{output}->output_add( long_msg => sprintf( "cooling unit '%s' status is '%s' [instance = %s] [state = %s]", $result->{coolingUnitName}, $result->{coolingUnitStatus}, $instance, $result->{coolingUnitStateSettings} ) ); my $exit = $self->get_severity(label => 'default.state', section => 'coolingunit.state', value => $result->{coolingUnitStateSettings}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Cooling unit '%s' state is '%s'", $result->{coolingUnitName}, $result->{coolingUnitStateSettings}) ); next; } $exit = $self->get_severity(label => 'default.status', section => 'coolingunit.status', value => $result->{coolingUnitStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Cooling unit '%s' status is '%s'", $result->{coolingUnitName}, $result->{coolingUnitStatus}) ); } } } 1; centreon-plugins-20220113/hardware/server/dell/idrac/snmp/mode/components/enclosure.pm000066400000000000000000000071401417000230700307660ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::idrac::snmp::mode::components::enclosure; use strict; use warnings; use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_status %map_enclosure_state); my $mapping = { enclosureName => { oid => '.1.3.6.1.4.1.674.10892.5.5.1.20.130.3.1.2' }, enclosureState => { oid => '.1.3.6.1.4.1.674.10892.5.5.1.20.130.3.1.4', map => \%map_enclosure_state }, enclosureRollUpStatus => { oid => '.1.3.6.1.4.1.674.10892.5.5.1.20.130.3.1.23', map => \%map_status } }; my $oid_enclosureTableEntry = '.1.3.6.1.4.1.674.10892.5.5.1.20.130.3'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_enclosureTableEntry, start => $mapping->{enclosureName}->{oid}, end => $mapping->{enclosureRollUpStatus}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking enclosures"); $self->{components}->{enclosure} = {name => 'enclosures', total => 0, skip => 0}; return if ($self->check_filter(section => 'enclosure')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_enclosureTableEntry}})) { next if ($oid !~ /^$mapping->{enclosureRollUpStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_enclosureTableEntry}, instance => $instance); next if ($self->check_filter(section => 'enclosure', instance => $instance, name => $result->{enclosureName})); $self->{components}->{enclosure}->{total}++; $self->{output}->output_add( long_msg => sprintf( "enclosure '%s' status is '%s' [instance = %s] [state = %s]", $result->{enclosureName}, $result->{enclosureRollUpStatus}, $instance, $result->{enclosureState} ) ); my $exit = $self->get_severity(section => 'enclosure.state', value => $result->{enclosureState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Enclosure '%s' state is '%s'", $result->{enclosureName}, $result->{enclosureState} ) ); next; } $exit = $self->get_severity(label => 'default.status', section => 'enclosure.status', value => $result->{enclosureRollUpStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Enclosure '%s' status is '%s'", $result->{enclosureName}, $result->{enclosureRollUpStatus} ) ); } } } 1; centreon-plugins-20220113/hardware/server/dell/idrac/snmp/mode/components/fru.pm000066400000000000000000000055311417000230700275650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::idrac::snmp::mode::components::fru; use strict; use warnings; use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_status); my $mapping = { fruInformationStatus => { oid => '.1.3.6.1.4.1.674.10892.5.4.2000.10.1.3', map => \%map_status }, fruSerialNumberName => { oid => '.1.3.6.1.4.1.674.10892.5.4.2000.10.1.7' } }; my $oid_fruTableEntry = '.1.3.6.1.4.1.674.10892.5.4.2000.10.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_fruTableEntry, start => $mapping->{fruInformationStatus}->{oid}, end => $mapping->{fruSerialNumberName}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking fru"); $self->{components}->{fru} = {name => 'fru', total => 0, skip => 0}; return if ($self->check_filter(section => 'fru')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_fruTableEntry}})) { next if ($oid !~ /^$mapping->{fruInformationStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_fruTableEntry}, instance => $instance); next if ($self->check_filter(section => 'fru', instance => $instance, name => $result->{fruSerialNumberName})); $self->{components}->{fru}->{total}++; $self->{output}->output_add( long_msg => sprintf( "fru '%s' status is '%s' [instance = %s]", $result->{fruSerialNumberName}, $result->{fruInformationStatus}, $instance, ) ); my $exit = $self->get_severity(label => 'default.status', section => 'fru.status', value => $result->{fruInformationStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Fru '%s' status is '%s'", $result->{fruSerialNumberName}, $result->{fruInformationStatus}) ); } } } 1; centreon-plugins-20220113/hardware/server/dell/idrac/snmp/mode/components/memory.pm000066400000000000000000000071271417000230700303040ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::idrac::snmp::mode::components::memory; use strict; use warnings; use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_status %map_state); my $mapping = { memoryDeviceStateSettings => { oid => '.1.3.6.1.4.1.674.10892.5.4.1100.50.1.4', map => \%map_state }, memoryDeviceStatus => { oid => '.1.3.6.1.4.1.674.10892.5.4.1100.50.1.5', map => \%map_status }, memoryDeviceLocationName => { oid => '.1.3.6.1.4.1.674.10892.5.4.1100.50.1.8' } }; my $oid_memoryDeviceTableEntry = '.1.3.6.1.4.1.674.10892.5.4.1100.50.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_memoryDeviceTableEntry, start => $mapping->{memoryDeviceStateSettings}->{oid}, end => $mapping->{memoryDeviceLocationName}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking memories"); $self->{components}->{memory} = {name => 'memories', total => 0, skip => 0}; return if ($self->check_filter(section => 'memory')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_memoryDeviceTableEntry}})) { next if ($oid !~ /^$mapping->{memoryDeviceStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_memoryDeviceTableEntry}, instance => $instance); next if ($self->check_filter(section => 'memory', instance => $instance, name => $result->{memoryDeviceLocationName})); $self->{components}->{memory}->{total}++; $self->{output}->output_add( long_msg => sprintf( "memory '%s' status is '%s' [instance = %s] [state = %s]", $result->{memoryDeviceLocationName}, $result->{memoryDeviceStatus}, $instance, $result->{memoryDeviceStateSettings} ) ); my $exit = $self->get_severity(label => 'default.state', section => 'memory.state', value => $result->{memoryDeviceStateSettings}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Memory '%s' state is '%s'", $result->{memoryDeviceLocationName}, $result->{memoryDeviceStateSettings}) ); next; } $exit = $self->get_severity(label => 'default.status', section => 'memory.status', value => $result->{memoryDeviceStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Memory '%s' status is '%s'", $result->{memoryDeviceLocationName}, $result->{memoryDeviceStatus}) ); } } } 1; centreon-plugins-20220113/hardware/server/dell/idrac/snmp/mode/components/network.pm000066400000000000000000000057001417000230700304600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::idrac::snmp::mode::components::network; use strict; use warnings; use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_status); my $mapping = { networkDeviceStatus => { oid => '.1.3.6.1.4.1.674.10892.5.4.1100.90.1.3', map => \%map_status }, networkDeviceProductName => { oid => '.1.3.6.1.4.1.674.10892.5.4.1100.90.1.6' } }; my $oid_networkDeviceTableEntry = '.1.3.6.1.4.1.674.10892.5.4.1100.90.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_networkDeviceTableEntry, start => $mapping->{networkDeviceStatus}->{oid}, end => $mapping->{networkDeviceProductName}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking networks"); $self->{components}->{network} = {name => 'networks', total => 0, skip => 0}; return if ($self->check_filter(section => 'network')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_networkDeviceTableEntry}})) { next if ($oid !~ /^$mapping->{networkDeviceStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_networkDeviceTableEntry}, instance => $instance); next if ($self->check_filter(section => 'network', instance => $instance, name => $result->{networkDeviceProductName})); $self->{components}->{network}->{total}++; $self->{output}->output_add( long_msg => sprintf( "network '%s' status is '%s' [instance = %s]", $result->{networkDeviceProductName}, $result->{networkDeviceStatus}, $instance ) ); my $exit = $self->get_severity(label => 'default.status', section => 'network.status', value => $result->{networkDeviceStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Network '%s' status is '%s'", $result->{networkDeviceProductName}, $result->{networkDeviceStatus}) ); } } } 1; centreon-plugins-20220113/hardware/server/dell/idrac/snmp/mode/components/pci.pm000066400000000000000000000070201417000230700275370ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::idrac::snmp::mode::components::pci; use strict; use warnings; use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_status %map_state); my $mapping = { pCIDeviceStateSettings => { oid => '.1.3.6.1.4.1.674.10892.5.4.1100.80.1.4', map => \%map_state }, pCIDeviceStatus => { oid => '.1.3.6.1.4.1.674.10892.5.4.1100.80.1.5', map => \%map_status }, pCIDeviceDescriptionName => { oid => '.1.3.6.1.4.1.674.10892.5.4.1100.80.1.9' } }; my $oid_pCIDeviceTableEntry = '.1.3.6.1.4.1.674.10892.5.4.1100.80.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_pCIDeviceTableEntry, start => $mapping->{pCIDeviceStateSettings}->{oid}, end => $mapping->{pCIDeviceDescriptionName}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking pci"); $self->{components}->{pci} = { name => 'pci', total => 0, skip => 0 }; return if ($self->check_filter(section => 'pci')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_pCIDeviceTableEntry}})) { next if ($oid !~ /^$mapping->{pCIDeviceStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_pCIDeviceTableEntry}, instance => $instance); next if ($self->check_filter(section => 'pci', instance => $instance, name => $result->{pCIDeviceDescriptionName})); $self->{components}->{pci}->{total}++; $self->{output}->output_add( long_msg => sprintf( "pci '%s' status is '%s' [instance = %s] [state = %s]", $result->{pCIDeviceDescriptionName}, $result->{pCIDeviceStatus}, $instance, $result->{pCIDeviceStateSettings} ) ); my $exit = $self->get_severity(label => 'default.state', section => 'pci.state', value => $result->{pCIDeviceStateSettings}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("PCI '%s' state is '%s'", $result->{pCIDeviceDescriptionName}, $result->{pCIDeviceStateSettings}) ); next; } $exit = $self->get_severity(label => 'default.status', section => 'pci.status', value => $result->{pCIDeviceStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("PCI '%s' status is '%s'", $result->{pCIDeviceDescriptionName}, $result->{pCIDeviceStatus}) ); } } } 1; centreon-plugins-20220113/hardware/server/dell/idrac/snmp/mode/components/pdisk.pm000066400000000000000000000113201417000230700300740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::idrac::snmp::mode::components::pdisk; use strict; use warnings; use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_status %map_pdisk_state %map_pdisk_smartstate); my $map_pdisk_sparestate = { 1 => '', # notASpare 2 => 'SpareDedicated', # dedicatedHotSpare 3 => 'SpareGlobal' # globalHotSpare }; my $mapping = { physicalDiskState => { oid => '.1.3.6.1.4.1.674.10892.5.5.1.20.130.4.1.4', map => \%map_pdisk_state }, physicalDiskSpareState => { oid => '.1.3.6.1.4.1.674.10892.5.5.1.20.130.4.1.22', map => $map_pdisk_sparestate }, physicalDiskComponentStatus => { oid => '.1.3.6.1.4.1.674.10892.5.5.1.20.130.4.1.24', map => \%map_status }, physicalDiskSmartAlertIndication => { oid => '.1.3.6.1.4.1.674.10892.5.5.1.20.130.4.1.31', map => \%map_pdisk_smartstate }, physicalDiskFQDD => { oid => '.1.3.6.1.4.1.674.10892.5.5.1.20.130.4.1.54' } }; my $oid_physicalDiskTableEntry = '.1.3.6.1.4.1.674.10892.5.5.1.20.130.4.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 physical disks"); $self->{components}->{pdisk} = {name => 'physical disks', total => 0, skip => 0}; return if ($self->check_filter(section => 'pdisk')); my $results = {}; foreach (keys %{$mapping}) { $results = { %$results, %{$self->{results}->{$mapping->{$_}->{oid}}} } } foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$mapping->{physicalDiskComponentStatus}->{oid}}})) { $oid =~ /^$mapping->{physicalDiskComponentStatus}->{oid}\.(.*)$/; my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $results, instance => $instance); next if ($self->check_filter(section => 'pdisk', instance => $instance, name => $result->{physicalDiskFQDD})); $self->{components}->{pdisk}->{total}++; if ($result->{physicalDiskState} eq 'ready') { $result->{physicalDiskState} .= $result->{physicalDiskSpareState}; } $self->{output}->output_add( long_msg => sprintf( "physical disk '%s' status is '%s' [instance = %s] [state = %s] [smart alert = %s]", $result->{physicalDiskFQDD}, $result->{physicalDiskComponentStatus}, $instance, $result->{physicalDiskState}, $result->{physicalDiskSmartAlertIndication} ) ); my $exit = $self->get_severity(section => 'pdisk.state', value => $result->{physicalDiskState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("physical disk '%s' state is '%s'", $result->{physicalDiskFQDD}, $result->{physicalDiskState}) ); next; } $exit = $self->get_severity(label => 'default.status', section => 'pdisk.status', value => $result->{physicalDiskComponentStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("physical disk '%s' status is '%s'", $result->{physicalDiskFQDD}, $result->{physicalDiskComponentStatus}) ); } $exit = $self->get_severity(section => 'pdisk.smartalert', value => $result->{physicalDiskSmartAlertIndication}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("physical disk '%s' smart alert predictive failure is '%s'", $result->{physicalDiskFQDD}, $result->{physicalDiskSmartAlertIndication}) ); } } } 1; centreon-plugins-20220113/hardware/server/dell/idrac/snmp/mode/components/processor.pm000066400000000000000000000074101417000230700310060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::idrac::snmp::mode::components::processor; use strict; use warnings; use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_status %map_state); my $mapping = { processorDeviceStateSettings => { oid => '.1.3.6.1.4.1.674.10892.5.4.1100.30.1.4', map => \%map_state }, processorDeviceStatus => { oid => '.1.3.6.1.4.1.674.10892.5.4.1100.30.1.5', map => \%map_status }, processorDeviceFQDD => { oid => '.1.3.6.1.4.1.674.10892.5.4.1100.30.1.26' } }; my $oid_processorDeviceTableEntry = '.1.3.6.1.4.1.674.10892.5.4.1100.30.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_processorDeviceTableEntry, start => $mapping->{processorDeviceStateSettings}->{oid}, end => $mapping->{processorDeviceStatus}->{oid} }, { oid => $mapping->{processorDeviceFQDD}->{oid} } ; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking processors"); $self->{components}->{processor} = { name => 'processors', total => 0, skip => 0 }; return if ($self->check_filter(section => 'processor')); my $snmp_result = { %{$self->{results}->{ $oid_processorDeviceTableEntry }}, %{$self->{results}->{ $mapping->{processorDeviceFQDD}->{oid} }} }; foreach my $oid ($self->{snmp}->oid_lex_sort(keys %$snmp_result)) { next if ($oid !~ /^$mapping->{processorDeviceStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); next if ($self->check_filter(section => 'processor', instance => $instance, name => $result->{processorDeviceFQDD})); $self->{components}->{processor}->{total}++; $self->{output}->output_add( long_msg => sprintf( "processor '%s' status is '%s' [instance = %s] [state = %s]", $result->{processorDeviceFQDD}, $result->{processorDeviceStatus}, $instance, $result->{processorDeviceStateSettings} ) ); my $exit = $self->get_severity(label => 'default.state', section => 'processor.state', value => $result->{processorDeviceStateSettings}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Processor '%s' state is '%s'", $result->{processorDeviceFQDD}, $result->{processorDeviceStateSettings}) ); next; } $exit = $self->get_severity(label => 'default.status', section => 'processor.status', value => $result->{processorDeviceStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Processor '%s' status is '%s'", $result->{processorDeviceFQDD}, $result->{processorDeviceStatus}) ); } } } 1; centreon-plugins-20220113/hardware/server/dell/idrac/snmp/mode/components/psu.pm000066400000000000000000000057511417000230700276040ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::idrac::snmp::mode::components::psu; use strict; use warnings; use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_status); my $mapping = { powerSupplyStatus => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.12.1.5', map => \%map_status }, powerSupplyLocationName => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.12.1.8' } }; my $oid_powerSupplyTableEntry = '.1.3.6.1.4.1.674.10892.5.4.600.12.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_powerSupplyTableEntry, start => $mapping->{powerSupplyStatus}->{oid}, end => $mapping->{powerSupplyLocationName}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking power supplies"); $self->{components}->{psu} = { name => 'power supplies', total => 0, skip => 0 }; return if ($self->check_filter(section => 'psu')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_powerSupplyTableEntry}})) { next if ($oid !~ /^$mapping->{powerSupplyStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_powerSupplyTableEntry}, instance => $instance); next if ($self->check_filter(section => 'psu', instance => $instance, name => $result->{powerSupplyLocationName})); $self->{components}->{psu}->{total}++; $self->{output}->output_add( long_msg => sprintf( "power supply '%s' status is '%s' [instance = %s]", $result->{powerSupplyLocationName}, $result->{powerSupplyStatus}, $instance ) ); my $exit = $self->get_severity(label => 'default.status', section => 'psu.status', value => $result->{powerSupplyStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Power supply '%s' status is '%s'", $result->{powerSupplyLocationName}, $result->{powerSupplyStatus} ) ); } } } 1; centreon-plugins-20220113/hardware/server/dell/idrac/snmp/mode/components/punit.pm000066400000000000000000000067761417000230700301440ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::idrac::snmp::mode::components::punit; use strict; use warnings; use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_status %map_state); my $mapping = { powerUnitStateSettings => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.10.1.4', map => \%map_state }, powerUnitName => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.10.1.7' }, powerUnitStatus => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.10.1.8', map => \%map_status } }; my $oid_powerUnitTableEntry = '.1.3.6.1.4.1.674.10892.5.4.600.10.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_powerUnitTableEntry, start => $mapping->{powerUnitStateSettings}->{oid}, end => $mapping->{powerUnitStatus}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking power units"); $self->{components}->{punit} = { name => 'power units', total => 0, skip => 0 }; return if ($self->check_filter(section => 'punit')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_powerUnitTableEntry}})) { next if ($oid !~ /^$mapping->{powerUnitStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_powerUnitTableEntry}, instance => $instance); next if ($self->check_filter(section => 'punit', instance => $instance, name => $result->{powerUnitName})); $self->{components}->{punit}->{total}++; $self->{output}->output_add( long_msg => sprintf( "power unit '%s' status is '%s' [instance = %s] [state = %s]", $result->{powerUnitName}, $result->{powerUnitStatus}, $instance, $result->{powerUnitStateSettings} ) ); my $exit = $self->get_severity(label => 'default.state', section => 'punit.state', value => $result->{powerUnitStateSettings}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Power unit '%s' state is '%s'", $result->{powerUnitName}, $result->{powerUnitStateSettings}) ); next; } $exit = $self->get_severity(label => 'default.status', section => 'punit.status', value => $result->{powerUnitStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Power unit '%s' status is '%s'", $result->{powerUnitName}, $result->{powerUnitStatus}) ); } } } 1; centreon-plugins-20220113/hardware/server/dell/idrac/snmp/mode/components/resources.pm000066400000000000000000000061461417000230700310060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::idrac::snmp::mode::components::resources; use strict; use warnings; use Exporter; our %map_state; our %map_status; our %map_probe_status; our %map_enclosure_state; our %map_amperage_type; our %map_pdisk_state; our %map_pdisk_smartstate; our %map_vdisk_state; our @ISA = qw(Exporter); our @EXPORT_OK = qw( %map_probe_status %map_enclosure_state %map_state %map_status %map_amperage_type %map_pdisk_state %map_pdisk_smartstate %map_vdisk_state ); %map_pdisk_smartstate = ( 0 => 'off', 1 => 'on' ); %map_probe_status = ( 1 => 'other', 2 => 'unknown', 3 => 'ok', 4 => 'nonCriticalUpper', 5 => 'criticalUpper', 6 => 'nonRecoverableUpper', 7 => 'nonCriticalLower', 8 => 'criticalLower', 9 => 'nonRecoverableLower', 10 => 'failed' ); %map_status = ( 1 => 'other', 2 => 'unknown', 3 => 'ok', 4 => 'nonCritical', 5 => 'critical', 6 => 'nonRecoverable' ); %map_state = ( 1 => 'unknown', 2 => 'enabled', 4 => 'notReady', 6 => 'enabledAndNotReady' ); %map_enclosure_state = ( 1 => 'unknown', 2 => 'ready', 3 => 'failed', 4 => 'missing', 5 => 'degraded' ); %map_pdisk_state = ( 1 => 'unknown', 2 => 'ready', 3 => 'online', 4 => 'foreign', 5 => 'offline', 6 => 'blocked', 7 => 'failed', 8 => 'non-raid', 9 => 'removed', 10 => 'readonly' ); %map_vdisk_state = ( 1 => 'unknown', 2 => 'online', 3 => 'failed', 4 => 'degraded' ); %map_amperage_type = ( 1 => 'amperageProbeTypeIsOther', 2 => 'amperageProbeTypeIsUnknown', 3 => 'amperageProbeTypeIs1Point5Volt', 4 => 'amperageProbeTypeIs3Point3volt', 5 => 'amperageProbeTypeIs5Volt', 6 => 'amperageProbeTypeIsMinus5Volt', 7 => 'amperageProbeTypeIs12Volt', 8 => 'amperageProbeTypeIsMinus12Volt', 9 => 'amperageProbeTypeIsIO', 10 => 'amperageProbeTypeIsCore', 11 => 'amperageProbeTypeIsFLEA', 12 => 'amperageProbeTypeIsBattery', 13 => 'amperageProbeTypeIsTerminator', 14 => 'amperageProbeTypeIs2Point5Volt', 15 => 'amperageProbeTypeIsGTL', 16 => 'amperageProbeTypeIsDiscrete', 23 => 'amperageProbeTypeIsPowerSupplyAmps', 24 => 'amperageProbeTypeIsPowerSupplyWatts', 25 => 'amperageProbeTypeIsSystemAmps', 26 => 'amperageProbeTypeIsSystemWatts' ); 1; centreon-plugins-20220113/hardware/server/dell/idrac/snmp/mode/components/slot.pm000066400000000000000000000056411417000230700277540ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::idrac::snmp::mode::components::slot; use strict; use warnings; use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_status); my $mapping = { systemSlotStatus => { oid => '.1.3.6.1.4.1.674.10892.5.4.1200.10.1.5', map => \%map_status }, systemSlotSlotExternalSlotName => { oid => '.1.3.6.1.4.1.674.10892.5.4.1200.10.1.8' } }; my $oid_systemSlotTableEntry = '.1.3.6.1.4.1.674.10892.5.4.1200.10.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_systemSlotTableEntry, start => $mapping->{systemSlotStatus}->{oid}, end => $mapping->{systemSlotSlotExternalSlotName}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking slots"); $self->{components}->{slot} = { name => 'slots', total => 0, skip => 0 }; return if ($self->check_filter(section => 'slot')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_systemSlotTableEntry}})) { next if ($oid !~ /^$mapping->{systemSlotStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_systemSlotTableEntry}, instance => $instance); next if ($self->check_filter(section => 'slot', instance => $instance, name => $result->{systemSlotSlotExternalSlotName})); $self->{components}->{slot}->{total}++; $self->{output}->output_add( long_msg => sprintf( "slot '%s' status is '%s' [instance = %s]", $result->{systemSlotSlotExternalSlotName}, $result->{systemSlotStatus}, $instance ) ); my $exit = $self->get_severity(label => 'default.status', section => 'slot.status', value => $result->{systemSlotStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Slot '%s' status is '%s'", $result->{systemSlotSlotExternalSlotName}, $result->{systemSlotStatus}) ); } } } 1; centreon-plugins-20220113/hardware/server/dell/idrac/snmp/mode/components/storagebattery.pm000066400000000000000000000056541417000230700320360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::idrac::snmp::mode::components::storagebattery; use strict; use warnings; use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_status); my $mapping = { batteryComponentStatus => { oid => '.1.3.6.1.4.1.674.10892.5.5.1.20.130.15.1.6', map => \%map_status }, batteryFQDD => { oid => '.1.3.6.1.4.1.674.10892.5.5.1.20.130.15.1.20' } }; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping->{batteryComponentStatus}->{oid} }, { oid => $mapping->{batteryFQDD}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking storage batteries"); $self->{components}->{storagebattery} = {name => 'storage batteries', total => 0, skip => 0}; return if ($self->check_filter(section => 'storagebattery')); my $snmp_result = { %{$self->{results}->{ $mapping->{batteryComponentStatus}->{oid} }}, %{$self->{results}->{ $mapping->{batteryFQDD}->{oid} }} }; foreach my $oid ($self->{snmp}->oid_lex_sort(keys %$snmp_result)) { next if ($oid !~ /^$mapping->{batteryComponentStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); next if ($self->check_filter(section => 'storagebattery', instance => $instance, name => $result->{batteryFQDD})); $self->{components}->{storagebattery}->{total}++; $self->{output}->output_add( long_msg => sprintf( "storage battery '%s' status is '%s' [instance = %s]", $result->{batteryFQDD}, $result->{batteryComponentStatus}, $instance ) ); my $exit = $self->get_severity(label => 'default.status', section => 'storagebattery.status', value => $result->{batteryComponentStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Storage battery '%s' status is '%s'", $result->{batteryFQDD}, $result->{batteryComponentStatus}) ); } } } 1; centreon-plugins-20220113/hardware/server/dell/idrac/snmp/mode/components/storagectrl.pm000066400000000000000000000057151417000230700313260ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::idrac::snmp::mode::components::storagectrl; use strict; use warnings; use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_status); my $mapping = { controllerComponentStatus => { oid => '.1.3.6.1.4.1.674.10892.5.5.1.20.130.1.1.38', map => \%map_status }, controllerFQDD => { oid => '.1.3.6.1.4.1.674.10892.5.5.1.20.130.1.1.78' } }; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping->{controllerComponentStatus}->{oid} }, { oid => $mapping->{controllerFQDD}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking storage controllers"); $self->{components}->{storagectrl} = {name => 'storage controllers', total => 0, skip => 0}; return if ($self->check_filter(section => 'storagectrl')); my $snmp_result = { %{$self->{results}->{ $mapping->{controllerComponentStatus}->{oid} }}, %{$self->{results}->{ $mapping->{controllerFQDD}->{oid} }} }; foreach my $oid ($self->{snmp}->oid_lex_sort(keys %$snmp_result)) { next if ($oid !~ /^$mapping->{controllerComponentStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); next if ($self->check_filter(section => 'storagectrl', instance => $instance, name => $result->{controllerFQDD})); $self->{components}->{storagectrl}->{total}++; $self->{output}->output_add( long_msg => sprintf( "storage controller '%s' status is '%s' [instance = %s]", $result->{controllerFQDD}, $result->{controllerComponentStatus}, $instance ) ); my $exit = $self->get_severity(label => 'default.status', section => 'storagectrl.status', value => $result->{controllerComponentStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Storage controllers '%s' status is '%s'", $result->{controllerFQDD}, $result->{controllerComponentStatus}) ); } } } 1; centreon-plugins-20220113/hardware/server/dell/idrac/snmp/mode/components/systembattery.pm000066400000000000000000000074341417000230700317140ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::idrac::snmp::mode::components::systembattery; use strict; use warnings; use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_status %map_state); my $mapping = { systemBatteryStateSettings => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.50.1.4', map => \%map_state }, systemBatteryStatus => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.50.1.5', map => \%map_status }, systemBatteryLocationName => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.50.1.7' } }; my $oid_systemBatteryTableEntry = '.1.3.6.1.4.1.674.10892.5.4.600.50.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_systemBatteryTableEntry, start => $mapping->{systemBatteryStateSettings}->{oid}, end => $mapping->{systemBatteryLocationName}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking system batteries"); $self->{components}->{systembattery} = {name => 'system batteries', total => 0, skip => 0}; return if ($self->check_filter(section => 'systembattery')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_systemBatteryTableEntry}})) { next if ($oid !~ /^$mapping->{systemBatteryStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_systemBatteryTableEntry}, instance => $instance); next if ($self->check_filter(section => 'systembattery', instance => $instance, name => $result->{systemBatteryLocationName})); $self->{components}->{systembattery}->{total}++; $self->{output}->output_add( long_msg => sprintf( "system battery '%s' status is '%s' [instance = %s] [state = %s]", $result->{systemBatteryLocationName}, $result->{systemBatteryStatus}, $instance, $result->{systemBatteryStateSettings} ) ); my $exit = $self->get_severity(label => 'default.state', section => 'systembattery.state', value => $result->{systemBatteryStateSettings}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "System battery '%s' state is '%s'", $result->{systemBatteryLocationName}, $result->{systemBatteryStateSettings} ) ); next; } $exit = $self->get_severity(label => 'default.status', section => 'systembattery.status', value => $result->{systemBatteryStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "System battery '%s' status is '%s'", $result->{systemBatteryLocationName}, $result->{systemBatteryStatus} ) ); } } } 1; centreon-plugins-20220113/hardware/server/dell/idrac/snmp/mode/components/temperature.pm000066400000000000000000000204401417000230700313220ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::idrac::snmp::mode::components::temperature; use strict; use warnings; use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_probe_status %map_state); my %map_temp_type = ( 1 => 'temperatureProbeTypeIsOther', 2 => 'temperatureProbeTypeIsUnknown', 3 => 'temperatureProbeTypeIsAmbientESM', 16 => 'temperatureProbeTypeIsDiscrete' ); my $mapping = { temperatureProbeStateSettings => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.20.1.4', map => \%map_state }, temperatureProbeStatus => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.20.1.5', map => \%map_probe_status }, temperatureProbeReading => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.20.1.6' }, temperatureProbeType => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.20.1.7', map => \%map_temp_type }, temperatureProbeLocationName => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.20.1.8' }, temperatureProbeUpperCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.20.1.10' }, temperatureProbeUpperNonCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.20.1.11' }, temperatureProbeLowerNonCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.20.1.12' }, temperatureProbeLowerCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.20.1.13' } }; my $oid_temperatureProbeTableEntry = '.1.3.6.1.4.1.674.10892.5.4.700.20.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_temperatureProbeTableEntry, start => $mapping->{temperatureProbeStateSettings}->{oid}, end => $mapping->{temperatureProbeLowerCriticalThreshold}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking temperatures"); $self->{components}->{temperature} = {name => 'temperatures', total => 0, skip => 0}; return if ($self->check_filter(section => 'temperature')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_temperatureProbeTableEntry}})) { next if ($oid !~ /^$mapping->{temperatureProbeStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_temperatureProbeTableEntry}, instance => $instance); next if ($self->check_filter(section => 'temperature', instance => $instance, name => $result->{temperatureProbeLocationName})); $self->{components}->{temperature}->{total}++; $result->{temperatureProbeReading} = (defined($result->{temperatureProbeReading})) ? $result->{temperatureProbeReading} / 10 : 'unknown'; $self->{output}->output_add( long_msg => sprintf( "temperature '%s' status is '%s' [instance = %s] [state = %s] [value = %s]", $result->{temperatureProbeLocationName}, $result->{temperatureProbeStatus}, $instance, $result->{temperatureProbeStateSettings}, $result->{temperatureProbeReading} ) ); my $exit = $self->get_severity(label => 'default.state', section => 'temperature.state', value => $result->{temperatureProbeStateSettings}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Temperature '%s' state is '%s'", $result->{temperatureProbeLocationName}, $result->{temperatureProbeStateSettings} ) ); next; } $exit = $self->get_severity(label => 'probe.status', section => 'temperature.status', value => $result->{temperatureProbeStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Temperature '%s' status is '%s'", $result->{temperatureProbeLocationName}, $result->{temperatureProbeStatus} ) ); } if (defined($result->{temperatureProbeReading}) && $result->{temperatureProbeReading} =~ /[0-9]/) { my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric( section => 'temperature', instance => $instance, name => $result->{temperatureProbeLocationName}, value => $result->{temperatureProbeReading} ); if ($checked == 0) { $result->{temperatureProbeLowerNonCriticalThreshold} = (defined($result->{temperatureProbeLowerNonCriticalThreshold}) && $result->{temperatureProbeLowerNonCriticalThreshold} =~ /[0-9]/) ? $result->{temperatureProbeLowerNonCriticalThreshold} / 10 : ''; $result->{temperatureProbeLowerCriticalThreshold} = (defined($result->{temperatureProbeLowerCriticalThreshold}) && $result->{temperatureProbeLowerCriticalThreshold} =~ /[0-9]/) ? $result->{temperatureProbeLowerCriticalThreshold} / 10 : ''; $result->{temperatureProbeUpperNonCriticalThreshold} = (defined($result->{temperatureProbeUpperNonCriticalThreshold}) && $result->{temperatureProbeUpperNonCriticalThreshold} =~ /[0-9]/) ? $result->{temperatureProbeUpperNonCriticalThreshold} / 10 : ''; $result->{temperatureProbeUpperCriticalThreshold} = (defined($result->{temperatureProbeUpperCriticalThreshold}) && $result->{temperatureProbeUpperCriticalThreshold} =~ /[0-9]/) ? $result->{temperatureProbeUpperCriticalThreshold} / 10 : ''; my $warn_th = $result->{temperatureProbeLowerNonCriticalThreshold} . ':' . $result->{temperatureProbeUpperNonCriticalThreshold}; my $crit_th = $result->{temperatureProbeLowerCriticalThreshold} . ':' . $result->{temperatureProbeUpperCriticalThreshold}; $self->{perfdata}->threshold_validate(label => 'warning-temperature-instance-' . $instance, value => $warn_th); $self->{perfdata}->threshold_validate(label => 'critical-temperature-instance-' . $instance, value => $crit_th); $exit = $self->{perfdata}->threshold_check( value => $result->{temperatureProbeReading}, threshold => [ { label => 'critical-temperature-instance-' . $instance, exit_litteral => 'critical' }, { label => 'warning-temperature-instance-' . $instance, exit_litteral => 'warning' } ] ); $warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-temperature-instance-' . $instance); $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-temperature-instance-' . $instance); } if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Temperature '%s' is %s degree centigrade", $result->{temperatureProbeLocationName}, $result->{temperatureProbeReading} ) ); } $self->{output}->perfdata_add( label => 'temp', unit => 'C', nlabel => 'hardware.probe.temperature.celsius', instances => $result->{temperatureProbeLocationName}, value => $result->{temperatureProbeReading}, warning => $warn, critical => $crit ); } } } 1; centreon-plugins-20220113/hardware/server/dell/idrac/snmp/mode/components/vdisk.pm000066400000000000000000000055201417000230700301070ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::idrac::snmp::mode::components::vdisk; use strict; use warnings; use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_vdisk_state); my $mapping = { virtualDiskState => { oid => '.1.3.6.1.4.1.674.10892.5.5.1.20.140.1.1.4', map => \%map_vdisk_state }, virtualDiskFQDD => { oid => '.1.3.6.1.4.1.674.10892.5.5.1.20.140.1.1.35' } }; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping->{virtualDiskState}->{oid} }, { oid => $mapping->{virtualDiskFQDD}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking virtual disks"); $self->{components}->{vdisk} = { name => 'virtual disks', total => 0, skip => 0 }; return if ($self->check_filter(section => 'vdisk')); my $snmp_result = { %{$self->{results}->{ $mapping->{virtualDiskState}->{oid} }}, %{$self->{results}->{ $mapping->{virtualDiskFQDD}->{oid} }} }; foreach my $oid ($self->{snmp}->oid_lex_sort(keys %$snmp_result)) { next if ($oid !~ /^$mapping->{virtualDiskState}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); next if ($self->check_filter(section => 'vdisk', instance => $instance, name => $result->{virtualDiskFQDD})); $self->{components}->{vdisk}->{total}++; $self->{output}->output_add( long_msg => sprintf( "virtual disk '%s' state is '%s' [instance = %s]", $result->{virtualDiskFQDD}, $result->{virtualDiskState}, $instance ) ); my $exit = $self->get_severity(section => 'vdisk.state', value => $result->{virtualDiskState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Virtual disk '%s' state is '%s'", $result->{virtualDiskFQDD}, $result->{virtualDiskState} ) ); } } } 1; centreon-plugins-20220113/hardware/server/dell/idrac/snmp/mode/components/voltage.pm000066400000000000000000000173001417000230700304270ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::idrac::snmp::mode::components::voltage; use strict; use warnings; use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_probe_status %map_state); my $mapping = { voltageProbeStateSettings => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.20.1.4', map => \%map_state }, voltageProbeStatus => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.20.1.5', map => \%map_probe_status }, voltageProbeReading => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.20.1.6' }, voltageProbeLocationName => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.20.1.8' }, voltageProbeUpperCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.20.1.10' }, voltageProbeUpperNonCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.20.1.11' }, voltageProbeLowerNonCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.20.1.12' }, voltageProbeLowerCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.20.1.13' } }; my $oid_voltageProbeTableEntry = '.1.3.6.1.4.1.674.10892.5.4.600.20.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_voltageProbeTableEntry, start => $mapping->{voltageProbeStateSettings}->{oid}, end => $mapping->{voltageProbeLowerCriticalThreshold}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking voltages"); $self->{components}->{voltage} = {name => 'voltages', total => 0, skip => 0}; return if ($self->check_filter(section => 'voltage')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_voltageProbeTableEntry}})) { next if ($oid !~ /^$mapping->{voltageProbeStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_voltageProbeTableEntry}, instance => $instance); next if ($self->check_filter(section => 'voltage', instance => $instance, name => $result->{voltageProbeLocationName})); $self->{components}->{voltage}->{total}++; $result->{voltageProbeReading} = (defined($result->{voltageProbeReading})) ? $result->{voltageProbeReading} / 1000 : 'unknown'; $self->{output}->output_add( long_msg => sprintf( "voltage '%s' status is '%s' [instance = %s] [state = %s] [value = %s]", $result->{voltageProbeLocationName}, $result->{voltageProbeStatus}, $instance, $result->{voltageProbeStateSettings}, $result->{voltageProbeReading} ) ); my $exit = $self->get_severity(label => 'default.state', section => 'voltage.state', value => $result->{voltageProbeStateSettings}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Voltage '%s' state is '%s'", $result->{voltageProbeLocationName}, $result->{voltageProbeStateSettings} ) ); next; } $exit = $self->get_severity(label => 'probe.status', section => 'voltage.status', value => $result->{voltageProbeStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Voltage '%s' status is '%s'", $result->{voltageProbeLocationName}, $result->{voltageProbeStatus} ) ); } if (defined($result->{voltageProbeReading}) && $result->{voltageProbeReading} =~ /[0-9]/) { my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric( section => 'voltage', instance => $instance, name => $result->{voltageProbeLocationName}, value => $result->{voltageProbeReading} ); if ($checked == 0) { $result->{voltageProbeLowerNonCriticalThreshold} = (defined($result->{voltageProbeLowerNonCriticalThreshold}) && $result->{voltageProbeLowerNonCriticalThreshold} =~ /[0-9]/) ? $result->{voltageProbeLowerNonCriticalThreshold} / 1000 : ''; $result->{voltageProbeLowerCriticalThreshold} = (defined($result->{voltageProbeLowerCriticalThreshold}) && $result->{voltageProbeLowerCriticalThreshold} =~ /[0-9]/) ? $result->{voltageProbeLowerCriticalThreshold} / 1000 : ''; $result->{voltageProbeUpperNonCriticalThreshold} = (defined($result->{voltageProbeUpperNonCriticalThreshold}) && $result->{voltageProbeUpperNonCriticalThreshold} =~ /[0-9]/) ? $result->{voltageProbeUpperNonCriticalThreshold} / 1000 : ''; $result->{voltageProbeUpperCriticalThreshold} = (defined($result->{voltageProbeUpperCriticalThreshold}) && $result->{voltageProbeUpperCriticalThreshold} =~ /[0-9]/) ? $result->{voltageProbeUpperCriticalThreshold} / 1000 : ''; my $warn_th = $result->{voltageProbeLowerNonCriticalThreshold} . ':' . $result->{voltageProbeUpperNonCriticalThreshold}; my $crit_th = $result->{voltageProbeLowerCriticalThreshold} . ':' . $result->{voltageProbeUpperCriticalThreshold}; $self->{perfdata}->threshold_validate(label => 'warning-voltage-instance-' . $instance, value => $warn_th); $self->{perfdata}->threshold_validate(label => 'critical-voltage-instance-' . $instance, value => $crit_th); $exit = $self->{perfdata}->threshold_check( value => $result->{voltageProbeReading}, threshold => [ { label => 'critical-voltage-instance-' . $instance, exit_litteral => 'critical' }, { label => 'warning-voltage-instance-' . $instance, exit_litteral => 'warning' } ] ); $warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-voltage-instance-' . $instance); $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-voltage-instance-' . $instance); } if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "Voltage '%s' is %s V", $result->{voltageProbeLocationName}, $result->{voltageProbeReading} ) ); } $self->{output}->perfdata_add( label => 'voltage', unit => 'V', nlabel => 'hardware.probe.voltage.volt', instances => $result->{voltageProbeLocationName}, value => $result->{voltageProbeReading}, warning => $warn, critical => $crit ); } } } 1; centreon-plugins-20220113/hardware/server/dell/idrac/snmp/mode/globalstatus.pm000066400000000000000000000153541417000230700273140ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::idrac::snmp::mode::globalstatus; use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); sub custom_status_output { my ($self, %options) = @_; my $msg = sprintf("global status is '%s'", $self->{result_values}->{status}); return $msg; } sub custom_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; return 0; } sub custom_storage_status_output { my ($self, %options) = @_; my $msg = sprintf("storage status is '%s'", $self->{result_values}->{status}); return $msg; } sub custom_storage_status_calc { my ($self, %options) = @_; $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_storage_status'}; return 0; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'global', type => 0, message_separator => ', ', cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ { label => 'status', threshold => 0, set => { key_values => [ { name => 'status' } ], 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 => \&catalog_status_threshold, } }, { label => 'storage-status', threshold => 0, set => { key_values => [ { name => 'storage_status' } ], closure_custom_calc => $self->can('custom_storage_status_calc'), closure_custom_output => $self->can('custom_storage_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => \&catalog_status_threshold, } }, ]; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => { "unknown-status:s" => { name => 'unknown_status', default => '%{status} =~ /unknown/' }, "warning-status:s" => { name => 'warning_status', default => '%{status} =~ /nonCritical|other/' }, "critical-status:s" => { name => 'critical_status', default => '%{status} =~ /critical|nonRecoverable/' }, "unknown-storage-status:s" => { name => 'unknown_storage_status', default => '%{status} =~ /unknown/' }, "warning-storage-status:s" => { name => 'warning_storage_status', default => '%{status} =~ /nonCritical|other/' }, "critical-storage-status:s" => { name => 'critical_storage_status', default => '%{status} =~ /critical|nonRecoverable/' }, }); return $self; } sub prefix_global_output { my ($self, %options) = @_; return "'" . $self->{global}->{display} . "' : "; } sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); $self->change_macros(macros => [ 'unknown_storage_status', 'warning_storage_status', 'critical_storage_status', 'unknown_status', 'warning_status', 'critical_status', ]); } my %states = ( 1 => 'other', 2 => 'unknown', 3 => 'ok', 4 => 'nonCritical', 5 => 'critical', 6 => 'nonRecoverable', ); sub manage_selection { my ($self, %options) = @_; my $oid_racShortName = '.1.3.6.1.4.1.674.10892.5.1.1.2.0'; my $oid_racVersion = '.1.3.6.1.4.1.674.10892.5.1.1.5.0'; my $oid_systemModelName = '.1.3.6.1.4.1.674.10892.5.1.3.12.0'; my $oid_drsGlobalSystemStatus = '.1.3.6.1.4.1.674.10892.2.2.1.0'; my $oid_globalSystemStatus = '.1.3.6.1.4.1.674.10892.5.2.1.0'; my $oid_globalStorageStatus = '.1.3.6.1.4.1.674.10892.5.2.3.0'; my $result = $options{snmp}->get_leef(oids => [ $oid_racShortName, $oid_racVersion, $oid_systemModelName, $oid_drsGlobalSystemStatus, $oid_globalSystemStatus, $oid_globalStorageStatus ], nothing_quit => 1); my ($global_status, $storage_status); if (defined($result->{$oid_globalSystemStatus})) { $global_status = $states{$result->{$oid_globalSystemStatus}}; $storage_status = defined($result->{$oid_globalStorageStatus}) ? $states{$result->{$oid_globalStorageStatus}} : undef; } else { $global_status = $states{$result->{$oid_drsGlobalSystemStatus}}; } my $display = 'unknown'; $display = $result->{$oid_racShortName} if (defined($result->{$oid_racShortName})); $display .= '.' . $result->{$oid_racVersion} if (defined($result->{$oid_racVersion})); $display .= '@' . $result->{$oid_systemModelName} if (defined($result->{$oid_systemModelName})); $self->{global} = { display => $display, status => $global_status, storage_status => $storage_status, }; } 1; __END__ =head1 MODE Check the overall status of iDrac card. =over 8 =item B<--unknown-status> Set warning threshold for status (Default: '%{status} =~ /unknown/'). Can used special variables like: %{status} =item B<--warning-status> Set warning threshold for status (Default: '%{status} =~ /nonCritical|other/'). Can used special variables like: %{status} =item B<--critical-status> Set critical threshold for status (Default: '%{status} =~ /critical|nonRecoverable/'). Can used special variables like: %{status} =item B<--unknown-storage-status> Set warning threshold for status (Default: '%{status} =~ /unknown/'). Can used special variables like: %{status} =item B<--warning-storage-status> Set warning threshold for status (Default: '%{status} =~ /nonCritical|other/'). Can used special variables like: %{status} =item B<--critical-storage-status> Set critical threshold for status (Default: '%{status} =~ /critical|nonRecoverable/'). Can used special variables like: %{status} =back =cut centreon-plugins-20220113/hardware/server/dell/idrac/snmp/mode/hardware.pm000066400000000000000000000116361417000230700264040ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::idrac::snmp::mode::hardware; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^(?:temperature|voltage|amperage|coolingdevice)$'; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { 'default.state' => [ ['unknown', 'UNKNOWN'], ['enabled', 'OK'], ['notReady', 'WARNING'], ['enabledAndNotReady', 'WARNING'] ], 'default.status' => [ ['other', 'UNKNOWN'], ['unknown', 'UNKNOWN'], ['ok', 'OK'], ['nonCritical', 'WARNING'], ['critical', 'CRITICAL'], ['nonRecoverable', 'CRITICAL'] ], 'probe.status' => [ ['other', 'UNKNOWN'], ['unknown', 'UNKNOWN'], ['ok', 'OK'], ['nonCriticalUpper', 'WARNING'], ['criticalUpper', 'CRITICAL'], ['nonRecoverableUpper', 'CRITICAL'], ['nonCriticalLower', 'WARNING'], ['criticalLower', 'CRITICAL'], ['nonRecoverableLower', 'CRITICAL'], ['failed', 'CRITICAL'] ], 'pdisk.state' => [ ['unknown', 'UNKNOWN'], ['readySpareDedicated', 'OK'], ['readySpareGlobal', 'OK'], ['ready', 'WARNING'], ['online', 'OK'], ['foreign', 'OK'], ['offline', 'WARNING'], ['blocked', 'WARNING'], ['failed', 'CRITICAL'], ['non-raid', 'OK'], ['removed', 'OK'], ['readonly', 'WARNING'] ], 'enclosure.state' => [ ['unknown', 'UNKNOWN'], ['ready', 'OK'], ['failed', 'CRITICAL'], ['missing', 'WARNING'], ['degraded', 'WARNING'] ], 'pdisk.smartalert' => [ ['off', 'OK'], ['on', 'WARNING'] ], 'vdisk.state' => [ ['unknown', 'UNKNOWN'], ['online', 'OK'], ['failed', 'CRITICAL'], ['degraded', 'WARNING'] ] }; $self->{components_path} = 'hardware::server::dell::idrac::snmp::mode::components'; $self->{components_module} = [ 'amperage', 'coolingdevice', 'coolingunit', 'enclosure', 'fru', 'memory', 'network', 'pci', 'pdisk', 'processor', 'psu', 'punit', 'slot', 'storagebattery', 'storagectrl', 'systembattery', 'temperature', 'voltage', 'vdisk' ]; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } 1; __END__ =head1 MODE Check hardware components. =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'amperage', 'coolingdevice', 'coolingunit', 'enclosure', 'fru', 'memory', 'network', 'pci', 'pdisk', 'processor', 'psu', 'punit', 'slot', 'storagebattery', 'storagectrl', 'systembattery', 'temperature', 'voltage', 'vdisk'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=temperature --filter=psu) Can also exclude specific instance: --filter=temperature,1.1 =item B<--add-name-instance> Add literal description for instance value (used in filter and threshold options). =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='temperature.state,CRITICAL,^(?!(enabled)$)' =item B<--warning> Set warning threshold (syntax: type,regexp,threshold) Example: --warning='temperature,.*,30' =item B<--critical> Set critical threshold (syntax: type,regexp,threshold) Example: --critical='temperature,.*,40' =back =cut centreon-plugins-20220113/hardware/server/dell/idrac/snmp/plugin.pm000066400000000000000000000025001417000230700251470ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::idrac::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} = { 'global-status' => 'hardware::server::dell::idrac::snmp::mode::globalstatus', 'hardware' => 'hardware::server::dell::idrac::snmp::mode::hardware' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Dell iDrac in SNMP. =cut centreon-plugins-20220113/hardware/server/dell/omem/000077500000000000000000000000001417000230700222145ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/dell/omem/snmp/000077500000000000000000000000001417000230700231715ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/dell/omem/snmp/mode/000077500000000000000000000000001417000230700241155ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/dell/omem/snmp/mode/components/000077500000000000000000000000001417000230700263025ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/dell/omem/snmp/mode/components/chassis.pm000066400000000000000000000055061417000230700303030ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::omem::snmp::mode::components::chassis; use strict; use warnings; my $mapping = { wattsReading => { oid => '.1.3.6.1.4.1.674.10892.6.4.1.1.9' } # dmmPowerWattsReading }; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping->{wattsReading}->{oid} }; } 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')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{ $mapping->{wattsReading}->{oid} }})) { $oid =~ /^$mapping->{wattsReading}->{oid}\.(.*)$/; my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{ $mapping->{wattsReading}->{oid} }, instance => $instance); next if ($self->check_filter(section => 'chassis', instance => $instance)); $self->{components}->{chassis}->{total}++; $self->{output}->output_add( long_msg => sprintf( "chassis '%s' power %s W [instance: %s]", $instance, $result->{wattsReading}, $instance ) ); my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'chassis.power', instance => $instance, value => $result->{wattsReading}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "chassis '%s' power is %s W", $instance, $result->{wattsReading} ) ); } $self->{output}->perfdata_add( nlabel => 'hardware.chassis.power.watt', unit => 'W', instances => $instance, value => $result->{wattsReading}, warning => $warn, critical => $crit ); } } 1; centreon-plugins-20220113/hardware/server/dell/omem/snmp/mode/components/health.pm000066400000000000000000000064001417000230700301050ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::omem::snmp::mode::components::health; use strict; use warnings; my %map_health_status = ( 1 => 'other', 2 => 'unknown', 3 => 'ok', 4 => 'nonCritical', 5 => 'critical', 6 => 'nonRecoverable' ); my $mapping = { IOMCurrStatus => { oid => '.1.3.6.1.4.1.674.10892.6.3.1.1', map => \%map_health_status, descr => 'IOM' }, redCurrStatus => { oid => '.1.3.6.1.4.1.674.10892.6.3.1.2', map => \%map_health_status, descr => 'redundancy' }, powerCurrStatus => { oid => '.1.3.6.1.4.1.674.10892.6.3.1.3', map => \%map_health_status, descr => 'power' }, fanCurrStatus => { oid => '.1.3.6.1.4.1.674.10892.6.3.1.4', map => \%map_health_status, descr => 'fan' }, bladeCurrStatus => { oid => '.1.3.6.1.4.1.674.10892.6.3.1.5', map => \%map_health_status, descr => 'blade' }, tempCurrStatus => { oid => '.1.3.6.1.4.1.674.10892.6.3.1.6', map => \%map_health_status, descr => 'temperature' }, MMCurrStatus => { oid => '.1.3.6.1.4.1.674.10892.6.3.1.7', map => \%map_health_status, descr => 'management module' } }; my $oid_dmmStatusNowGroup = '.1.3.6.1.4.1.674.10892.6.3.1'; sub load {} sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking health"); $self->{components}->{health} = { name => 'health', total => 0, skip => 0 }; return if ($self->check_filter(section => 'health')); my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_dmmStatusNowGroup}, instance => 0); foreach my $probe (sort keys %$mapping) { next if (!defined($result->{$probe})); $mapping->{$probe}->{oid} =~ /\.(\d+)$/; my $instance = $1; next if ( $self->check_filter(section => 'health', instance => $instance)); $self->{components}->{health}->{total}++; $self->{output}->output_add( long_msg => sprintf( "%s status is %s [instance: %s]", $mapping->{$probe}->{descr}, $result->{$probe}, $instance ) ); my $exit = $self->get_severity(label => 'default', section => 'health', value => $result->{$probe}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("%s status is %s", $mapping->{$probe}->{descr}, $result->{$probe} ) ); } } } 1; centreon-plugins-20220113/hardware/server/dell/omem/snmp/mode/components/psu.pm000066400000000000000000000054561417000230700274610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::omem::snmp::mode::components::psu; use strict; use warnings; my %map_status = ( 1 => 'other', 2 => 'unknown', 3 => 'ok', 4 => 'nonCritical', 5 => 'critical', 6 => 'nonRecoverable' ); my $mapping = { dmmPSULocation => { oid => '.1.3.6.1.4.1.674.10892.6.4.2.1.3' }, dmmPSUCurrStatus => { oid => '.1.3.6.1.4.1.674.10892.6.4.2.1.8', map => \%map_status } }; my $oid_dmmPSUTableEntry = '.1.3.6.1.4.1.674.10892.6.4.2.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_dmmPSUTableEntry }; } 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')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_dmmPSUTableEntry}})) { next if ($oid !~ /^$mapping->{dmmPSUCurrStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_dmmPSUTableEntry}, 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' status is %s [instance: %s]", $result->{dmmPSULocation}, $result->{dmmPSUCurrStatus}, $instance ) ); my $exit = $self->get_severity(label => 'default', section => 'psu', value => $result->{dmmPSUCurrStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf( "power supply '%s' status is %s", $result->{dmmPSULocation}, $result->{dmmPSUCurrStatus} ) ); } } } 1; centreon-plugins-20220113/hardware/server/dell/omem/snmp/mode/components/temperature.pm000066400000000000000000000054131417000230700312000ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::omem::snmp::mode::components::temperature; use strict; use warnings; my $mapping = { dmmChassisFrontPanelAmbientTemperature => { oid => '.1.3.6.1.4.1.674.10892.6.3.1.8', instance => 'chassis', descr => 'chassis ambient temperature' } }; my $oid_dmmStatusNowGroup = '.1.3.6.1.4.1.674.10892.6.3.1'; sub load {} sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking temperatures"); $self->{components}->{temperature} = { name => 'temperatures', total => 0, skip => 0 }; return if ($self->check_filter(section => 'temperature')); my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_dmmStatusNowGroup}, instance => 0); foreach my $probe (keys %$mapping) { next if (!defined($result->{$probe})); next if ($self->check_filter(section => 'temperature', instance => $mapping->{$probe}->{instance})); $self->{components}->{temperature}->{total}++; $self->{output}->output_add( long_msg => sprintf( "%s is %dC [instance: %s]", $mapping->{$probe}->{descr}, $result->{$probe}, $mapping->{$probe}->{instance} ) ); my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $mapping->{$probe}->{instance}, value => $result->{$probe}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("%s is %sC", $mapping->{$probe}->{descr}, $result->{$probe} ) ); } $self->{output}->perfdata_add( nlabel => 'hardware.temperature.celsius', unit => 'C', instances => $mapping->{$probe}->{instance}, value => $result->{$probe}, warning => $warn, critical => $crit ); } } 1; centreon-plugins-20220113/hardware/server/dell/omem/snmp/mode/hardware.pm000066400000000000000000000103661417000230700262560ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::omem::snmp::mode::hardware; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; use centreon::plugins::misc; sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^(?:temperature|psu\.(voltage|power|current)|chassis\.(power|current))$'; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { default => [ [ 'other', 'UNKNOWN' ], [ 'unknown', 'UNKNOWN' ], [ 'ok', 'OK' ], [ 'nonCritical', 'WARNING' ], [ 'critical', 'CRITICAL' ], [ 'nonRecoverable', 'CRITICAL' ] ] }; $self->{components_path} = 'hardware::server::dell::omem::snmp::mode::components'; $self->{components_module} = ['chassis', 'health', 'psu', 'temperature']; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->display_system_information(); push @{$self->{request}}, { oid => '.1.3.6.1.4.1.674.10892.6.3.1' }; $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); } sub display_system_information { my ($self, %options) = @_; my $oid_dmmProductShortName = '.1.3.6.1.4.1.674.10892.6.1.1.2.0'; my $oid_dmmChassisServiceTag = '.1.3.6.1.4.1.674.10892.6.1.1.6.0'; my $oid_dmmFirmwareVersion = '.1.3.6.1.4.1.674.10892.6.1.2.1.0'; my $oid_dmmFirmwareVersion2 = '.1.3.6.1.4.1.674.10892.6.1.2.2.0'; my $snmp_result = $self->{snmp}->get_leef(oids => [$oid_dmmProductShortName, $oid_dmmChassisServiceTag, $oid_dmmFirmwareVersion, $oid_dmmFirmwareVersion2]); $self->{output}->output_add( long_msg => sprintf( "Product Name: %s, Service Tag: %s, Firmware Version of MM1: %s, Firmware Version of MM2: %s", defined($snmp_result->{$oid_dmmProductShortName}) ? centreon::plugins::misc::trim($snmp_result->{$oid_dmmProductShortName}) : 'unknown', defined($snmp_result->{$oid_dmmChassisServiceTag}) ? $snmp_result->{$oid_dmmChassisServiceTag} : 'unknown', defined($snmp_result->{$oid_dmmFirmwareVersion}) ? $snmp_result->{$oid_dmmFirmwareVersion} : 'unknown', defined($snmp_result->{$oid_dmmFirmwareVersion2}) ? $snmp_result->{$oid_dmmFirmwareVersion2} : 'unknown' ) ); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } 1; __END__ =head1 MODE Check hardware (health, temperatures, power supplies metrics and chassis metrics). =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'health', 'temperature', 'chassis', 'psu'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=fan) Can also exclude specific instance: --filter=health,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,status,regexp) It used before default thresholds (order stays). Example: --threshold-overload='health,CRITICAL,^(?!(ok)$)' =item B<--warning> Set warning threshold for temperature (syntax: type,regexp,threshold) Example: --warning='temperature,.*,30' =item B<--critical> Set critical threshold for temperature (syntax: type,regexp,threshold) Example: --critical='temperature,.*,40' =back =cut centreon-plugins-20220113/hardware/server/dell/omem/snmp/plugin.pm000066400000000000000000000024401417000230700250250ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::omem::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} = { 'hardware' => 'hardware::server::dell::omem::snmp::mode::hardware', 'uptime' => 'snmp_standard::mode::uptime' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Dell OpenManage Enterprise Modular in SNMP (Dell MX7000). =cut centreon-plugins-20220113/hardware/server/dell/openmanage/000077500000000000000000000000001417000230700233715ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/dell/openmanage/snmp/000077500000000000000000000000001417000230700243465ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/dell/openmanage/snmp/mode/000077500000000000000000000000001417000230700252725ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/dell/openmanage/snmp/mode/components/000077500000000000000000000000001417000230700274575ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/dell/openmanage/snmp/mode/components/battery.pm000066400000000000000000000061731417000230700314760ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::openmanage::snmp::mode::components::battery; use strict; use warnings; my %map_status = ( 1 => 'other', 2 => 'unknown', 3 => 'ok', 4 => 'nonCritical', 5 => 'critical', 6 => 'nonRecoverable', ); my %map_reading = ( 1 => 'Predictive Failure', 2 => 'Failed', 4 => 'Presence Detected', ); # In MIB '10892.mib' my $mapping = { batteryStatus => { oid => '.1.3.6.1.4.1.674.10892.1.600.50.1.5', map => \%map_status }, batteryReading => { oid => '.1.3.6.1.4.1.674.10892.1.600.50.1.6', map => \%map_reading }, batteryLocationName => { oid => '.1.3.6.1.4.1.674.10892.1.600.50.1.7' }, }; my $oid_batteryTableEntry = '.1.3.6.1.4.1.674.10892.1.600.50.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_batteryTableEntry, start => $mapping->{batteryStatus}->{oid}, end => $mapping->{batteryLocationName}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking batteries"); $self->{components}->{battery} = {name => 'batteries', total => 0, skip => 0}; return if ($self->check_filter(section => 'battery')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_batteryTableEntry}})) { next if ($oid !~ /^$mapping->{batteryStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_batteryTableEntry}, instance => $instance); next if ($self->check_filter(section => 'battery', instance => $instance)); $self->{components}->{battery}->{total}++; $self->{output}->output_add(long_msg => sprintf("Battery '%s' status is '%s' [instance: %s, reading: %s, location: %s]", $instance, $result->{batteryStatus}, $instance, $result->{batteryReading}, $result->{batteryLocationName} )); my $exit = $self->get_severity(label => 'default', section => 'battery', value => $result->{batteryStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Battery '%s' status is '%s'", $instance, $result->{batteryStatus})); } } } 1; centreon-plugins-20220113/hardware/server/dell/openmanage/snmp/mode/components/cachebattery.pm000066400000000000000000000112731417000230700324570ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::openmanage::snmp::mode::components::cachebattery; use strict; use warnings; my %map_state = ( 0 => 'unknown', 1 => 'ready', 2 => 'failed', 6 => 'degraded', 7 => 'reconditioning', 9 => 'high', 10 => 'powerLow', 12 => 'charging', 21 => 'missing', 36 => 'learning', ); my %map_status = ( 1 => 'other', 2 => 'unknown', 3 => 'ok', 4 => 'nonCritical', 5 => 'critical', 6 => 'nonRecoverable', ); my %map_learnState = ( 1 => 'failed', 2 => 'active', 4 => 'timedOut', 8 => 'requested', 16 => 'idle', 32 => 'due', ); my %map_predictedCapacity = ( 1 => 'failed', 2 => 'ready', 4 => 'unknown', ); # In MIB 'dcstorag.mib' my $mapping = { batteryState => { oid => '.1.3.6.1.4.1.674.10893.1.20.130.15.1.4', map => \%map_state }, }; my $mapping2 = { batteryComponentStatus => { oid => '.1.3.6.1.4.1.674.10893.1.20.130.15.1.6', map => \%map_status }, }; my $mapping3 = { batteryPredictedCapicity => { oid => '.1.3.6.1.4.1.674.10893.1.20.130.15.1.10', map => \%map_predictedCapacity }, }; my $mapping4 = { batteryLearnState => { oid => '.1.3.6.1.4.1.674.10893.1.20.130.15.1.12', map => \%map_learnState }, }; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping->{batteryState}->{oid} }, { oid => $mapping2->{batteryComponentStatus}->{oid} }, { oid => $mapping3->{batteryPredictedCapicity}->{oid} }, { oid => $mapping4->{batteryLearnState}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking cache batteries"); $self->{components}->{cachebattery} = {name => 'cache batteries', total => 0, skip => 0}; return if ($self->check_filter(section => 'cachebattery')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$mapping2->{batteryComponentStatus}->{oid}}})) { next if ($oid !~ /^$mapping2->{batteryComponentStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$mapping->{batteryState}->{oid}}, instance => $instance); my $result2 = $self->{snmp}->map_instance(mapping => $mapping2, results => $self->{results}->{$mapping2->{batteryComponentStatus}->{oid}}, instance => $instance); my $result3 = $self->{snmp}->map_instance(mapping => $mapping3, results => $self->{results}->{$mapping3->{batteryPredictedCapicity}->{oid}}, instance => $instance); my $result4 = $self->{snmp}->map_instance(mapping => $mapping4, results => $self->{results}->{$mapping4->{batteryLearnState}->{oid}}, instance => $instance); $result4->{batteryLearnState} = defined($result4->{batteryLearnState}) ? $result4->{batteryLearnState} : '-'; $result3->{batteryPredictedCapicity} = defined($result3->{batteryPredictedCapicity}) ? $result3->{batteryPredictedCapicity} : '-'; next if ($self->check_filter(section => 'cachebattery', instance => $instance)); $self->{components}->{cachebattery}->{total}++; $self->{output}->output_add(long_msg => sprintf("Cache battery '%s' status is '%s' [instance: %s, state: %s, learn state: %s, predicted capacity: %s]", $instance, $result2->{batteryComponentStatus}, $instance, $result->{batteryState}, $result4->{batteryLearnState}, $result3->{batteryPredictedCapicity} )); my $exit = $self->get_severity(label => 'default', section => 'cachebattery', value => $result2->{batteryComponentStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Cache battery '%s' status is '%s'", $instance, $result2->{batteryComponentStatus})); } } } 1; centreon-plugins-20220113/hardware/server/dell/openmanage/snmp/mode/components/connector.pm000066400000000000000000000101701417000230700320060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::openmanage::snmp::mode::components::connector; use strict; use warnings; my %map_state = ( 0 => 'unknown', 1 => 'ready', 2 => 'failed', 3 => 'online', 4 => 'offline', 6 => 'degraded', ); my %map_status = ( 1 => 'other', 2 => 'unknown', 3 => 'ok', 4 => 'nonCritical', 5 => 'critical', 6 => 'nonRecoverable', ); my %map_busType = ( 1 => 'SCSI', 2 => 'IDE', 3 => 'Fibre Channel', 4 => 'SSA', 6 => 'USB', 7 => 'SATA', 8 => 'SAS', ); # In MIB 'dcstorag.mib' my $mapping = { channelName => { oid => '.1.3.6.1.4.1.674.10893.1.20.130.2.1.2' }, channelState => { oid => '.1.3.6.1.4.1.674.10893.1.20.130.2.1.3', map => \%map_state }, }; my $mapping2 = { channelComponentStatus => { oid => '.1.3.6.1.4.1.674.10893.1.20.130.2.1.8', map => \%map_status }, }; my $mapping3 = { channelBusType => { oid => '.1.3.6.1.4.1.674.10893.1.20.130.2.1.11', map => \%map_busType }, }; my $oid_channelEntry = '.1.3.6.1.4.1.674.10893.1.20.130.2.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_channelEntry, start => $mapping->{channelName}->{oid}, end => $mapping->{channelState}->{oid} }, { oid => $mapping2->{channelComponentStatus}->{oid} }, { oid => $mapping3->{channelBusType}->{oid} } ; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking connectors (channels)"); $self->{components}->{connector} = {name => 'connectors', total => 0, skip => 0}; return if ($self->check_filter(section => 'connector')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$mapping2->{channelComponentStatus}->{oid}}})) { next if ($oid !~ /^$mapping2->{channelComponentStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_channelEntry}, instance => $instance); my $result2 = $self->{snmp}->map_instance(mapping => $mapping2, results => $self->{results}->{$mapping2->{channelComponentStatus}->{oid}}, instance => $instance); my $result3 = $self->{snmp}->map_instance(mapping => $mapping3, results => $self->{results}->{$mapping3->{channelBusType}->{oid}}, instance => $instance); $result3->{channelBusType} = defined($result3->{channelBusType}) ? $result3->{channelBusType} : '-'; next if ($self->check_filter(section => 'connector', instance => $instance)); $self->{components}->{connector}->{total}++; $self->{output}->output_add(long_msg => sprintf("Connector '%s' status is '%s' [instance: %s, state: %s, bus type: %s]", $result->{channelName}, $result2->{channelComponentStatus}, $instance, $result->{channelState}, $result3->{channelBusType} )); my $exit = $self->get_severity(label => 'default', section => 'connector', value => $result2->{channelComponentStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Connector '%s' status is '%s'", $result->{channelName}, $result2->{channelComponentStatus})); } } } 1; centreon-plugins-20220113/hardware/server/dell/openmanage/snmp/mode/components/controller.pm000066400000000000000000000100031417000230700321720ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::openmanage::snmp::mode::components::controller; use strict; use warnings; my %map_state = ( 0 => 'unknown', 1 => 'ready', 2 => 'failed', 3 => 'online', 4 => 'offline', 6 => 'degraded', ); my %map_status = ( 1 => 'other', 2 => 'unknown', 3 => 'ok', 4 => 'nonCritical', 5 => 'critical', 6 => 'nonRecoverable', ); # In MIB 'dcstorag.mib' my $mapping = { controllerName => { oid => '.1.3.6.1.4.1.674.10893.1.20.130.1.1.2' }, }; my $mapping2 = { controllerComponentStatus => { oid => '.1.3.6.1.4.1.674.10893.1.20.130.1.1.38', map => \%map_status }, }; my $mapping3 = { controllerState => { oid => '.1.3.6.1.4.1.674.10893.1.20.130.1.1.5', map => \%map_state }, }; my $mapping4 = { controllerFWVersion => { oid => '.1.3.6.1.4.1.674.10893.1.20.130.1.1.8' }, }; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping->{controllerName}->{oid} }, { oid => $mapping2->{controllerComponentStatus}->{oid} }, { oid => $mapping3->{controllerState}->{oid} }, { oid => $mapping4->{controllerFWVersion}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking controllers"); $self->{components}->{controller} = {name => 'controllers', total => 0, skip => 0}; return if ($self->check_filter(section => 'controller')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$mapping2->{controllerComponentStatus}->{oid}}})) { next if ($oid !~ /^$mapping2->{controllerComponentStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$mapping->{controllerName}->{oid}}, instance => $instance); my $result2 = $self->{snmp}->map_instance(mapping => $mapping2, results => $self->{results}->{$mapping2->{controllerComponentStatus}->{oid}}, instance => $instance); my $result3 = $self->{snmp}->map_instance(mapping => $mapping3, results => $self->{results}->{$mapping3->{controllerState}->{oid}}, instance => $instance); my $result4 = $self->{snmp}->map_instance(mapping => $mapping4, results => $self->{results}->{$mapping4->{controllerFWVersion}->{oid}}, instance => $instance); next if ($self->check_filter(section => 'controller', instance => $instance)); $self->{components}->{controller}->{total}++; $self->{output}->output_add(long_msg => sprintf("Controller '%s' status is '%s' [instance: %s, state: %s, firmware: %s]", $result->{controllerName}, $result2->{controllerComponentStatus}, $instance, $result3->{controllerState}, $result4->{controllerFWVersion} )); my $exit = $self->get_severity(label => 'default', section => 'controller', value => $result2->{controllerComponentStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Controller '%s' status is '%s'", $result->{controllerName}, $result2->{controllerComponentStatus})); } } } 1; centreon-plugins-20220113/hardware/server/dell/openmanage/snmp/mode/components/cpu.pm000066400000000000000000000107721417000230700306130ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::openmanage::snmp::mode::components::cpu; use strict; use warnings; my %map_status = ( 1 => 'other', 2 => 'unknown', 3 => 'ok', 4 => 'nonCritical', 5 => 'critical', 6 => 'nonRecoverable', ); my %map_statusState = ( 1 => 'other', 2 => 'unknown', 3 => 'enabled', 4 => 'userDisabled', 5 => 'biosDisabled', 6 => 'idle', ); # In MIB '10892.mib' my $mapping = { processorDeviceStatus => { oid => '.1.3.6.1.4.1.674.10892.1.1100.30.1.5', map => \%map_status }, }; my $mapping2 = { processorDeviceManufacturerName => { oid => '.1.3.6.1.4.1.674.10892.1.1100.30.1.8' }, processorDeviceStatusState => { oid => '.1.3.6.1.4.1.674.10892.1.1100.30.1.9', map => \%map_statusState }, }; my $mapping3 = { processorDeviceCurrentSpeed => { oid => '.1.3.6.1.4.1.674.10892.1.1100.30.1.12' }, # in mHz }; my $mapping4 = { processorDeviceBrandName => { oid => '.1.3.6.1.4.1.674.10892.1.1100.30.1.23' }, }; my $oid_processorDeviceTableEntry = '.1.3.6.1.4.1.674.10892.1.1100.30.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping->{processorDeviceStatus}->{oid} }, { oid => $oid_processorDeviceTableEntry, start => $mapping2->{processorDeviceManufacturerName}->{oid}, end => $mapping2->{processorDeviceStatusState}->{oid} }, { oid => $mapping3->{processorDeviceCurrentSpeed}->{oid} }, { oid => $mapping4->{processorDeviceBrandName}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking processor units"); $self->{components}->{cpu} = {name => 'CPUs', total => 0, skip => 0}; return if ($self->check_filter(section => 'cpu')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$mapping->{processorDeviceStatus}->{oid}}})) { next if ($oid !~ /^$mapping->{processorDeviceStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$mapping->{processorDeviceStatus}->{oid}}, instance => $instance); my $result2 = $self->{snmp}->map_instance(mapping => $mapping2, results => $self->{results}->{$oid_processorDeviceTableEntry}, instance => $instance); my $result3 = $self->{snmp}->map_instance(mapping => $mapping3, results => $self->{results}->{$mapping3->{processorDeviceCurrentSpeed}->{oid}}, instance => $instance); my $result4 = $self->{snmp}->map_instance(mapping => $mapping4, results => $self->{results}->{$mapping4->{processorDeviceBrandName}->{oid}}, instance => $instance); next if ($self->check_filter(section => 'cpu', instance => $instance)); $self->{components}->{cpu}->{total}++; $self->{output}->output_add(long_msg => sprintf("Cpu '%s' status is '%s' [instance: %s, manufacturer name: %s, brand name: %s, state: %s, speed: %s]", $instance, $result->{processorDeviceStatus}, $instance, $result2->{processorDeviceManufacturerName}, defined($result4->{processorDeviceBrandName}) ? $result4->{processorDeviceBrandName} : '-', $result2->{processorDeviceStatusState}, $result3->{processorDeviceCurrentSpeed} )); my $exit = $self->get_severity(label => 'default', section => 'cpu', value => $result->{processorDeviceStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Cpu '%s' status is '%s'", $instance, $result->{processorDeviceStatus})); } } } 1; centreon-plugins-20220113/hardware/server/dell/openmanage/snmp/mode/components/esmlog.pm000066400000000000000000000053721417000230700313120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::openmanage::snmp::mode::components::esmlog; use strict; use warnings; my %map_status = ( 1 => 'other', 2 => 'unknown', 3 => 'ok', 4 => 'nonCritical', 5 => 'critical', 6 => 'nonRecoverable', ); # In MIB '10892.mib' my $mapping = { systemStateEventLogStatus => { oid => '.1.3.6.1.4.1.674.10892.1.200.10.1.41', map => \%map_status }, }; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping->{systemStateEventLogStatus}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking ESM log filling"); $self->{components}->{esmlog} = {name => 'ESM log', total => 0, skip => 0}; return if ($self->check_filter(section => 'esmlog')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$mapping->{systemStateEventLogStatus}->{oid}}})) { next if ($oid !~ /^$mapping->{systemStateEventLogStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$mapping->{systemStateEventLogStatus}->{oid}}, instance => $instance); next if ($self->check_filter(section => 'globalstatus', instance => $instance)); $self->{components}->{esmlog}->{total}++; $self->{output}->output_add(long_msg => sprintf("ESM '%s' log status is '%s' [instance: %s]", $instance, $result->{systemStateEventLogStatus}, $instance )); my $exit = $self->get_severity(label => 'default', section => 'esmlog', value => $result->{systemStateEventLogStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("ESM '%s' log status is '%s'", $instance, $result->{systemStateEventLogStatus})); } } } 1; centreon-plugins-20220113/hardware/server/dell/openmanage/snmp/mode/components/fan.pm000066400000000000000000000106071417000230700305650ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::openmanage::snmp::mode::components::fan; use strict; use warnings; my %map_status = ( 1 => 'other', 2 => 'unknown', 3 => 'ok', 4 => 'nonCriticalUpper', 5 => 'criticalUpper', 6 => 'nonRecoverableUpper', 7 => 'nonCriticalLower', 8 => 'criticalLower', 9 => 'nonRecoverableLower', 10 => 'failed', ); # In MIB '10892.mib' my $mapping = { coolingDeviceStatus => { oid => '.1.3.6.1.4.1.674.10892.1.700.12.1.5', map => \%map_status }, coolingDeviceReading => { oid => '.1.3.6.1.4.1.674.10892.1.700.12.1.6' }, }; my $mapping2 = { coolingDeviceLocationName => { oid => '.1.3.6.1.4.1.674.10892.1.700.12.1.8' }, }; my $oid_coolingDeviceTableEntry = '.1.3.6.1.4.1.674.10892.1.700.12.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_coolingDeviceTableEntry, start => $mapping->{coolingDeviceStatus}->{oid}, end => $mapping->{coolingDeviceReading}->{oid} }, { oid => $mapping2->{coolingDeviceLocationName}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking fans"); $self->{components}->{fan} = {name => 'fans', total => 0, skip => 0}; return if ($self->check_filter(section => 'fan')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_coolingDeviceTableEntry}})) { next if ($oid !~ /^$mapping->{coolingDeviceStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_coolingDeviceTableEntry}, instance => $instance); my $result2 = $self->{snmp}->map_instance(mapping => $mapping2, results => $self->{results}->{$mapping2->{coolingDeviceLocationName}->{oid}}, instance => $instance); next if ($self->check_filter(section => 'fan', instance => $instance)); $self->{components}->{fan}->{total}++; $self->{output}->output_add(long_msg => sprintf("Fan '%s' status is '%s' [instance: %s, Location: %s, reading: %s]", $instance, $result->{coolingDeviceStatus}, $instance, $result2->{coolingDeviceLocationName}, $result->{coolingDeviceReading} )); my $exit = $self->get_severity(label => 'default', section => 'fan', value => $result->{coolingDeviceStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Fan '%s' status is '%s'", $instance, $result->{coolingDeviceStatus})); } if (defined($result->{coolingDeviceReading}) && $result->{coolingDeviceReading} =~ /[0-9]/) { my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'fan', instance => $instance, value => $result->{coolingDeviceReading}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Fan '%s' speed is %s rpm", $instance, $result->{coolingDeviceReading})); } $self->{output}->perfdata_add( label => 'fan', unit => 'rpm', nlabel => 'hardware.fan.speed.rpm', instances => $instance, value => $result->{coolingDeviceReading}, warning => $warn, critical => $crit, min => 0 ); } } } 1; centreon-plugins-20220113/hardware/server/dell/openmanage/snmp/mode/components/globalstatus.pm000066400000000000000000000053771417000230700325350ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::openmanage::snmp::mode::components::globalstatus; use strict; use warnings; my %map_status = ( 1 => 'other', 2 => 'unknown', 3 => 'ok', 4 => 'nonCritical', 5 => 'critical', 6 => 'nonRecoverable', ); # In MIB '10892.mib' my $mapping = { globalSystemStatus => { oid => '.1.3.6.1.4.1.674.10892.1.200.10.1.2', map => \%map_status }, }; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping->{globalSystemStatus}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking global system status"); $self->{components}->{globalstatus} = {name => 'global system status', total => 0, skip => 0}; return if ($self->check_filter(section => 'globalstatus')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$mapping->{globalSystemStatus}->{oid}}})) { next if ($oid !~ /^$mapping->{globalSystemStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$mapping->{globalSystemStatus}->{oid}}, instance => $instance); next if ($self->check_filter(section => 'globalstatus', instance => $instance)); $self->{components}->{globalstatus}->{total}++; $self->{output}->output_add(long_msg => sprintf("Chassis '%s' global status is '%s' [instance: %s]", $instance, $result->{globalSystemStatus}, $instance )); my $exit = $self->get_severity(label => 'default', section => 'globalstatus', value => $result->{globalSystemStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Chassis '%s' global status is '%s'", $instance, $result->{globalSystemStatus})); } } } 1; centreon-plugins-20220113/hardware/server/dell/openmanage/snmp/mode/components/logicaldrive.pm000066400000000000000000000121051417000230700324600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::openmanage::snmp::mode::components::logicaldrive; use strict; use warnings; my %map_state = ( 0 => 'unknown', 1 => 'ready', 2 => 'failed', 3 => 'online', 4 => 'offline', 6 => 'degraded', 15 => 'resynching', 24 => 'rebuild', 26 => 'formatting', 35 => 'initializing', ); my %map_layout = ( 1 => 'Concatened', 2 => 'RAID-0', 3 => 'RAID-1', 4 => 'RAID-2', 5 => 'RAID-3', 6 => 'RAID-4', 7 => 'RAID-5', 8 => 'RAID-6', 9 => 'RAID-7', 10 => 'RAID-10', 11 => 'RAID-30', 12 => 'RAID-50', 13 => 'Add spares', 14 => 'Delete logical', 15 => 'Transform logical', 18 => 'RAID-0-plus-1 - Mylex only', 19 => 'Concatened RAID 1', 20 => 'Concatened RAID 5', 21 => 'no RAID', 22 => 'RAID Morph - Adapted only', ); my %map_status = ( 1 => 'other', 2 => 'unknown', 3 => 'ok', 4 => 'nonCritical', 5 => 'critical', 6 => 'nonRecoverable', ); # In MIB 'dcstorag.mib' my $mapping = { virtualDiskName => { oid => '.1.3.6.1.4.1.674.10893.1.20.140.1.1.2' }, virtualDiskDeviceName => { oid => '.1.3.6.1.4.1.674.10893.1.20.140.1.1.3' }, virtualDiskState => { oid => '.1.3.6.1.4.1.674.10893.1.20.140.1.1.4', map => \%map_state }, }; my $mapping2 = { virtualDiskLengthInMB => { oid => '.1.3.6.1.4.1.674.10893.1.20.140.1.1.6' }, }; my $mapping3 = { virtualDiskLayout => { oid => '.1.3.6.1.4.1.674.10893.1.20.140.1.1.13', map => \%map_layout }, }; my $mapping4 = { virtualDiskComponentStatus => { oid => '.1.3.6.1.4.1.674.10893.1.20.140.1.1.20', map => \%map_status }, }; my $oid_virtualDiskEntry = '.1.3.6.1.4.1.674.10893.1.20.140.1.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_virtualDiskEntry, start => $mapping->{virtualDiskName}->{oid}, end => $mapping->{virtualDiskState}->{oid} }, { oid => $mapping2->{virtualDiskLengthInMB}->{oid} }, { oid => $mapping3->{virtualDiskLayout}->{oid} }, { oid => $mapping4->{virtualDiskComponentStatus}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking logical drives"); $self->{components}->{logicaldrive} = {name => 'logical drives', total => 0, skip => 0}; return if ($self->check_filter(section => 'logicaldrive')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$mapping4->{virtualDiskComponentStatus}->{oid}}})) { next if ($oid !~ /^$mapping4->{virtualDiskComponentStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_virtualDiskEntry}, instance => $instance); my $result2 = $self->{snmp}->map_instance(mapping => $mapping2, results => $self->{results}->{$mapping2->{virtualDiskLengthInMB}->{oid}}, instance => $instance); my $result3 = $self->{snmp}->map_instance(mapping => $mapping3, results => $self->{results}->{$mapping3->{virtualDiskLayout}->{oid}}, instance => $instance); my $result4 = $self->{snmp}->map_instance(mapping => $mapping4, results => $self->{results}->{$mapping4->{virtualDiskComponentStatus}->{oid}}, instance => $instance); next if ($self->check_filter(section => 'logicaldrive', instance => $instance)); $self->{components}->{logicaldrive}->{total}++; $self->{output}->output_add(long_msg => sprintf("Logical drive '%s' status is '%s' [instance: %s, size: %s MB, layout: %s, state: %s, device name: %s]", $result->{virtualDiskName}, $result4->{virtualDiskComponentStatus}, $instance, $result2->{virtualDiskLengthInMB}, $result3->{virtualDiskLayout}, $result->{virtualDiskState}, $result->{virtualDiskDeviceName} )); my $exit = $self->get_severity(label => 'default', section => 'logicaldrive', value => $result4->{virtualDiskComponentStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Logical drive '%s' status is '%s'", $result->{virtualDiskName}, $result4->{virtualDiskComponentStatus})); } } } 1; centreon-plugins-20220113/hardware/server/dell/openmanage/snmp/mode/components/memory.pm000066400000000000000000000103061417000230700313250ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::openmanage::snmp::mode::components::memory; use strict; use warnings; my %map_status = ( 1 => 'other', 2 => 'unknown', 3 => 'ok', 4 => 'nonCritical', 5 => 'critical', 6 => 'nonRecoverable', ); my %map_failureModes = ( 0 => 'Not failure', 1 => 'ECC single bit correction warning rate exceeded', 2 => 'ECC single bit correction failure rate exceeded', 4 => 'ECC multibit fault encountered', 8 => 'ECC single bit correction logging disabled', 16 => 'device disabled because of spare activation', ); # In MIB '10892.mib' my $mapping = { memoryDeviceStatus => { oid => '.1.3.6.1.4.1.674.10892.1.1100.50.1.5', map => \%map_status }, }; my $mapping2 = { memoryDeviceLocationName => { oid => '.1.3.6.1.4.1.674.10892.1.1100.50.1.8' }, }; my $mapping3 = { memoryDeviceSize => { oid => '.1.3.6.1.4.1.674.10892.1.1100.50.1.14' }, }; my $mapping4 = { memoryDeviceFailureModes => { oid => '.1.3.6.1.4.1.674.10892.1.1100.50.1.20', map => \%map_failureModes }, }; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping->{memoryDeviceStatus}->{oid} }, { oid => $mapping2->{memoryDeviceLocationName}->{oid} }, { oid => $mapping3->{memoryDeviceSize}->{oid} }, { oid => $mapping4->{memoryDeviceFailureModes}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking memory modules"); $self->{components}->{memory} = {name => 'memory modules', total => 0, skip => 0}; return if ($self->check_filter(section => 'memory')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$mapping->{memoryDeviceStatus}->{oid}}})) { next if ($oid !~ /^$mapping->{memoryDeviceStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$mapping->{memoryDeviceStatus}->{oid}}, instance => $instance); my $result2 = $self->{snmp}->map_instance(mapping => $mapping2, results => $self->{results}->{$mapping2->{memoryDeviceLocationName}->{oid}}, instance => $instance); my $result3 = $self->{snmp}->map_instance(mapping => $mapping3, results => $self->{results}->{$mapping3->{memoryDeviceSize}->{oid}}, instance => $instance); my $result4 = $self->{snmp}->map_instance(mapping => $mapping4, results => $self->{results}->{$mapping4->{memoryDeviceFailureModes}->{oid}}, instance => $instance); next if ($self->check_filter(section => 'memory', instance => $instance)); $self->{components}->{memory}->{total}++; $self->{output}->output_add(long_msg => sprintf("Memory module '%s' status is '%s' [instance: %s, Location: %s, Size: %s MB, Failure mode: %s]", $instance, $result->{memoryDeviceStatus}, $instance, $result2->{memoryDeviceLocationName}, $result3->{memoryDeviceSize}, $result4->{memoryDeviceFailureModes} )); my $exit = $self->get_severity(label => 'default', section => 'memory', value => $result->{memoryDeviceStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Memory module '%s' status is '%s'", $instance, $result->{memoryDeviceStatus})); } } } 1; centreon-plugins-20220113/hardware/server/dell/openmanage/snmp/mode/components/physicaldisk.pm000066400000000000000000000130661417000230700325120ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::openmanage::snmp::mode::components::physicaldisk; use strict; use warnings; my %map_state = ( 0 => 'unknown', 1 => 'ready', 2 => 'failed', 3 => 'online', 4 => 'offline', 6 => 'degraded', 7 => 'recovering', 11 => 'removed', 15 => 'resynching', 24 => 'rebuild', 25 => 'noMedia', 26 => 'formatting', 28 => 'diagnostics', 35 => 'initializing', ); my %map_spareState = ( 1 => 'memberVD', 2 => 'memberDG', 3 => 'globalHostSpare', 4 => 'dedicatedHostSpare', 5 => 'notASpare', ); my %map_status = ( 1 => 'other', 2 => 'unknown', 3 => 'ok', 4 => 'nonCritical', 5 => 'critical', 6 => 'nonRecoverable', ); my %map_smartAlertIndication = ( 1 => 'no', 2 => 'yes', ); # In MIB 'dcstorag.mib' my $mapping = { arrayDiskName => { oid => '.1.3.6.1.4.1.674.10893.1.20.130.4.1.2' }, }; my $mapping2 = { arrayDiskState => { oid => '.1.3.6.1.4.1.674.10893.1.20.130.4.1.4', map => \%map_state }, }; my $mapping3 = { arrayDiskSpareState => { oid => '.1.3.6.1.4.1.674.10893.1.20.130.4.1.22', map => \%map_spareState }, }; my $mapping4 = { arrayDiskComponentStatus => { oid => '.1.3.6.1.4.1.674.10893.1.20.130.4.1.24', map => \%map_status }, }; my $mapping5 = { arrayDiskSmartAlertIndication => { oid => '.1.3.6.1.4.1.674.10893.1.20.130.4.1.31', map => \%map_smartAlertIndication }, }; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping->{arrayDiskName}->{oid} }, { oid => $mapping2->{arrayDiskState}->{oid} }, { oid => $mapping3->{arrayDiskSpareState}->{oid} }, { oid => $mapping4->{arrayDiskComponentStatus}->{oid} }, { oid => $mapping5->{arrayDiskSmartAlertIndication}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking physical disks"); $self->{components}->{physicaldisk} = {name => 'physical disks', total => 0, skip => 0}; return if ($self->check_filter(section => 'physicaldisk')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$mapping4->{arrayDiskComponentStatus}->{oid}}})) { next if ($oid !~ /^$mapping4->{arrayDiskComponentStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$mapping->{arrayDiskName}->{oid}}, instance => $instance); my $result2 = $self->{snmp}->map_instance(mapping => $mapping2, results => $self->{results}->{$mapping2->{arrayDiskState}->{oid}}, instance => $instance); my $result3 = $self->{snmp}->map_instance(mapping => $mapping3, results => $self->{results}->{$mapping3->{arrayDiskSpareState}->{oid}}, instance => $instance); my $result4 = $self->{snmp}->map_instance(mapping => $mapping4, results => $self->{results}->{$mapping4->{arrayDiskComponentStatus}->{oid}}, instance => $instance); my $result5 = $self->{snmp}->map_instance(mapping => $mapping5, results => $self->{results}->{$mapping5->{arrayDiskSmartAlertIndication}->{oid}}, instance => $instance); next if ($self->check_filter(section => 'physicaldisk', instance => $instance)); $self->{components}->{physicaldisk}->{total}++; $self->{output}->output_add(long_msg => sprintf("Physical Disk '%s' status is '%s' [instance: %s, state: %s, spare state: %s, smart alert: %s]", $result->{arrayDiskName}, $result4->{arrayDiskComponentStatus}, $instance, $result2->{arrayDiskState}, $result3->{arrayDiskSpareState}, defined($result5->{arrayDiskSmartAlertIndication}) ? $result5->{arrayDiskSmartAlertIndication} : '-' )); my $exit = $self->get_severity(label => 'default', section => 'physicaldisk', value => $result4->{arrayDiskComponentStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Physical Disk '%s' status is '%s'", $result->{arrayDiskName}, $result4->{arrayDiskComponentStatus})); } if (defined($result5->{arrayDiskSmartAlertIndication})) { $exit = $self->get_severity(section => 'physicaldisk_smartalert', value => $result5->{arrayDiskSmartAlertIndication}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("physical disk '%s' has received a predictive failure alert", $result->{arrayDiskName})); } } } } 1; centreon-plugins-20220113/hardware/server/dell/openmanage/snmp/mode/components/psu.pm000066400000000000000000000134641417000230700306340ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::openmanage::snmp::mode::components::psu; use strict; use warnings; my %map_status = ( 1 => 'other', 2 => 'unknown', 3 => 'ok', 4 => 'nonCritical', 5 => 'critical', 6 => 'nonRecoverable', ); my %map_type = ( 1 => 'other', 2 => 'unknown', 3 => 'Linear', 4 => 'switching', 5 => 'Battery', 6 => 'UPS', 7 => 'Converter', 8 => 'Regulator', 9 => 'AC', 10 => 'DC', 11 => 'VRM', ); my %map_state = ( 1 => 'present', 2 => 'failure', 4 => 'predictiveFailure', 8 => 'ACLost', 16 => 'ACLostOrOutOfRange', 32 => 'ACPresentButOutOfRange', 64 => 'configurationError', ); my %map_ConfigurationErrorType = ( 1 => 'vendorMismatch', 2 => 'revisionMismatch', 3 => 'processorMissing', ); # In MIB '10892.mib' my $mapping = { powerSupplyStatus => { oid => '.1.3.6.1.4.1.674.10892.1.600.12.1.5', map => \%map_status }, powerSupplyOutputWatts => { oid => '.1.3.6.1.4.1.674.10892.1.600.12.1.6' }, powerSupplyType => { oid => '.1.3.6.1.4.1.674.10892.1.600.12.1.7', map => \%map_type }, powerSupplyLocationName => { oid => '.1.3.6.1.4.1.674.10892.1.600.12.1.8' }, }; my $mapping2 = { powerSupplySensorState => { oid => '.1.3.6.1.4.1.674.10892.1.600.12.1.11', map => \%map_state }, powerSupplyConfigurationErrorType => { oid => '.1.3.6.1.4.1.674.10892.1.600.12.1.12', map => \%map_ConfigurationErrorType }, }; my $oid_powerSupplyTable = '.1.3.6.1.4.1.674.10892.1.600.12'; my $oid_powerSupplyTableEntry = '.1.3.6.1.4.1.674.10892.1.600.12.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_powerSupplyTable, start => $mapping->{powerSupplyStatus}->{oid}, end => $mapping->{powerSupplyLocationName}->{oid} }, { oid => $oid_powerSupplyTableEntry, start => $mapping2->{powerSupplySensorState}->{oid}, end => $mapping2->{powerSupplyConfigurationErrorType}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking power supplies"); $self->{components}->{psu} = {name => 'power supplies', total => 0, skip => 0}; return if ($self->check_filter(section => 'psu')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_powerSupplyTable}})) { next if ($oid !~ /^$mapping->{powerSupplyStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_powerSupplyTable}, instance => $instance); my $result2 = $self->{snmp}->map_instance(mapping => $mapping2, results => $self->{results}->{$oid_powerSupplyTableEntry}, instance => $instance); $result2->{powerSupplyConfigurationErrorType} = defined($result2->{powerSupplyConfigurationErrorType}) ? $result2->{powerSupplyConfigurationErrorType} : '-'; next if ($self->check_filter(section => 'psu', instance => $instance)); $self->{components}->{psu}->{total}++; $self->{output}->output_add(long_msg => sprintf("Power supply '%s' status is '%s' [instance: %s, location: %s, type: %s, output watts: %s, state: %s, configuration error: %s]", $instance, $result->{powerSupplyStatus}, $instance, $result->{powerSupplyLocationName}, $result->{powerSupplyType}, defined($result->{powerSupplyOutputWatts}) ? $result->{powerSupplyOutputWatts} : '-', $result2->{powerSupplySensorState}, $result2->{powerSupplyConfigurationErrorType} )); my $exit = $self->get_severity(label => 'default', section => 'psu', value => $result->{powerSupplyStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Power supply '%s' status is '%s'", $instance, $result->{powerSupplyStatus})); } if (defined($result->{powerSupplyOutputWatts}) && $result->{powerSupplyOutputWatts} =~ /[0-9]/) { $result->{powerSupplyOutputWatts} /= 10; my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'psu.power', instance => $instance, value => $result->{powerSupplyOutputWatts}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Power supply '%s' power is %s W", $instance, $result->{powerSupplyOutputWatts})); } $self->{output}->perfdata_add( label => 'psu_power', unit => 'W', nlabel => 'hardware.powersupply.power.watt', instances => $instance, value => $result->{powerSupplyOutputWatts}, warning => $warn, critical => $crit, min => 0 ); } } } 1; centreon-plugins-20220113/hardware/server/dell/openmanage/snmp/mode/components/temperature.pm000066400000000000000000000110301417000230700323450ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::openmanage::snmp::mode::components::temperature; use strict; use warnings; my %map_status = ( 1 => 'other', 2 => 'unknown', 3 => 'ok', 4 => 'nonCriticalUpper', 5 => 'criticalUpper', 6 => 'nonRecoverableUpper', 7 => 'nonCriticalLower', 8 => 'criticalLower', 9 => 'nonRecoverableLower', 10 => 'failed', ); my %map_type = ( 1 => 'other', 2 => 'unknown', 3 => 'Ambient ESM', 4 => 'Discrete', ); # In MIB '10892.mib' my $mapping = { temperatureProbeStatus => { oid => '.1.3.6.1.4.1.674.10892.1.700.20.1.5', map => \%map_status }, temperatureProbeReading => { oid => '.1.3.6.1.4.1.674.10892.1.700.20.1.6' }, temperatureProbeType => { oid => '.1.3.6.1.4.1.674.10892.1.700.20.1.7', map => \%map_type }, temperatureProbeLocationName => { oid => '.1.3.6.1.4.1.674.10892.1.700.20.1.8' }, }; my $oid_temperatureProbeTable = '.1.3.6.1.4.1.674.10892.1.700.20'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_temperatureProbeTable, start => $mapping->{temperatureProbeStatus}->{oid}, end => $mapping->{temperatureProbeLocationName}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking temperatures"); $self->{components}->{temperature} = {name => 'temperatures', total => 0, skip => 0}; return if ($self->check_filter(section => 'temperature')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_temperatureProbeTable}})) { next if ($oid !~ /^$mapping->{temperatureProbeStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_temperatureProbeTable}, instance => $instance); next if ($self->check_filter(section => 'temperature', instance => $instance)); $self->{components}->{temperature}->{total}++; $self->{output}->output_add(long_msg => sprintf("Temperature '%s' status is '%s' [instance: %s, location: %s, reading: %s]", $instance, $result->{temperatureProbeStatus}, $instance, $result->{temperatureProbeLocationName}, $result->{temperatureProbeReading} )); my $exit = $self->get_severity(label => 'default', section => 'temperature', value => $result->{temperatureProbeStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Temperature '%s' status is '%s'", $instance, $result->{temperatureProbeStatus})); } if (defined($result->{temperatureProbeReading}) && $result->{temperatureProbeReading} =~ /[0-9]/) { $result->{temperatureProbeReading} /= 10; my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $instance, value => $result->{temperatureProbeReading}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Temperature '%s' is %s degree centigrade", $instance, $result->{temperatureProbeReading})); } $self->{output}->perfdata_add( label => 'temp', unit => 'C', nlabel => 'hardware.temperature.celsius', instances => $instance, value => $result->{temperatureProbeReading}, warning => $warn, critical => $crit, min => 0 ); } } } 1; centreon-plugins-20220113/hardware/server/dell/openmanage/snmp/mode/hardware.pm000066400000000000000000000076771417000230700274460ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::openmanage::snmp::mode::hardware; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; use centreon::plugins::misc; sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^(temperature|fan|psu\.power)$'; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { default => [ ['other', 'CRITICAL'], ['unknown', 'UNKNOWN'], ['ok', 'OK'], ['nonCritical', 'WARNING'], # nonCriticalUpper # nonCriticalLower ['critical', 'CRITICAL'], # criticalUpper ['nonRecoverable', 'CRITICAL'], # nonRecoverableUpper # nonRecoverableLower ['failed', 'CRITICAL'] ], physicaldisk_smartalert => [ ['yes', 'WARNING'], ['no', 'OK'] ] }; $self->{components_path} = 'hardware::server::dell::openmanage::snmp::mode::components'; $self->{components_module} = [ 'globalstatus', 'fan', 'psu', 'temperature', 'cpu', 'cachebattery', 'memory', 'physicaldisk', 'logicaldrive', 'esmlog', 'battery', 'controller', 'connector' ]; } sub snmp_execute { my ($self, %options) = @_; # In '10892-MIB' my $oid_chassisModelName = '.1.3.6.1.4.1.674.10892.1.300.10.1.9'; $self->{snmp} = $options{snmp}; push @{$self->{request}}, { oid => $oid_chassisModelName }; $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_chassisModelName}})) { my $name = defined($self->{results}->{$oid_chassisModelName}->{$oid}) ? centreon::plugins::misc::trim($self->{results}->{$oid_chassisModelName}->{$oid}) : 'unknown'; $self->{output}->output_add(long_msg => sprintf("Product Name: %s", $name)); } } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } 1; __END__ =head1 MODE Check Hardware (Global status, Fans, CPUs, Power Supplies, Temperature, Storage). =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'globalstatus', 'fan', 'cpu', 'psu', 'temperature', 'cachebattery', 'physicaldisk', 'logicaldrive', 'battery', 'controller', 'connector'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=fan) Can also exclude specific instance: --filter=fan,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,status,regexp) It used before default thresholds (order stays). Example: --threshold-overload='temperature,CRITICAL,^(?!(ok)$)' =item B<--warning> Set warning threshold for temperature, psu.power or fan (syntax: type,regexp,threshold) Example: --warning='temperature,.*,30' =item B<--critical> Set critical threshold for temperature, psu.power or fan (syntax: type,regexp,threshold) Example: --critical='temperature,.*,40' =back =cut centreon-plugins-20220113/hardware/server/dell/openmanage/snmp/plugin.pm000066400000000000000000000024171417000230700262060ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::dell::openmanage::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}} = ( 'hardware' => 'hardware::server::dell::openmanage::snmp::mode::hardware', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Dell servers in SNMP thanks to Dell Openmanage. =cut centreon-plugins-20220113/hardware/server/fujitsu/000077500000000000000000000000001417000230700220305ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/fujitsu/snmp/000077500000000000000000000000001417000230700230055ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/fujitsu/snmp/mode/000077500000000000000000000000001417000230700237315ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/fujitsu/snmp/mode/components/000077500000000000000000000000001417000230700261165ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/fujitsu/snmp/mode/components/cpu.pm000066400000000000000000000075261417000230700272550ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::fujitsu::snmp::mode::components::cpu; use strict; use warnings; my $map_sc_cpu_status = { 1 => 'unknown', 2 => 'disabled', 3 => 'ok', 4 => 'not-present', 5 => 'error', 6 => 'fail', 7 => 'missing-termination', 8 => 'prefailure-warning' }; my $map_sc2_cpu_status = { 1 => 'unknown', 2 => 'not-present', 3 => 'ok', 4 => 'disabled', 5 => 'error', 6 => 'failed', 7 => 'missing-termination', 8 => 'prefailure-warning' }; my $mapping = { sc => { cpuStatus => { oid => '.1.3.6.1.4.1.231.2.10.2.2.5.4.1.1.6', map => $map_sc_cpu_status } }, sc2 => { sc2cpuDesignation => { oid => '.1.3.6.1.4.1.231.2.10.2.2.10.6.4.1.3' }, sc2cpuStatus => { oid => '.1.3.6.1.4.1.231.2.10.2.2.10.6.4.1.4', map => $map_sc2_cpu_status } } }; my $oid_sc2CPUs = '.1.3.6.1.4.1.231.2.10.2.2.10.6.4.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_sc2CPUs, end => $mapping->{sc2}->{sc2cpuStatus} }, { oid => $mapping->{sc}->{cpuStatus}->{oid} }; } sub check_cpu { my ($self, %options) = @_; my ($exit, $warn, $crit, $checked); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$options{entry}}})) { next if ($oid !~ /^$options{mapping}->{$options{status}}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $options{mapping}, results => $self->{results}->{$options{entry}}, instance => $instance); $result->{instance} = $instance; next if ($self->check_filter(section => 'cpu', instance => $instance)); next if ($result->{$options{status}} =~ /not-present|not-available/i && $self->absent_problem(section => 'cpu', instance => $instance)); $self->{components}->{cpu}->{total}++; $self->{output}->output_add( long_msg => sprintf( "cpu '%s' status is '%s' [instance: %s]", $result->{$options{name}}, $result->{$options{status}}, $instance ) ); $exit = $self->get_severity(section => 'cpu', value => $result->{$options{status}}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Cpu '%s' status is '%s'", $result->{$options{name}}, $result->{$options{status}}) ); } } } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => 'Checking cpu'); $self->{components}->{cpu} = { name => 'cpu', total => 0, skip => 0 }; return if ($self->check_filter(section => 'cpu')); if (defined($self->{results}->{$oid_sc2CPUs}) && scalar(keys %{$self->{results}->{$oid_sc2CPUs}}) > 0) { check_cpu( $self, entry => $oid_sc2CPUs, mapping => $mapping->{sc2}, name => 'sc2cpuDesignation', status => 'sc2cpuStatus' ); } else { check_cpu( $self, entry => $mapping->{sc}->{cpuStatus}, mapping => $mapping->{sc}, name => 'instance', status => 'cpuStatus' ); } } 1; centreon-plugins-20220113/hardware/server/fujitsu/snmp/mode/components/disk.pm000066400000000000000000000053321417000230700274110ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::fujitsu::snmp::mode::components::disk; use strict; use warnings; my $map_drive_status = { 1 => 'unknown', 2 => 'noDisk', 3 => 'online', 4 => 'ready', 5 => 'failed', 6 => 'rebuilding', 7 => 'hotspareGlobal', 8 => 'hotspareDedicated', 9 => 'offline', 10 => 'unconfiguredFailed', 11 => 'formatting', 12 => 'dead' }; my $mapping = { status => { oid => '.1.3.6.1.4.1.231.2.49.1.5.2.1.15', map => $map_drive_status } # svrPhysicalDeviceStatus }; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $mapping->{status}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => 'Checking disks'); $self->{components}->{disk} = { name => 'disks', total => 0, skip => 0 }; return if ($self->check_filter(section => 'disk')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{ $mapping->{status}->{oid} }})) { next if ($oid !~ /^$mapping->{status}->{oid}\.(\d+)\.(\d+)\.(\d+)\.(\d+)$/); my $instance = $1 . '.' . $2 . '.' . $3 . '.' . $4; my $name = $1 . ':' . $2 . ':' . $3 . ':' . $4; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{ $mapping->{status}->{oid} }, instance => $instance); next if ($self->check_filter(section => 'disk', instance => $instance)); $self->{components}->{disk}->{total}++; $self->{output}->output_add( long_msg => sprintf( "disk '%s' status is '%s' [instance: %s]", $name, $result->{status}, $instance ) ); my $exit = $self->get_severity(section => 'disk', value => $result->{status}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Disk '%s' status is '%s'", $name, $result->{status}) ); } } } 1; centreon-plugins-20220113/hardware/server/fujitsu/snmp/mode/components/fan.pm000066400000000000000000000120441417000230700272210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::fujitsu::snmp::mode::components::fan; use strict; use warnings; my $map_sc_fan_status = { 1 => 'unknown', 2 => 'disabled', 3 => 'ok', 4 => 'fail', 5 => 'prefailure-predicted', 6 => 'redundant-fan-failed', 7 => 'not-manageable', 8 => 'not-present' }; my $map_sc2_fan_status = { 1 => 'unknown', 2 => 'disabled', 3 => 'ok', 4 => 'failed', 5 => 'prefailure-predicted', 6 => 'redundant-fan-failed', 7 => 'not-manageable', 8 => 'not-present' }; my $mapping = { sc => { fanStatus => { oid => '.1.3.6.1.4.1.231.2.10.2.2.5.2.2.1.3', map => $map_sc_fan_status }, fanCurrentSpeed => { oid => '.1.3.6.1.4.1.231.2.10.2.2.5.2.2.1.8' }, fanDesignation => { oid => '.1.3.6.1.4.1.231.2.10.2.2.5.2.2.1.16' } }, sc2 => { sc2fanDesignation => { oid => '.1.3.6.1.4.1.231.2.10.2.2.10.5.2.1.3' }, sc2fanStatus => { oid => '.1.3.6.1.4.1.231.2.10.2.2.10.5.2.1.5', map => $map_sc2_fan_status }, sc2fanCurrentSpeed => { oid => '.1.3.6.1.4.1.231.2.10.2.2.10.5.2.1.6' } } }; my $oid_sc2Fans = '.1.3.6.1.4.1.231.2.10.2.2.10.5.2.1'; my $oid_fans = '.1.3.6.1.4.1.231.2.10.2.2.5.2.2.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_sc2Fans, end => $mapping->{sc2}->{sc2fanCurrentSpeed} }, { oid => $oid_fans }; } sub check_fan { my ($self, %options) = @_; my ($exit, $warn, $crit, $checked); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$options{entry}}})) { next if ($oid !~ /^$options{mapping}->{$options{status}}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $options{mapping}, results => $self->{results}->{$options{entry}}, instance => $instance); next if ($self->check_filter(section => 'fan', instance => $instance)); next if ($result->{$options{status}} =~ /not-present|not-available/i && $self->absent_problem(section => 'fan', instance => $instance)); $self->{components}->{fan}->{total}++; $self->{output}->output_add( long_msg => sprintf( "fan '%s' status is '%s' [instance: %s] [speed: %s]", $result->{$options{name}}, $result->{$options{status}}, $instance, $result->{$options{speed}} ) ); $exit = $self->get_severity(section => 'fan', value => $result->{$options{status}}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Fan '%s' status is '%s'", $result->{$options{name}}, $result->{$options{status}}) ); } next if (!defined($result->{$options{speed}}) || $result->{$options{speed}} == -1); ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'fan', instance => $instance, value => $result->{$options{speed}}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Fan '%s' speed is %s rpm", $result->{$options{name}}, $result->{$options{speed}}) ); } $self->{output}->perfdata_add( nlabel => 'hardware.fan.speed.rpm', unit => 'rpm', instances => $result->{$options{name}}, value => $result->{$options{speed}}, warning => $warn, critical => $crit, min => 0 ); } } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => 'Checking fans'); $self->{components}->{fan} = { name => 'fans', total => 0, skip => 0 }; return if ($self->check_filter(section => 'fan')); if (defined($self->{results}->{$oid_sc2Fans}) && scalar(keys %{$self->{results}->{$oid_sc2Fans}}) > 0) { check_fan( $self, entry => $oid_sc2Fans, mapping => $mapping->{sc2}, name => 'sc2fanDesignation', speed => 'sc2fanCurrentSpeed', status => 'sc2fanStatus' ); } else { check_fan( $self, entry => $oid_fans, mapping => $mapping->{sc}, name => 'fanDesignation', speed => 'fanCurrentSpeed', status => 'fanStatus' ); } } 1; centreon-plugins-20220113/hardware/server/fujitsu/snmp/mode/components/memory.pm000066400000000000000000000100671417000230700277700ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::fujitsu::snmp::mode::components::memory; use strict; use warnings; my $map_sc_memory_status = { 1 => 'unknown', 2 => 'error', 3 => 'ok', 4 => 'not-available', 5 => 'fail', 6 => 'prefailure-warning', 7 => 'hot-spare', 8 => 'mirror', 9 => 'disabled', 10 => 'raid' }; my $map_sc2_memory_status = { 1 => 'unknown', 2 => 'not-present', 3 => 'ok', 4 => 'disabled', 5 => 'error', 6 => 'failed', 7 => 'prefailure-predicted', 8 => 'hot-spare', 9 => 'mirror', 10 => 'raid', 11 => 'hidden' }; my $mapping = { sc => { memModuleStatus => { oid => '.1.3.6.1.4.1.231.2.10.2.2.5.4.10.1.3', map => $map_sc_memory_status } }, sc2 => { sc2memModuleDesignation => { oid => '.1.3.6.1.4.1.231.2.10.2.2.10.6.5.1.3' }, sc2memModuleStatus => { oid => '.1.3.6.1.4.1.231.2.10.2.2.10.6.5.1.4', map => $map_sc2_memory_status } } }; my $oid_sc2MemoryModules = '.1.3.6.1.4.1.231.2.10.2.2.10.6.5.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_sc2MemoryModules, end => $mapping->{sc2}->{sc2memModuleStatus} }, { oid => $mapping->{sc}->{memModuleStatus}->{oid} }; } sub check_memory { my ($self, %options) = @_; my ($exit, $warn, $crit, $checked); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$options{entry}}})) { next if ($oid !~ /^$options{mapping}->{$options{status}}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $options{mapping}, results => $self->{results}->{$options{entry}}, instance => $instance); $result->{instance} = $instance; next if ($self->check_filter(section => 'memory', instance => $instance)); next if ($result->{$options{status}} =~ /not-present|not-available/i && $self->absent_problem(section => 'memory', instance => $instance)); $self->{components}->{memory}->{total}++; $self->{output}->output_add( long_msg => sprintf( "memory '%s' status is '%s' [instance: %s]", $result->{$options{name}}, $result->{$options{status}}, $instance ) ); $exit = $self->get_severity(section => 'memory', value => $result->{$options{status}}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Memory '%s' status is '%s'", $result->{$options{name}}, $result->{$options{status}}) ); } } } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => 'Checking memories'); $self->{components}->{memory} = { name => 'memories', total => 0, skip => 0 }; return if ($self->check_filter(section => 'memory')); if (defined($self->{results}->{$oid_sc2MemoryModules}) && scalar(keys %{$self->{results}->{$oid_sc2MemoryModules}}) > 0) { check_memory( $self, entry => $oid_sc2MemoryModules, mapping => $mapping->{sc2}, name => 'sc2memModuleDesignation', status => 'sc2memModuleStatus' ); } else { check_memory( $self, entry => $mapping->{sc}->{memModuleStatus}, mapping => $mapping->{sc}, name => 'instance', status => 'memModuleStatus' ); } } 1; centreon-plugins-20220113/hardware/server/fujitsu/snmp/mode/components/psu.pm000066400000000000000000000120101417000230700272550ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::fujitsu::snmp::mode::components::psu; use strict; use warnings; my $map_psu_status = { 1 => 'unknown', 2 => 'not-present', 3 => 'ok', 4 => 'failed', 5 => 'ac-fail', 6 => 'dc-fail', 7 => 'critical-temperature', 8 => 'not-manageable', 9 => 'fan-failure-predicted', 10 => 'fan-failure', 11 => 'power-safe-mode', 12 => 'non-redundant-dc-fail', 13 => 'non-redundant-ac-fail' }; my $mapping = { sc => { powerSupplyUnitStatus => { oid => '.1.3.6.1.4.1.231.2.10.2.2.5.11.2.1.3', map => $map_psu_status }, powerSupplyUnitDesignation => { oid => '.1.3.6.1.4.1.231.2.10.2.2.5.11.2.1.4' } }, sc2 => { sc2PowerSupplyDesignation => { oid => '.1.3.6.1.4.1.231.2.10.2.2.10.6.2.1.3' }, sc2PowerSupplyStatus => { oid => '.1.3.6.1.4.1.231.2.10.2.2.10.6.2.1.5', map => $map_psu_status }, sc2psPowerSupplyLoad => { oid => '.1.3.6.1.4.1.231.2.10.2.2.10.6.2.1.6' } } }; my $oid_sc2PowerSupply = '.1.3.6.1.4.1.231.2.10.2.2.10.6.2.1'; my $oid_powerSupplyUnits = '.1.3.6.1.4.1.231.2.10.2.2.5.11.2.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_sc2PowerSupply }, { oid => $oid_powerSupplyUnits }; } sub check_psu { my ($self, %options) = @_; my ($exit, $warn, $crit, $checked); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$options{entry}}})) { next if ($oid !~ /^$options{mapping}->{$options{status}}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $options{mapping}, results => $self->{results}->{$options{entry}}, instance => $instance); next if ($self->check_filter(section => 'psu', instance => $instance)); next if ($result->{$options{status}} =~ /not-present|not-available/i && $self->absent_problem(section => 'psu', instance => $instance)); $self->{components}->{psu}->{total}++; $self->{output}->output_add( long_msg => sprintf( "power supply '%s' status is '%s' [instance: %s] [value: %s]", $result->{$options{name}}, $result->{$options{status}}, $instance, $result->{$options{current}} ) ); $exit = $self->get_severity(section => 'psu', value => $result->{$options{status}}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Power supply '%s' status is '%s'", $result->{$options{name}}, $result->{$options{status}}) ); } next if (!defined($result->{$options{current}}) || $result->{$options{current}} == 0); ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'power', instance => $instance, value => $result->{$options{current}}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Power supply '%s' is %s W", $result->{$options{name}}, $result->{$options{current}}) ); } $self->{output}->perfdata_add( nlabel => 'hardware.powersupply.power.watt', unit => 'W', instances => $result->{$options{name}}, value => $result->{$options{current}}, warning => $warn, critical => $crit, min => 0 ); } } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => 'Checking poer supplies'); $self->{components}->{psu} = { name => 'psus', total => 0, skip => 0 }; return if ($self->check_filter(section => 'psu')); if (defined($self->{results}->{$oid_sc2PowerSupply}) && scalar(keys %{$self->{results}->{$oid_sc2PowerSupply}}) > 0) { check_psu( $self, entry => $oid_sc2PowerSupply, mapping => $mapping->{sc2}, name => 'sc2PowerSupplyDesignation', current => 'sc2psPowerSupplyLoad', status => 'sc2PowerSupplyStatus' ); } else { check_psu( $self, entry => $oid_powerSupplyUnits, mapping => $mapping->{sc}, name => 'powerSupplyUnitDesignation', status => 'powerSupplyUnitStatus' ); } } 1; centreon-plugins-20220113/hardware/server/fujitsu/snmp/mode/components/raid.pm000066400000000000000000000054701417000230700274010ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::fujitsu::snmp::mode::components::raid; use strict; use warnings; my $map_raid_status = { 1 => 'unknown', 2 => 'online', 3 => 'degraded', 4 => 'offline', 5 => 'rebuilding', 6 => 'verifying', 7 => 'initializing', 8 => 'morphing', 9 => 'partialDegraded' }; my $mapping = { status => { oid => '.1.3.6.1.4.1.231.2.49.1.6.2.1.10', map => $map_raid_status }, # svrLogicalDriveStatus name => { oid => '.1.3.6.1.4.1.231.2.49.1.6.2.1.11' } # svrLogicalDriveName }; my $oid_ldrive_table = '.1.3.6.1.4.1.231.2.49.1.6.2'; # svrLogicalDriveTable sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_ldrive_table, start => $mapping->{status}->{oid}, end => $mapping->{name}->{oid} }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => 'Checking raids'); $self->{components}->{raid} = { name => 'raids', total => 0, skip => 0 }; return if ($self->check_filter(section => 'raid')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{ $oid_ldrive_table }})) { next if ($oid !~ /^$mapping->{status}->{oid}\.(\d+)\.(\d+)$/); my $instance = $1 . '.' . $2; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{ $oid_ldrive_table }, instance => $instance); next if ($self->check_filter(section => 'disk', instance => $instance)); $self->{components}->{disk}->{total}++; $self->{output}->output_add( long_msg => sprintf( "raid '%s' status is '%s' [instance: %s]", $result->{name}, $result->{status}, $instance ) ); my $exit = $self->get_severity(section => 'raid', value => $result->{status}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Raid '%s' status is '%s'", $result->{name}, $result->{status}) ); } } } 1; centreon-plugins-20220113/hardware/server/fujitsu/snmp/mode/components/temperature.pm000066400000000000000000000130361417000230700310140ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::fujitsu::snmp::mode::components::temperature; use strict; use warnings; my $map_sc_temp_status = { 1 => 'unknown', 2 => 'sensor-disabled', 3 => 'ok', 4 => 'sensor-fail', 5 => 'warning-temp-warm', 6 => 'warning-temp-cold', 7 => 'critical-temp-warm', 8 => 'critical-temp-cold', 9 => 'damage-temp-warm', 10 => 'damage-temp-cold', 99 => 'not-available' }; my $map_sc2_temp_status = { 1 => 'unknown', 2 => 'not-available', 3 => 'ok', 4 => 'sensor-failed', 5 => 'failed', 6 => 'temperature-warning-toohot', 7 => 'temperature-critical-toohot', 8 => 'temperature-normal', 9 => 'temperature-warning' }; my $mapping = { sc => { tempSensorStatus => { oid => '.1.3.6.1.4.1.231.2.10.2.2.5.2.1.1.3', map => $map_sc_temp_status }, tempCurrentValue => { oid => '.1.3.6.1.4.1.231.2.10.2.2.5.2.1.1.11' }, tempSensorDesignation => { oid => '.1.3.6.1.4.1.231.2.10.2.2.5.2.1.1.13' } }, sc2 => { sc2tempSensorDesignation => { oid => '.1.3.6.1.4.1.231.2.10.2.2.10.5.1.1.3' }, sc2tempSensorStatus => { oid => '.1.3.6.1.4.1.231.2.10.2.2.10.5.1.1.5', map => $map_sc2_temp_status }, sc2tempCurrentTemperature => { oid => '.1.3.6.1.4.1.231.2.10.2.2.10.5.1.1.6' } } }; my $oid_sc2TemperatureSensors = '.1.3.6.1.4.1.231.2.10.2.2.10.5.1.1'; my $oid_temperatureSensors = '.1.3.6.1.4.1.231.2.10.2.2.5.2.1.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_sc2TemperatureSensors, end => $mapping->{sc2}->{sc2tempCurrentTemperature} }, { oid => $oid_temperatureSensors }; } sub check_temperature { my ($self, %options) = @_; my ($exit, $warn, $crit, $checked); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$options{entry}}})) { next if ($oid !~ /^$options{mapping}->{$options{status}}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $options{mapping}, results => $self->{results}->{$options{entry}}, instance => $instance); next if ($self->check_filter(section => 'temperature', instance => $instance)); next if ($result->{$options{status}} =~ /not-present|not-available/i && $self->absent_problem(section => 'temperature', instance => $instance)); $self->{components}->{temperature}->{total}++; $self->{output}->output_add( long_msg => sprintf( "temperature '%s' status is '%s' [instance: %s] [value: %s]", $result->{$options{name}}, $result->{$options{status}}, $instance, $result->{$options{current}} ) ); $exit = $self->get_severity(section => 'temperature', value => $result->{$options{status}}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Temperature '%s' status is '%s'", $result->{$options{name}}, $result->{$options{status}}) ); } next if (!defined($result->{$options{current}}) || $result->{$options{current}} <= 0 || $result->{$options{current}} == 255); ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $instance, value => $result->{$options{current}}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Temperature '%s' is %s V", $result->{$options{name}}, $result->{$options{current}}) ); } $self->{output}->perfdata_add( nlabel => 'hardware.temperature.celsius', unit => 'C', instances => $result->{$options{name}}, value => $result->{$options{current}}, warning => $warn, critical => $crit ); } } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => 'Checking temperatures'); $self->{components}->{temperature} = { name => 'temperatures', total => 0, skip => 0 }; return if ($self->check_filter(section => 'temperature')); if (defined($self->{results}->{$oid_sc2TemperatureSensors}) && scalar(keys %{$self->{results}->{$oid_sc2TemperatureSensors}}) > 0) { check_temperature( $self, entry => $oid_sc2TemperatureSensors, mapping => $mapping->{sc2}, name => 'sc2tempSensorDesignation', current => 'sc2tempCurrentTemperature', status => 'sc2tempSensorStatus' ); } else { check_temperature( $self, entry => $oid_temperatureSensors, mapping => $mapping->{sc}, name => 'tempSensorDesignation', current => 'tempCurrentValue', status => 'tempSensorStatus' ); } } 1; centreon-plugins-20220113/hardware/server/fujitsu/snmp/mode/components/voltage.pm000066400000000000000000000123561417000230700301240ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::fujitsu::snmp::mode::components::voltage; use strict; use warnings; my $map_sc_voltage_status = { 1 => 'unknown', 2 => 'not-available', 3 => 'ok', 4 => 'too-low', 5 => 'too-high', 6 => 'out-of-range', 7 => 'battery-prefailure' }; my $map_sc2_voltage_status = { 1 => 'unknown', 2 => 'not-available', 3 => 'ok', 4 => 'too-low', 5 => 'too-high', 6 => 'out-of-range', 7 => 'warning' }; my $mapping = { sc => { sniScVoltageStatus => { oid => '.1.3.6.1.4.1.231.2.10.2.2.5.11.4.1.3', map => $map_sc_voltage_status }, sniScVoltageDesignation => { oid => '.1.3.6.1.4.1.231.2.10.2.2.5.11.4.1.4' }, sniScVoltageCurrentValue => { oid => '.1.3.6.1.4.1.231.2.10.2.2.5.11.4.1.7' } }, sc2 => { sc2VoltageDesignation => { oid => '.1.3.6.1.4.1.231.2.10.2.2.10.6.3.1.3' }, sc2VoltageStatus => { oid => '.1.3.6.1.4.1.231.2.10.2.2.10.6.3.1.4', map => $map_sc2_voltage_status }, sc2VoltageCurrentValue => { oid => '.1.3.6.1.4.1.231.2.10.2.2.10.6.3.1.5' } } }; my $oid_sc2Voltages = '.1.3.6.1.4.1.231.2.10.2.2.10.6.3.1'; my $oid_sniScVoltages = '.1.3.6.1.4.1.231.2.10.2.2.5.11.4.1'; sub load { my ($self) = @_; push @{$self->{request}}, { oid => $oid_sc2Voltages, end => $mapping->{sc2}->{sc2VoltageCurrentValue} }, { oid => $oid_sniScVoltages }; } sub check_voltage { my ($self, %options) = @_; my ($exit, $warn, $crit, $checked); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$options{entry}}})) { next if ($oid !~ /^$options{mapping}->{$options{status}}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $options{mapping}, results => $self->{results}->{$options{entry}}, instance => $instance); next if ($self->check_filter(section => 'voltage', instance => $instance)); next if ($result->{$options{status}} =~ /not-present|not-available/i && $self->absent_problem(section => 'voltage', instance => $instance)); $self->{components}->{voltage}->{total}++; $result->{$options{current}} = $result->{$options{current}} / 1000 if (defined($result->{$options{current}})); $self->{output}->output_add( long_msg => sprintf( "voltage '%s' status is '%s' [instance: %s] [value: %s]", $result->{$options{name}}, $result->{$options{status}}, $instance, $result->{$options{current}} ) ); $exit = $self->get_severity(section => 'voltage', value => $result->{$options{status}}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Voltage '%s' status is '%s'", $result->{$options{name}}, $result->{$options{status}}) ); } next if (!defined($result->{$options{current}})); ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'voltage', instance => $instance, value => $result->{$options{current}}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Voltage '%s' is %s V", $result->{$options{name}}, $result->{$options{current}}) ); } $self->{output}->perfdata_add( nlabel => 'hardware.voltage.volt', unit => 'V', instances => $result->{$options{name}}, value => $result->{$options{current}}, warning => $warn, critical => $crit ); } } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => 'Checking voltages'); $self->{components}->{voltage} = { name => 'voltages', total => 0, skip => 0 }; return if ($self->check_filter(section => 'voltage')); if (defined($self->{results}->{$oid_sc2Voltages}) && scalar(keys %{$self->{results}->{$oid_sc2Voltages}}) > 0) { check_voltage( $self, entry => $oid_sc2Voltages, mapping => $mapping->{sc2}, name => 'sc2VoltageDesignation', current => 'sc2VoltageCurrentValue', status => 'sc2VoltageStatus' ); } else { check_voltage( $self, entry => $oid_sniScVoltages, mapping => $mapping->{sc}, name => 'sniScVoltageDesignation', current => 'sniScVoltageCurrentValue', status => 'sniScVoltageStatus' ); } } 1; centreon-plugins-20220113/hardware/server/fujitsu/snmp/mode/hardware.pm000066400000000000000000000144661417000230700260770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::fujitsu::snmp::mode::hardware; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_numeric_check_section_option} = '^(temperature|fan|voltage|power)$'; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { cpu => [ ['unknown', 'UNKNOWN'], ['disabled', 'OK'], ['ok', 'OK'], ['not-present', 'OK'], ['error', 'CRITICAL'], ['prefailure-warning', 'WARNING'], ['fail', 'CRITICAL'], # can be failed also ['missing-termination', 'WARNING'] ], disk => [ ['unknown', 'UNKNOWN'], ['noDisk', 'OK'], ['online', 'OK'], ['ready', 'OK'], ['failed', 'CRITICAL'], ['rebuilding', 'WARNING'], ['hotspareGlobal', 'OK'], ['hotspareDedicated', 'OK'], ['offline', 'OK'], ['unconfiguredFailed', 'WARNING'], ['formatting', 'WARNING'], ['dead', 'CRITICAL'] ], fan => [ ['unknown', 'UNKNOWN'], ['disabled', 'OK'], ['ok', 'OK'], ['prefailure-predicted', 'WARNING'], ['fail', 'CRITICAL'], ['redundant-fan-failed', 'WARNING'], ['not-manageable', 'OK'], ['not-present', 'OK'], ], memory => [ ['unknown', 'UNKNOWN'], ['not-present|not-available', 'OK'], ['ok', 'OK'], ['disabled', 'OK'], ['error', 'CRITICAL'], ['prefailure-predicted|prefailure-warning', 'WARNING'], ['fail', 'CRITICAL'], # can be failed ['disabled', 'OK'], ['hot-spare', 'OK'], ['mirror', 'OK'], ['raid', 'OK'], ['hidden', 'OK'] ], psu => [ ['unknown', 'UNKNOWN'], ['not-present', 'OK'], ['ok', 'OK'], ['ac-fail', 'CRITICAL'], ['dc-fail', 'CRITICAL'], ['failed', 'CRITICAL'], ['critical-temperature', 'CRITICAL'], ['not-manageable', 'OK'], ['fan-failure-predicted', 'WARNING'], ['fan-failure', 'CRITICAL'], ['power-safe-mode', 'WARNING'], ['non-redundant-dc-fail', 'WARNING'], ['non-redundant-ac-fail', 'WARNING'], ['degraded', 'WARNING'], ['critical', 'CRITICAL'] ], raid => [ ['unknown', 'UNKNOWN'], ['online', 'OK'], ['degraded', 'WARNING'], ['offline', 'ok'], ['rebuilding', 'WARNING'], ['verifying', 'OK'], ['initializing', 'OK'], ['morphing', 'OK'], ['partialDegraded', 'WARNING'] ], temperature => [ ['unknown', 'UNKNOWN'], ['sensor-disabled', 'OK'], ['ok', 'OK'], ['sensor-fail', 'CRITICAL'], # can be also sensor-failed ['warning-temp-warm', 'WARNING'], ['warning-temp-cold', 'WARNING'], ['critical-temp-warm', 'CRITICAL'], ['critical-temp-cold', 'CRITICAL'], ['damage-temp-warm', 'WARNING'], ['damage-temp-cold', 'CRITICAL'], ['not-available', 'OK'], ['temperature-warning', 'WARNING'], # can be also temperature-warning-toohot ['temperature-critical-toohot', 'CRITICAL'], ['temperature-normal', 'OK'] ], voltage => [ ['unknown', 'UNKNOWN'], ['not-available', 'OK'], ['ok', 'OK'], ['too-low', 'WARNING'], ['too-high', 'WARNING'], ['out-of-range', 'CRITICAL'], ['battery-prefailure', 'CRITICAL'], ['warning', 'WARNING'] ] }; $self->{components_path} = 'hardware::server::fujitsu::snmp::mode::components'; $self->{components_module} = ['cpu', 'disk', 'fan', 'memory', 'psu', 'raid', 'temperature', 'voltage']; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => {}); return $self; } 1; __END__ =head1 MODE Check hardware. =over 8 =item B<--component> Which component to check (Default: '.*'). Can be: 'temperature', 'fan', 'psu', 'voltage', 'cpu', 'memory'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=temperature) Can also exclude specific instance: --filter=temperature,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,1.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,^(?!(ok)$)' =item B<--warning> Set warning threshold (syntax: type,regexp,threshold) Example: --warning='temperature,.*,30' =item B<--critical> Set critical threshold (syntax: type,regexp,threshold) Example: --critical='temperature,.*,40' =back =cut centreon-plugins-20220113/hardware/server/fujitsu/snmp/plugin.pm000066400000000000000000000023411417000230700246410ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::fujitsu::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} = { 'hardware' => 'hardware::server::fujitsu::snmp::mode::hardware' }; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check Fujitsu server in SNMP. =cut centreon-plugins-20220113/hardware/server/hp/000077500000000000000000000000001417000230700207465ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/hp/bladechassis/000077500000000000000000000000001417000230700233735ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/hp/bladechassis/snmp/000077500000000000000000000000001417000230700243505ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/hp/bladechassis/snmp/mode/000077500000000000000000000000001417000230700252745ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/hp/bladechassis/snmp/mode/components/000077500000000000000000000000001417000230700274615ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/hp/bladechassis/snmp/mode/components/blade.pm000066400000000000000000000104651417000230700310740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::hp::bladechassis::snmp::mode::components::blade; use strict; use warnings; my %map_conditions = ( 1 => 'other', 2 => 'ok', 3 => 'degraded', 4 => 'failed', ); my %present_map = ( 1 => 'other', 2 => 'absent', 3 => 'present', 4 => 'Weird!!!', # for blades it can return 4, which is NOT spesified in MIB ); my $mapping = { blade_name => { oid => '.1.3.6.1.4.1.232.22.2.4.1.1.1.4' }, # cpqRackServerBladeName blade_part => { oid => '.1.3.6.1.4.1.232.22.2.4.1.1.1.6' }, # cpqRackServerBladePartNumber blade_status => { oid => '.1.3.6.1.4.1.232.22.2.4.1.1.1.21', map => \%map_conditions }, # cpqRackServerBladeStatus (v2) blade_spare => { oid => '.1.3.6.1.4.1.232.22.2.4.1.1.1.7' }, # cpqRackServerBladeSparePartNumber blade_productid => { oid => '.1.3.6.1.4.1.232.22.2.4.1.1.1.17' }, # cpqRackServerBladeProductId blade_diago => { oid => '.1.3.6.1.4.1.232.22.2.4.1.1.1.24' }, # cpqRackServerBladeFaultDiagnosticString (v2) }; sub check { my ($self) = @_; $self->{components}->{blade} = {name => 'blades', total => 0, skip => 0}; $self->{output}->output_add(long_msg => "checking blades"); return if ($self->check_filter(section => 'blade')); my $oid_cpqRackServerBladePresent = '.1.3.6.1.4.1.232.22.2.4.1.1.1.12'; my $snmp_result = $self->{snmp}->get_table(oid => $oid_cpqRackServerBladePresent); return if (scalar(keys %$snmp_result) <= 0); my @get_oids = (); my @oids_end = (); foreach my $key ($self->{snmp}->oid_lex_sort(keys %$snmp_result)) { $key =~ /\.([0-9]+)$/; my $oid_end = $1; next if ($present_map{$snmp_result->{$key}} ne 'present' && $self->absent_problem(section => 'blade', instance => $oid_end)); push @oids_end, $oid_end; push @get_oids, map($_->{oid} . '.' . $oid_end, values(%$mapping)); } $snmp_result = $self->{snmp}->get_leef(oids => \@get_oids); foreach (@oids_end) { my $blade_index = $_; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $blade_index); next if ($self->check_filter(section => 'blade', instance => $blade_index)); $self->{components}->{blade}->{total}++; if (!defined($result->{blade_status})) { $self->{output}->output_add(long_msg => sprintf("skipping blade '%s' (%s, %s). Cant get status.", $blade_index, $result->{blade_name}, $result->{blade_productid})); next; } $self->{output}->output_add( long_msg => sprintf("blade '%s' (%s, %s) status is %s [part: %s, spare: %s]%s.", $blade_index, $result->{blade_name}, $result->{blade_productid}, $result->{blade_status}, $result->{blade_part}, $result->{blade_spare}, defined($result->{blade_diago}) ? " (Diagnostic '$result->{blade_diago}')" : '' ) ); my $exit = $self->get_severity(label => 'default', section => 'blade', instance => $blade_index, value => $result->{blade_status}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, short_msg => sprintf("Blade '%s' (%s, %s) status is %s", $blade_index, $result->{blade_name}, $result->{blade_productid}, $result->{blade_status} ) ); } } } 1; centreon-plugins-20220113/hardware/server/hp/bladechassis/snmp/mode/components/enclosure.pm000066400000000000000000000070241417000230700320210ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::hp::bladechassis::snmp::mode::components::enclosure; use strict; use warnings; my $map_conditions = { 1 => 'other', 2 => 'ok', 3 => 'degraded', 4 => 'failed', }; my $mapping = { cpqRackCommonEnclosureSparePartNumber => { oid => '.1.3.6.1.4.1.232.22.2.3.1.1.1.6' }, cpqRackCommonEnclosureSerialNum => { oid => '.1.3.6.1.4.1.232.22.2.3.1.1.1.7' }, cpqRackCommonEnclosureFWRev => { oid => '.1.3.6.1.4.1.232.22.2.3.1.1.1.8' }, cpqRackCommonEnclosureCondition => { oid => '.1.3.6.1.4.1.232.22.2.3.1.1.1.16', map => $map_conditions }, }; sub check { my ($self) = @_; $self->{components}->{enclosure} = {name => 'enclosure', total => 0, skip => 0}; $self->{output}->output_add(long_msg => "checking enclosure"); return if ($self->check_filter(section => 'enclosure')); my $oid_cpqRackCommonEnclosurePartNumber = '.1.3.6.1.4.1.232.22.2.3.1.1.1.5'; my $snmp_result = $self->{snmp}->get_table(oid => $oid_cpqRackCommonEnclosurePartNumber); return if (scalar(keys %$snmp_result) <= 0); my @get_oids = (); my @oids_end = (); foreach my $key ($self->{snmp}->oid_lex_sort(keys %$snmp_result)) { $key =~ /^$oid_cpqRackCommonEnclosurePartNumber\.(.*)$/; my $oid_end = $1; push @oids_end, $oid_end; push @get_oids, map($_->{oid} . '.' . $oid_end, values(%$mapping)); } my $snmp_result2 = $self->{snmp}->get_leef(oids => \@get_oids); foreach (@oids_end) { my $instance = $_; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $snmp_result2, instance => $instance); next if ($self->check_filter(section => 'enclosure', instance => $instance)); $self->{components}->{enclosure}->{total}++; $self->{output}->output_add(long_msg => sprintf("enclosure '%s' overall health condition is %s [part: %s, spare: %s, sn: %s, fw: %s].", $instance, $result->{cpqRackCommonEnclosureCondition}, $snmp_result->{$oid_cpqRackCommonEnclosurePartNumber . '.' . $instance}, $result->{cpqRackCommonEnclosureSparePartNumber}, $result->{cpqRackCommonEnclosureSerialNum}, $result->{cpqRackCommonEnclosureFWRev} ) ); my $exit = $self->get_severity(label => 'default', section => 'enclosure', value => $result->{cpqRackCommonEnclosureCondition}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Enclosure '%s' overall health condition is %s", $instance, $result->{cpqRackCommonEnclosureCondition})); } } } 1; centreon-plugins-20220113/hardware/server/hp/bladechassis/snmp/mode/components/fan.pm000066400000000000000000000066371417000230700305770ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::hp::bladechassis::snmp::mode::components::fan; use strict; use warnings; my %map_conditions = ( 1 => 'other', 2 => 'ok', 3 => 'degraded', 4 => 'failed', ); my %present_map = ( 1 => 'other', 2 => 'absent', 3 => 'present', 4 => 'Weird!!!', # for blades it can return 4, which is NOT spesified in MIB ); my $mapping = { fan_part => { oid => '.1.3.6.1.4.1.232.22.2.3.1.3.1.6' }, # cpqRackCommonEnclosureFanPartNumber fan_spare => { oid => '.1.3.6.1.4.1.232.22.2.3.1.3.1.7' }, # cpqRackCommonEnclosureFanSparePartNumber fan_condition => { oid => '.1.3.6.1.4.1.232.22.2.3.1.3.1.11', map => \%map_conditions }, # cpqRackCommonEnclosureFanCondition }; sub check { my ($self) = @_; $self->{components}->{fan} = {name => 'fans', total => 0, skip => 0}; $self->{output}->output_add(long_msg => "checking fans"); return if ($self->check_filter(section => 'fan')); my $oid_cpqRackCommonEnclosureFanPresent = '.1.3.6.1.4.1.232.22.2.3.1.3.1.8'; my $snmp_result = $self->{snmp}->get_table(oid => $oid_cpqRackCommonEnclosureFanPresent); return if (scalar(keys %$snmp_result) <= 0); my @get_oids = (); my @oids_end = (); foreach my $key ($self->{snmp}->oid_lex_sort(keys %$snmp_result)) { $key =~ /\.([0-9]+)$/; my $oid_end = $1; next if ($present_map{$snmp_result->{$key}} ne 'present' && $self->absent_problem(section => 'fan', instance => $oid_end)); push @oids_end, $oid_end; push @get_oids, map($_->{oid} . '.' . $oid_end, values(%$mapping)); } $snmp_result = $self->{snmp}->get_leef(oids => \@get_oids); foreach (@oids_end) { my $fan_index = $_; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $fan_index); next if ($self->check_filter(section => 'fan', instance => $fan_index)); $self->{components}->{fan}->{total}++; $self->{output}->output_add(long_msg => sprintf("fan '%s' condition is %s [part: %s, spare: %s].", $fan_index, $result->{fan_condition}, $result->{fan_part}, $result->{fan_spare})); my $exit = $self->get_severity(label => 'default', section => 'fan', instance => $fan_index, value => $result->{fan_condition}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Fan '%s' condition is %s", $fan_index, $result->{fan_condition})); } } } 1; centreon-plugins-20220113/hardware/server/hp/bladechassis/snmp/mode/components/fuse.pm000066400000000000000000000070271417000230700307670ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::hp::bladechassis::snmp::mode::components::fuse; use strict; use warnings; my %map_conditions = ( 1 => 'other', 2 => 'ok', 3 => 'degraded', 4 => 'failed', ); my %present_map = ( 1 => 'other', 2 => 'absent', 3 => 'present', 4 => 'Weird!!!', # for blades it can return 4, which is NOT spesified in MIB ); my $mapping = { fuse_name => { oid => '.1.3.6.1.4.1.232.22.2.3.1.4.1.4' }, # cpqRackCommonEnclosureFuseEnclosureName fuse_location => { oid => '.1.3.6.1.4.1.232.22.2.3.1.4.1.5' }, # cpqRackCommonEnclosureFuseLocation fuse_condition => { oid => '.1.3.6.1.4.1.232.22.2.3.1.4.1.7', map => \%map_conditions }, # cpqRackCommonEnclosureFuseCondition }; sub check { my ($self) = @_; $self->{components}->{fuse} = {name => 'fuses', total => 0, skip => 0}; $self->{output}->output_add(long_msg => "checking fuse"); return if ($self->check_filter(section => 'fuse')); my $oid_cpqRackCommonEnclosureFusePresent = '.1.3.6.1.4.1.232.22.2.3.1.4.1.6'; my $snmp_result = $self->{snmp}->get_table(oid => $oid_cpqRackCommonEnclosureFusePresent); return if (scalar(keys %$snmp_result) <= 0); my @get_oids = (); my @oids_end = (); foreach my $key ($self->{snmp}->oid_lex_sort(keys %$snmp_result)) { $key =~ /^$oid_cpqRackCommonEnclosureFusePresent\.(.*)$/; my $oid_end = $1; next if ($present_map{$snmp_result->{$key}} ne 'present' && $self->absent_problem(section => 'fuse', instance => $oid_end)); push @oids_end, $oid_end; push @get_oids, map($_->{oid} . '.' . $oid_end, values(%$mapping)); } $snmp_result = $self->{snmp}->get_leef(oids => \@get_oids); foreach (@oids_end) { my $fuse_index = $_; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $fuse_index); next if ($self->check_filter(section => 'fuse', instance => $fuse_index)); $self->{components}->{fuse}->{total}++; $self->{output}->output_add(long_msg => sprintf("fuse '%s' status is %s [name: %s, location: %s].", $fuse_index, $result->{fuse_condition}, $result->{fuse_name}, $result->{fuse_location})); my $exit = $self->get_severity(label => 'default', section => 'fuse', instance => $fuse_index, value => $result->{fuse_condition}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Fuse '%s' status is %s", $fuse_index, $result->{fuse_condition})); } } } 1; centreon-plugins-20220113/hardware/server/hp/bladechassis/snmp/mode/components/manager.pm000066400000000000000000000073411417000230700314360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::hp::bladechassis::snmp::mode::components::manager; use strict; use warnings; my %map_conditions = ( 0 => 'other', # maybe on standby mode only!! 1 => 'other', 2 => 'ok', 3 => 'degraded', 4 => 'failed', ); my %map_role = ( 1 => 'Standby', 2 => 'Active', ); my $mapping = { man_part => { oid => '.1.3.6.1.4.1.232.22.2.3.1.6.1.6' }, # cpqRackCommonEnclosureManagerPartNumber man_spare => { oid => '.1.3.6.1.4.1.232.22.2.3.1.6.1.7' }, # cpqRackCommonEnclosureManagerSparePartNumber man_serial => { oid => '.1.3.6.1.4.1.232.22.2.3.1.6.1.8' }, # cpqRackCommonEnclosureManagerSerialNum man_role => { oid => '.1.3.6.1.4.1.232.22.2.3.1.6.1.9', map => \%map_role }, # cpqRackCommonEnclosureManagerRole man_condition => { oid => '.1.3.6.1.4.1.232.22.2.3.1.6.1.12', map => \%map_conditions }, # cpqRackCommonEnclosureManagerConditio }; sub check { my ($self, %options) = @_; $self->{components}->{manager} = { name => 'managers', total => 0, skip => 0 }; return if ($self->check_filter(section => 'manager')); $self->{output}->output_add(long_msg => "checking managers"); my $oid_cpqRackCommonEnclosureManagerIndex = '.1.3.6.1.4.1.232.22.2.3.1.6.1.3'; my $snmp_result = $self->{snmp}->get_table(oid => $oid_cpqRackCommonEnclosureManagerIndex); return if (scalar(keys %$snmp_result) <= 0); my @get_oids = (); my @oids_end = (); foreach my $key ($self->{snmp}->oid_lex_sort(keys %$snmp_result)) { $key =~ /^$oid_cpqRackCommonEnclosureManagerIndex\.(.*)$/; my $oid_end = $1; push @oids_end, $oid_end; push @get_oids, map($_->{oid} . '.' . $oid_end, values(%$mapping)); } $snmp_result = $self->{snmp}->get_leef(oids => \@get_oids); foreach (@oids_end) { my $instance = $_; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); next if ($self->check_filter(section => 'manager', instance => $instance)); $self->{components}->{manager}->{total}++; $self->{output}->output_add(long_msg => sprintf("enclosure management module '%s' is %s, status is %s [serial: %s, part: %s, spare: %s].", $instance, $result->{man_condition}, $result->{man_role}, $result->{man_serial}, $result->{man_part}, $result->{man_spare})); my $exit = $self->get_severity(label => 'default', section => 'manager', instance => $instance, value => $result->{man_condition}); if ($result->{man_role} eq 'Active' && !$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Enclosure management module '%s' is %s, status is %s", $instance, $result->{man_condition}, $result->{man_role})); } } } 1; centreon-plugins-20220113/hardware/server/hp/bladechassis/snmp/mode/components/network.pm000066400000000000000000000063661417000230700315230ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::hp::bladechassis::snmp::mode::components::network; use strict; use warnings; my %present_map = ( 1 => 'other', 2 => 'absent', 3 => 'present', 4 => 'Weird!!!', # for blades it can return 4, which is NOT spesified in MIB ); my %device_type = ( 1 => 'noconnect', 2 => 'network', 3 => 'fibrechannel', 4 => 'sas', 5 => 'inifiband', 6 => 'pciexpress', ); my $mapping = { nc_model => { oid => '.1.3.6.1.4.1.232.22.2.6.1.1.1.6' }, # cpqRackNetConnectorModel nc_serial => { oid => '.1.3.6.1.4.1.232.22.2.6.1.1.1.7' }, # cpqRackNetConnectorSerialNum nc_part => { oid => '.1.3.6.1.4.1.232.22.2.6.1.1.1.8' }, # cpqRackNetConnectorPartNumber nc_spare => { oid => '.1.3.6.1.4.1.232.22.2.6.1.1.1.9' }, # cpqRackNetConnectorSparePartNumber nc_device => { oid => '.1.3.6.1.4.1.232.22.2.6.1.1.1.17', map => \%device_type }, # cpqRackNetConnectorDeviceType }; sub check { my ($self) = @_; $self->{components}->{network} = {name => 'network connectors', total => 0, skip => 0}; $self->{output}->output_add(long_msg => "checking network connectors"); return if ($self->check_filter(section => 'network')); my $oid_cpqRackNetConnectorPresent = '.1.3.6.1.4.1.232.22.2.6.1.1.1.13'; my $snmp_result = $self->{snmp}->get_table(oid => $oid_cpqRackNetConnectorPresent); return if (scalar(keys %$snmp_result) <= 0); my @get_oids = (); my @oids_end = (); foreach my $key ($self->{snmp}->oid_lex_sort(keys %$snmp_result)) { next if ($present_map{$snmp_result->{$key}} ne 'present'); $key =~ /^$oid_cpqRackNetConnectorPresent\.(.*)$/; my $oid_end = $1; push @oids_end, $oid_end; push @get_oids, map($_->{oid} . '.' . $oid_end, values(%$mapping)); } $snmp_result = $self->{snmp}->get_leef(oids => \@get_oids); foreach (@oids_end) { my $nc_index = $_; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $_); next if ($self->check_filter(section => 'network', instance => $nc_index)); $self->{components}->{network}->{total}++; $self->{output}->output_add( long_msg => sprintf("network connector '%s' (%s) type '%s' is present [serial: %s, part: %s, spare: %s].", $nc_index, $result->{nc_model}, $result->{nc_device}, $result->{nc_serial}, $result->{nc_part}, $result->{nc_spare} ) ); } } 1; centreon-plugins-20220113/hardware/server/hp/bladechassis/snmp/mode/components/psu.pm000066400000000000000000000143731417000230700306360ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::hp::bladechassis::snmp::mode::components::psu; use strict; use warnings; my %map_conditions = ( 1 => 'other', 2 => 'ok', 3 => 'degraded', 4 => 'failed', ); my %present_map = ( 1 => 'other', 2 => 'absent', 3 => 'present', 4 => 'Weird!!!', # for blades it can return 4, which is NOT spesified in MIB ); my %psu_status_map = ( 1 => 'noError', 2 => 'generalFailure', 3 => 'bistFailure', 4 => 'fanFailure', 5 => 'tempFailure', 6 => 'interlockOpen', 7 => 'epromFailed', 8 => 'vrefFailed', 9 => 'dacFailed', 10 => 'ramTestFailed', 11 => 'voltageChannelFailed', 12 => 'orringdiodeFailed', 13 => 'brownOut', 14 => 'giveupOnStartup', 15 => 'nvramInvalid', 16 => 'calibrationTableInvalid', ); my %inputline_status_map = ( 1 => 'noError', 2 => 'lineOverVoltage', 3 => 'lineUnderVoltage', 4 => 'lineHit', 5 => 'brownOut', 6 => 'linePowerLoss', ); my $mapping = { psu_status => { oid => '.1.3.6.1.4.1.232.22.2.5.1.1.1.14', map => \%psu_status_map }, # cpqRackPowerSupplyStatus psu_serial => { oid => '.1.3.6.1.4.1.232.22.2.5.1.1.1.5' }, # cpqRackPowerSupplySerialNum psu_part => { oid => '.1.3.6.1.4.1.232.22.2.5.1.1.1.6' }, # cpqRackPowerSupplyPartNumber psu_spare => { oid => '.1.3.6.1.4.1.232.22.2.5.1.1.1.7' }, # cpqRackPowerSupplySparePartNumber psu_inputlinestatus => { oid => '.1.3.6.1.4.1.232.22.2.5.1.1.1.15', map => \%inputline_status_map }, # cpqRackPowerSupplyInputLineStatus psu_condition => { oid => '.1.3.6.1.4.1.232.22.2.5.1.1.1.17', map => \%map_conditions }, # cpqRackPowerSupplyCondition psu_pwrout => { oid => '.1.3.6.1.4.1.232.22.2.5.1.1.1.10' }, # cpqRackPowerSupplyCurPwrOutput in Watts psu_intemp => { oid => '.1.3.6.1.4.1.232.22.2.5.1.1.1.12' }, # cpqRackPowerSupplyIntakeTemp psu_exhtemp => { oid => '.1.3.6.1.4.1.232.22.2.5.1.1.1.13' }, # cpqRackPowerSupplyExhaustTemp }; sub check { my ($self) = @_; # We dont check 'cpqRackPowerEnclosureTable' (the overall power system status) # We check 'cpqRackPowerSupplyTable' (unitary) $self->{components}->{psu} = {name => 'power supplies', total => 0, skip => 0}; $self->{output}->output_add(long_msg => "checking power supplies"); return if ($self->check_filter(section => 'psu')); my $oid_cpqRackPowerSupplyPresent = '.1.3.6.1.4.1.232.22.2.5.1.1.1.16'; my $snmp_result = $self->{snmp}->get_table(oid => $oid_cpqRackPowerSupplyPresent); return if (scalar(keys %$snmp_result) <= 0); my @get_oids = (); my @oids_end = (); foreach my $key ($self->{snmp}->oid_lex_sort(keys %$snmp_result)) { $key =~ /^$oid_cpqRackPowerSupplyPresent\.(.*)$/; my $oid_end = $1; next if ($present_map{$snmp_result->{$key}} ne 'present' && $self->absent_problem(section => 'psu', instance => $oid_end)); push @oids_end, $oid_end; push @get_oids, map($_->{oid} . '.' . $oid_end, values(%$mapping)); } $snmp_result = $self->{snmp}->get_leef(oids => \@get_oids); my $total_watts = 0; foreach (@oids_end) { my $psu_index = $_; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $_); next if ($self->check_filter(section => 'psu', instance => $psu_index)); $total_watts += $result->{psu_pwrout}; $self->{components}->{psu}->{total}++; $self->{output}->output_add( long_msg => sprintf("psu '%s' status is %s [serial: %s, part: %s, spare: %s] (input line status %s) (status %s).", $psu_index, $result->{psu_condition}, $result->{psu_serial}, $result->{psu_part}, $result->{psu_spare}, $result->{psu_inputlinestatus}, $result->{psu_status} ) ); my $exit = $self->get_severity(label => 'default', section => 'psu', instance => $psu_index, value => $result->{psu_condition}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("PSU '%s' status is %s", $psu_index, $result->{psu_condition})); } $self->{output}->perfdata_add( label => 'psu_power', unit => 'W', nlabel => 'hardware.powersupply.power.watt', instances => $psu_index, value => $result->{psu_pwrout} ); if (defined($result->{psu_intemp}) && $result->{psu_intemp} != -1) { $self->{output}->perfdata_add( label => 'psu_temp', unit => 'C', nlabel => 'hardware.powersupply.temperature.celsius', instances => [$psu_index, 'intake'], value => $result->{psu_intemp} ); } if (defined($result->{psu_exhtemp}) && $result->{psu_exhtemp} != -1) { $self->{output}->perfdata_add( label => 'psu_temp', unit => 'C', nlabel => 'hardware.powersupply.temperature.celsius', instances => [$psu_index, 'exhaust'], value => $result->{psu_exhtemp} ); } } $self->{output}->perfdata_add( label => 'total_power', unit => 'W', nlabel => 'hardware.powersupply.power.watt', value => $total_watts ); } 1; centreon-plugins-20220113/hardware/server/hp/bladechassis/snmp/mode/components/temperature.pm000066400000000000000000000106161417000230700323600ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::hp::bladechassis::snmp::mode::components::temperature; use strict; use warnings; my $map_conditions = { 1 => 'other', 2 => 'ok', 3 => 'degraded', 4 => 'failed', }; my $map_temp_type = { 1 => 'other', 5 => 'blowout', 9 => 'caution', 15 => 'critical', }; my $mapping = { temp_name => { oid => '.1.3.6.1.4.1.232.22.2.3.1.2.1.4' }, # cpqRackCommonEnclosureTempSensorEnclosureName temp_location => { oid => '.1.3.6.1.4.1.232.22.2.3.1.2.1.5' }, # cpqRackCommonEnclosureTempLocation temp_current => { oid => '.1.3.6.1.4.1.232.22.2.3.1.2.1.6' }, # cpqRackCommonEnclosureTempCurrent temp_threshold => { oid => '.1.3.6.1.4.1.232.22.2.3.1.2.1.7' }, # cpqRackCommonEnclosureTempThreshold temp_condition => { oid => '.1.3.6.1.4.1.232.22.2.3.1.2.1.8', map => $map_conditions }, # cpqRackCommonEnclosureTempCondition temp_type => { oid => '.1.3.6.1.4.1.232.22.2.3.1.2.1.9', map => $map_temp_type }, # cpqRackCommonEnclosureTempType }; sub check { my ($self) = @_; $self->{components}->{temperature} = { name => 'temperatures', total => 0, skip => 0 }; $self->{output}->output_add(long_msg => "checking temperatures"); return if ($self->check_filter(section => 'temperature')); my $oid_cpqRackCommonEnclosureTempSensorIndex = '.1.3.6.1.4.1.232.22.2.3.1.2.1.3'; my $snmp_result = $self->{snmp}->get_table(oid => $oid_cpqRackCommonEnclosureTempSensorIndex); return if (scalar(keys %$snmp_result) <= 0); my @get_oids = (); my @oids_end = (); foreach my $key ($self->{snmp}->oid_lex_sort(keys %$snmp_result)) { $key =~ /^$oid_cpqRackCommonEnclosureTempSensorIndex\.(.*)$/; my $oid_end = $1; push @oids_end, $oid_end; push @get_oids, map($_->{oid} . '.' . $oid_end, values(%$mapping)); } $snmp_result = $self->{snmp}->get_leef(oids => \@get_oids); foreach (@oids_end) { my $temp_index = $_; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $temp_index); if ($result->{temp_current} == -1) { $self->{output}->output_add(long_msg => sprintf("skipping instance $temp_index: current -1"), debug => 1); next; } next if ($self->check_filter(section => 'temperature', instance => $temp_index)); $self->{components}->{temperature}->{total}++; $self->{output}->output_add(long_msg => sprintf("temperature '%s' status is %s [name: %s, location: %s] (value = %s, threshold = %s%s).", $temp_index, $result->{temp_condition}, $result->{temp_name}, $result->{temp_location}, $result->{temp_current}, $result->{temp_threshold}, defined($result->{temp_type}) ? ", status type = " . $result->{temp_type} : '')); my $exit = $self->get_severity(label => 'default', section => 'temperature', instance => $temp_index, value => $result->{temp_condition}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Temperature '%s' status is %s", $temp_index, $result->{temp_condition})); } $self->{output}->perfdata_add( label => "temp", unit => 'C', nlabel => 'hardware.temperature.celsius', instances => $temp_index, value => $result->{temp_current}, warning => $result->{temp_threshold} ); } } 1; centreon-plugins-20220113/hardware/server/hp/bladechassis/snmp/mode/hardware.pm000066400000000000000000000052211417000230700274270ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::hp::bladechassis::snmp::mode::hardware; use base qw(centreon::plugins::templates::hardware); use strict; use warnings; use centreon::plugins::misc; sub set_system { my ($self, %options) = @_; $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { default => [ ['other', 'CRITICAL'], ['ok', 'OK'], ['degraded', 'WARNING'], ['failed', 'CRITICAL'] ] }; $self->{components_exec_load} = 0; $self->{components_path} = 'hardware::server::hp::bladechassis::snmp::mode::components'; $self->{components_module} = [ 'enclosure', 'manager', 'fan', 'blade', 'network', 'psu', 'temperature', 'fuse' ]; } sub snmp_execute { my ($self, %options) = @_; $self->{snmp} = $options{snmp}; } sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_performance => 1); bless $self, $class; $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: 'enclosure', 'manager', 'fan', 'blade', 'network', 'psu', 'temperature', 'fuse'. =item B<--filter> Exclude some parts (comma seperated list) (Example: --filter=psu) Can also exclude specific instance: --filter=temperature,1 =item B<--absent-problem> Return an error if an entity is not 'present' (default is skipping) Can be specific or global: --absent-problem="blade,12" =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='temperature,OK,other' =back =cut centreon-plugins-20220113/hardware/server/hp/bladechassis/snmp/plugin.pm000066400000000000000000000023721417000230700262100ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::hp::bladechassis::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}} = ( 'hardware' => 'hardware::server::hp::bladechassis::snmp::mode::hardware', ); return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check HP Blades chassis in SNMP. =cut centreon-plugins-20220113/hardware/server/hp/ilo/000077500000000000000000000000001417000230700215315ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/hp/ilo/restapi/000077500000000000000000000000001417000230700232005ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/hp/ilo/restapi/custom/000077500000000000000000000000001417000230700245125ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/hp/ilo/restapi/custom/api.pm000066400000000000000000000203751417000230700256300ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::hp::ilo::restapi::custom::api; use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::http; use centreon::plugins::statefile; use JSON::XS; use Digest::MD5 qw(md5_hex); sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); 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 => { 'hostname:s' => { name => 'hostname' }, 'port:s' => { name => 'port'}, 'proto:s' => { name => 'proto' }, 'api-username:s' => { name => 'api_username' }, 'api-password:s' => { name => 'api_password' }, 'timeout:s' => { name => 'timeout', default => 30 } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); $self->{cache} = centreon::plugins::statefile->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : undef; $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 30; $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : undef; $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : undef; if (!defined($self->{hostname}) || $self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } if (!defined($self->{api_username}) || $self->{api_username} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-username option."); $self->{output}->option_exit(); } if (!defined($self->{api_password}) || $self->{api_password} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --api-password option."); $self->{output}->option_exit(); } $self->{cache}->check_options(option_results => $self->{option_results}); return 0; } sub build_options_for_httplib { my ($self, %options) = @_; $self->{option_results}->{hostname} = $self->{hostname}; $self->{option_results}->{port} = $self->{port}; $self->{option_results}->{proto} = $self->{proto}; $self->{option_results}->{timeout} = $self->{timeout}; } sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Content-Type', value => 'application/json;charset=UTF-8'); $self->{http}->add_header(key => 'Accept', value => 'application/json;charset=UTF-8'); $self->{http}->set_options(%{$self->{option_results}}); } sub json_decode { my ($self, %options) = @_; my $decoded; eval { $decoded = JSON::XS->new->utf8->decode($options{content}); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); $self->{output}->option_exit(); } return $decoded; } sub clean_token { my ($self, %options) = @_; my $datas = { last_timestamp => time() }; $options{statefile}->write(data => $datas); $self->{token} = undef; $self->{http}->add_header(key => 'X-Auth-Token', value => undef); } sub authenticate { my ($self, %options) = @_; my $has_cache_file = $options{statefile}->read(statefile => 'ilo_redfish_' . md5_hex($self->{option_results}->{hostname}) . '_' . md5_hex($self->{option_results}->{api_username})); my $token = $options{statefile}->get(name => 'token'); if ($has_cache_file == 0 || !defined($token)) { my $json_request = { UserName => $self->{api_username}, Password => $self->{api_password} }; my $encoded; eval { $encoded = encode_json($json_request); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot encode json request"); $self->{output}->option_exit(); } my $content = $self->{http}->request( method => 'POST', url_path => '/redfish/v1/SessionService/Sessions/', query_form_post => $encoded, warning_status => '', unknown_status => '', critical_status => '' ); if ($self->{http}->get_code() < 200 || $self->{http}->get_code() >= 300) { $self->{output}->add_option_msg(short_msg => "Login error [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); $self->{output}->option_exit(); } $token = $self->{http}->get_header(name => 'X-Auth-Token'); if (!defined($token)) { $self->{output}->add_option_msg(short_msg => "Error retrieving token"); $self->{output}->option_exit(); } my $datas = { last_timestamp => time(), token => $token }; $options{statefile}->write(data => $datas); } $self->{token} = $token; $self->{http}->add_header(key => 'X-Auth-Token', value => $self->{token}); } sub request_api { my ($self, %options) = @_; $self->settings(); if (!defined($self->{token})) { $self->authenticate(statefile => $self->{cache}); } my $content = $self->{http}->request(%options, warning_status => '', unknown_status => '', critical_status => '' ); # Maybe there is an issue with the token. So we retry. if ($self->{http}->get_code() < 200 || $self->{http}->get_code() >= 300) { $self->clean_token(statefile => $self->{cache}); $self->authenticate(statefile => $self->{cache}); $content = $self->{http}->request(%options, warning_status => '', unknown_status => '', critical_status => '' ); } my $decoded = $self->json_decode(content => $content); if (!defined($decoded)) { $self->{output}->add_option_msg(short_msg => "Error while retrieving data (add --debug option for detailed message)"); $self->{output}->option_exit(); } if ($self->{http}->get_code() < 200 || $self->{http}->get_code() >= 300) { $self->{output}->add_option_msg(short_msg => 'api request error: ' . (defined($decoded->{type}) ? $decoded->{type} : 'unknown')); $self->{output}->option_exit(); } return $decoded; } 1; __END__ =head1 NAME ILO Rest API =head1 REST API OPTIONS =over 8 =item B<--hostname> Set hostname or IP of ILO. =item B<--port> Set port (Default: '443'). =item B<--proto> Specify https if needed (Default: 'https'). =item B<--api-username> Set username. =item B<--api-password> Set password. =item B<--timeout> Threshold for HTTP timeout (Default: '30'). =back =cut centreon-plugins-20220113/hardware/server/hp/ilo/restapi/plugin.pm000066400000000000000000000025071417000230700250400ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::hp::ilo::restapi::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} = { 'hardware' => 'centreon::common::redfish::restapi::mode::hardware' }; $self->{custom_modes}->{api} = 'hardware::server::hp::ilo::restapi::custom::api'; return $self; } 1; __END__ =head1 PLUGIN DESCRIPTION Check ilo 5 with Redfish Rest API. =cut centreon-plugins-20220113/hardware/server/hp/ilo/xmlapi/000077500000000000000000000000001417000230700230235ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/hp/ilo/xmlapi/custom/000077500000000000000000000000001417000230700243355ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/hp/ilo/xmlapi/custom/api.pm000066400000000000000000000272661417000230700254610ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::hp::ilo::xmlapi::custom::api; use strict; use warnings; use IO::Socket::SSL; use XML::Simple; use centreon::plugins::http; 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 => { 'hostname:s' => { name => 'hostname' }, 'timeout:s' => { name => 'timeout', default => 30 }, 'port:s' => { name => 'port', default => 443 }, 'username:s' => { name => 'username' }, 'password:s' => { name => 'password' }, 'force-ilo3' => { name => 'force_ilo3' } }); } $options{options}->add_help(package => __PACKAGE__, sections => 'XML API OPTIONS', once => 1); $self->{output} = $options{output}; $self->{http} = centreon::plugins::http->new(%options); return $self; } sub set_options { my ($self, %options) = @_; $self->{option_results} = $options{option_results}; } sub set_defaults {} sub check_options { my ($self, %options) = @_; if (!defined($self->{option_results}->{hostname}) || $self->{option_results}->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to set hostname option."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{username}) || $self->{option_results}->{username} eq '') { $self->{output}->add_option_msg(short_msg => "Need to set username option."); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{password})) { $self->{output}->add_option_msg(short_msg => "Need to set password option."); $self->{output}->option_exit(); } $self->{ssl_opts} = ''; if (!defined($self->{option_results}->{ssl_opt})) { $self->{option_results}->{ssl_opt} = ['SSL_verify_mode => SSL_VERIFY_NONE']; $self->{ssl_opts} = 'SSL_verify_mode => SSL_VERIFY_NONE'; } else { foreach (@{$self->{option_results}->{ssl_opt}}) { $self->{ssl_opts} .= "$_, "; } } if (!defined($self->{option_results}->{curl_opt})) { $self->{option_results}->{curl_opt} = ['CURLOPT_SSL_VERIFYPEER => 0', 'CURLOPT_SSL_VERIFYHOST => 0']; } $self->{http}->set_options(%{$self->{option_results}}); return 0; } sub find_ilo_version { my ($self, %options) = @_; ($self->{ilo2}, $self->{ilo3}) = (0, 0); my $client = new IO::Socket::SSL->new(PeerAddr => $self->{option_results}->{hostname} . ':' . $self->{option_results}->{port}, eval $self->{ssl_opts}, Timeout => $self->{option_results}->{timeout}); if (!$client) { $self->{output}->add_option_msg(short_msg => "Failed to establish SSL connection: $!, ssl_error=$SSL_ERROR"); $self->{output}->option_exit(); } print $client 'POST /ribcl HTTP/1.1' . "\r\n"; print $client "HOST: me" . "\r\n"; # Mandatory for http 1.1 print $client "User-Agent: locfg-Perl-script/3.0\r\n"; print $client "Content-length: 30" . "\r\n"; # Mandatory for http 1.1 print $client 'Connection: Close' . "\r\n"; # Required print $client "\r\n"; # End of http header print $client "\r\n"; # Used by Content-length my $ln = <$client>; if ($ln =~ m/HTTP.1.1 200 OK/) { $self->{ilo3} = 1; } else { $self->{ilo2} = 1; } close $client; } sub get_ilo2_data { my ($self, %options) = @_; my $client = new IO::Socket::SSL->new(PeerAddr => $self->{option_results}->{hostname} . ':' . $self->{option_results}->{port}, eval $self->{ssl_opts}, Timeout => $self->{option_results}->{timeout}); if (!$client) { $self->{output}->add_option_msg(short_msg => "Failed to establish SSL connection: $!, ssl_error=$SSL_ERROR"); $self->{output}->option_exit(); } print $client '' . "\r\n"; print $client '' . "\r\n"; print $client '' . "\r\n"; print $client '' . "\r\n"; print $client '' . "\r\n"; print $client '' . "\r\n"; print $client '' . "\r\n"; print $client '' . "\r\n"; while (my $line = <$client>) { $self->{content} .= $line; } close $client; } sub get_ilo3_data { my ($self, %options) = @_; my $xml_script = " {option_results}->{username}\" PASSWORD=\"$self->{option_results}->{password}\"> "; $self->{http}->add_header(key => 'TE', value => 'chunked'); $self->{http}->add_header(key => 'Connection', value => 'Close'); $self->{http}->add_header(key => 'Content-Type', value => 'text/xml'); $self->{content} = $self->{http}->request( method => 'POST', proto => 'https', url_path => '/ribcl', query_form_post => $xml_script, ); } sub check_ilo_error { my ($self, %options) = @_; # Looking for: # while ($self->{content} =~ /]*?status="0x(.*?)"[^>]*?message='(.*?)'/msig) { my ($status_code, $message) = ($1, $2); if ($status_code !~ /^0+$/) { $self->{output}->add_option_msg(short_msg => "Cannot get data: $2"); $self->{output}->option_exit(); } } } sub change_shitty_xml { my ($self, %options) = @_; # Can be like that the root ???!! $options{response} =~ s///mg; # ILO2 can send: # # # # # # # # # # # # $options{response} =~ s///mg; #Other shitty xml: # # # # # # $options{response} =~ s///msg; # 3rd variant, known as the ArnoMLT variant # # # # # # # # # # # # # # # # # # # # $options{response} =~ s////msg; return $options{response}; } sub get_ilo_response { my ($self, %options) = @_; # ilo result is so shitty. We get the good result from size... my ($length, $response) = (0, ''); foreach (split /<\?xml.*?\?>/, $self->{content}) { if (length($_) > $length) { $response = $_; $length = length($_); } } $response = $self->change_shitty_xml(response => $response); my $xml_result; eval { $xml_result = XMLin($response, ForceArray => ['FAN', 'TEMP', 'MODULE', 'SUPPLY', 'PROCESSOR', 'NIC', 'SMART_STORAGE_BATTERY', 'CONTROLLER', 'DRIVE_ENCLOSURE', 'LOGICAL_DRIVE', 'PHYSICAL_DRIVE', 'DRIVE_BAY', 'BACKPLANE']); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot decode xml response: $@"); $self->{output}->option_exit(); } return $xml_result; } sub get_ilo_data { my ($self, %options) = @_; $self->{content} = ''; if (!defined($self->{option_results}->{force_ilo3})) { $self->find_ilo_version(); } else { $self->{ilo3} = 1; } if ($self->{ilo3} == 1) { $self->get_ilo3_data(); } else { $self->get_ilo2_data(); } $self->{content} =~ s/\r//sg; $self->{output}->output_add(long_msg => $self->{content}, debug => 1); $self->check_ilo_error(); return $self->get_ilo_response(); } 1; __END__ =head1 NAME ILO API =head1 SYNOPSIS ilo api =head1 XML API OPTIONS =over 8 =item B<--hostname> Hostname to query. =item B<--username> ILO username. =item B<--password> ILO password. =item B<--port> ILO Port (Default: 443). =item B<--timeout> Set timeout (Default: 30). =item B<--force-ilo3> Don't try to find ILO version. =back =head1 DESCRIPTION B. =cut centreon-plugins-20220113/hardware/server/hp/ilo/xmlapi/mode/000077500000000000000000000000001417000230700237475ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/hp/ilo/xmlapi/mode/components/000077500000000000000000000000001417000230700261345ustar00rootroot00000000000000centreon-plugins-20220113/hardware/server/hp/ilo/xmlapi/mode/components/battery.pm000066400000000000000000000054161417000230700301520ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::hp::ilo::xmlapi::mode::components::battery; use strict; use warnings; sub load { } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking batteries"); $self->{components}->{battery} = {name => 'battery', total => 0, skip => 0}; return if ($self->check_filter(section => 'battery')); return if (!defined($self->{xml_result}->{GET_EMBEDDED_HEALTH_DATA}->{POWER_SUPPLIES}->{SMART_STORAGE_BATTERY})); # # # foreach my $result (@{$self->{xml_result}->{GET_EMBEDDED_HEALTH_DATA}->{POWER_SUPPLIES}->{SMART_STORAGE_BATTERY}}) { my $instance = $result->{LABEL}->{VALUE}; next if ($self->check_filter(section => 'battery', instance => $instance)); next if ($result->{STATUS}->{VALUE} =~ /not installed|n\/a|not present|not applicable/i && $self->absent_problem(section => 'battery', instance => $instance)); $self->{components}->{battery}->{total}++; $self->{output}->output_add(long_msg => sprintf("battery '%s' status is '%s' [instance = %s]", $result->{LABEL}->{VALUE}, $result->{STATUS}->{VALUE}, $instance)); my $exit = $self->get_severity(label => 'default', section => 'battery', value => $result->{STATUS}->{VALUE}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Battery '%s' status is '%s'", $result->{LABEL}->{VALUE}, $result->{STATUS}->{VALUE})); } } } 1;centreon-plugins-20220113/hardware/server/hp/ilo/xmlapi/mode/components/bios.pm000066400000000000000000000037661417000230700274420ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package 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;centreon-plugins-20220113/hardware/server/hp/ilo/xmlapi/mode/components/cpu.pm000066400000000000000000000056371417000230700272740ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::hp::ilo::xmlapi::mode::components::cpu; use strict; use warnings; sub load { } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking cpu"); $self->{components}->{cpu} = {name => 'cpu', total => 0, skip => 0}; return if ($self->check_filter(section => 'cpu')); return if (!defined($self->{xml_result}->{GET_EMBEDDED_HEALTH_DATA}->{PROCESSORS}->{PROCESSOR})); # STATUS can be missing # # # # foreach my $result (@{$self->{xml_result}->{GET_EMBEDDED_HEALTH_DATA}->{PROCESSORS}->{PROCESSOR}}) { next if (!defined($result->{STATUS})); my $instance = $result->{LABEL}->{VALUE}; next if ($self->check_filter(section => 'cpu', instance => $instance)); next if ($result->{STATUS}->{VALUE} =~ /not installed|n\/a|not present|not applicable/i && $self->absent_problem(section => 'cpu', instance => $instance)); $self->{components}->{cpu}->{total}++; $self->{output}->output_add(long_msg => sprintf("cpu '%s' status is '%s' [instance = %s]", $result->{LABEL}->{VALUE}, $result->{STATUS}->{VALUE}, $instance)); my $exit = $self->get_severity(label => 'default', section => 'CPU', value => $result->{STATUS}->{VALUE}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("CPU '%s' status is '%s'", $result->{LABEL}->{VALUE}, $result->{STATUS}->{VALUE})); } } } 1;centreon-plugins-20220113/hardware/server/hp/ilo/xmlapi/mode/components/ctrl.pm000066400000000000000000000055141417000230700274430ustar00rootroot00000000000000# # Copyright 2022 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for # service performance. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package hardware::server::hp::ilo::xmlapi::mode::components::ctrl; use strict; use warnings; sub load { } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking controllers"); $self->{components}->{ctrl} = {name => 'ctrl', total => 0, skip => 0}; return if ($self->check_filter(section => 'ctrl')); return if (!defined($self->{xml_result}->{GET_EMBEDDED_HEALTH_DATA}->{STORAGE}->{CONTROLLER})); # # #